From d822ad2b77ec772f2ae5e9ca631b38c5e175764a Mon Sep 17 00:00:00 2001
From: Stefan Mayer-Popp <mail@stefanpopp.de>
Date: Wed, 23 Mar 2016 11:41:10 +0100
Subject: [PATCH 001/685] Update module.modulemap

Imports the SDK based on current architecture. Fixes incompatibility problems for Xcode 7.3.
Also includes link flag for convenience.
---
 podstuff/module.modulemap | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/podstuff/module.modulemap b/podstuff/module.modulemap
index 122acd2e..443b93e9 100644
--- a/podstuff/module.modulemap
+++ b/podstuff/module.modulemap
@@ -5,7 +5,18 @@ framework module SQLite {
     //
     //     header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/sqlite3.h"
     //     header "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/sqlite3.h"
-    header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/sqlite3.h"
+    //     header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/sqlite3.h"
+    module arm {
+        header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/sqlite3.h"
+        link "sqlite3"
+        requires arm
+    }
+    
+    module x86 {
+        header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/sqlite3.h"
+        link "sqlite3"
+        requires x86
+    }
 
     export *
     module * { export * }

From d0277040a8bc3ece266f3651a73445080a6a5022 Mon Sep 17 00:00:00 2001
From: Stefan Mayer-Popp <mail@stefanpopp.de>
Date: Wed, 23 Mar 2016 12:10:00 +0100
Subject: [PATCH 002/685] Fixes missing arm64 compatibility

I've just missed arm64 compatibility. Works now fine with Xcode 7.2.1
---
 podstuff/module.modulemap | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/podstuff/module.modulemap b/podstuff/module.modulemap
index 443b93e9..50c31a61 100644
--- a/podstuff/module.modulemap
+++ b/podstuff/module.modulemap
@@ -8,15 +8,20 @@ framework module SQLite {
     //     header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/sqlite3.h"
     module arm {
         header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/sqlite3.h"
-        link "sqlite3"
         requires arm
     }
     
+    module arm64 {
+        header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/sqlite3.h"
+        requires arm64
+    }
+    
     module x86 {
         header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/sqlite3.h"
-        link "sqlite3"
         requires x86
     }
+    
+    link "sqlite3"
 
     export *
     module * { export * }

From 8d2903bd70029379184e77e2b6916cf2d884b6de Mon Sep 17 00:00:00 2001
From: Stephen Celis <stephen@stephencelis.com>
Date: Wed, 23 Mar 2016 10:59:24 -0400
Subject: [PATCH 003/685] CocoaPods fix: Use platform-specific module maps

Xcode 7.3 got more strict about SDK headers. We need to use multiple
module maps to accommodate various platforms and we need to scope
`requires` to accommodate various architecturers.

Signed-off-by: Stephen Celis <stephen@stephencelis.com>
---
 .../ios.modulemap                              | 11 +++--------
 CocoaPods/osx.modulemap                        | 10 ++++++++++
 CocoaPods/tvos.modulemap                       | 18 ++++++++++++++++++
 SQLite.swift.podspec                           |  5 ++++-
 SQLite.xcodeproj/project.pbxproj               |  2 +-
 5 files changed, 36 insertions(+), 10 deletions(-)
 rename podstuff/module.modulemap => CocoaPods/ios.modulemap (56%)
 create mode 100644 CocoaPods/osx.modulemap
 create mode 100644 CocoaPods/tvos.modulemap

diff --git a/podstuff/module.modulemap b/CocoaPods/ios.modulemap
similarity index 56%
rename from podstuff/module.modulemap
rename to CocoaPods/ios.modulemap
index 50c31a61..502383f3 100644
--- a/podstuff/module.modulemap
+++ b/CocoaPods/ios.modulemap
@@ -1,26 +1,21 @@
 framework module SQLite {
     umbrella header "SQLite.h"
 
-    // Load the SDK header alongside SQLite.swift. Alternate headers:
-    //
-    //     header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/sqlite3.h"
-    //     header "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/sqlite3.h"
-    //     header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/sqlite3.h"
     module arm {
         header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/sqlite3.h"
         requires arm
     }
-    
+
     module arm64 {
         header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/sqlite3.h"
         requires arm64
     }
-    
+
     module x86 {
         header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/sqlite3.h"
         requires x86
     }
-    
+
     link "sqlite3"
 
     export *
diff --git a/CocoaPods/osx.modulemap b/CocoaPods/osx.modulemap
new file mode 100644
index 00000000..80628c7b
--- /dev/null
+++ b/CocoaPods/osx.modulemap
@@ -0,0 +1,10 @@
+framework module SQLite {
+    umbrella header "SQLite.h"
+
+    header "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/sqlite3.h"
+
+    link "sqlite3"
+
+    export *
+    module * { export * }
+}
diff --git a/CocoaPods/tvos.modulemap b/CocoaPods/tvos.modulemap
new file mode 100644
index 00000000..480ff6f3
--- /dev/null
+++ b/CocoaPods/tvos.modulemap
@@ -0,0 +1,18 @@
+framework module SQLite {
+    umbrella header "SQLite.h"
+
+    module arm64 {
+        header "/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk/usr/include/sqlite3.h"
+        requires arm64
+    }
+
+    module x86 {
+        header "/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVSimulator.platform/Developer/SDKs/AppleTVSimulator.sdk/usr/include/sqlite3.h"
+        requires x86
+    }
+
+    link "sqlite3"
+
+    export *
+    module * { export * }
+}
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index b8160396..a4a79ba4 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -24,7 +24,10 @@ Pod::Spec.new do |s|
   s.tvos.deployment_target = "9.0"
   s.osx.deployment_target = "10.9"
 
-  s.module_map = "podstuff/module.modulemap"
+  s.ios.module_map = "CocoaPods/ios.modulemap"
+  s.tvos.module_map = "CocoaPods/tvos.modulemap"
+  s.osx.module_map = "CocoaPods/osx.modulemap"
+
   s.libraries = 'sqlite3'
   s.source_files = 'SQLite/**/*.{c,h,m,swift}'
   s.private_header_files = 'SQLite/Core/fts3_tokenizer.h'
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index d73ebb51..4960525a 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -153,7 +153,7 @@
 /* Begin PBXFileReference section */
 		03A65E5A1C6BB0F50062603F /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		03A65E631C6BB0F60062603F /* SQLiteTests tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SQLiteTests tvOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
-		03A65E961C6BB3210062603F /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.1.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
+		03A65E961C6BB3210062603F /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
 		EE247AD31C3F04ED00AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AD61C3F04ED00AE3E12 /* SQLite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLite.h; sourceTree = "<group>"; };
 		EE247AD81C3F04ED00AE3E12 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };

From 82a5f8ce62013c73775a5f0aaa78c792b60efbd7 Mon Sep 17 00:00:00 2001
From: Andrew Crookston <andrew@caoos.com>
Date: Wed, 23 Mar 2016 16:36:59 -0700
Subject: [PATCH 004/685] Adds watchOS support

---
 CocoaPods/watchos.modulemap      |  18 ++++++
 SQLite.swift.podspec             |   2 +
 SQLite.xcodeproj/project.pbxproj | 104 +++++++++++++++++++++++++++++++
 3 files changed, 124 insertions(+)
 create mode 100644 CocoaPods/watchos.modulemap

diff --git a/CocoaPods/watchos.modulemap b/CocoaPods/watchos.modulemap
new file mode 100644
index 00000000..59660448
--- /dev/null
+++ b/CocoaPods/watchos.modulemap
@@ -0,0 +1,18 @@
+framework module SQLite {
+    umbrella header "SQLite.h"
+
+    module arm64 {
+        header "/Applications/Xcode.app/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs/WatchOS.sdk/usr/include/sqlite3.h"
+        requires arm64
+    }
+
+    module x86 {
+        header "/Applications/Xcode.app/Contents/Developer/Platforms/WatchSimulator.platform/Developer/SDKs/WatchSimulator.sdk/usr/include/sqlite3.h"
+        requires x86
+    }
+
+    link "sqlite3"
+
+    export *
+    module * { export * }
+}
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index a4a79ba4..a7dc8f6e 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -23,10 +23,12 @@ Pod::Spec.new do |s|
   s.ios.deployment_target = "8.0"
   s.tvos.deployment_target = "9.0"
   s.osx.deployment_target = "10.9"
+  s.watchos.deployment_target = "2.0"
 
   s.ios.module_map = "CocoaPods/ios.modulemap"
   s.tvos.module_map = "CocoaPods/tvos.modulemap"
   s.osx.module_map = "CocoaPods/osx.modulemap"
+  s.watchos.module_map = "CocoaPods/watchos.modulemap"
 
   s.libraries = 'sqlite3'
   s.source_files = 'SQLite/**/*.{c,h,m,swift}'
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 4960525a..bc23874a 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -154,6 +154,7 @@
 		03A65E5A1C6BB0F50062603F /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		03A65E631C6BB0F60062603F /* SQLiteTests tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SQLiteTests tvOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
 		03A65E961C6BB3210062603F /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
+		A121AC451CA35C79005A31D1 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AD31C3F04ED00AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AD61C3F04ED00AE3E12 /* SQLite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLite.h; sourceTree = "<group>"; };
 		EE247AD81C3F04ED00AE3E12 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -226,6 +227,13 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		A121AC411CA35C79005A31D1 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		EE247ACF1C3F04ED00AE3E12 /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
@@ -280,6 +288,7 @@
 				EE247B451C3F3ED000AE3E12 /* SQLiteTests Mac.xctest */,
 				03A65E5A1C6BB0F50062603F /* SQLite.framework */,
 				03A65E631C6BB0F60062603F /* SQLiteTests tvOS.xctest */,
+				A121AC451CA35C79005A31D1 /* SQLite.framework */,
 			);
 			name = Products;
 			sourceTree = "<group>";
@@ -409,6 +418,13 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		A121AC421CA35C79005A31D1 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		EE247AD01C3F04ED00AE3E12 /* Headers */ = {
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
@@ -470,6 +486,24 @@
 			productReference = 03A65E631C6BB0F60062603F /* SQLiteTests tvOS.xctest */;
 			productType = "com.apple.product-type.bundle.unit-test";
 		};
+		A121AC441CA35C79005A31D1 /* SQLite watchOS */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = A121AC4C1CA35C79005A31D1 /* Build configuration list for PBXNativeTarget "SQLite watchOS" */;
+			buildPhases = (
+				A121AC401CA35C79005A31D1 /* Sources */,
+				A121AC411CA35C79005A31D1 /* Frameworks */,
+				A121AC421CA35C79005A31D1 /* Headers */,
+				A121AC431CA35C79005A31D1 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "SQLite watchOS";
+			productName = "SQLite watchOS";
+			productReference = A121AC451CA35C79005A31D1 /* SQLite.framework */;
+			productType = "com.apple.product-type.framework";
+		};
 		EE247AD21C3F04ED00AE3E12 /* SQLite iOS */ = {
 			isa = PBXNativeTarget;
 			buildConfigurationList = EE247AE71C3F04ED00AE3E12 /* Build configuration list for PBXNativeTarget "SQLite iOS" */;
@@ -557,6 +591,9 @@
 					03A65E621C6BB0F60062603F = {
 						CreatedOnToolsVersion = 7.2;
 					};
+					A121AC441CA35C79005A31D1 = {
+						CreatedOnToolsVersion = 7.3;
+					};
 					EE247AD21C3F04ED00AE3E12 = {
 						CreatedOnToolsVersion = 7.2;
 					};
@@ -589,6 +626,7 @@
 				EE247B441C3F3ED000AE3E12 /* SQLiteTests Mac */,
 				03A65E591C6BB0F50062603F /* SQLite tvOS */,
 				03A65E621C6BB0F60062603F /* SQLiteTests tvOS */,
+				A121AC441CA35C79005A31D1 /* SQLite watchOS */,
 			);
 		};
 /* End PBXProject section */
@@ -608,6 +646,13 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		A121AC431CA35C79005A31D1 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		EE247AD11C3F04ED00AE3E12 /* Resources */ = {
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
@@ -686,6 +731,13 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		A121AC401CA35C79005A31D1 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		EE247ACE1C3F04ED00AE3E12 /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
@@ -861,6 +913,48 @@
 			};
 			name = Release;
 		};
+		A121AC4A1CA35C79005A31D1 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				APPLICATION_EXTENSION_API_ONLY = YES;
+				CLANG_ANALYZER_NONNULL = YES;
+				DEFINES_MODULE = YES;
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				DYLIB_INSTALL_NAME_BASE = "@rpath";
+				INFOPLIST_FILE = SQLite/Info.plist;
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
+				PRODUCT_NAME = SQLite;
+				SDKROOT = watchos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = 4;
+				WATCHOS_DEPLOYMENT_TARGET = 2.2;
+			};
+			name = Debug;
+		};
+		A121AC4B1CA35C79005A31D1 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				APPLICATION_EXTENSION_API_ONLY = YES;
+				CLANG_ANALYZER_NONNULL = YES;
+				DEFINES_MODULE = YES;
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				DYLIB_INSTALL_NAME_BASE = "@rpath";
+				INFOPLIST_FILE = SQLite/Info.plist;
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
+				PRODUCT_NAME = SQLite;
+				SDKROOT = watchos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = 4;
+				WATCHOS_DEPLOYMENT_TARGET = 2.2;
+			};
+			name = Release;
+		};
 		EE247AE51C3F04ED00AE3E12 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
@@ -1099,6 +1193,7 @@
 				03A65E6C1C6BB0F60062603F /* Release */,
 			);
 			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
 		};
 		03A65E701C6BB0F60062603F /* Build configuration list for PBXNativeTarget "SQLiteTests tvOS" */ = {
 			isa = XCConfigurationList;
@@ -1107,6 +1202,15 @@
 				03A65E6E1C6BB0F60062603F /* Release */,
 			);
 			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		A121AC4C1CA35C79005A31D1 /* Build configuration list for PBXNativeTarget "SQLite watchOS" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				A121AC4A1CA35C79005A31D1 /* Debug */,
+				A121AC4B1CA35C79005A31D1 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
 		};
 		EE247ACD1C3F04ED00AE3E12 /* Build configuration list for PBXProject "SQLite" */ = {
 			isa = XCConfigurationList;

From 4243bc42d4aec145607d1b9af275883382681ab9 Mon Sep 17 00:00:00 2001
From: Andrew Crookston <andrew@caoos.com>
Date: Thu, 24 Mar 2016 16:12:38 -0700
Subject: [PATCH 005/685] Use armv7k architecture, not arm64, for the WatchOS
 SDK

---
 CocoaPods/watchos.modulemap | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CocoaPods/watchos.modulemap b/CocoaPods/watchos.modulemap
index 59660448..7de53767 100644
--- a/CocoaPods/watchos.modulemap
+++ b/CocoaPods/watchos.modulemap
@@ -1,7 +1,7 @@
 framework module SQLite {
     umbrella header "SQLite.h"
 
-    module arm64 {
+    module armv7k {
         header "/Applications/Xcode.app/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs/WatchOS.sdk/usr/include/sqlite3.h"
         requires arm64
     }

From 5d09ab210525f6f21b37eaf7e5263bb3f9779ddc Mon Sep 17 00:00:00 2001
From: Andrew Crookston <andrew@caoos.com>
Date: Thu, 24 Mar 2016 16:21:47 -0700
Subject: [PATCH 006/685] Changes a missed arm64 reference to armv7k from
 previous commit

---
 CocoaPods/watchos.modulemap | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CocoaPods/watchos.modulemap b/CocoaPods/watchos.modulemap
index 7de53767..ff9080ab 100644
--- a/CocoaPods/watchos.modulemap
+++ b/CocoaPods/watchos.modulemap
@@ -3,7 +3,7 @@ framework module SQLite {
 
     module armv7k {
         header "/Applications/Xcode.app/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs/WatchOS.sdk/usr/include/sqlite3.h"
-        requires arm64
+        requires armv7k
     }
 
     module x86 {

From fb15120895170a2d336d8bc09f68e506f8471777 Mon Sep 17 00:00:00 2001
From: Stephen Celis <stephen@stephencelis.com>
Date: Wed, 23 Mar 2016 16:48:59 -0400
Subject: [PATCH 007/685] Update CocoaPods requirements

Signed-off-by: Stephen Celis <stephen@stephencelis.com>
---
 Documentation/Index.md |  8 +++++++-
 README.md              | 10 ++++++++--
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 5906ccff..9fbd4640 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -93,7 +93,13 @@ install SQLite.swift with Carthage:
 
 [CocoaPods][] is a dependency manager for Cocoa projects. To install SQLite.swift with CocoaPods:
 
- 1. Make sure CocoaPods is [installed][CocoaPods Installation] (SQLite.swift requires version 0.37 or greater).
+ 1. Make sure the latest CocoaPods beta is [installed][CocoaPods Installation]. (SQLite.swift requires version 1.0.0.beta.6 or greater.)
+
+    ``` sh
+    # Using the default Ruby install will require you to use sudo when
+    # installing and updating gems.
+    sudo gem install --pre cocoapods
+    ```
 
  2. Update your Podfile to include the following:
 
diff --git a/README.md b/README.md
index 02291cbe..d07aa06a 100644
--- a/README.md
+++ b/README.md
@@ -143,8 +143,14 @@ install SQLite.swift with Carthage:
 [CocoaPods][] is a dependency manager for Cocoa projects. To install
 SQLite.swift with CocoaPods:
 
- 1. Make sure CocoaPods is [installed][CocoaPods Installation]. (SQLite.swift
-    requires version 0.37 or greater.)
+ 1. Make sure the latest CocoaPods beta is [installed][CocoaPods
+    Installation]. (SQLite.swift requires version 1.0.0.beta.6 or greater.)
+
+    ``` sh
+    # Using the default Ruby install will require you to use sudo when
+    # installing and updating gems.
+    sudo gem install --pre cocoapods
+    ```
 
  2. Update your Podfile to include the following:
 

From 29c2fafc91a722ba8dba77816726e60cf38b916b Mon Sep 17 00:00:00 2001
From: Stephen Celis <stephen@stephencelis.com>
Date: Fri, 25 Mar 2016 14:48:30 -0400
Subject: [PATCH 008/685] Bump to 0.10.0

Signed-off-by: Stephen Celis <stephen@stephencelis.com>
---
 Documentation/Index.md           | 4 ++--
 README.md                        | 4 ++--
 SQLite.swift.podspec             | 2 +-
 SQLite.xcodeproj/project.pbxproj | 1 +
 SQLite/Info.plist                | 2 +-
 5 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 9fbd4640..fe1a4084 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -78,7 +78,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```
-    github "stephencelis/SQLite.swift" ~> 0.9.2
+    github "stephencelis/SQLite.swift" ~> 0.10.0
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -106,7 +106,7 @@ install SQLite.swift with Carthage:
     ``` ruby
     use_frameworks!
 
-    pod 'SQLite.swift', '~> 0.9.2'
+    pod 'SQLite.swift', '~> 0.10.0'
     ```
 
  3. Run `pod install`.
diff --git a/README.md b/README.md
index d07aa06a..89d9aef4 100644
--- a/README.md
+++ b/README.md
@@ -127,7 +127,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```
-    github "stephencelis/SQLite.swift" ~> 0.9.2
+    github "stephencelis/SQLite.swift" ~> 0.10.0
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -157,7 +157,7 @@ SQLite.swift with CocoaPods:
     ``` ruby
     use_frameworks!
 
-    pod 'SQLite.swift', '~> 0.9.2'
+    pod 'SQLite.swift', '~> 0.10.0'
     ```
 
  3. Run `pod install`.
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index a7dc8f6e..ad211a3a 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -5,7 +5,7 @@
 
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.9.2"
+  s.version          = "0.10.0"
   s.summary          = "A type-safe, Swift-language layer over SQLite3 for iOS and OS X."
 
   s.description      = <<-DESC
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index bc23874a..55385ce3 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1211,6 +1211,7 @@
 				A121AC4B1CA35C79005A31D1 /* Release */,
 			);
 			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
 		};
 		EE247ACD1C3F04ED00AE3E12 /* Build configuration list for PBXProject "SQLite" */ = {
 			isa = XCConfigurationList;
diff --git a/SQLite/Info.plist b/SQLite/Info.plist
index 230b60f6..378e663f 100644
--- a/SQLite/Info.plist
+++ b/SQLite/Info.plist
@@ -15,7 +15,7 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>0.9.2</string>
+	<string>0.10.0</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>

From 5652283be519024b32578f58f869ee8f0103f2db Mon Sep 17 00:00:00 2001
From: Caesar Wirth <cjwirth@gmail.com>
Date: Sat, 26 Mar 2016 12:38:06 +0900
Subject: [PATCH 009/685] [CocoaPods] Add SQLite module map for each
 architecture

---
 CocoaPods/appletvos/module.modulemap          |  4 +
 CocoaPods/appletvsimulator/module.modulemap   |  4 +
 CocoaPods/ios.modulemap                       | 23 -----
 CocoaPods/iphoneos/module.modulemap           |  4 +
 CocoaPods/iphonesimulator/module.modulemap    |  4 +
 .../module.modulemap}                         |  8 +-
 CocoaPods/tvos.modulemap                      | 18 ----
 CocoaPods/watchos.modulemap                   | 18 ----
 CocoaPods/watchos/module.modulemap            |  4 +
 CocoaPods/watchsimulator/module.modulemap     |  4 +
 SQLite.swift.podspec                          | 14 ++-
 SQLite.xcodeproj/project.pbxproj              | 92 ++++++++++++++++++-
 SQLite/Core/Connection.swift                  |  1 +
 SQLite/Core/Statement.swift                   |  2 +
 SQLite/Helpers.swift                          |  2 +
 15 files changed, 129 insertions(+), 73 deletions(-)
 create mode 100644 CocoaPods/appletvos/module.modulemap
 create mode 100644 CocoaPods/appletvsimulator/module.modulemap
 delete mode 100644 CocoaPods/ios.modulemap
 create mode 100644 CocoaPods/iphoneos/module.modulemap
 create mode 100644 CocoaPods/iphonesimulator/module.modulemap
 rename CocoaPods/{osx.modulemap => macosx/module.modulemap} (58%)
 delete mode 100644 CocoaPods/tvos.modulemap
 delete mode 100644 CocoaPods/watchos.modulemap
 create mode 100644 CocoaPods/watchos/module.modulemap
 create mode 100644 CocoaPods/watchsimulator/module.modulemap

diff --git a/CocoaPods/appletvos/module.modulemap b/CocoaPods/appletvos/module.modulemap
new file mode 100644
index 00000000..637d9935
--- /dev/null
+++ b/CocoaPods/appletvos/module.modulemap
@@ -0,0 +1,4 @@
+module CSQLite [system] {
+    header "/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk/usr/include/sqlite3.h"
+    export *
+}
diff --git a/CocoaPods/appletvsimulator/module.modulemap b/CocoaPods/appletvsimulator/module.modulemap
new file mode 100644
index 00000000..f8b9b671
--- /dev/null
+++ b/CocoaPods/appletvsimulator/module.modulemap
@@ -0,0 +1,4 @@
+module CSQLite [system] {
+    header "/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVSimulator.platform/Developer/SDKs/AppleTVSimulator.sdk/usr/include/sqlite3.h"
+    export *
+}
diff --git a/CocoaPods/ios.modulemap b/CocoaPods/ios.modulemap
deleted file mode 100644
index 502383f3..00000000
--- a/CocoaPods/ios.modulemap
+++ /dev/null
@@ -1,23 +0,0 @@
-framework module SQLite {
-    umbrella header "SQLite.h"
-
-    module arm {
-        header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/sqlite3.h"
-        requires arm
-    }
-
-    module arm64 {
-        header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/sqlite3.h"
-        requires arm64
-    }
-
-    module x86 {
-        header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/sqlite3.h"
-        requires x86
-    }
-
-    link "sqlite3"
-
-    export *
-    module * { export * }
-}
diff --git a/CocoaPods/iphoneos/module.modulemap b/CocoaPods/iphoneos/module.modulemap
new file mode 100644
index 00000000..043db6c4
--- /dev/null
+++ b/CocoaPods/iphoneos/module.modulemap
@@ -0,0 +1,4 @@
+module CSQLite [system] {
+    header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/sqlite3.h"
+    export *
+}
diff --git a/CocoaPods/iphonesimulator/module.modulemap b/CocoaPods/iphonesimulator/module.modulemap
new file mode 100644
index 00000000..a7b14cbb
--- /dev/null
+++ b/CocoaPods/iphonesimulator/module.modulemap
@@ -0,0 +1,4 @@
+module CSQLite [system] {
+    header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/sqlite3.h"
+    export *
+}
diff --git a/CocoaPods/osx.modulemap b/CocoaPods/macosx/module.modulemap
similarity index 58%
rename from CocoaPods/osx.modulemap
rename to CocoaPods/macosx/module.modulemap
index 80628c7b..9e091297 100644
--- a/CocoaPods/osx.modulemap
+++ b/CocoaPods/macosx/module.modulemap
@@ -1,10 +1,4 @@
-framework module SQLite {
-    umbrella header "SQLite.h"
-
+module CSQLite [system] {
     header "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/sqlite3.h"
-
-    link "sqlite3"
-
     export *
-    module * { export * }
 }
diff --git a/CocoaPods/tvos.modulemap b/CocoaPods/tvos.modulemap
deleted file mode 100644
index 480ff6f3..00000000
--- a/CocoaPods/tvos.modulemap
+++ /dev/null
@@ -1,18 +0,0 @@
-framework module SQLite {
-    umbrella header "SQLite.h"
-
-    module arm64 {
-        header "/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk/usr/include/sqlite3.h"
-        requires arm64
-    }
-
-    module x86 {
-        header "/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVSimulator.platform/Developer/SDKs/AppleTVSimulator.sdk/usr/include/sqlite3.h"
-        requires x86
-    }
-
-    link "sqlite3"
-
-    export *
-    module * { export * }
-}
diff --git a/CocoaPods/watchos.modulemap b/CocoaPods/watchos.modulemap
deleted file mode 100644
index ff9080ab..00000000
--- a/CocoaPods/watchos.modulemap
+++ /dev/null
@@ -1,18 +0,0 @@
-framework module SQLite {
-    umbrella header "SQLite.h"
-
-    module armv7k {
-        header "/Applications/Xcode.app/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs/WatchOS.sdk/usr/include/sqlite3.h"
-        requires armv7k
-    }
-
-    module x86 {
-        header "/Applications/Xcode.app/Contents/Developer/Platforms/WatchSimulator.platform/Developer/SDKs/WatchSimulator.sdk/usr/include/sqlite3.h"
-        requires x86
-    }
-
-    link "sqlite3"
-
-    export *
-    module * { export * }
-}
diff --git a/CocoaPods/watchos/module.modulemap b/CocoaPods/watchos/module.modulemap
new file mode 100644
index 00000000..62a6c4ee
--- /dev/null
+++ b/CocoaPods/watchos/module.modulemap
@@ -0,0 +1,4 @@
+module CSQLite [system] {
+    header "/Applications/Xcode.app/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs/WatchOS.sdk/usr/include/sqlite3.h"
+    export *
+}
diff --git a/CocoaPods/watchsimulator/module.modulemap b/CocoaPods/watchsimulator/module.modulemap
new file mode 100644
index 00000000..086fbab2
--- /dev/null
+++ b/CocoaPods/watchsimulator/module.modulemap
@@ -0,0 +1,4 @@
+module CSQLite [system] {
+    header "/Applications/Xcode.app/Contents/Developer/Platforms/WatchSimulator.platform/Developer/SDKs/WatchSimulator.sdk/usr/include/sqlite3.h"
+    export *
+}
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index ad211a3a..ac2b3d24 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -25,10 +25,16 @@ Pod::Spec.new do |s|
   s.osx.deployment_target = "10.9"
   s.watchos.deployment_target = "2.0"
 
-  s.ios.module_map = "CocoaPods/ios.modulemap"
-  s.tvos.module_map = "CocoaPods/tvos.modulemap"
-  s.osx.module_map = "CocoaPods/osx.modulemap"
-  s.watchos.module_map = "CocoaPods/watchos.modulemap"
+  s.preserve_paths = 'CocoaPods/**/*'
+  s.pod_target_xcconfig = {
+    'SWIFT_INCLUDE_PATHS[sdk=macosx*]'           => '$(SRCROOT)/SQLite.swift/CocoaPods/macosx',
+    'SWIFT_INCLUDE_PATHS[sdk=iphoneos*]'         => '$(SRCROOT)/SQLite.swift/CocoaPods/iphoneos',
+    'SWIFT_INCLUDE_PATHS[sdk=iphonesimulator*]'  => '$(SRCROOT)/SQLite.swift/CocoaPods/iphonesimulator',
+    'SWIFT_INCLUDE_PATHS[sdk=appletvos*]'        => '$(SRCROOT)/SQLite.swift/CocoaPods/appletvos',
+    'SWIFT_INCLUDE_PATHS[sdk=appletvsimulator*]' => '$(SRCROOT)/SQLite.swift/CocoaPods/appletvsimulator',
+    'SWIFT_INCLUDE_PATHS[sdk=watchos*]'          => '$(SRCROOT)/SQLite.swift/CocoaPods/watchos',
+    'SWIFT_INCLUDE_PATHS[sdk=watchsimulator*]'   => '$(SRCROOT)/SQLite.swift/CocoaPods/watchsimulator'
+  }
 
   s.libraries = 'sqlite3'
   s.source_files = 'SQLite/**/*.{c,h,m,swift}'
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 55385ce3..d2ac9df4 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -154,6 +154,13 @@
 		03A65E5A1C6BB0F50062603F /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		03A65E631C6BB0F60062603F /* SQLiteTests tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SQLiteTests tvOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
 		03A65E961C6BB3210062603F /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
+		39548A631CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
+		39548A651CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
+		39548A671CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
+		39548A691CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
+		39548A6B1CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
+		39548A6D1CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
+		39548A6F1CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
 		A121AC451CA35C79005A31D1 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AD31C3F04ED00AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AD61C3F04ED00AE3E12 /* SQLite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLite.h; sourceTree = "<group>"; };
@@ -203,7 +210,7 @@
 		EE247B8F1C3F822500AE3E12 /* Index.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Index.md; sourceTree = "<group>"; };
 		EE247B911C3F822500AE3E12 /* installation@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "installation@2x.png"; sourceTree = "<group>"; };
 		EE247B921C3F822600AE3E12 /* playground@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "playground@2x.png"; sourceTree = "<group>"; };
-		EE247B931C3F826100AE3E12 /* SQLite.swift.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = SQLite.swift.podspec; sourceTree = "<group>"; };
+		EE247B931C3F826100AE3E12 /* SQLite.swift.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; path = SQLite.swift.podspec; sourceTree = "<group>"; };
 		EE91808B1C46E34A0038162A /* usr/include/sqlite3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = usr/include/sqlite3.h; sourceTree = SDKROOT; };
 		EE91808D1C46E5230038162A /* SQLite-Bridging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SQLite-Bridging.h"; sourceTree = "<group>"; };
 		EE9180911C46E9D30038162A /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
@@ -269,6 +276,76 @@
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
+		39548A611CA63C740003E3B5 /* CocoaPods */ = {
+			isa = PBXGroup;
+			children = (
+				39548A621CA63C740003E3B5 /* appletvos */,
+				39548A641CA63C740003E3B5 /* appletvsimulator */,
+				39548A661CA63C740003E3B5 /* iphoneos */,
+				39548A681CA63C740003E3B5 /* iphonesimulator */,
+				39548A6A1CA63C740003E3B5 /* macosx */,
+				39548A6C1CA63C740003E3B5 /* watchos */,
+				39548A6E1CA63C740003E3B5 /* watchsimulator */,
+			);
+			path = CocoaPods;
+			sourceTree = "<group>";
+		};
+		39548A621CA63C740003E3B5 /* appletvos */ = {
+			isa = PBXGroup;
+			children = (
+				39548A631CA63C740003E3B5 /* module.modulemap */,
+			);
+			path = appletvos;
+			sourceTree = "<group>";
+		};
+		39548A641CA63C740003E3B5 /* appletvsimulator */ = {
+			isa = PBXGroup;
+			children = (
+				39548A651CA63C740003E3B5 /* module.modulemap */,
+			);
+			path = appletvsimulator;
+			sourceTree = "<group>";
+		};
+		39548A661CA63C740003E3B5 /* iphoneos */ = {
+			isa = PBXGroup;
+			children = (
+				39548A671CA63C740003E3B5 /* module.modulemap */,
+			);
+			path = iphoneos;
+			sourceTree = "<group>";
+		};
+		39548A681CA63C740003E3B5 /* iphonesimulator */ = {
+			isa = PBXGroup;
+			children = (
+				39548A691CA63C740003E3B5 /* module.modulemap */,
+			);
+			path = iphonesimulator;
+			sourceTree = "<group>";
+		};
+		39548A6A1CA63C740003E3B5 /* macosx */ = {
+			isa = PBXGroup;
+			children = (
+				39548A6B1CA63C740003E3B5 /* module.modulemap */,
+			);
+			path = macosx;
+			sourceTree = "<group>";
+		};
+		39548A6C1CA63C740003E3B5 /* watchos */ = {
+			isa = PBXGroup;
+			children = (
+				39548A6D1CA63C740003E3B5 /* module.modulemap */,
+			);
+			path = watchos;
+			sourceTree = "<group>";
+		};
+		39548A6E1CA63C740003E3B5 /* watchsimulator */ = {
+			isa = PBXGroup;
+			children = (
+				39548A6F1CA63C740003E3B5 /* module.modulemap */,
+			);
+			path = watchsimulator;
+			sourceTree = "<group>";
+		};
 		EE247AC91C3F04ED00AE3E12 = {
 			isa = PBXGroup;
 			children = (
@@ -373,6 +450,7 @@
 		EE247B8A1C3F81D000AE3E12 /* Metadata */ = {
 			isa = PBXGroup;
 			children = (
+				39548A611CA63C740003E3B5 /* CocoaPods */,
 				EE247B771C3F40D700AE3E12 /* README.md */,
 				EE247B8B1C3F820300AE3E12 /* CONTRIBUTING.md */,
 				EE247B931C3F826100AE3E12 /* SQLite.swift.podspec */,
@@ -867,6 +945,8 @@
 				PRODUCT_NAME = SQLite;
 				SDKROOT = appletvos;
 				SKIP_INSTALL = YES;
+				"SWIFT_INCLUDE_PATHS[sdk=appletvos*]" = "$(SRCROOT)/CocoaPods/appletvos";
+				"SWIFT_INCLUDE_PATHS[sdk=appletvsimulator*]" = "$(SRCROOT)/CocoaPods/appletvsimulator";
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
 			name = Debug;
@@ -885,6 +965,8 @@
 				PRODUCT_NAME = SQLite;
 				SDKROOT = appletvos;
 				SKIP_INSTALL = YES;
+				"SWIFT_INCLUDE_PATHS[sdk=appletvos*]" = "$(SRCROOT)/CocoaPods/appletvos";
+				"SWIFT_INCLUDE_PATHS[sdk=appletvsimulator*]" = "$(SRCROOT)/CocoaPods/appletvsimulator";
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
 			name = Release;
@@ -1064,7 +1146,8 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
-				SWIFT_INCLUDE_PATHS = "";
+				"SWIFT_INCLUDE_PATHS[sdk=iphoneos*]" = "$(SRCROOT)/CocoaPods/iphoneos";
+				"SWIFT_INCLUDE_PATHS[sdk=iphonesimulator*]" = "$(SRCROOT)/CocoaPods/iphonesimulator";
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
 			};
 			name = Debug;
@@ -1085,7 +1168,8 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
-				SWIFT_INCLUDE_PATHS = "";
+				"SWIFT_INCLUDE_PATHS[sdk=iphoneos*]" = "$(SRCROOT)/CocoaPods/iphoneos";
+				"SWIFT_INCLUDE_PATHS[sdk=iphonesimulator*]" = "$(SRCROOT)/CocoaPods/iphonesimulator";
 			};
 			name = Release;
 		};
@@ -1129,6 +1213,7 @@
 				SDKROOT = macosx;
 				SKIP_INSTALL = YES;
 				SWIFT_INCLUDE_PATHS = "";
+				"SWIFT_INCLUDE_PATHS[sdk=macosx*]" = "$(SRCROOT)/CocoaPods/macosx";
 			};
 			name = Debug;
 		};
@@ -1152,6 +1237,7 @@
 				SDKROOT = macosx;
 				SKIP_INSTALL = YES;
 				SWIFT_INCLUDE_PATHS = "";
+				"SWIFT_INCLUDE_PATHS[sdk=macosx*]" = "$(SRCROOT)/CocoaPods/macosx";
 			};
 			name = Release;
 		};
diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index 0243317f..7d67b051 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -23,6 +23,7 @@
 //
 
 import Dispatch
+import CSQLite
 
 /// A connection to SQLite.
 public final class Connection {
diff --git a/SQLite/Core/Statement.swift b/SQLite/Core/Statement.swift
index 9fb87c49..39fb000d 100644
--- a/SQLite/Core/Statement.swift
+++ b/SQLite/Core/Statement.swift
@@ -22,6 +22,8 @@
 // THE SOFTWARE.
 //
 
+import CSQLite
+
 /// A single SQL statement.
 public final class Statement {
 
diff --git a/SQLite/Helpers.swift b/SQLite/Helpers.swift
index c4d3df65..33fc6a62 100644
--- a/SQLite/Helpers.swift
+++ b/SQLite/Helpers.swift
@@ -22,6 +22,8 @@
 // THE SOFTWARE.
 //
 
+import CSQLite
+
 public typealias Star = (Expression<Binding>?, Expression<Binding>?) -> Expression<Void>
 
 public func *(_: Expression<Binding>?, _: Expression<Binding>?) -> Expression<Void> {

From b43a31f9020c42790d763a2cbf4af0b57aed5ab9 Mon Sep 17 00:00:00 2001
From: Stephen Celis <stephen@stephencelis.com>
Date: Sun, 27 Mar 2016 14:27:09 -0400
Subject: [PATCH 010/685] Bump to 0.10.1

Includes installation fix still affecting some CocoaPods users.

Signed-off-by: Stephen Celis <stephen@stephencelis.com>
---
 Documentation/Index.md | 4 ++--
 README.md              | 4 ++--
 SQLite.swift.podspec   | 2 +-
 SQLite/Info.plist      | 2 +-
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index fe1a4084..52d04c69 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -78,7 +78,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```
-    github "stephencelis/SQLite.swift" ~> 0.10.0
+    github "stephencelis/SQLite.swift" ~> 0.10.1
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -106,7 +106,7 @@ install SQLite.swift with Carthage:
     ``` ruby
     use_frameworks!
 
-    pod 'SQLite.swift', '~> 0.10.0'
+    pod 'SQLite.swift', '~> 0.10.1'
     ```
 
  3. Run `pod install`.
diff --git a/README.md b/README.md
index 89d9aef4..56d4374d 100644
--- a/README.md
+++ b/README.md
@@ -127,7 +127,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```
-    github "stephencelis/SQLite.swift" ~> 0.10.0
+    github "stephencelis/SQLite.swift" ~> 0.10.1
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -157,7 +157,7 @@ SQLite.swift with CocoaPods:
     ``` ruby
     use_frameworks!
 
-    pod 'SQLite.swift', '~> 0.10.0'
+    pod 'SQLite.swift', '~> 0.10.1'
     ```
 
  3. Run `pod install`.
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index ac2b3d24..fe814100 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -5,7 +5,7 @@
 
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.10.0"
+  s.version          = "0.10.1"
   s.summary          = "A type-safe, Swift-language layer over SQLite3 for iOS and OS X."
 
   s.description      = <<-DESC
diff --git a/SQLite/Info.plist b/SQLite/Info.plist
index 378e663f..d93473a7 100644
--- a/SQLite/Info.plist
+++ b/SQLite/Info.plist
@@ -15,7 +15,7 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>0.10.0</string>
+	<string>0.10.1</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>

From 993295ad4ad4c23d2093445170d67f95e81b13dc Mon Sep 17 00:00:00 2001
From: James Lawton <james.lawton@gmail.com>
Date: Sun, 3 Apr 2016 16:55:51 -0700
Subject: [PATCH 011/685] Don't use qualified table name when creating an index

---
 SQLite/Typed/Query.swift      | 7 +++++++
 SQLite/Typed/Schema.swift     | 2 +-
 SQLiteTests/SchemaTests.swift | 4 ++++
 3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/SQLite/Typed/Query.swift b/SQLite/Typed/Query.swift
index f5803770..e45034ca 100644
--- a/SQLite/Typed/Query.swift
+++ b/SQLite/Typed/Query.swift
@@ -744,6 +744,13 @@ extension QueryType {
         ])
     }
 
+    func tableName(qualified qualified: Bool) -> Expressible {
+        if qualified {
+            return tableName()
+        }
+        return Expression<Void>(clauses.from.alias ?? clauses.from.name)
+    }
+
     func database(namespace name: String) -> Expressible {
         let name = Expression<Void>(name)
 
diff --git a/SQLite/Typed/Schema.swift b/SQLite/Typed/Schema.swift
index f1f0287d..bc204bdf 100644
--- a/SQLite/Typed/Schema.swift
+++ b/SQLite/Typed/Schema.swift
@@ -134,7 +134,7 @@ extension Table {
         let clauses: [Expressible?] = [
             create("INDEX", indexName(columns), unique ? .Unique : nil, ifNotExists),
             Expression<Void>(literal: "ON"),
-            tableName(),
+            tableName(qualified: false),
             "".wrap(columns) as Expression<Void>
         ]
 
diff --git a/SQLiteTests/SchemaTests.swift b/SQLiteTests/SchemaTests.swift
index b3cb9a63..0c6e2135 100644
--- a/SQLiteTests/SchemaTests.swift
+++ b/SQLiteTests/SchemaTests.swift
@@ -724,6 +724,10 @@ class SchemaTests : XCTestCase {
             "CREATE UNIQUE INDEX IF NOT EXISTS \"index_table_on_int64\" ON \"table\" (\"int64\")",
             table.createIndex([int64], unique: true, ifNotExists: true)
         )
+        XCTAssertEqual(
+            "CREATE UNIQUE INDEX IF NOT EXISTS \"main\".\"index_table_on_int64\" ON \"table\" (\"int64\")",
+            Table("table", database: "main").createIndex([int64], unique: true, ifNotExists: true)
+        )
     }
 
     func test_dropIndex_compilesCreateIndexExpression() {

From 3825894ae7e499e5b74f0cf7cd73dcb235104b59 Mon Sep 17 00:00:00 2001
From: James Lawton <james.lawton@gmail.com>
Date: Sun, 3 Apr 2016 17:12:42 -0700
Subject: [PATCH 012/685] Don't use qualified table name when creating a
 foreign key reference

---
 SQLite/Typed/Schema.swift     | 2 +-
 SQLiteTests/SchemaTests.swift | 6 +++++-
 SQLiteTests/TestHelpers.swift | 1 +
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/SQLite/Typed/Schema.swift b/SQLite/Typed/Schema.swift
index bc204bdf..16e11c16 100644
--- a/SQLite/Typed/Schema.swift
+++ b/SQLite/Typed/Schema.swift
@@ -505,7 +505,7 @@ private func definition(column: Expressible, _ datatype: String, _ primaryKey: P
 private func reference(primary: (QueryType, Expressible)) -> Expressible {
     return " ".join([
         Expression<Void>(literal: "REFERENCES"),
-        primary.0.tableName(),
+        primary.0.tableName(qualified: false),
         "".wrap(primary.1) as Expression<Void>
     ])
 }
diff --git a/SQLiteTests/SchemaTests.swift b/SQLiteTests/SchemaTests.swift
index 0c6e2135..416b3646 100644
--- a/SQLiteTests/SchemaTests.swift
+++ b/SQLiteTests/SchemaTests.swift
@@ -300,6 +300,10 @@ class SchemaTests : XCTestCase {
             "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL REFERENCES \"table\" (\"int64\"))",
             table.create { t in t.column(int64, references: table, int64) }
         )
+        XCTAssertEqual(
+            "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL REFERENCES \"table\" (\"int64\"))",
+            table.create { t in t.column(int64, references: qualifiedTable, int64) }
+        )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL UNIQUE REFERENCES \"table\" (\"int64\"))",
             table.create { t in t.column(int64, unique: true, references: table, int64) }
@@ -726,7 +730,7 @@ class SchemaTests : XCTestCase {
         )
         XCTAssertEqual(
             "CREATE UNIQUE INDEX IF NOT EXISTS \"main\".\"index_table_on_int64\" ON \"table\" (\"int64\")",
-            Table("table", database: "main").createIndex([int64], unique: true, ifNotExists: true)
+            qualifiedTable.createIndex([int64], unique: true, ifNotExists: true)
         )
     }
 
diff --git a/SQLiteTests/TestHelpers.swift b/SQLiteTests/TestHelpers.swift
index c0ff9bb9..464b9c27 100644
--- a/SQLiteTests/TestHelpers.swift
+++ b/SQLiteTests/TestHelpers.swift
@@ -110,5 +110,6 @@ func AssertThrows<T>(@autoclosure expression: () throws -> T, file: StaticString
 }
 
 let table = Table("table")
+let qualifiedTable = Table("table", database: "main")
 let virtualTable = VirtualTable("virtual_table")
 let _view = View("view") // avoid Mac XCTestCase collision

From 709d137ef7255734ce4775c685352f2a4f286ee1 Mon Sep 17 00:00:00 2001
From: Will Richardson <william.hamish@gmail.com>
Date: Wed, 6 Apr 2016 23:24:12 +1200
Subject: [PATCH 013/685] Changed scalar functions to throw errors

---
 SQLite/Core/Connection.swift      | 16 ++++++++--------
 SQLite/Core/Statement.swift       | 14 +++++++-------
 SQLite/Typed/Query.swift          | 20 ++++++++++----------
 SQLiteTests/ConnectionTests.swift | 30 +++++++++++++++---------------
 SQLiteTests/FTS4Tests.swift       |  2 +-
 SQLiteTests/QueryTests.swift      |  8 ++++----
 6 files changed, 45 insertions(+), 45 deletions(-)

diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index 7d67b051..e982673a 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -231,8 +231,8 @@ public final class Connection {
     ///   - bindings: A list of parameters to bind to the statement.
     ///
     /// - Returns: The first value of the first row returned.
-    @warn_unused_result public func scalar(statement: String, _ bindings: Binding?...) -> Binding? {
-        return scalar(statement, bindings)
+    @warn_unused_result public func scalar(statement: String, _ bindings: Binding?...) throws -> Binding? {
+        return try scalar(statement, bindings)
     }
 
     /// Runs a single SQL statement (with optional parameter bindings),
@@ -245,8 +245,8 @@ public final class Connection {
     ///   - bindings: A list of parameters to bind to the statement.
     ///
     /// - Returns: The first value of the first row returned.
-    @warn_unused_result public func scalar(statement: String, _ bindings: [Binding?]) -> Binding? {
-        return try! prepare(statement).scalar(bindings)
+    @warn_unused_result public func scalar(statement: String, _ bindings: [Binding?]) throws -> Binding? {
+        return try prepare(statement).scalar(bindings)
     }
 
     /// Runs a single SQL statement (with optional parameter bindings),
@@ -259,8 +259,8 @@ public final class Connection {
     ///   - bindings: A dictionary of named parameters to bind to the statement.
     ///
     /// - Returns: The first value of the first row returned.
-    @warn_unused_result public func scalar(statement: String, _ bindings: [String: Binding?]) -> Binding? {
-        return try! prepare(statement).scalar(bindings)
+    @warn_unused_result public func scalar(statement: String, _ bindings: [String: Binding?]) throws -> Binding? {
+        return try prepare(statement).scalar(bindings)
     }
 
     // MARK: - Transactions
@@ -551,11 +551,11 @@ public final class Connection {
     ///
     ///   - block: A collation function that takes two strings and returns the
     ///     comparison result.
-    public func createCollation(collation: String, _ block: (lhs: String, rhs: String) -> ComparisonResult) {
+    public func createCollation(collation: String, _ block: (lhs: String, rhs: String) -> ComparisonResult) throws {
         let box: Collation = { lhs, rhs in
             Int32(block(lhs: String.fromCString(UnsafePointer<Int8>(lhs))!, rhs: String.fromCString(UnsafePointer<Int8>(rhs))!).rawValue)
         }
-        try! check(sqlite3_create_collation_v2(handle, collation, SQLITE_UTF8, unsafeBitCast(box, UnsafeMutablePointer<Void>.self), { callback, _, lhs, _, rhs in
+        try check(sqlite3_create_collation_v2(handle, collation, SQLITE_UTF8, unsafeBitCast(box, UnsafeMutablePointer<Void>.self), { callback, _, lhs, _, rhs in
             unsafeBitCast(callback, Collation.self)(lhs, rhs)
         }, nil))
         collations[collation] = box
diff --git a/SQLite/Core/Statement.swift b/SQLite/Core/Statement.swift
index 39fb000d..62fc95eb 100644
--- a/SQLite/Core/Statement.swift
+++ b/SQLite/Core/Statement.swift
@@ -148,21 +148,21 @@ public final class Statement {
     /// - Parameter bindings: A list of parameters to bind to the statement.
     ///
     /// - Returns: The first value of the first row returned.
-    @warn_unused_result public func scalar(bindings: Binding?...) -> Binding? {
+    @warn_unused_result public func scalar(bindings: Binding?...) throws -> Binding? {
         guard bindings.isEmpty else {
-            return scalar(bindings)
+            return try scalar(bindings)
         }
 
         reset(clearBindings: false)
-        try! step()
+        try step()
         return row[0]
     }
 
     /// - Parameter bindings: A list of parameters to bind to the statement.
     ///
     /// - Returns: The first value of the first row returned.
-    @warn_unused_result public func scalar(bindings: [Binding?]) -> Binding? {
-        return bind(bindings).scalar()
+    @warn_unused_result public func scalar(bindings: [Binding?]) throws -> Binding? {
+        return try bind(bindings).scalar()
     }
 
 
@@ -170,8 +170,8 @@ public final class Statement {
     ///   statement.
     ///
     /// - Returns: The first value of the first row returned.
-    @warn_unused_result public func scalar(bindings: [String: Binding?]) -> Binding? {
-        return bind(bindings).scalar()
+    @warn_unused_result public func scalar(bindings: [String: Binding?]) throws -> Binding? {
+        return try bind(bindings).scalar()
     }
 
     public func step() throws -> Bool {
diff --git a/SQLite/Typed/Query.swift b/SQLite/Typed/Query.swift
index e45034ca..36b3b2e1 100644
--- a/SQLite/Typed/Query.swift
+++ b/SQLite/Typed/Query.swift
@@ -932,30 +932,30 @@ extension Connection {
         }
     }
 
-    public func scalar<V : Value>(query: ScalarQuery<V>) -> V {
+    public func scalar<V : Value>(query: ScalarQuery<V>) throws -> V {
         let expression = query.expression
-        return value(scalar(expression.template, expression.bindings))
+        return value(try scalar(expression.template, expression.bindings))
     }
 
-    public func scalar<V : Value>(query: ScalarQuery<V?>) -> V.ValueType? {
+    public func scalar<V : Value>(query: ScalarQuery<V?>) throws -> V.ValueType? {
         let expression = query.expression
-        guard let value = scalar(expression.template, expression.bindings) as? V.Datatype else { return nil }
+        guard let value = try scalar(expression.template, expression.bindings) as? V.Datatype else { return nil }
         return V.fromDatatypeValue(value)
     }
 
-    public func scalar<V : Value>(query: Select<V>) -> V {
+    public func scalar<V : Value>(query: Select<V>) throws -> V {
         let expression = query.expression
-        return value(scalar(expression.template, expression.bindings))
+        return value(try scalar(expression.template, expression.bindings))
     }
 
-    public func scalar<V : Value>(query: Select<V?>) ->  V.ValueType? {
+    public func scalar<V : Value>(query: Select<V?>) throws ->  V.ValueType? {
         let expression = query.expression
-        guard let value = scalar(expression.template, expression.bindings) as? V.Datatype else { return nil }
+        guard let value = try scalar(expression.template, expression.bindings) as? V.Datatype else { return nil }
         return V.fromDatatypeValue(value)
     }
 
-    public func pluck(query: QueryType) -> Row? {
-        return try! prepare(query.limit(1, query.clauses.limit?.offset)).generate().next()
+    public func pluck(query: QueryType) throws -> Row? {
+        return try prepare(query.limit(1, query.clauses.limit?.offset)).generate().next()
     }
 
     /// Runs an `Insert` query.
diff --git a/SQLiteTests/ConnectionTests.swift b/SQLiteTests/ConnectionTests.swift
index aeec9b72..3d7dd3eb 100644
--- a/SQLiteTests/ConnectionTests.swift
+++ b/SQLiteTests/ConnectionTests.swift
@@ -87,10 +87,10 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_scalar_preparesRunsAndReturnsScalarValues() {
-        XCTAssertEqual(0, db.scalar("SELECT count(*) FROM users WHERE admin = 0") as? Int64)
-        XCTAssertEqual(0, db.scalar("SELECT count(*) FROM users WHERE admin = ?", 0) as? Int64)
-        XCTAssertEqual(0, db.scalar("SELECT count(*) FROM users WHERE admin = ?", [0]) as? Int64)
-        XCTAssertEqual(0, db.scalar("SELECT count(*) FROM users WHERE admin = $admin", ["$admin": 0]) as? Int64)
+        XCTAssertEqual(0, try! db.scalar("SELECT count(*) FROM users WHERE admin = 0") as? Int64)
+        XCTAssertEqual(0, try! db.scalar("SELECT count(*) FROM users WHERE admin = ?", 0) as? Int64)
+        XCTAssertEqual(0, try! db.scalar("SELECT count(*) FROM users WHERE admin = ?", [0]) as? Int64)
+        XCTAssertEqual(0, try! db.scalar("SELECT count(*) FROM users WHERE admin = $admin", ["$admin": 0]) as? Int64)
         AssertSQL("SELECT count(*) FROM users WHERE admin = 0", 4)
     }
 
@@ -238,7 +238,7 @@ class ConnectionTests : SQLiteTestCase {
             try! db.transaction {
                 try self.InsertUser("alice")
             }
-            XCTAssertEqual(1, db.scalar("SELECT count(*) FROM users") as? Int64)
+            XCTAssertEqual(1, try! db.scalar("SELECT count(*) FROM users") as? Int64)
         }
     }
 
@@ -252,7 +252,7 @@ class ConnectionTests : SQLiteTestCase {
                 }
             } catch {
             }
-            XCTAssertEqual(0, db.scalar("SELECT count(*) FROM users") as? Int64)
+            XCTAssertEqual(0, try! db.scalar("SELECT count(*) FROM users") as? Int64)
         }
     }
 
@@ -268,36 +268,36 @@ class ConnectionTests : SQLiteTestCase {
                 }
             } catch {
             }
-            XCTAssertEqual(0, db.scalar("SELECT count(*) FROM users") as? Int64)
+            XCTAssertEqual(0, try! db.scalar("SELECT count(*) FROM users") as? Int64)
         }
     }
 
     func test_createFunction_withArrayArguments() {
         db.createFunction("hello") { $0[0].map { "Hello, \($0)!" } }
 
-        XCTAssertEqual("Hello, world!", db.scalar("SELECT hello('world')") as? String)
-        XCTAssert(db.scalar("SELECT hello(NULL)") == nil)
+        XCTAssertEqual("Hello, world!", try! db.scalar("SELECT hello('world')") as? String)
+        XCTAssert(try! db.scalar("SELECT hello(NULL)") == nil)
     }
 
     func test_createFunction_createsQuotableFunction() {
         db.createFunction("hello world") { $0[0].map { "Hello, \($0)!" } }
 
-        XCTAssertEqual("Hello, world!", db.scalar("SELECT \"hello world\"('world')") as? String)
-        XCTAssert(db.scalar("SELECT \"hello world\"(NULL)") == nil)
+        XCTAssertEqual("Hello, world!", try! db.scalar("SELECT \"hello world\"('world')") as? String)
+        XCTAssert(try! db.scalar("SELECT \"hello world\"(NULL)") == nil)
     }
 
     func test_createCollation_createsCollation() {
-        db.createCollation("NODIACRITIC") { lhs, rhs in
+        try! db.createCollation("NODIACRITIC") { lhs, rhs in
             return lhs.compare(rhs, options: .DiacriticInsensitiveSearch)
         }
-        XCTAssertEqual(1, db.scalar("SELECT ? = ? COLLATE NODIACRITIC", "cafe", "café") as? Int64)
+        XCTAssertEqual(1, try! db.scalar("SELECT ? = ? COLLATE NODIACRITIC", "cafe", "café") as? Int64)
     }
 
     func test_createCollation_createsQuotableCollation() {
-        db.createCollation("NO DIACRITIC") { lhs, rhs in
+        try! db.createCollation("NO DIACRITIC") { lhs, rhs in
             return lhs.compare(rhs, options: .DiacriticInsensitiveSearch)
         }
-        XCTAssertEqual(1, db.scalar("SELECT ? = ? COLLATE \"NO DIACRITIC\"", "cafe", "café") as? Int64)
+        XCTAssertEqual(1, try! db.scalar("SELECT ? = ? COLLATE \"NO DIACRITIC\"", "cafe", "café") as? Int64)
     }
 
     func test_interrupt_interruptsLongRunningQuery() {
diff --git a/SQLiteTests/FTS4Tests.swift b/SQLiteTests/FTS4Tests.swift
index a94d9073..c36c5739 100644
--- a/SQLiteTests/FTS4Tests.swift
+++ b/SQLiteTests/FTS4Tests.swift
@@ -71,7 +71,7 @@ class FTS4IntegrationTests : SQLiteTestCase {
         AssertSQL("CREATE VIRTUAL TABLE \"emails\" USING fts4(\"subject\", \"body\", tokenize=\"SQLite.swift\" \"tokenizer\")")
 
         try! db.run(emails.insert(subject <- "Aún más cáfe!"))
-        XCTAssertEqual(1, db.scalar(emails.filter(emails.match("aun")).count))
+        XCTAssertEqual(1, try! db.scalar(emails.filter(emails.match("aun")).count))
     }
 
 }
diff --git a/SQLiteTests/QueryTests.swift b/SQLiteTests/QueryTests.swift
index b76da61e..f584bfcf 100644
--- a/SQLiteTests/QueryTests.swift
+++ b/SQLiteTests/QueryTests.swift
@@ -306,16 +306,16 @@ class QueryIntegrationTests : SQLiteTestCase {
     }
 
     func test_scalar() {
-        XCTAssertEqual(0, db.scalar(users.count))
-        XCTAssertEqual(false, db.scalar(users.exists))
+        XCTAssertEqual(0, try! db.scalar(users.count))
+        XCTAssertEqual(false, try! db.scalar(users.exists))
 
         try! InsertUsers("alice")
-        XCTAssertEqual(1, db.scalar(users.select(id.average)))
+        XCTAssertEqual(1, try! db.scalar(users.select(id.average)))
     }
 
     func test_pluck() {
         let rowid = try! db.run(users.insert(email <- "alice@example.com"))
-        XCTAssertEqual(rowid, db.pluck(users)![id])
+        XCTAssertEqual(rowid, try! db.pluck(users)![id])
     }
 
     func test_insert() {

From 68815609ab1173ec36e4978b2a060ff7c0a8a013 Mon Sep 17 00:00:00 2001
From: Kevin Wooten <kevin@wooten.com>
Date: Sun, 29 Nov 2015 01:54:06 -0700
Subject: [PATCH 014/685] Add connection pool for concurrent access

Uses WAL mode to support multiple reads and a single writer.
---
 SQLite.xcodeproj/project.pbxproj      |  28 +++
 SQLite/Core/Connection.swift          | 256 +++++++++++++++++++++++---
 SQLite/Core/ConnectionPool.swift      | 144 +++++++++++++++
 SQLite/Core/Dispatcher.swift          |  55 ++++++
 SQLiteTests/ConnectionPoolTests.swift |  57 ++++++
 5 files changed, 511 insertions(+), 29 deletions(-)
 create mode 100644 SQLite/Core/ConnectionPool.swift
 create mode 100644 SQLite/Core/Dispatcher.swift
 create mode 100644 SQLiteTests/ConnectionPoolTests.swift

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index d2ac9df4..edc79e3f 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -46,6 +46,17 @@
 		03A65E941C6BB3030062603F /* ValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B331C3F142E00AE3E12 /* ValueTests.swift */; };
 		03A65E951C6BB3030062603F /* TestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B161C3F127200AE3E12 /* TestHelpers.swift */; };
 		03A65E971C6BB3210062603F /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 03A65E961C6BB3210062603F /* libsqlite3.tbd */; };
+		AA780B3D1CC201A700E0E95E /* ConnectionPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA780B3B1CC201A700E0E95E /* ConnectionPool.swift */; };
+		AA780B3E1CC201A700E0E95E /* Dispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA780B3C1CC201A700E0E95E /* Dispatcher.swift */; };
+		AA780B411CC202C800E0E95E /* ConnectionPoolTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA780B3F1CC202B000E0E95E /* ConnectionPoolTests.swift */; };
+		AA780B421CC202C900E0E95E /* ConnectionPoolTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA780B3F1CC202B000E0E95E /* ConnectionPoolTests.swift */; };
+		AA780B431CC202CA00E0E95E /* ConnectionPoolTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA780B3F1CC202B000E0E95E /* ConnectionPoolTests.swift */; };
+		AA780B441CC202F300E0E95E /* ConnectionPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA780B3B1CC201A700E0E95E /* ConnectionPool.swift */; };
+		AA780B451CC202F300E0E95E /* Dispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA780B3C1CC201A700E0E95E /* Dispatcher.swift */; };
+		AA780B461CC202F400E0E95E /* ConnectionPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA780B3B1CC201A700E0E95E /* ConnectionPool.swift */; };
+		AA780B471CC202F400E0E95E /* Dispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA780B3C1CC201A700E0E95E /* Dispatcher.swift */; };
+		AA780B481CC202F500E0E95E /* ConnectionPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA780B3B1CC201A700E0E95E /* ConnectionPool.swift */; };
+		AA780B491CC202F500E0E95E /* Dispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA780B3C1CC201A700E0E95E /* Dispatcher.swift */; };
 		EE247AD71C3F04ED00AE3E12 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		EE247ADE1C3F04ED00AE3E12 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE247AD31C3F04ED00AE3E12 /* SQLite.framework */; };
 		EE247B031C3F06E900AE3E12 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
@@ -162,6 +173,9 @@
 		39548A6D1CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
 		39548A6F1CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
 		A121AC451CA35C79005A31D1 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		AA780B3B1CC201A700E0E95E /* ConnectionPool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectionPool.swift; sourceTree = "<group>"; };
+		AA780B3C1CC201A700E0E95E /* Dispatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Dispatcher.swift; sourceTree = "<group>"; };
+		AA780B3F1CC202B000E0E95E /* ConnectionPoolTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectionPoolTests.swift; sourceTree = "<group>"; };
 		EE247AD31C3F04ED00AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AD61C3F04ED00AE3E12 /* SQLite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLite.h; sourceTree = "<group>"; };
 		EE247AD81C3F04ED00AE3E12 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -388,6 +402,7 @@
 		EE247AE11C3F04ED00AE3E12 /* SQLiteTests */ = {
 			isa = PBXGroup;
 			children = (
+				AA780B3F1CC202B000E0E95E /* ConnectionPoolTests.swift */,
 				EE247B1A1C3F137700AE3E12 /* AggregateFunctionsTests.swift */,
 				EE247B1B1C3F137700AE3E12 /* BlobTests.swift */,
 				EE247B1D1C3F137700AE3E12 /* ConnectionTests.swift */,
@@ -411,6 +426,8 @@
 		EE247AED1C3F06E900AE3E12 /* Core */ = {
 			isa = PBXGroup;
 			children = (
+				AA780B3B1CC201A700E0E95E /* ConnectionPool.swift */,
+				AA780B3C1CC201A700E0E95E /* Dispatcher.swift */,
 				EE91808D1C46E5230038162A /* SQLite-Bridging.h */,
 				EE247AEE1C3F06E900AE3E12 /* Blob.swift */,
 				EE247AEF1C3F06E900AE3E12 /* Connection.swift */,
@@ -780,9 +797,11 @@
 				03A65E741C6BB2DA0062603F /* Helpers.swift in Sources */,
 				03A65E831C6BB2FB0062603F /* Operators.swift in Sources */,
 				03A65E851C6BB2FB0062603F /* Schema.swift in Sources */,
+				AA780B471CC202F400E0E95E /* Dispatcher.swift in Sources */,
 				03A65E841C6BB2FB0062603F /* Query.swift in Sources */,
 				03A65E7C1C6BB2F70062603F /* FTS4.swift in Sources */,
 				03A65E771C6BB2E60062603F /* Connection.swift in Sources */,
+				AA780B461CC202F400E0E95E /* ConnectionPool.swift in Sources */,
 				03A65E7E1C6BB2FB0062603F /* AggregateFunctions.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -792,6 +811,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				03A65E881C6BB3030062603F /* BlobTests.swift in Sources */,
+				AA780B431CC202CA00E0E95E /* ConnectionPoolTests.swift in Sources */,
 				03A65E901C6BB3030062603F /* R*TreeTests.swift in Sources */,
 				03A65E941C6BB3030062603F /* ValueTests.swift in Sources */,
 				03A65E8F1C6BB3030062603F /* QueryTests.swift in Sources */,
@@ -813,6 +833,8 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				AA780B491CC202F500E0E95E /* Dispatcher.swift in Sources */,
+				AA780B481CC202F500E0E95E /* ConnectionPool.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -834,9 +856,11 @@
 				EE247B081C3F06E900AE3E12 /* Value.swift in Sources */,
 				EE247B121C3F06E900AE3E12 /* Operators.swift in Sources */,
 				EE247B141C3F06E900AE3E12 /* Schema.swift in Sources */,
+				AA780B3E1CC201A700E0E95E /* Dispatcher.swift in Sources */,
 				EE247B131C3F06E900AE3E12 /* Query.swift in Sources */,
 				EE247B061C3F06E900AE3E12 /* SQLite-Bridging.m in Sources */,
 				EE247B071C3F06E900AE3E12 /* Statement.swift in Sources */,
+				AA780B3D1CC201A700E0E95E /* ConnectionPool.swift in Sources */,
 				EE247B0D1C3F06E900AE3E12 /* AggregateFunctions.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -846,6 +870,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				EE247B261C3F137700AE3E12 /* CoreFunctionsTests.swift in Sources */,
+				AA780B411CC202C800E0E95E /* ConnectionPoolTests.swift in Sources */,
 				EE247B291C3F137700AE3E12 /* FTS4Tests.swift in Sources */,
 				EE247B191C3F134A00AE3E12 /* SetterTests.swift in Sources */,
 				EE247B311C3F141E00AE3E12 /* SchemaTests.swift in Sources */,
@@ -881,9 +906,11 @@
 				EE247B641C3F3FDB00AE3E12 /* Helpers.swift in Sources */,
 				EE247B721C3F3FEC00AE3E12 /* Operators.swift in Sources */,
 				EE247B741C3F3FEC00AE3E12 /* Schema.swift in Sources */,
+				AA780B451CC202F300E0E95E /* Dispatcher.swift in Sources */,
 				EE247B731C3F3FEC00AE3E12 /* Query.swift in Sources */,
 				EE247B6B1C3F3FEC00AE3E12 /* FTS4.swift in Sources */,
 				EE247B661C3F3FEC00AE3E12 /* Connection.swift in Sources */,
+				AA780B441CC202F300E0E95E /* ConnectionPool.swift in Sources */,
 				EE247B6D1C3F3FEC00AE3E12 /* AggregateFunctions.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -893,6 +920,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				EE247B561C3F3FC700AE3E12 /* CoreFunctionsTests.swift in Sources */,
+				AA780B421CC202C900E0E95E /* ConnectionPoolTests.swift in Sources */,
 				EE247B5A1C3F3FC700AE3E12 /* OperatorsTests.swift in Sources */,
 				EE247B541C3F3FC700AE3E12 /* BlobTests.swift in Sources */,
 				EE247B5D1C3F3FC700AE3E12 /* SchemaTests.swift in Sources */,
diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index 7d67b051..1b7b3d59 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -25,8 +25,207 @@
 import Dispatch
 import CSQLite
 
+
+/// The mode in which a transaction acquires a lock.
+public enum TransactionMode : String {
+    
+    /// Defers locking the database till the first read/write executes.
+    case Deferred = "DEFERRED"
+    
+    /// Immediately acquires a reserved lock on the database.
+    case Immediate = "IMMEDIATE"
+    
+    /// Immediately acquires an exclusive lock on all databases.
+    case Exclusive = "EXCLUSIVE"
+    
+}
+
+
+/// Protocol to an SQLite connection
+public protocol ConnectionType {
+    
+    /// Whether or not the database was opened in a read-only state.
+    var readonly : Bool { get }
+    
+    /// The last rowid inserted into the database via this connection.
+    var lastInsertRowid : Int64? { get }
+    
+    /// The last number of changes (inserts, updates, or deletes) made to the
+    /// database via this connection.
+    var changes : Int { get }
+    
+    /// The total number of changes (inserts, updates, or deletes) made to the
+    /// database via this connection.
+    var totalChanges : Int { get }
+    
+    // MARK: - Execute
+    
+    /// Executes a batch of SQL statements.
+    ///
+    /// - Parameter SQL: A batch of zero or more semicolon-separated SQL
+    ///   statements.
+    ///
+    /// - Throws: `Result.Error` if query execution fails.
+    func execute(SQL: String) throws
+    
+    // MARK: - Prepare
+    
+    /// Prepares a single SQL statement (with optional parameter bindings).
+    ///
+    /// - Parameters:
+    ///
+    ///   - statement: A single SQL statement.
+    ///
+    ///   - bindings: A list of parameters to bind to the statement.
+    ///
+    /// - Returns: A prepared statement.
+    @warn_unused_result func prepare(statement: String, _ bindings: Binding?...) throws -> Statement
+
+    /// Prepares a single SQL statement and binds parameters to it.
+    ///
+    /// - Parameters:
+    ///
+    ///   - statement: A single SQL statement.
+    ///
+    ///   - bindings: A list of parameters to bind to the statement.
+    ///
+    /// - Returns: A prepared statement.
+    @warn_unused_result func prepare(statement: String, _ bindings: [Binding?]) throws -> Statement
+
+    /// Prepares a single SQL statement and binds parameters to it.
+    ///
+    /// - Parameters:
+    ///
+    ///   - statement: A single SQL statement.
+    ///
+    ///   - bindings: A dictionary of named parameters to bind to the statement.
+    ///
+    /// - Returns: A prepared statement.
+    @warn_unused_result func prepare(statement: String, _ bindings: [String: Binding?]) throws -> Statement
+    
+    // MARK: - Run
+    
+    /// Runs a single SQL statement (with optional parameter bindings).
+    ///
+    /// - Parameters:
+    ///
+    ///   - statement: A single SQL statement.
+    ///
+    ///   - bindings: A list of parameters to bind to the statement.
+    ///
+    /// - Throws: `Result.Error` if query execution fails.
+    ///
+    /// - Returns: The statement.
+    func run(statement: String, _ bindings: Binding?...) throws -> Statement
+
+    /// Prepares, binds, and runs a single SQL statement.
+    ///
+    /// - Parameters:
+    ///
+    ///   - statement: A single SQL statement.
+    ///
+    ///   - bindings: A list of parameters to bind to the statement.
+    ///
+    /// - Throws: `Result.Error` if query execution fails.
+    ///
+    /// - Returns: The statement.
+    func run(statement: String, _ bindings: [Binding?]) throws -> Statement
+
+    /// Prepares, binds, and runs a single SQL statement.
+    ///
+    /// - Parameters:
+    ///
+    ///   - statement: A single SQL statement.
+    ///
+    ///   - bindings: A dictionary of named parameters to bind to the statement.
+    ///
+    /// - Throws: `Result.Error` if query execution fails.
+    ///
+    /// - Returns: The statement.
+    func run(statement: String, _ bindings: [String: Binding?]) throws -> Statement
+
+    // MARK: - Scalar
+    
+    /// Runs a single SQL statement (with optional parameter bindings),
+    /// returning the first value of the first row.
+    ///
+    /// - Parameters:
+    ///
+    ///   - statement: A single SQL statement.
+    ///
+    ///   - bindings: A list of parameters to bind to the statement.
+    ///
+    /// - Returns: The first value of the first row returned.
+    @warn_unused_result func scalar(statement: String, _ bindings: Binding?...) -> Binding?
+
+    /// Runs a single SQL statement (with optional parameter bindings),
+    /// returning the first value of the first row.
+    ///
+    /// - Parameters:
+    ///
+    ///   - statement: A single SQL statement.
+    ///
+    ///   - bindings: A list of parameters to bind to the statement.
+    ///
+    /// - Returns: The first value of the first row returned.
+    @warn_unused_result func scalar(statement: String, _ bindings: [Binding?]) -> Binding?
+
+    /// Runs a single SQL statement (with optional parameter bindings),
+    /// returning the first value of the first row.
+    ///
+    /// - Parameters:
+    ///
+    ///   - statement: A single SQL statement.
+    ///
+    ///   - bindings: A dictionary of named parameters to bind to the statement.
+    ///
+    /// - Returns: The first value of the first row returned.
+    @warn_unused_result func scalar(statement: String, _ bindings: [String: Binding?]) -> Binding?
+
+    // MARK: - Transactions
+    
+    // TODO: Consider not requiring a throw to roll back?
+    /// Runs a transaction with the given mode.
+    ///
+    /// - Note: Transactions cannot be nested. To nest transactions, see
+    ///   `savepoint()`, instead.
+    ///
+    /// - Parameters:
+    ///
+    ///   - mode: The mode in which a transaction acquires a lock.
+    ///
+    ///     Default: `.Deferred`
+    ///
+    ///   - block: A closure to run SQL statements within the transaction.
+    ///     The transaction will be committed when the block returns. The block
+    ///     must throw to roll the transaction back.
+    ///
+    /// - Throws: `Result.Error`, and rethrows.
+    func transaction(mode: TransactionMode, block: () throws -> Void) throws
+
+    // TODO: Consider not requiring a throw to roll back?
+    // TODO: Consider removing ability to set a name?
+    /// Runs a transaction with the given savepoint name (if omitted, it will
+    /// generate a UUID).
+    ///
+    /// - SeeAlso: `transaction()`.
+    ///
+    /// - Parameters:
+    ///
+    ///   - savepointName: A unique identifier for the savepoint (optional).
+    ///
+    ///   - block: A closure to run SQL statements within the transaction.
+    ///     The savepoint will be released (committed) when the block returns.
+    ///     The block must throw to roll the savepoint back.
+    ///
+    /// - Throws: `SQLite.Result.Error`, and rethrows.
+    func savepoint(name: String, block: () throws -> Void) throws
+    
+}
+
+
 /// A connection to SQLite.
-public final class Connection {
+public final class Connection : ConnectionType, Equatable {
 
     /// The location of a SQLite database.
     public enum Location {
@@ -67,10 +266,27 @@ public final class Connection {
     ///     Default: `false`.
     ///
     /// - Returns: A new database connection.
-    public init(_ location: Location = .InMemory, readonly: Bool = false) throws {
+    public convenience init(_ location: Location = .InMemory, readonly: Bool = false) throws {
         let flags = readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE
-        try check(sqlite3_open_v2(location.description, &_handle, flags | SQLITE_OPEN_FULLMUTEX, nil))
-        dispatch_queue_set_specific(queue, Connection.queueKey, queueContext, nil)
+        try self.init(location, flags: flags, dispatcher: ReentrantDispatcher("SQLite.Connection"))
+    }
+  
+    /// Initializes a new SQLite connection.
+    ///
+    /// - Parameters:
+    ///
+    ///   - location: The location of the database. Creates a new database if it
+    ///     doesn’t already exist (unless in read-only mode).
+    ///
+    ///   - flags: SQLite open flags
+    ///
+    ///   - dispatcher: Dispatcher synchronization blocks
+    ///
+    /// - Returns: A new database connection.
+    public init(_ location: Location, flags: Int32, dispatcher: Dispatcher) throws {
+        self.dispatcher = dispatcher
+        try check(sqlite3_open_v2(location.description, &_handle, flags, nil))
+        try check(sqlite3_extended_result_codes(handle, 1))
     }
 
     /// Initializes a new connection to a database.
@@ -265,20 +481,6 @@ public final class Connection {
 
     // MARK: - Transactions
 
-    /// The mode in which a transaction acquires a lock.
-    public enum TransactionMode : String {
-
-        /// Defers locking the database till the first read/write executes.
-        case Deferred = "DEFERRED"
-
-        /// Immediately acquires a reserved lock on the database.
-        case Immediate = "IMMEDIATE"
-
-        /// Immediately acquires an exclusive lock on all databases.
-        case Exclusive = "EXCLUSIVE"
-
-    }
-
     // TODO: Consider not requiring a throw to roll back?
     /// Runs a transaction with the given mode.
     ///
@@ -577,11 +779,7 @@ public final class Connection {
             }
         }
 
-        if dispatch_get_specific(Connection.queueKey) == queueContext {
-            box()
-        } else {
-            dispatch_sync(queue, box) // FIXME: rdar://problem/21389236
-        }
+        dispatcher.dispatch(box)
 
         if let failure = failure {
             try { () -> Void in throw failure }()
@@ -597,12 +795,8 @@ public final class Connection {
 
         throw error
     }
-
-    private var queue = dispatch_queue_create("SQLite.Database", DISPATCH_QUEUE_SERIAL)
-
-    private static let queueKey = unsafeBitCast(Connection.self, UnsafePointer<Void>.self)
-
-    private lazy var queueContext: UnsafeMutablePointer<Void> = unsafeBitCast(self, UnsafeMutablePointer<Void>.self)
+  
+    private var dispatcher : Dispatcher
 
 }
 
@@ -629,6 +823,10 @@ extension Connection.Location : CustomStringConvertible {
 
 }
 
+public func ==(lhs: Connection, rhs: Connection) -> Bool {
+    return lhs === rhs
+}
+
 /// An SQL operation passed to update callbacks.
 public enum Operation {
 
diff --git a/SQLite/Core/ConnectionPool.swift b/SQLite/Core/ConnectionPool.swift
new file mode 100644
index 00000000..5a6ee5b9
--- /dev/null
+++ b/SQLite/Core/ConnectionPool.swift
@@ -0,0 +1,144 @@
+//
+// SQLite.swift
+// https://github.com/stephencelis/SQLite.swift
+// Copyright © 2014-2015 Stephen Celis.
+//
+// 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.
+//
+
+import Foundation
+
+
+/// Connection pool delegate
+public protocol ConnectionPoolDelegate {
+    
+    func pool(pool: ConnectionPool, shouldAddConnection: Connection)
+    func pool(pool: ConnectionPool, didAddConnection: Connection)
+    
+}
+
+
+// Connection pool for accessing an SQLite database
+// with multiple readers & a single writer. Utilizes
+// WAL mode.
+public final class ConnectionPool {
+
+    private let location : Connection.Location
+    private var availableReadConnections = [Connection]()
+    private var unavailableReadConnections = [Connection]()
+    private let lockQueue : dispatch_queue_t
+    private var writeConnection : Connection!
+    
+    public init(_ location: Connection.Location) throws {
+        self.location = location
+        self.lockQueue = dispatch_queue_create("SQLite.ConnectionPool", DISPATCH_QUEUE_SERIAL)
+        
+        try writable.execute("PRAGMA locking_mode = EXCLUSIVE; PRAGMA journal_mode = WAL;")
+    }
+    
+    // Connection that automatically returns itself
+    // to the pool when it goes out of scope
+    private class BorrowedConnection : ConnectionType, Equatable {
+        
+        let pool : ConnectionPool
+        let connection : Connection
+        
+        init(pool: ConnectionPool, connection: Connection) {
+            self.pool = pool
+            self.connection = connection
+        }
+        
+        deinit {
+            dispatch_sync(pool.lockQueue) {
+                if let index = self.pool.unavailableReadConnections.indexOf(self.connection) {
+                    self.pool.unavailableReadConnections.removeAtIndex(index)
+                }
+                self.pool.availableReadConnections.append(self.connection)
+            }
+        }
+
+        var readonly : Bool { return connection.readonly }
+        var lastInsertRowid : Int64? { return connection.lastInsertRowid }
+        var changes : Int { return connection.changes }
+        var totalChanges : Int { return connection.totalChanges }
+        
+        func execute(SQL: String) throws { return try connection.execute(SQL) }
+        @warn_unused_result func prepare(statement: String, _ bindings: Binding?...) throws -> Statement { return try connection.prepare(statement, bindings) }
+        @warn_unused_result func prepare(statement: String, _ bindings: [Binding?]) throws -> Statement { return try connection.prepare(statement, bindings) }
+        @warn_unused_result func prepare(statement: String, _ bindings: [String: Binding?]) throws -> Statement { return try connection.prepare(statement, bindings) }
+        
+        func run(statement: String, _ bindings: Binding?...) throws -> Statement { return try connection.run(statement, bindings) }
+        func run(statement: String, _ bindings: [Binding?]) throws -> Statement { return try connection.run(statement, bindings) }
+        func run(statement: String, _ bindings: [String: Binding?]) throws -> Statement { return try connection.run(statement, bindings) }
+        
+        @warn_unused_result func scalar(statement: String, _ bindings: Binding?...) -> Binding? { return connection.scalar(statement, bindings) }
+        @warn_unused_result func scalar(statement: String, _ bindings: [Binding?]) -> Binding? { return connection.scalar(statement, bindings) }
+        @warn_unused_result func scalar(statement: String, _ bindings: [String: Binding?]) -> Binding? { return connection.scalar(statement, bindings) }
+        
+        func transaction(mode: TransactionMode, block: () throws -> Void) throws { return try connection.transaction(mode, block: block) }
+        func savepoint(name: String, block: () throws -> Void) throws { return try connection.savepoint(name, block: block) }
+        
+    }
+    
+    
+    // Acquires a read/write connection to the database
+    public var writable : Connection {
+        
+        var writeConnectionInit = dispatch_once_t()
+        dispatch_once(&writeConnectionInit) {
+            let flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_WAL
+            self.writeConnection = try! Connection(self.location, flags: flags, dispatcher: ReentrantDispatcher("SQLite.WriteConnection"))
+            self.writeConnection.busyTimeout = 2
+        }
+        
+        return writeConnection
+    }
+    
+    // Acquires a read only connection to the database
+    public var readable : ConnectionType {
+        
+        var borrowed : BorrowedConnection!
+        
+        dispatch_sync(lockQueue) {
+            
+            let connection : Connection
+            
+            if let availableConnection = self.availableReadConnections.popLast() {
+                connection = availableConnection
+            }
+            else {
+                let flags = SQLITE_OPEN_READONLY | SQLITE_OPEN_WAL
+                connection = try! Connection(self.location, flags: flags, dispatcher: ImmediateDispatcher())
+                connection.busyTimeout = 2
+            }
+            
+            self.unavailableReadConnections.append(connection)
+            
+            borrowed = BorrowedConnection(pool: self, connection: connection)
+        }
+        
+        return borrowed
+    }
+    
+}
+
+    
+private func ==(lhs: ConnectionPool.BorrowedConnection, rhs: ConnectionPool.BorrowedConnection) -> Bool {
+    return lhs.connection == rhs.connection
+}
diff --git a/SQLite/Core/Dispatcher.swift b/SQLite/Core/Dispatcher.swift
new file mode 100644
index 00000000..b5010488
--- /dev/null
+++ b/SQLite/Core/Dispatcher.swift
@@ -0,0 +1,55 @@
+//
+//  Dispatcher.swift
+//  SQLite
+//
+//  Created by Kevin Wooten on 11/28/15.
+//  Copyright © 2015 stephencelis. All rights reserved.
+//
+
+import Foundation
+
+
+/// Block dispatch method
+public protocol Dispatcher {
+
+  /// Dispatches the provided block
+  func dispatch(block: dispatch_block_t)
+  
+}
+
+
+/// Dispatches block immediately on current thread
+public final class ImmediateDispatcher : Dispatcher {
+  
+  public func dispatch(block: dispatch_block_t) {
+    block()
+  }
+  
+}
+
+
+/// Synchronously dispatches block on a serial
+/// queue. Specifically allows reentrant calls
+public final class ReentrantDispatcher : Dispatcher {
+  
+  static let queueKey = unsafeBitCast(ReentrantDispatcher.self, UnsafePointer<Void>.self)
+  
+  let queue : dispatch_queue_t
+  
+  let queueContext : UnsafeMutablePointer<Void>!
+  
+  public init(_ name: String) {
+    queue = dispatch_queue_create(name, DISPATCH_QUEUE_SERIAL)
+    queueContext = unsafeBitCast(queue, UnsafeMutablePointer<Void>.self)
+    dispatch_queue_set_specific(queue, ReentrantDispatcher.queueKey, queueContext, nil)
+  }
+  
+  public func dispatch(block: dispatch_block_t) {
+    if dispatch_get_specific(ReentrantDispatcher.queueKey) == self.queueContext {
+      block()
+    } else {
+      dispatch_sync(self.queue, block) // FIXME: rdar://problem/21389236
+    }
+  }
+  
+}
diff --git a/SQLiteTests/ConnectionPoolTests.swift b/SQLiteTests/ConnectionPoolTests.swift
new file mode 100644
index 00000000..e79d3a8c
--- /dev/null
+++ b/SQLiteTests/ConnectionPoolTests.swift
@@ -0,0 +1,57 @@
+import XCTest
+import SQLite
+
+class ConnectionPoolTests : SQLiteTestCase {
+
+    override func setUp() {
+        super.setUp()
+    }
+
+    func testConcurrentAccess() {
+        
+        let _ = try? NSFileManager.defaultManager().removeItemAtPath("\(NSTemporaryDirectory())/SQLiteswiftTests.sqlite")
+        let pool = try! ConnectionPool(.URI("\(NSTemporaryDirectory())/SQLiteswiftTests.sqlite"))
+        
+        let conn = pool.writable
+        try! conn.execute("CREATE TABLE IF NOT EXISTS test(id INTEGER PRIMARY KEY, name TEXT)")
+        try! conn.execute("DELETE FROM test")
+        try! conn.execute("INSERT INTO test(id,name) VALUES(0, 'test0')")
+        try! conn.execute("INSERT INTO test(id,name) VALUES(1, 'test1')")
+        try! conn.execute("INSERT INTO test(id,name) VALUES(2, 'test2')")
+        try! conn.execute("INSERT INTO test(id,name) VALUES(3, 'test3')")
+        try! conn.execute("INSERT INTO test(id,name) VALUES(4, 'test4')")
+        
+        var quit = false
+        let queue = dispatch_queue_create("Readers", DISPATCH_QUEUE_CONCURRENT)
+        for x in 0..<5 {
+            var reads = 0
+            let ex = expectationWithDescription("thread" + String(x))
+            dispatch_async(queue) {
+                print("started", x)
+                let conn = pool.readable
+                var curr = conn.scalar("SELECT name FROM test WHERE id = ?", x) as! String
+                while !quit {
+                    let now = conn.scalar("SELECT name FROM test WHERE id = ?", x) as! String
+                    if now != curr {
+                        print(now)
+                        curr = now
+                    }
+                    reads += 1
+                }
+                print("ended at", reads, "reads")
+                ex.fulfill()
+            }
+        }
+        
+        for x in 10..<500 {
+            let name = "test" + String(x)
+            let idx = Int(rand()) % 5
+            try! conn.run("UPDATE test SET name=? WHERE id=?", name, idx)
+            usleep(15000)
+        }
+        
+        quit = true
+        waitForExpectationsWithTimeout(1000, handler: nil)
+    }
+  
+}

From 42ebd18a06e06319933ce866dd9fbc84faf2e03a Mon Sep 17 00:00:00 2001
From: Kevin Wooten <kevin@wooten.com>
Date: Sun, 29 Nov 2015 03:06:14 -0700
Subject: [PATCH 015/685] Add delegate to connection pool

Allows customizing new connections once created
---
 SQLite/Core/ConnectionPool.swift      | 53 +++++++++++++++++++--------
 SQLiteTests/ConnectionPoolTests.swift | 38 +++++++++++++++++--
 2 files changed, 71 insertions(+), 20 deletions(-)

diff --git a/SQLite/Core/ConnectionPool.swift b/SQLite/Core/ConnectionPool.swift
index 5a6ee5b9..d4a0c3f5 100644
--- a/SQLite/Core/ConnectionPool.swift
+++ b/SQLite/Core/ConnectionPool.swift
@@ -28,7 +28,7 @@ import Foundation
 /// Connection pool delegate
 public protocol ConnectionPoolDelegate {
     
-    func pool(pool: ConnectionPool, shouldAddConnection: Connection)
+    func poolShouldAddConnection(pool: ConnectionPool) -> Bool
     func pool(pool: ConnectionPool, didAddConnection: Connection)
     
 }
@@ -45,6 +45,8 @@ public final class ConnectionPool {
     private let lockQueue : dispatch_queue_t
     private var writeConnection : Connection!
     
+    public var delegate : ConnectionPoolDelegate?
+    
     public init(_ location: Connection.Location) throws {
         self.location = location
         self.lockQueue = dispatch_queue_create("SQLite.ConnectionPool", DISPATCH_QUEUE_SERIAL)
@@ -52,6 +54,14 @@ public final class ConnectionPool {
         try writable.execute("PRAGMA locking_mode = EXCLUSIVE; PRAGMA journal_mode = WAL;")
     }
     
+    public var totalReadableConnectionCount : Int {
+        return availableReadConnections.count + unavailableReadConnections.count
+    }
+    
+    public var availableReadableConnectionCount : Int {
+        return availableReadConnections.count
+    }
+    
     // Connection that automatically returns itself
     // to the pool when it goes out of scope
     private class BorrowedConnection : ConnectionType, Equatable {
@@ -98,7 +108,7 @@ public final class ConnectionPool {
     
     
     // Acquires a read/write connection to the database
-    public var writable : Connection {
+    public var writable : ConnectionType {
         
         var writeConnectionInit = dispatch_once_t()
         dispatch_once(&writeConnectionInit) {
@@ -115,23 +125,34 @@ public final class ConnectionPool {
         
         var borrowed : BorrowedConnection!
         
-        dispatch_sync(lockQueue) {
-            
-            let connection : Connection
+        repeat {
             
-            if let availableConnection = self.availableReadConnections.popLast() {
-                connection = availableConnection
-            }
-            else {
-                let flags = SQLITE_OPEN_READONLY | SQLITE_OPEN_WAL
-                connection = try! Connection(self.location, flags: flags, dispatcher: ImmediateDispatcher())
-                connection.busyTimeout = 2
+            dispatch_sync(lockQueue) {
+                
+                let connection : Connection
+                
+                if let availableConnection = self.availableReadConnections.popLast() {
+                    connection = availableConnection
+                }
+                else if self.delegate?.poolShouldAddConnection(self) ?? true {
+        
+                    let flags = SQLITE_OPEN_READONLY | SQLITE_OPEN_WAL
+                    connection = try! Connection(self.location, flags: flags, dispatcher: ImmediateDispatcher())
+                    connection.busyTimeout = 2
+                
+                    self.delegate?.pool(self, didAddConnection: connection)
+                    
+                }
+                else {
+                    return
+                }
+                
+                self.unavailableReadConnections.append(connection)
+                
+                borrowed = BorrowedConnection(pool: self, connection: connection)
             }
             
-            self.unavailableReadConnections.append(connection)
-            
-            borrowed = BorrowedConnection(pool: self, connection: connection)
-        }
+        } while borrowed == nil
         
         return borrowed
     }
diff --git a/SQLiteTests/ConnectionPoolTests.swift b/SQLiteTests/ConnectionPoolTests.swift
index e79d3a8c..12e6402f 100644
--- a/SQLiteTests/ConnectionPoolTests.swift
+++ b/SQLiteTests/ConnectionPoolTests.swift
@@ -9,7 +9,7 @@ class ConnectionPoolTests : SQLiteTestCase {
 
     func testConcurrentAccess() {
         
-        let _ = try? NSFileManager.defaultManager().removeItemAtPath("\(NSTemporaryDirectory())/SQLiteswiftTests.sqlite")
+        let _ = try? NSFileManager.defaultManager().removeItemAtPath("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite")
         let pool = try! ConnectionPool(.URI("\(NSTemporaryDirectory())/SQLiteswiftTests.sqlite"))
         
         let conn = pool.writable
@@ -25,33 +25,63 @@ class ConnectionPoolTests : SQLiteTestCase {
         let queue = dispatch_queue_create("Readers", DISPATCH_QUEUE_CONCURRENT)
         for x in 0..<5 {
             var reads = 0
+
             let ex = expectationWithDescription("thread" + String(x))
+            
             dispatch_async(queue) {
+                
                 print("started", x)
+
                 let conn = pool.readable
-                var curr = conn.scalar("SELECT name FROM test WHERE id = ?", x) as! String
+                
+                let stmt = conn.prepare("SELECT name FROM test WHERE id = ?")
+                var curr = stmt.scalar(x) as! String
                 while !quit {
-                    let now = conn.scalar("SELECT name FROM test WHERE id = ?", x) as! String
+                    
+                    let now = stmt.scalar(x) as! String
                     if now != curr {
                         print(now)
                         curr = now
                     }
                     reads += 1
                 }
+                
                 print("ended at", reads, "reads")
+                
                 ex.fulfill()
             }
+            
         }
         
         for x in 10..<500 {
+            
             let name = "test" + String(x)
             let idx = Int(rand()) % 5
-            try! conn.run("UPDATE test SET name=? WHERE id=?", name, idx)
+            
+            do {
+                try conn.run("UPDATE test SET name=? WHERE id=?", name, idx)
+            }
+            catch let error {
+                XCTFail((error as? CustomStringConvertible)?.description ?? "Unknown")
+            }
+            
             usleep(15000)
         }
         
         quit = true
         waitForExpectationsWithTimeout(1000, handler: nil)
     }
+    
+    func testAutoRelease() {
+        
+        let _ = try? NSFileManager.defaultManager().removeItemAtPath("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite")
+        let pool = try! ConnectionPool(.URI("\(NSTemporaryDirectory())/SQLiteswiftTests.sqlite"))
+        
+        do {
+            try! pool.readable.execute("SELECT 1")
+        }
+        
+        XCTAssertEqual(pool.totalReadableConnectionCount, pool.availableReadableConnectionCount)
+    }
   
 }

From 68f46d5069e0e146055103c6501cc36369181484 Mon Sep 17 00:00:00 2001
From: Kevin Wooten <kevin@wooten.com>
Date: Fri, 15 Apr 2016 21:46:45 -0700
Subject: [PATCH 016/685] Better names for protocols and classes

ConnectionType is now Connection and Connection is now DBConnection
---
 SQLite/Core/Connection.swift          | 38 +++++++++++++-------------
 SQLite/Core/ConnectionPool.swift      | 39 +++++++++++++++------------
 SQLite/Core/Statement.swift           |  4 +--
 SQLite/Extensions/FTS4.swift          |  2 +-
 SQLite/Typed/CustomFunctions.swift    |  2 +-
 SQLite/Typed/Query.swift              |  2 +-
 SQLiteTests/ConnectionPoolTests.swift |  8 +++---
 SQLiteTests/ConnectionTests.swift     | 38 +++++++++++++-------------
 SQLiteTests/TestHelpers.swift         |  2 +-
 9 files changed, 71 insertions(+), 64 deletions(-)

diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index 1b7b3d59..e1b82b76 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -42,7 +42,7 @@ public enum TransactionMode : String {
 
 
 /// Protocol to an SQLite connection
-public protocol ConnectionType {
+public protocol Connection {
     
     /// Whether or not the database was opened in a read-only state.
     var readonly : Bool { get }
@@ -201,8 +201,8 @@ public protocol ConnectionType {
     ///     must throw to roll the transaction back.
     ///
     /// - Throws: `Result.Error`, and rethrows.
-    func transaction(mode: TransactionMode, block: () throws -> Void) throws
-
+    func transaction(mode: TransactionMode, block: (Connection) throws -> Void) throws
+    
     // TODO: Consider not requiring a throw to roll back?
     // TODO: Consider removing ability to set a name?
     /// Runs a transaction with the given savepoint name (if omitted, it will
@@ -219,13 +219,15 @@ public protocol ConnectionType {
     ///     The block must throw to roll the savepoint back.
     ///
     /// - Throws: `SQLite.Result.Error`, and rethrows.
-    func savepoint(name: String, block: () throws -> Void) throws
+    func savepoint(name: String, block: (Connection) throws -> Void) throws
     
+    func sync<T>(block: () throws -> T) rethrows -> T
+
 }
 
 
 /// A connection to SQLite.
-public final class Connection : ConnectionType, Equatable {
+public final class DBConnection : Connection, Equatable {
 
     /// The location of a SQLite database.
     public enum Location {
@@ -498,10 +500,10 @@ public final class Connection : ConnectionType, Equatable {
     ///     must throw to roll the transaction back.
     ///
     /// - Throws: `Result.Error`, and rethrows.
-    public func transaction(mode: TransactionMode = .Deferred, block: () throws -> Void) throws {
+    public func transaction(mode: TransactionMode = .Deferred, block: (Connection) throws -> Void) throws {
         try transaction("BEGIN \(mode.rawValue) TRANSACTION", block, "COMMIT TRANSACTION", or: "ROLLBACK TRANSACTION")
     }
-
+    
     // TODO: Consider not requiring a throw to roll back?
     // TODO: Consider removing ability to set a name?
     /// Runs a transaction with the given savepoint name (if omitted, it will
@@ -518,18 +520,18 @@ public final class Connection : ConnectionType, Equatable {
     ///     The block must throw to roll the savepoint back.
     ///
     /// - Throws: `SQLite.Result.Error`, and rethrows.
-    public func savepoint(name: String = NSUUID().UUIDString, block: () throws -> Void) throws {
+    public func savepoint(name: String = NSUUID().UUIDString, block: (Connection) throws -> Void) throws {
         let name = name.quote("'")
         let savepoint = "SAVEPOINT \(name)"
-
+        
         try transaction(savepoint, block, "RELEASE \(savepoint)", or: "ROLLBACK TO \(savepoint)")
     }
-
-    private func transaction(begin: String, _ block: () throws -> Void, _ commit: String, or rollback: String) throws {
+    
+    private func transaction(begin: String, _ block: (Connection) throws -> Void, _ commit: String, or rollback: String) throws {
         return try sync {
             try self.run(begin)
             do {
-                try block()
+                try block(self)
             } catch {
                 try self.run(rollback)
                 throw error
@@ -537,7 +539,7 @@ public final class Connection : ConnectionType, Equatable {
             try self.run(commit)
         }
     }
-
+    
     /// Interrupts any long-running queries.
     public func interrupt() {
         sqlite3_interrupt(handle)
@@ -767,7 +769,7 @@ public final class Connection : ConnectionType, Equatable {
 
     // MARK: - Error Handling
 
-    func sync<T>(block: () throws -> T) rethrows -> T {
+    public func sync<T>(block: () throws -> T) rethrows -> T {
         var success: T?
         var failure: ErrorType?
 
@@ -800,7 +802,7 @@ public final class Connection : ConnectionType, Equatable {
 
 }
 
-extension Connection : CustomStringConvertible {
+extension DBConnection : CustomStringConvertible {
 
     public var description: String {
         return String.fromCString(sqlite3_db_filename(handle, nil))!
@@ -808,7 +810,7 @@ extension Connection : CustomStringConvertible {
 
 }
 
-extension Connection.Location : CustomStringConvertible {
+extension DBConnection.Location : CustomStringConvertible {
 
     public var description: String {
         switch self {
@@ -823,7 +825,7 @@ extension Connection.Location : CustomStringConvertible {
 
 }
 
-public func ==(lhs: Connection, rhs: Connection) -> Bool {
+public func ==(lhs: DBConnection, rhs: DBConnection) -> Bool {
     return lhs === rhs
 }
 
@@ -860,7 +862,7 @@ public enum Result : ErrorType {
 
     case Error(message: String, code: Int32, statement: Statement?)
 
-    init?(errorCode: Int32, connection: Connection, statement: Statement? = nil) {
+    init?(errorCode: Int32, connection: DBConnection, statement: Statement? = nil) {
         guard !Result.successCodes.contains(errorCode) else { return nil }
 
         let message = String.fromCString(sqlite3_errmsg(connection.handle))!
diff --git a/SQLite/Core/ConnectionPool.swift b/SQLite/Core/ConnectionPool.swift
index d4a0c3f5..87c12845 100644
--- a/SQLite/Core/ConnectionPool.swift
+++ b/SQLite/Core/ConnectionPool.swift
@@ -39,18 +39,19 @@ public protocol ConnectionPoolDelegate {
 // WAL mode.
 public final class ConnectionPool {
 
-    private let location : Connection.Location
-    private var availableReadConnections = [Connection]()
-    private var unavailableReadConnections = [Connection]()
+    private let location : DBConnection.Location
+    private var availableReadConnections = [DBConnection]()
+    private var unavailableReadConnections = [DBConnection]()
     private let lockQueue : dispatch_queue_t
-    private var writeConnection : Connection!
+    private var writeConnection : DBConnection!
+    private let writeQueue : dispatch_queue_t
     
     public var delegate : ConnectionPoolDelegate?
     
-    public init(_ location: Connection.Location) throws {
+    public init(_ location: DBConnection.Location) throws {
         self.location = location
-        self.lockQueue = dispatch_queue_create("SQLite.ConnectionPool", DISPATCH_QUEUE_SERIAL)
-        
+        self.lockQueue = dispatch_queue_create("SQLite.ConnectionPool.Lock", DISPATCH_QUEUE_SERIAL)
+        self.writeQueue = dispatch_queue_create("SQLite.ConnectionPool.Write", DISPATCH_QUEUE_SERIAL)
         try writable.execute("PRAGMA locking_mode = EXCLUSIVE; PRAGMA journal_mode = WAL;")
     }
     
@@ -64,12 +65,12 @@ public final class ConnectionPool {
     
     // Connection that automatically returns itself
     // to the pool when it goes out of scope
-    private class BorrowedConnection : ConnectionType, Equatable {
+    private class BorrowedConnection : Connection, Equatable {
         
         let pool : ConnectionPool
-        let connection : Connection
+        let connection : DBConnection
         
-        init(pool: ConnectionPool, connection: Connection) {
+        init(pool: ConnectionPool, connection: DBConnection) {
             self.pool = pool
             self.connection = connection
         }
@@ -101,19 +102,23 @@ public final class ConnectionPool {
         @warn_unused_result func scalar(statement: String, _ bindings: [Binding?]) -> Binding? { return connection.scalar(statement, bindings) }
         @warn_unused_result func scalar(statement: String, _ bindings: [String: Binding?]) -> Binding? { return connection.scalar(statement, bindings) }
         
-        func transaction(mode: TransactionMode, block: () throws -> Void) throws { return try connection.transaction(mode, block: block) }
-        func savepoint(name: String, block: () throws -> Void) throws { return try connection.savepoint(name, block: block) }
+        func transaction(mode: TransactionMode, block: (Connection) throws -> Void) throws { return try connection.transaction(mode, block: block) }
+        func savepoint(name: String, block: (Connection) throws -> Void) throws { return try connection.savepoint(name, block: block) }
+
+        func sync<T>(block: () throws -> T) rethrows -> T { return try connection.sync(block) }
+        func check(resultCode: Int32, statement: Statement? = nil) throws -> Int32 { return try connection.check(resultCode, statement: statement) }
         
     }
     
     
     // Acquires a read/write connection to the database
-    public var writable : ConnectionType {
+    public var writable : DBConnection {
+        
         
         var writeConnectionInit = dispatch_once_t()
         dispatch_once(&writeConnectionInit) {
             let flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_WAL
-            self.writeConnection = try! Connection(self.location, flags: flags, dispatcher: ReentrantDispatcher("SQLite.WriteConnection"))
+            self.writeConnection = try! DBConnection(self.location, flags: flags, dispatcher: ReentrantDispatcher("SQLite.WriteConnection"))
             self.writeConnection.busyTimeout = 2
         }
         
@@ -121,7 +126,7 @@ public final class ConnectionPool {
     }
     
     // Acquires a read only connection to the database
-    public var readable : ConnectionType {
+    public var readable : Connection {
         
         var borrowed : BorrowedConnection!
         
@@ -129,7 +134,7 @@ public final class ConnectionPool {
             
             dispatch_sync(lockQueue) {
                 
-                let connection : Connection
+                let connection : DBConnection
                 
                 if let availableConnection = self.availableReadConnections.popLast() {
                     connection = availableConnection
@@ -137,7 +142,7 @@ public final class ConnectionPool {
                 else if self.delegate?.poolShouldAddConnection(self) ?? true {
         
                     let flags = SQLITE_OPEN_READONLY | SQLITE_OPEN_WAL
-                    connection = try! Connection(self.location, flags: flags, dispatcher: ImmediateDispatcher())
+                    connection = try! DBConnection(self.location, flags: flags, dispatcher: ImmediateDispatcher())
                     connection.busyTimeout = 2
                 
                     self.delegate?.pool(self, didAddConnection: connection)
diff --git a/SQLite/Core/Statement.swift b/SQLite/Core/Statement.swift
index 39fb000d..07942ae0 100644
--- a/SQLite/Core/Statement.swift
+++ b/SQLite/Core/Statement.swift
@@ -29,9 +29,9 @@ public final class Statement {
 
     private var handle: COpaquePointer = nil
 
-    private let connection: Connection
+    private let connection: DBConnection
 
-    init(_ connection: Connection, _ SQL: String) throws {
+    init(_ connection: DBConnection, _ SQL: String) throws {
         self.connection = connection
         try connection.check(sqlite3_prepare_v2(connection.handle, SQL, -1, &handle, nil))
     }
diff --git a/SQLite/Extensions/FTS4.swift b/SQLite/Extensions/FTS4.swift
index e5a1d815..351bb721 100644
--- a/SQLite/Extensions/FTS4.swift
+++ b/SQLite/Extensions/FTS4.swift
@@ -140,7 +140,7 @@ extension Tokenizer : CustomStringConvertible {
 
 }
 
-extension Connection {
+extension DBConnection {
 
     public func registerTokenizer(submoduleName: String, next: String -> (String, Range<String.Index>)?) throws {
         try check(_SQLiteRegisterTokenizer(handle, Tokenizer.moduleName, submoduleName) { input, offset, length in
diff --git a/SQLite/Typed/CustomFunctions.swift b/SQLite/Typed/CustomFunctions.swift
index 068d0340..e32ab3c4 100644
--- a/SQLite/Typed/CustomFunctions.swift
+++ b/SQLite/Typed/CustomFunctions.swift
@@ -22,7 +22,7 @@
 // THE SOFTWARE.
 //
 
-public extension Connection {
+public extension DBConnection {
 
     /// Creates or redefines a custom SQL function.
     ///
diff --git a/SQLite/Typed/Query.swift b/SQLite/Typed/Query.swift
index e45034ca..9f966250 100644
--- a/SQLite/Typed/Query.swift
+++ b/SQLite/Typed/Query.swift
@@ -1051,7 +1051,7 @@ public struct Row {
     }
 
     // FIXME: rdar://problem/18673897 // subscript<T>…
-
+    
     public subscript(column: Expression<Blob>) -> Blob {
         return get(column)
     }
diff --git a/SQLiteTests/ConnectionPoolTests.swift b/SQLiteTests/ConnectionPoolTests.swift
index 12e6402f..349891ec 100644
--- a/SQLiteTests/ConnectionPoolTests.swift
+++ b/SQLiteTests/ConnectionPoolTests.swift
@@ -10,7 +10,7 @@ class ConnectionPoolTests : SQLiteTestCase {
     func testConcurrentAccess() {
         
         let _ = try? NSFileManager.defaultManager().removeItemAtPath("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite")
-        let pool = try! ConnectionPool(.URI("\(NSTemporaryDirectory())/SQLiteswiftTests.sqlite"))
+        let pool = try! ConnectionPool(.URI("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite"))
         
         let conn = pool.writable
         try! conn.execute("CREATE TABLE IF NOT EXISTS test(id INTEGER PRIMARY KEY, name TEXT)")
@@ -53,7 +53,7 @@ class ConnectionPoolTests : SQLiteTestCase {
             
         }
         
-        for x in 10..<500 {
+        for x in 10..<50000 {
             
             let name = "test" + String(x)
             let idx = Int(rand()) % 5
@@ -75,7 +75,7 @@ class ConnectionPoolTests : SQLiteTestCase {
     func testAutoRelease() {
         
         let _ = try? NSFileManager.defaultManager().removeItemAtPath("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite")
-        let pool = try! ConnectionPool(.URI("\(NSTemporaryDirectory())/SQLiteswiftTests.sqlite"))
+        let pool = try! ConnectionPool(.URI("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite"))
         
         do {
             try! pool.readable.execute("SELECT 1")
@@ -83,5 +83,5 @@ class ConnectionPoolTests : SQLiteTestCase {
         
         XCTAssertEqual(pool.totalReadableConnectionCount, pool.availableReadableConnectionCount)
     }
-  
+    
 }
diff --git a/SQLiteTests/ConnectionTests.swift b/SQLiteTests/ConnectionTests.swift
index aeec9b72..ab43c52d 100644
--- a/SQLiteTests/ConnectionTests.swift
+++ b/SQLiteTests/ConnectionTests.swift
@@ -10,27 +10,27 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_init_withInMemory_returnsInMemoryConnection() {
-        let db = try! Connection(.InMemory)
+        let db = try! DBConnection(.InMemory)
         XCTAssertEqual("", db.description)
     }
 
     func test_init_returnsInMemoryByDefault() {
-        let db = try! Connection()
+        let db = try! DBConnection()
         XCTAssertEqual("", db.description)
     }
 
     func test_init_withTemporary_returnsTemporaryConnection() {
-        let db = try! Connection(.Temporary)
+        let db = try! DBConnection(.Temporary)
         XCTAssertEqual("", db.description)
     }
 
     func test_init_withURI_returnsURIConnection() {
-        let db = try! Connection(.URI("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3"))
+        let db = try! DBConnection(.URI("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3"))
         XCTAssertEqual("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3", db.description)
     }
 
     func test_init_withString_returnsURIConnection() {
-        let db = try! Connection("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3")
+        let db = try! DBConnection("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3")
         XCTAssertEqual("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3", db.description)
     }
 
@@ -39,7 +39,7 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_readonly_returnsTrueOnReadOnlyConnections() {
-        let db = try! Connection(readonly: true)
+        let db = try! DBConnection(readonly: true)
         XCTAssertTrue(db.readonly)
     }
 
@@ -95,19 +95,19 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_transaction_executesBeginDeferred() {
-        try! db.transaction(.Deferred) {}
+        try! db.transaction(.Deferred) {_ in }
 
         AssertSQL("BEGIN DEFERRED TRANSACTION")
     }
 
     func test_transaction_executesBeginImmediate() {
-        try! db.transaction(.Immediate) {}
+        try! db.transaction(.Immediate) {_ in }
 
         AssertSQL("BEGIN IMMEDIATE TRANSACTION")
     }
 
     func test_transaction_executesBeginExclusive() {
-        try! db.transaction(.Exclusive) {}
+        try! db.transaction(.Exclusive) {_ in }
 
         AssertSQL("BEGIN EXCLUSIVE TRANSACTION")
     }
@@ -115,7 +115,7 @@ class ConnectionTests : SQLiteTestCase {
     func test_transaction_beginsAndCommitsTransactions() {
         let stmt = try! db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com")
 
-        try! db.transaction {
+        try! db.transaction {_ in 
             try stmt.run()
         }
 
@@ -129,7 +129,7 @@ class ConnectionTests : SQLiteTestCase {
         let stmt = try! db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com")
 
         do {
-            try db.transaction {
+            try db.transaction {_ in 
                 try stmt.run()
                 try stmt.run()
             }
@@ -145,8 +145,8 @@ class ConnectionTests : SQLiteTestCase {
     func test_savepoint_beginsAndCommitsSavepoints() {
         let db = self.db
 
-        try! db.savepoint("1") {
-            try db.savepoint("2") {
+        try! db.savepoint("1") {_ in 
+            try db.savepoint("2") {_ in 
                 try db.run("INSERT INTO users (email) VALUES (?)", "alice@example.com")
             }
         }
@@ -165,13 +165,13 @@ class ConnectionTests : SQLiteTestCase {
         let stmt = try! db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com")
 
         do {
-            try db.savepoint("1") {
-                try db.savepoint("2") {
+            try db.savepoint("1") {_ in 
+                try db.savepoint("2") {_ in 
                     try stmt.run()
                     try stmt.run()
                     try stmt.run()
                 }
-                try db.savepoint("2") {
+                try db.savepoint("2") {_ in 
                     try stmt.run()
                     try stmt.run()
                     try stmt.run()
@@ -235,7 +235,7 @@ class ConnectionTests : SQLiteTestCase {
             db.commitHook {
                 done()
             }
-            try! db.transaction {
+            try! db.transaction {_ in 
                 try self.InsertUser("alice")
             }
             XCTAssertEqual(1, db.scalar("SELECT count(*) FROM users") as? Int64)
@@ -246,7 +246,7 @@ class ConnectionTests : SQLiteTestCase {
         async { done in
             db.rollbackHook(done)
             do {
-                try db.transaction {
+                try db.transaction {_ in 
                     try self.InsertUser("alice")
                     try self.InsertUser("alice") // throw
                 }
@@ -263,7 +263,7 @@ class ConnectionTests : SQLiteTestCase {
             }
             db.rollbackHook(done)
             do {
-                try db.transaction {
+                try db.transaction {_ in 
                     try self.InsertUser("alice")
                 }
             } catch {
diff --git a/SQLiteTests/TestHelpers.swift b/SQLiteTests/TestHelpers.swift
index 464b9c27..0854b410 100644
--- a/SQLiteTests/TestHelpers.swift
+++ b/SQLiteTests/TestHelpers.swift
@@ -5,7 +5,7 @@ class SQLiteTestCase : XCTestCase {
 
     var trace = [String: Int]()
 
-    let db = try! Connection()
+    let db = try! DBConnection()
 
     let users = Table("users")
 

From 66b82b0e0ac957518ce8afe115538c41a080f47f Mon Sep 17 00:00:00 2001
From: Kevin Wooten <kevin@wooten.com>
Date: Fri, 15 Apr 2016 23:25:26 -0700
Subject: [PATCH 017/685] Use vfs for exclusivity

vfs seems to be a more reliable handling of exclusive mode.
---
 SQLite/Core/Connection.swift          | 13 +++++++++----
 SQLite/Core/ConnectionPool.swift      | 22 ++++++++++++++--------
 SQLiteTests/ConnectionPoolTests.swift |  4 ++--
 3 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index e1b82b76..a2574af2 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -268,9 +268,9 @@ public final class DBConnection : Connection, Equatable {
     ///     Default: `false`.
     ///
     /// - Returns: A new database connection.
-    public convenience init(_ location: Location = .InMemory, readonly: Bool = false) throws {
+    public convenience init(_ location: Location = .InMemory, readonly: Bool = false, vfsName: String? = nil) throws {
         let flags = readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE
-        try self.init(location, flags: flags, dispatcher: ReentrantDispatcher("SQLite.Connection"))
+        try self.init(location, flags: flags, dispatcher: ReentrantDispatcher("SQLite.Connection"), vfsName: vfsName)
     }
   
     /// Initializes a new SQLite connection.
@@ -285,9 +285,14 @@ public final class DBConnection : Connection, Equatable {
     ///   - dispatcher: Dispatcher synchronization blocks
     ///
     /// - Returns: A new database connection.
-    public init(_ location: Location, flags: Int32, dispatcher: Dispatcher) throws {
+    public init(_ location: Location, flags: Int32, dispatcher: Dispatcher, vfsName: String? = nil) throws {
         self.dispatcher = dispatcher
-        try check(sqlite3_open_v2(location.description, &_handle, flags, nil))
+        if let vfsName = vfsName {
+            try check(sqlite3_open_v2(location.description, &_handle, flags, vfsName))
+        }
+        else {
+            try check(sqlite3_open_v2(location.description, &_handle, flags, nil))
+        }
         try check(sqlite3_extended_result_codes(handle, 1))
     }
 
diff --git a/SQLite/Core/ConnectionPool.swift b/SQLite/Core/ConnectionPool.swift
index 87c12845..c231f4ce 100644
--- a/SQLite/Core/ConnectionPool.swift
+++ b/SQLite/Core/ConnectionPool.swift
@@ -25,6 +25,9 @@
 import Foundation
 
 
+private let vfsName = "unix-excl"
+
+
 /// Connection pool delegate
 public protocol ConnectionPoolDelegate {
     
@@ -44,15 +47,13 @@ public final class ConnectionPool {
     private var unavailableReadConnections = [DBConnection]()
     private let lockQueue : dispatch_queue_t
     private var writeConnection : DBConnection!
-    private let writeQueue : dispatch_queue_t
     
     public var delegate : ConnectionPoolDelegate?
     
     public init(_ location: DBConnection.Location) throws {
         self.location = location
         self.lockQueue = dispatch_queue_create("SQLite.ConnectionPool.Lock", DISPATCH_QUEUE_SERIAL)
-        self.writeQueue = dispatch_queue_create("SQLite.ConnectionPool.Write", DISPATCH_QUEUE_SERIAL)
-        try writable.execute("PRAGMA locking_mode = EXCLUSIVE; PRAGMA journal_mode = WAL;")
+        try writable.execute("PRAGMA journal_mode = WAL;")
     }
     
     public var totalReadableConnectionCount : Int {
@@ -114,12 +115,16 @@ public final class ConnectionPool {
     // Acquires a read/write connection to the database
     public var writable : DBConnection {
         
-        
         var writeConnectionInit = dispatch_once_t()
         dispatch_once(&writeConnectionInit) {
-            let flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_WAL
-            self.writeConnection = try! DBConnection(self.location, flags: flags, dispatcher: ReentrantDispatcher("SQLite.WriteConnection"))
+        
+            let flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_WAL | SQLITE_OPEN_NOMUTEX
+            self.writeConnection = try! DBConnection(self.location, flags: flags, dispatcher: ReentrantDispatcher("SQLite.ConnectionPool.Write"), vfsName: vfsName)
             self.writeConnection.busyTimeout = 2
+            
+            if let delegate = self.delegate {
+                delegate.pool(self, didAddConnection: self.writeConnection)
+            }
         }
         
         return writeConnection
@@ -141,8 +146,9 @@ public final class ConnectionPool {
                 }
                 else if self.delegate?.poolShouldAddConnection(self) ?? true {
         
-                    let flags = SQLITE_OPEN_READONLY | SQLITE_OPEN_WAL
-                    connection = try! DBConnection(self.location, flags: flags, dispatcher: ImmediateDispatcher())
+                    let flags = SQLITE_OPEN_READONLY | SQLITE_OPEN_WAL | SQLITE_OPEN_NOMUTEX
+                    
+                    connection = try! DBConnection(self.location, flags: flags, dispatcher: ImmediateDispatcher(), vfsName: vfsName)
                     connection.busyTimeout = 2
                 
                     self.delegate?.pool(self, didAddConnection: connection)
diff --git a/SQLiteTests/ConnectionPoolTests.swift b/SQLiteTests/ConnectionPoolTests.swift
index 349891ec..47ee1f31 100644
--- a/SQLiteTests/ConnectionPoolTests.swift
+++ b/SQLiteTests/ConnectionPoolTests.swift
@@ -34,7 +34,7 @@ class ConnectionPoolTests : SQLiteTestCase {
 
                 let conn = pool.readable
                 
-                let stmt = conn.prepare("SELECT name FROM test WHERE id = ?")
+                let stmt = try! conn.prepare("SELECT name FROM test WHERE id = ?")
                 var curr = stmt.scalar(x) as! String
                 while !quit {
                     
@@ -65,7 +65,7 @@ class ConnectionPoolTests : SQLiteTestCase {
                 XCTFail((error as? CustomStringConvertible)?.description ?? "Unknown")
             }
             
-            usleep(15000)
+            usleep(1500)
         }
         
         quit = true

From dd2bd5c67d9908a994305ee5d140567ef7a0488e Mon Sep 17 00:00:00 2001
From: Kevin Wooten <kevin@wooten.com>
Date: Sat, 16 Apr 2016 00:01:06 -0700
Subject: [PATCH 018/685] Set project tab & indent settings

---
 SQLite.xcodeproj/project.pbxproj | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index d2ac9df4..786c2c77 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -354,7 +354,9 @@
 				EE247B8A1C3F81D000AE3E12 /* Metadata */,
 				EE247AD41C3F04ED00AE3E12 /* Products */,
 			);
+			indentWidth = 4;
 			sourceTree = "<group>";
+			tabWidth = 4;
 		};
 		EE247AD41C3F04ED00AE3E12 /* Products */ = {
 			isa = PBXGroup;

From ccc20e574a6bab6be91f452f0ecf141b18011deb Mon Sep 17 00:00:00 2001
From: Kevin Wooten <kevin@wooten.com>
Date: Sat, 16 Apr 2016 01:15:49 -0700
Subject: [PATCH 019/685] Added alternate concurrency test

---
 SQLiteTests/ConnectionPoolTests.swift | 52 ++++++++++++++++++++++++---
 1 file changed, 47 insertions(+), 5 deletions(-)

diff --git a/SQLiteTests/ConnectionPoolTests.swift b/SQLiteTests/ConnectionPoolTests.swift
index 47ee1f31..ce460fe5 100644
--- a/SQLiteTests/ConnectionPoolTests.swift
+++ b/SQLiteTests/ConnectionPoolTests.swift
@@ -7,13 +7,13 @@ class ConnectionPoolTests : SQLiteTestCase {
         super.setUp()
     }
 
-    func testConcurrentAccess() {
+    func testConcurrentAccess2() {
         
         let _ = try? NSFileManager.defaultManager().removeItemAtPath("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite")
         let pool = try! ConnectionPool(.URI("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite"))
         
         let conn = pool.writable
-        try! conn.execute("CREATE TABLE IF NOT EXISTS test(id INTEGER PRIMARY KEY, name TEXT)")
+        try! conn.execute("DROP TABLE IF EXISTS test; CREATE TABLE test(id INTEGER PRIMARY KEY, name TEXT);")
         try! conn.execute("DELETE FROM test")
         try! conn.execute("INSERT INTO test(id,name) VALUES(0, 'test0')")
         try! conn.execute("INSERT INTO test(id,name) VALUES(1, 'test1')")
@@ -40,7 +40,7 @@ class ConnectionPoolTests : SQLiteTestCase {
                     
                     let now = stmt.scalar(x) as! String
                     if now != curr {
-                        print(now)
+                        //print(now)
                         curr = now
                     }
                     reads += 1
@@ -53,7 +53,7 @@ class ConnectionPoolTests : SQLiteTestCase {
             
         }
         
-        for x in 10..<50000 {
+        for x in 10..<5000 {
             
             let name = "test" + String(x)
             let idx = Int(rand()) % 5
@@ -65,13 +65,55 @@ class ConnectionPoolTests : SQLiteTestCase {
                 XCTFail((error as? CustomStringConvertible)?.description ?? "Unknown")
             }
             
-            usleep(1500)
+            usleep(500)
         }
         
         quit = true
         waitForExpectationsWithTimeout(1000, handler: nil)
     }
     
+    func testConcurrentAccess() throws {
+        
+        let _ = try? NSFileManager.defaultManager().removeItemAtPath("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite")
+        let pool = try! ConnectionPool(.URI("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite"))
+        
+        try! pool.writable.execute("DROP TABLE IF EXISTS test; CREATE TABLE test(value);")
+        try! pool.writable.run("INSERT INTO test(value) VALUES(?)", 0)
+        
+        let q = dispatch_queue_create("Readers/Writers", DISPATCH_QUEUE_CONCURRENT);
+        var finished = false
+        
+        for _ in 0..<5 {
+            
+            dispatch_async(q) {
+                
+                while !finished {
+                    
+                    let val = pool.readable.scalar("SELECT value FROM test")
+                    assert(val != nil, "DB query returned nil result set")
+                    
+                }
+                
+            }
+            
+        }
+        
+        for c in 0..<5000 {
+            
+            try pool.writable.run("INSERT INTO test(value) VALUES(?)", c)
+            
+            usleep(100);
+            
+        }
+        
+        finished = true
+        
+        // Wait for readers to finish
+        dispatch_barrier_sync(q) {
+        }
+        
+    }
+    
     func testAutoRelease() {
         
         let _ = try? NSFileManager.defaultManager().removeItemAtPath("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite")

From 18f612fd112bdedc6fecec558fb27cd119a2c59e Mon Sep 17 00:00:00 2001
From: Kevin Wooten <kevin@wooten.com>
Date: Sat, 16 Apr 2016 01:23:10 -0700
Subject: [PATCH 020/685] Fix imports in ConnectionPool.swift

---
 SQLite/Core/ConnectionPool.swift | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/SQLite/Core/ConnectionPool.swift b/SQLite/Core/ConnectionPool.swift
index c231f4ce..5166e6eb 100644
--- a/SQLite/Core/ConnectionPool.swift
+++ b/SQLite/Core/ConnectionPool.swift
@@ -22,7 +22,8 @@
 // THE SOFTWARE.
 //
 
-import Foundation
+import Dispatch
+import CSQLite
 
 
 private let vfsName = "unix-excl"

From 2a5908b513d5b44b1070f2667011f1972482bbd4 Mon Sep 17 00:00:00 2001
From: Kevin Wooten <kevin@wooten.com>
Date: Sun, 17 Apr 2016 15:55:59 -0700
Subject: [PATCH 021/685] Rename `DBConnection` to `DirectConnection`

---
 SQLite.xcodeproj/project.pbxproj   | 12 ++++++------
 SQLite/Core/Connection.swift       | 10 +++++-----
 SQLite/Core/ConnectionPool.swift   | 22 +++++++++++-----------
 SQLite/Core/Statement.swift        |  4 ++--
 SQLite/Extensions/FTS4.swift       |  2 +-
 SQLite/Typed/CustomFunctions.swift |  2 +-
 SQLiteTests/ConnectionTests.swift  | 12 ++++++------
 SQLiteTests/TestHelpers.swift      |  2 +-
 8 files changed, 33 insertions(+), 33 deletions(-)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index edc79e3f..6b145ca1 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -173,7 +173,7 @@
 		39548A6D1CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
 		39548A6F1CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
 		A121AC451CA35C79005A31D1 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
-		AA780B3B1CC201A700E0E95E /* ConnectionPool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectionPool.swift; sourceTree = "<group>"; };
+		AA780B3B1CC201A700E0E95E /* ConnectionPool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ConnectionPool.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
 		AA780B3C1CC201A700E0E95E /* Dispatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Dispatcher.swift; sourceTree = "<group>"; };
 		AA780B3F1CC202B000E0E95E /* ConnectionPoolTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectionPoolTests.swift; sourceTree = "<group>"; };
 		EE247AD31C3F04ED00AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -182,19 +182,19 @@
 		EE247ADD1C3F04ED00AE3E12 /* SQLiteTests iOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SQLiteTests iOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AE41C3F04ED00AE3E12 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		EE247AEE1C3F06E900AE3E12 /* Blob.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Blob.swift; sourceTree = "<group>"; };
-		EE247AEF1C3F06E900AE3E12 /* Connection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Connection.swift; sourceTree = "<group>"; };
+		EE247AEF1C3F06E900AE3E12 /* Connection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Connection.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
 		EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fts3_tokenizer.h; sourceTree = "<group>"; };
 		EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "SQLite-Bridging.m"; sourceTree = "<group>"; };
-		EE247AF21C3F06E900AE3E12 /* Statement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Statement.swift; sourceTree = "<group>"; };
+		EE247AF21C3F06E900AE3E12 /* Statement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Statement.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
 		EE247AF31C3F06E900AE3E12 /* Value.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Value.swift; sourceTree = "<group>"; };
-		EE247AF51C3F06E900AE3E12 /* FTS4.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS4.swift; sourceTree = "<group>"; };
+		EE247AF51C3F06E900AE3E12 /* FTS4.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = FTS4.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
 		EE247AF61C3F06E900AE3E12 /* R*Tree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "R*Tree.swift"; sourceTree = "<group>"; };
 		EE247AF71C3F06E900AE3E12 /* Foundation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Foundation.swift; sourceTree = "<group>"; };
 		EE247AF81C3F06E900AE3E12 /* Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = "<group>"; };
 		EE247AFA1C3F06E900AE3E12 /* AggregateFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AggregateFunctions.swift; sourceTree = "<group>"; };
 		EE247AFB1C3F06E900AE3E12 /* Collation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Collation.swift; sourceTree = "<group>"; };
 		EE247AFC1C3F06E900AE3E12 /* CoreFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreFunctions.swift; sourceTree = "<group>"; };
-		EE247AFD1C3F06E900AE3E12 /* CustomFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomFunctions.swift; sourceTree = "<group>"; };
+		EE247AFD1C3F06E900AE3E12 /* CustomFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = CustomFunctions.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
 		EE247AFE1C3F06E900AE3E12 /* Expression.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Expression.swift; sourceTree = "<group>"; };
 		EE247AFF1C3F06E900AE3E12 /* Operators.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Operators.swift; sourceTree = "<group>"; };
 		EE247B001C3F06E900AE3E12 /* Query.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Query.swift; sourceTree = "<group>"; };
@@ -204,7 +204,7 @@
 		EE247B181C3F134A00AE3E12 /* SetterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetterTests.swift; sourceTree = "<group>"; };
 		EE247B1A1C3F137700AE3E12 /* AggregateFunctionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AggregateFunctionsTests.swift; sourceTree = "<group>"; };
 		EE247B1B1C3F137700AE3E12 /* BlobTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlobTests.swift; sourceTree = "<group>"; };
-		EE247B1D1C3F137700AE3E12 /* ConnectionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectionTests.swift; sourceTree = "<group>"; };
+		EE247B1D1C3F137700AE3E12 /* ConnectionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ConnectionTests.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
 		EE247B1E1C3F137700AE3E12 /* CoreFunctionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreFunctionsTests.swift; sourceTree = "<group>"; };
 		EE247B1F1C3F137700AE3E12 /* CustomFunctionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomFunctionsTests.swift; sourceTree = "<group>"; };
 		EE247B201C3F137700AE3E12 /* ExpressionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExpressionTests.swift; sourceTree = "<group>"; };
diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index a2574af2..4ae468dd 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -227,7 +227,7 @@ public protocol Connection {
 
 
 /// A connection to SQLite.
-public final class DBConnection : Connection, Equatable {
+public final class DirectConnection : Connection, Equatable {
 
     /// The location of a SQLite database.
     public enum Location {
@@ -807,7 +807,7 @@ public final class DBConnection : Connection, Equatable {
 
 }
 
-extension DBConnection : CustomStringConvertible {
+extension DirectConnection : CustomStringConvertible {
 
     public var description: String {
         return String.fromCString(sqlite3_db_filename(handle, nil))!
@@ -815,7 +815,7 @@ extension DBConnection : CustomStringConvertible {
 
 }
 
-extension DBConnection.Location : CustomStringConvertible {
+extension DirectConnection.Location : CustomStringConvertible {
 
     public var description: String {
         switch self {
@@ -830,7 +830,7 @@ extension DBConnection.Location : CustomStringConvertible {
 
 }
 
-public func ==(lhs: DBConnection, rhs: DBConnection) -> Bool {
+public func ==(lhs: DirectConnection, rhs: DirectConnection) -> Bool {
     return lhs === rhs
 }
 
@@ -867,7 +867,7 @@ public enum Result : ErrorType {
 
     case Error(message: String, code: Int32, statement: Statement?)
 
-    init?(errorCode: Int32, connection: DBConnection, statement: Statement? = nil) {
+    init?(errorCode: Int32, connection: DirectConnection, statement: Statement? = nil) {
         guard !Result.successCodes.contains(errorCode) else { return nil }
 
         let message = String.fromCString(sqlite3_errmsg(connection.handle))!
diff --git a/SQLite/Core/ConnectionPool.swift b/SQLite/Core/ConnectionPool.swift
index 5166e6eb..931e5874 100644
--- a/SQLite/Core/ConnectionPool.swift
+++ b/SQLite/Core/ConnectionPool.swift
@@ -43,15 +43,15 @@ public protocol ConnectionPoolDelegate {
 // WAL mode.
 public final class ConnectionPool {
 
-    private let location : DBConnection.Location
-    private var availableReadConnections = [DBConnection]()
-    private var unavailableReadConnections = [DBConnection]()
+    private let location : DirectConnection.Location
+    private var availableReadConnections = [DirectConnection]()
+    private var unavailableReadConnections = [DirectConnection]()
     private let lockQueue : dispatch_queue_t
-    private var writeConnection : DBConnection!
+    private var writeConnection : DirectConnection!
     
     public var delegate : ConnectionPoolDelegate?
     
-    public init(_ location: DBConnection.Location) throws {
+    public init(_ location: DirectConnection.Location) throws {
         self.location = location
         self.lockQueue = dispatch_queue_create("SQLite.ConnectionPool.Lock", DISPATCH_QUEUE_SERIAL)
         try writable.execute("PRAGMA journal_mode = WAL;")
@@ -70,9 +70,9 @@ public final class ConnectionPool {
     private class BorrowedConnection : Connection, Equatable {
         
         let pool : ConnectionPool
-        let connection : DBConnection
+        let connection : DirectConnection
         
-        init(pool: ConnectionPool, connection: DBConnection) {
+        init(pool: ConnectionPool, connection: DirectConnection) {
             self.pool = pool
             self.connection = connection
         }
@@ -114,13 +114,13 @@ public final class ConnectionPool {
     
     
     // Acquires a read/write connection to the database
-    public var writable : DBConnection {
+    public var writable : DirectConnection {
         
         var writeConnectionInit = dispatch_once_t()
         dispatch_once(&writeConnectionInit) {
         
             let flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_WAL | SQLITE_OPEN_NOMUTEX
-            self.writeConnection = try! DBConnection(self.location, flags: flags, dispatcher: ReentrantDispatcher("SQLite.ConnectionPool.Write"), vfsName: vfsName)
+            self.writeConnection = try! DirectConnection(self.location, flags: flags, dispatcher: ReentrantDispatcher("SQLite.ConnectionPool.Write"), vfsName: vfsName)
             self.writeConnection.busyTimeout = 2
             
             if let delegate = self.delegate {
@@ -140,7 +140,7 @@ public final class ConnectionPool {
             
             dispatch_sync(lockQueue) {
                 
-                let connection : DBConnection
+                let connection : DirectConnection
                 
                 if let availableConnection = self.availableReadConnections.popLast() {
                     connection = availableConnection
@@ -149,7 +149,7 @@ public final class ConnectionPool {
         
                     let flags = SQLITE_OPEN_READONLY | SQLITE_OPEN_WAL | SQLITE_OPEN_NOMUTEX
                     
-                    connection = try! DBConnection(self.location, flags: flags, dispatcher: ImmediateDispatcher(), vfsName: vfsName)
+                    connection = try! DirectConnection(self.location, flags: flags, dispatcher: ImmediateDispatcher(), vfsName: vfsName)
                     connection.busyTimeout = 2
                 
                     self.delegate?.pool(self, didAddConnection: connection)
diff --git a/SQLite/Core/Statement.swift b/SQLite/Core/Statement.swift
index 07942ae0..d7652c1a 100644
--- a/SQLite/Core/Statement.swift
+++ b/SQLite/Core/Statement.swift
@@ -29,9 +29,9 @@ public final class Statement {
 
     private var handle: COpaquePointer = nil
 
-    private let connection: DBConnection
+    private let connection: DirectConnection
 
-    init(_ connection: DBConnection, _ SQL: String) throws {
+    init(_ connection: DirectConnection, _ SQL: String) throws {
         self.connection = connection
         try connection.check(sqlite3_prepare_v2(connection.handle, SQL, -1, &handle, nil))
     }
diff --git a/SQLite/Extensions/FTS4.swift b/SQLite/Extensions/FTS4.swift
index 351bb721..045e5303 100644
--- a/SQLite/Extensions/FTS4.swift
+++ b/SQLite/Extensions/FTS4.swift
@@ -140,7 +140,7 @@ extension Tokenizer : CustomStringConvertible {
 
 }
 
-extension DBConnection {
+extension DirectConnection {
 
     public func registerTokenizer(submoduleName: String, next: String -> (String, Range<String.Index>)?) throws {
         try check(_SQLiteRegisterTokenizer(handle, Tokenizer.moduleName, submoduleName) { input, offset, length in
diff --git a/SQLite/Typed/CustomFunctions.swift b/SQLite/Typed/CustomFunctions.swift
index e32ab3c4..d004f75e 100644
--- a/SQLite/Typed/CustomFunctions.swift
+++ b/SQLite/Typed/CustomFunctions.swift
@@ -22,7 +22,7 @@
 // THE SOFTWARE.
 //
 
-public extension DBConnection {
+public extension DirectConnection {
 
     /// Creates or redefines a custom SQL function.
     ///
diff --git a/SQLiteTests/ConnectionTests.swift b/SQLiteTests/ConnectionTests.swift
index ab43c52d..bbad19a8 100644
--- a/SQLiteTests/ConnectionTests.swift
+++ b/SQLiteTests/ConnectionTests.swift
@@ -10,27 +10,27 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_init_withInMemory_returnsInMemoryConnection() {
-        let db = try! DBConnection(.InMemory)
+        let db = try! DirectConnection(.InMemory)
         XCTAssertEqual("", db.description)
     }
 
     func test_init_returnsInMemoryByDefault() {
-        let db = try! DBConnection()
+        let db = try! DirectConnection()
         XCTAssertEqual("", db.description)
     }
 
     func test_init_withTemporary_returnsTemporaryConnection() {
-        let db = try! DBConnection(.Temporary)
+        let db = try! DirectConnection(.Temporary)
         XCTAssertEqual("", db.description)
     }
 
     func test_init_withURI_returnsURIConnection() {
-        let db = try! DBConnection(.URI("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3"))
+        let db = try! DirectConnection(.URI("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3"))
         XCTAssertEqual("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3", db.description)
     }
 
     func test_init_withString_returnsURIConnection() {
-        let db = try! DBConnection("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3")
+        let db = try! DirectConnection("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3")
         XCTAssertEqual("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3", db.description)
     }
 
@@ -39,7 +39,7 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_readonly_returnsTrueOnReadOnlyConnections() {
-        let db = try! DBConnection(readonly: true)
+        let db = try! DirectConnection(readonly: true)
         XCTAssertTrue(db.readonly)
     }
 
diff --git a/SQLiteTests/TestHelpers.swift b/SQLiteTests/TestHelpers.swift
index 0854b410..855bf7bd 100644
--- a/SQLiteTests/TestHelpers.swift
+++ b/SQLiteTests/TestHelpers.swift
@@ -5,7 +5,7 @@ class SQLiteTestCase : XCTestCase {
 
     var trace = [String: Int]()
 
-    let db = try! DBConnection()
+    let db = try! DirectConnection()
 
     let users = Table("users")
 

From 9548d172655ed841be1ba31600cf47417c58389c Mon Sep 17 00:00:00 2001
From: Kevin Wooten <kevin@wooten.com>
Date: Mon, 18 Apr 2016 14:41:19 -0700
Subject: [PATCH 022/685] Replace pool delegate with setup closures

---
 SQLite/Core/ConnectionPool.swift      | 58 ++++++++++++++++++---------
 SQLiteTests/ConnectionPoolTests.swift | 13 ++++++
 2 files changed, 53 insertions(+), 18 deletions(-)

diff --git a/SQLite/Core/ConnectionPool.swift b/SQLite/Core/ConnectionPool.swift
index 931e5874..d430d7cf 100644
--- a/SQLite/Core/ConnectionPool.swift
+++ b/SQLite/Core/ConnectionPool.swift
@@ -29,15 +29,6 @@ import CSQLite
 private let vfsName = "unix-excl"
 
 
-/// Connection pool delegate
-public protocol ConnectionPoolDelegate {
-    
-    func poolShouldAddConnection(pool: ConnectionPool) -> Bool
-    func pool(pool: ConnectionPool, didAddConnection: Connection)
-    
-}
-
-
 // Connection pool for accessing an SQLite database
 // with multiple readers & a single writer. Utilizes
 // WAL mode.
@@ -49,12 +40,29 @@ public final class ConnectionPool {
     private let lockQueue : dispatch_queue_t
     private var writeConnection : DirectConnection!
     
-    public var delegate : ConnectionPoolDelegate?
+    public var foreignKeys : Bool {
+        get {
+            return internalSetup[.ForeignKeys] != nil
+        }
+        set {
+            internalSetup[.ForeignKeys] = newValue ? { try $0.execute("PRAGMA foreign_keys = ON;") } : nil
+        }
+    }
+    
+    public typealias ConnectionProcessor = Connection throws -> Void
+    public var setup = [ConnectionProcessor]()
+    
+    private enum InternalOption {
+        case WriteAheadLogging
+        case ForeignKeys
+    }
+    
+    private var internalSetup = [InternalOption: ConnectionProcessor]()
     
     public init(_ location: DirectConnection.Location) throws {
         self.location = location
         self.lockQueue = dispatch_queue_create("SQLite.ConnectionPool.Lock", DISPATCH_QUEUE_SERIAL)
-        try writable.execute("PRAGMA journal_mode = WAL;")
+        self.internalSetup[.WriteAheadLogging] = { try $0.execute("PRAGMA journal_mode = WAL;") }
     }
     
     public var totalReadableConnectionCount : Int {
@@ -123,9 +131,14 @@ public final class ConnectionPool {
             self.writeConnection = try! DirectConnection(self.location, flags: flags, dispatcher: ReentrantDispatcher("SQLite.ConnectionPool.Write"), vfsName: vfsName)
             self.writeConnection.busyTimeout = 2
             
-            if let delegate = self.delegate {
-                delegate.pool(self, didAddConnection: self.writeConnection)
+            for setupProcessor in self.internalSetup.values {
+                try! setupProcessor(self.writeConnection)
             }
+            
+            for setupProcessor in self.setup {
+                try! setupProcessor(self.writeConnection)
+            }
+            
         }
         
         return writeConnection
@@ -140,23 +153,32 @@ public final class ConnectionPool {
             
             dispatch_sync(lockQueue) {
                 
+                // Ensure database is open
+                self.writable
+                
                 let connection : DirectConnection
                 
                 if let availableConnection = self.availableReadConnections.popLast() {
                     connection = availableConnection
                 }
-                else if self.delegate?.poolShouldAddConnection(self) ?? true {
+                else {
         
                     let flags = SQLITE_OPEN_READONLY | SQLITE_OPEN_WAL | SQLITE_OPEN_NOMUTEX
                     
                     connection = try! DirectConnection(self.location, flags: flags, dispatcher: ImmediateDispatcher(), vfsName: vfsName)
                     connection.busyTimeout = 2
                 
-                    self.delegate?.pool(self, didAddConnection: connection)
+                    for (type, setupProcessor) in self.internalSetup {
+                        if type == .WriteAheadLogging {
+                            continue
+                        }
+                        try! setupProcessor(connection)
+                    }
+                    
+                    for setupProcessor in self.setup {
+                        try! setupProcessor(connection)
+                    }
                     
-                }
-                else {
-                    return
                 }
                 
                 self.unavailableReadConnections.append(connection)
diff --git a/SQLiteTests/ConnectionPoolTests.swift b/SQLiteTests/ConnectionPoolTests.swift
index ce460fe5..b621396c 100644
--- a/SQLiteTests/ConnectionPoolTests.swift
+++ b/SQLiteTests/ConnectionPoolTests.swift
@@ -6,6 +6,19 @@ class ConnectionPoolTests : SQLiteTestCase {
     override func setUp() {
         super.setUp()
     }
+    
+    func testConnectionSetupClosures() {
+        
+        let _ = try? NSFileManager.defaultManager().removeItemAtPath("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite")
+        let pool = try! ConnectionPool(.URI("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite"))
+        
+        pool.foreignKeys = true
+        pool.setup.append { try $0.execute("CREATE TABLE IF NOT EXISTS test(value INT)") }
+        
+        XCTAssertTrue(try pool.readable.scalar("PRAGMA foreign_keys") as! Int64 == 1)
+        try! pool.writable.execute("INSERT INTO test(value) VALUES (1)")
+        try! pool.readable.execute("SELECT value FROM test")
+    }
 
     func testConcurrentAccess2() {
         

From ffb92745ad76b7a5eb2e3e293da755fa8d760a7a Mon Sep 17 00:00:00 2001
From: Kevin Wooten <kevin@wooten.com>
Date: Mon, 18 Apr 2016 17:18:22 -0700
Subject: [PATCH 023/685] Fix writable connection initialization

Was using incorrect dispatch_once token.
---
 SQLite/Core/ConnectionPool.swift | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/SQLite/Core/ConnectionPool.swift b/SQLite/Core/ConnectionPool.swift
index d430d7cf..dd644304 100644
--- a/SQLite/Core/ConnectionPool.swift
+++ b/SQLite/Core/ConnectionPool.swift
@@ -122,9 +122,11 @@ public final class ConnectionPool {
     
     
     // Acquires a read/write connection to the database
+    
+    var writeConnectionInit = dispatch_once_t()
+    
     public var writable : DirectConnection {
-        
-        var writeConnectionInit = dispatch_once_t()
+
         dispatch_once(&writeConnectionInit) {
         
             let flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_WAL | SQLITE_OPEN_NOMUTEX

From b7a0eb1a58936071a6d171036f3e36f75af8f401 Mon Sep 17 00:00:00 2001
From: Kevin Wooten <kevin@wooten.com>
Date: Mon, 18 Apr 2016 17:51:38 -0700
Subject: [PATCH 024/685] Cleanup connection pool tests

# Conflicts:
#	SQLiteTests/ConnectionPoolTests.swift
---
 SQLiteTests/ConnectionPoolTests.swift | 23 +++++++----------------
 1 file changed, 7 insertions(+), 16 deletions(-)

diff --git a/SQLiteTests/ConnectionPoolTests.swift b/SQLiteTests/ConnectionPoolTests.swift
index b621396c..74351527 100644
--- a/SQLiteTests/ConnectionPoolTests.swift
+++ b/SQLiteTests/ConnectionPoolTests.swift
@@ -3,28 +3,25 @@ import SQLite
 
 class ConnectionPoolTests : SQLiteTestCase {
 
+    var pool : ConnectionPool!
+    
     override func setUp() {
-        super.setUp()
+        let _ = try? NSFileManager.defaultManager().removeItemAtPath("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite")
+        pool = try! ConnectionPool(.URI("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite"))
     }
     
     func testConnectionSetupClosures() {
         
-        let _ = try? NSFileManager.defaultManager().removeItemAtPath("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite")
-        let pool = try! ConnectionPool(.URI("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite"))
-        
         pool.foreignKeys = true
         pool.setup.append { try $0.execute("CREATE TABLE IF NOT EXISTS test(value INT)") }
         
-        XCTAssertTrue(try pool.readable.scalar("PRAGMA foreign_keys") as! Int64 == 1)
+        XCTAssertTrue(pool.readable.scalar("PRAGMA foreign_keys") as! Int64 == 1)
         try! pool.writable.execute("INSERT INTO test(value) VALUES (1)")
         try! pool.readable.execute("SELECT value FROM test")
     }
 
     func testConcurrentAccess2() {
         
-        let _ = try? NSFileManager.defaultManager().removeItemAtPath("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite")
-        let pool = try! ConnectionPool(.URI("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite"))
-        
         let conn = pool.writable
         try! conn.execute("DROP TABLE IF EXISTS test; CREATE TABLE test(id INTEGER PRIMARY KEY, name TEXT);")
         try! conn.execute("DELETE FROM test")
@@ -45,7 +42,7 @@ class ConnectionPoolTests : SQLiteTestCase {
                 
                 print("started", x)
 
-                let conn = pool.readable
+                let conn = self.pool.readable
                 
                 let stmt = try! conn.prepare("SELECT name FROM test WHERE id = ?")
                 var curr = stmt.scalar(x) as! String
@@ -87,9 +84,6 @@ class ConnectionPoolTests : SQLiteTestCase {
     
     func testConcurrentAccess() throws {
         
-        let _ = try? NSFileManager.defaultManager().removeItemAtPath("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite")
-        let pool = try! ConnectionPool(.URI("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite"))
-        
         try! pool.writable.execute("DROP TABLE IF EXISTS test; CREATE TABLE test(value);")
         try! pool.writable.run("INSERT INTO test(value) VALUES(?)", 0)
         
@@ -102,7 +96,7 @@ class ConnectionPoolTests : SQLiteTestCase {
                 
                 while !finished {
                     
-                    let val = pool.readable.scalar("SELECT value FROM test")
+                    let val = self.pool.readable.scalar("SELECT value FROM test")
                     assert(val != nil, "DB query returned nil result set")
                     
                 }
@@ -129,9 +123,6 @@ class ConnectionPoolTests : SQLiteTestCase {
     
     func testAutoRelease() {
         
-        let _ = try? NSFileManager.defaultManager().removeItemAtPath("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite")
-        let pool = try! ConnectionPool(.URI("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite"))
-        
         do {
             try! pool.readable.execute("SELECT 1")
         }

From 0eeedfeedafce317d2bb2770ca72f3cbded9f80c Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 12 May 2016 17:39:40 +0100
Subject: [PATCH 025/685] Split into standard / standalone subspecs

The standard subspec is the default and behaves
as previously; the standalone subspec adds a
dependency to the sqlite3 pod which downloads and
compiles a version of SQLite instead of using the
system-supplied version.

The version of SQLite used can be further customized
by requiring another sqlite3 subspec from the main
Podfile.
---
 SQLite.swift.podspec         | 39 +++++++++++++++++++++++-------------
 SQLite/Core/Connection.swift |  4 ++++
 SQLite/Core/Statement.swift  |  4 ++++
 SQLite/Helpers.swift         |  4 ++++
 4 files changed, 37 insertions(+), 14 deletions(-)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index fe814100..6e5e25d5 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -24,19 +24,30 @@ Pod::Spec.new do |s|
   s.tvos.deployment_target = "9.0"
   s.osx.deployment_target = "10.9"
   s.watchos.deployment_target = "2.0"
+  s.default_subspec  = 'standard'
 
-  s.preserve_paths = 'CocoaPods/**/*'
-  s.pod_target_xcconfig = {
-    'SWIFT_INCLUDE_PATHS[sdk=macosx*]'           => '$(SRCROOT)/SQLite.swift/CocoaPods/macosx',
-    'SWIFT_INCLUDE_PATHS[sdk=iphoneos*]'         => '$(SRCROOT)/SQLite.swift/CocoaPods/iphoneos',
-    'SWIFT_INCLUDE_PATHS[sdk=iphonesimulator*]'  => '$(SRCROOT)/SQLite.swift/CocoaPods/iphonesimulator',
-    'SWIFT_INCLUDE_PATHS[sdk=appletvos*]'        => '$(SRCROOT)/SQLite.swift/CocoaPods/appletvos',
-    'SWIFT_INCLUDE_PATHS[sdk=appletvsimulator*]' => '$(SRCROOT)/SQLite.swift/CocoaPods/appletvsimulator',
-    'SWIFT_INCLUDE_PATHS[sdk=watchos*]'          => '$(SRCROOT)/SQLite.swift/CocoaPods/watchos',
-    'SWIFT_INCLUDE_PATHS[sdk=watchsimulator*]'   => '$(SRCROOT)/SQLite.swift/CocoaPods/watchsimulator'
-  }
-
-  s.libraries = 'sqlite3'
-  s.source_files = 'SQLite/**/*.{c,h,m,swift}'
-  s.private_header_files = 'SQLite/Core/fts3_tokenizer.h'
+  s.subspec 'standard' do |ss|
+    ss.source_files = 'SQLite/**/*.{c,h,m,swift}'
+    ss.private_header_files = 'SQLite/Core/fts3_tokenizer.h'
+
+    ss.library = 'sqlite3'
+    ss.preserve_paths = 'CocoaPods/**/*'
+    ss.pod_target_xcconfig = {
+      'SWIFT_INCLUDE_PATHS[sdk=macosx*]'           => '$(SRCROOT)/SQLite.swift/CocoaPods/macosx',
+      'SWIFT_INCLUDE_PATHS[sdk=iphoneos*]'         => '$(SRCROOT)/SQLite.swift/CocoaPods/iphoneos',
+      'SWIFT_INCLUDE_PATHS[sdk=iphonesimulator*]'  => '$(SRCROOT)/SQLite.swift/CocoaPods/iphonesimulator',
+      'SWIFT_INCLUDE_PATHS[sdk=appletvos*]'        => '$(SRCROOT)/SQLite.swift/CocoaPods/appletvos',
+      'SWIFT_INCLUDE_PATHS[sdk=appletvsimulator*]' => '$(SRCROOT)/SQLite.swift/CocoaPods/appletvsimulator',
+      'SWIFT_INCLUDE_PATHS[sdk=watchos*]'          => '$(SRCROOT)/SQLite.swift/CocoaPods/watchos',
+      'SWIFT_INCLUDE_PATHS[sdk=watchsimulator*]'   => '$(SRCROOT)/SQLite.swift/CocoaPods/watchsimulator'
+    }
+  end
+
+  s.subspec 'standalone' do |ss|
+    ss.source_files = 'SQLite/**/*.{c,h,m,swift}'
+    ss.private_header_files = 'SQLite/Core/fts3_tokenizer.h'
+    ss.xcconfig = { 'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_SWIFT_STANDALONE' }
+
+    ss.dependency 'sqlite3'
+  end
 end
diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index 7d67b051..f4be7983 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -23,7 +23,11 @@
 //
 
 import Dispatch
+#if SQLITE_SWIFT_STANDALONE
+import sqlite3
+#else
 import CSQLite
+#endif
 
 /// A connection to SQLite.
 public final class Connection {
diff --git a/SQLite/Core/Statement.swift b/SQLite/Core/Statement.swift
index 39fb000d..9a4bfa1e 100644
--- a/SQLite/Core/Statement.swift
+++ b/SQLite/Core/Statement.swift
@@ -22,7 +22,11 @@
 // THE SOFTWARE.
 //
 
+#if SQLITE_SWIFT_STANDALONE
+import sqlite3
+#else
 import CSQLite
+#endif
 
 /// A single SQL statement.
 public final class Statement {
diff --git a/SQLite/Helpers.swift b/SQLite/Helpers.swift
index 33fc6a62..cc6da27c 100644
--- a/SQLite/Helpers.swift
+++ b/SQLite/Helpers.swift
@@ -22,7 +22,11 @@
 // THE SOFTWARE.
 //
 
+#if SQLITE_SWIFT_STANDALONE
+import sqlite3
+#else
 import CSQLite
+#endif
 
 public typealias Star = (Expression<Binding>?, Expression<Binding>?) -> Expression<Void>
 

From c29ec30fe86dd48d8a510b53fb04b43979f84e5e Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 12 May 2016 18:02:33 +0100
Subject: [PATCH 026/685] Add documentation

---
 Documentation/Index.md | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 52d04c69..700deb9f 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -111,8 +111,26 @@ install SQLite.swift with Carthage:
 
  3. Run `pod install`.
 
+ #### Requiring a specific version of SQLite
+
+ If you want to use a more recent version of SQLite than what is provided with the OS you can require the `standalone` subspec:
+
+``` ruby
+    pod 'SQLite.swift/standalone', '~> 0.10.1'
+```
+
+By default this will use the most recent version of SQLite without any extras. If you want you can further customize this by adding another dependency to sqlite3 or one of its subspecs:
+
+``` ruby
+    pod 'SQLite.swift/standalone', '~> 0.10.1'
+    pod 'sqlite3/fts5', '= 3.11.1'  # SQLite 3.11.1 with FTS5 enabled
+```
+
+See the [sqlite3 podspec][sqlite3pod] for more details.
+
 [CocoaPods]: https://cocoapods.org
 [CocoaPods Installation]: https://guides.cocoapods.org/using/getting-started.html#getting-started
+[sqlite3pod]: https://github.com/clemensg/sqlite3pod
 
 
 ### Manual

From aacdde0778264c652048dffbf01598dfbcac8e82 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 13 May 2016 19:30:15 +0100
Subject: [PATCH 027/685] [CocoaPods] integration tests

---
 .travis.yml                              |  1 +
 CocoaPodsTests/.gitignore                |  1 +
 CocoaPodsTests/Gemfile                   |  4 ++
 CocoaPodsTests/Gemfile.lock              | 65 +++++++++++++++++
 CocoaPodsTests/Makefile                  | 10 +++
 CocoaPodsTests/integration_test.rb       | 33 +++++++++
 CocoaPodsTests/test_running_validator.rb | 91 ++++++++++++++++++++++++
 SQLiteTests/FTS4Tests.swift              |  4 +-
 8 files changed, 207 insertions(+), 2 deletions(-)
 create mode 100644 CocoaPodsTests/.gitignore
 create mode 100644 CocoaPodsTests/Gemfile
 create mode 100644 CocoaPodsTests/Gemfile.lock
 create mode 100644 CocoaPodsTests/Makefile
 create mode 100755 CocoaPodsTests/integration_test.rb
 create mode 100644 CocoaPodsTests/test_running_validator.rb

diff --git a/.travis.yml b/.travis.yml
index 1964faf9..ad0f18b9 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,4 +6,5 @@ before_install:
   - gem install xcpretty --no-document
 script:
   - make test
+  - cd CocoaPodsTests && make test
 osx_image: xcode7.3
diff --git a/CocoaPodsTests/.gitignore b/CocoaPodsTests/.gitignore
new file mode 100644
index 00000000..4cf24de2
--- /dev/null
+++ b/CocoaPodsTests/.gitignore
@@ -0,0 +1 @@
+gems/
diff --git a/CocoaPodsTests/Gemfile b/CocoaPodsTests/Gemfile
new file mode 100644
index 00000000..0a6af5c8
--- /dev/null
+++ b/CocoaPodsTests/Gemfile
@@ -0,0 +1,4 @@
+source 'https://rubygems.org'
+
+gem 'cocoapods'
+gem 'minitest'
diff --git a/CocoaPodsTests/Gemfile.lock b/CocoaPodsTests/Gemfile.lock
new file mode 100644
index 00000000..7173e2c4
--- /dev/null
+++ b/CocoaPodsTests/Gemfile.lock
@@ -0,0 +1,65 @@
+GEM
+  remote: https://rubygems.org/
+  specs:
+    activesupport (4.2.6)
+      i18n (~> 0.7)
+      json (~> 1.7, >= 1.7.7)
+      minitest (~> 5.1)
+      thread_safe (~> 0.3, >= 0.3.4)
+      tzinfo (~> 1.1)
+    claide (1.0.0)
+    cocoapods (1.0.0)
+      activesupport (>= 4.0.2)
+      claide (>= 1.0.0, < 2.0)
+      cocoapods-core (= 1.0.0)
+      cocoapods-deintegrate (>= 1.0.0, < 2.0)
+      cocoapods-downloader (>= 1.0.0, < 2.0)
+      cocoapods-plugins (>= 1.0.0, < 2.0)
+      cocoapods-search (>= 1.0.0, < 2.0)
+      cocoapods-stats (>= 1.0.0, < 2.0)
+      cocoapods-trunk (>= 1.0.0, < 2.0)
+      cocoapods-try (>= 1.0.0, < 2.0)
+      colored (~> 1.2)
+      escape (~> 0.0.4)
+      fourflusher (~> 0.3.0)
+      molinillo (~> 0.4.5)
+      nap (~> 1.0)
+      xcodeproj (>= 1.0.0, < 2.0)
+    cocoapods-core (1.0.0)
+      activesupport (>= 4.0.2)
+      fuzzy_match (~> 2.0.4)
+      nap (~> 1.0)
+    cocoapods-deintegrate (1.0.0)
+    cocoapods-downloader (1.0.0)
+    cocoapods-plugins (1.0.0)
+      nap
+    cocoapods-search (1.0.0)
+    cocoapods-stats (1.0.0)
+    cocoapods-trunk (1.0.0)
+      nap (>= 0.8, < 2.0)
+      netrc (= 0.7.8)
+    cocoapods-try (1.0.0)
+    colored (1.2)
+    escape (0.0.4)
+    fourflusher (0.3.0)
+    fuzzy_match (2.0.4)
+    i18n (0.7.0)
+    json (1.8.3)
+    minitest (5.8.4)
+    molinillo (0.4.5)
+    nap (1.1.0)
+    netrc (0.7.8)
+    thread_safe (0.3.5)
+    tzinfo (1.2.2)
+      thread_safe (~> 0.1)
+    xcodeproj (1.0.0)
+      activesupport (>= 3)
+      claide (>= 1.0.0, < 2.0)
+      colored (~> 1.2)
+
+PLATFORMS
+  ruby
+
+DEPENDENCIES
+  cocoapods
+  minitest
diff --git a/CocoaPodsTests/Makefile b/CocoaPodsTests/Makefile
new file mode 100644
index 00000000..c9a3182e
--- /dev/null
+++ b/CocoaPodsTests/Makefile
@@ -0,0 +1,10 @@
+test: install
+	@set -e; \
+	for test in *_test.rb; do \
+		bundle exec ./$$test; \
+	done
+
+install:
+	@bundle install --path gems
+
+.PHONY: test install
diff --git a/CocoaPodsTests/integration_test.rb b/CocoaPodsTests/integration_test.rb
new file mode 100755
index 00000000..325b8493
--- /dev/null
+++ b/CocoaPodsTests/integration_test.rb
@@ -0,0 +1,33 @@
+#!/usr/bin/env ruby
+
+require 'minitest/autorun'
+require_relative 'test_running_validator'
+
+class IntegrationTest < Minitest::Test
+
+  def test_validate_project
+    assert validator.validate, "validation failed: #{validator.failure_reason}"
+  end
+
+  private
+
+  def validator
+    @validator ||= TestRunningValidator.new(podspec, []).tap do |validator|
+        validator.test_files = Dir["#{project_test_dir}/*.swift"]
+        validator.config.verbose = true
+        validator.no_clean = true
+        validator.use_frameworks = true
+        validator.fail_fast = true
+        validator.local = true
+        validator.allow_warnings = true
+    end
+  end
+
+  def podspec
+    File.expand_path(File.dirname(__FILE__) + '/../SQLite.swift.podspec')
+  end
+
+  def project_test_dir
+    File.expand_path(File.dirname(__FILE__) + '/../SQLiteTests')
+  end
+end
diff --git a/CocoaPodsTests/test_running_validator.rb b/CocoaPodsTests/test_running_validator.rb
new file mode 100644
index 00000000..10f4db61
--- /dev/null
+++ b/CocoaPodsTests/test_running_validator.rb
@@ -0,0 +1,91 @@
+require 'cocoapods'
+require 'cocoapods/validator'
+require 'fileutils'
+
+class TestRunningValidator < Pod::Validator
+  APP_TARGET = 'App'
+  TEST_TARGET = 'Tests'
+
+  attr_accessor :test_files
+
+  def create_app_project
+    super.tap do
+      project = Xcodeproj::Project.open(validation_dir + "#{APP_TARGET}.xcodeproj")
+      create_test_target(project)
+    end
+  end
+
+  def install_pod
+    super.tap do
+      if local?
+        FileUtils.ln_s file.dirname, validation_dir + "Pods/#{spec.name}"
+      end
+    end
+  end
+
+  def podfile_from_spec(*args)
+    super(*args).tap do |pod_file|
+      add_test_target(pod_file)
+    end
+  end
+
+  def build_pod
+    super
+    Pod::UI.message "\Testing with xcodebuild.\n".yellow do
+      run_tests
+    end
+  end
+
+  private
+  def create_test_target(project)
+    test_target = project.new_target(:unit_test_bundle, TEST_TARGET, consumer.platform_name, deployment_target)
+    group = project.new_group(TEST_TARGET)
+    test_target.add_file_references(test_files.map { |file| group.new_file(file) })
+    project.save
+    create_test_scheme(project, test_target)
+    project
+  end
+
+  def create_test_scheme(project, test_target)
+    project.recreate_user_schemes
+    test_scheme = Xcodeproj::XCScheme.new(test_scheme_path(project))
+    test_scheme.add_test_target(test_target)
+    test_scheme.save!
+  end
+
+  def test_scheme_path(project)
+    Xcodeproj::XCScheme.user_data_dir(project.path) + "#{TEST_TARGET}.xcscheme"
+  end
+
+  def add_test_target(pod_file)
+    app_target = pod_file.target_definitions[APP_TARGET]
+    Pod::Podfile::TargetDefinition.new(TEST_TARGET, app_target)
+  end
+
+  def run_tests
+    command = %W(clean test -workspace #{APP_TARGET}.xcworkspace -scheme #{TEST_TARGET} -configuration Debug)
+    case consumer.platform_name
+    when :ios
+      command += %w(CODE_SIGN_IDENTITY=- -sdk iphonesimulator)
+      command += Fourflusher::SimControl.new.destination('iPhone 4s', deployment_target)
+    when :osx
+      command += %w(LD_RUNPATH_SEARCH_PATHS=@loader_path/../Frameworks)
+    when :tvos
+      command += %w(CODE_SIGN_IDENTITY=- -sdk appletvsimulator)
+      command += Fourflusher::SimControl.new.destination('Apple TV 1080p', deployment_target)
+    else
+      return # skip watchos
+    end
+
+    output, status = Dir.chdir(validation_dir) { _xcodebuild(command) }
+    unless status.success?
+      message = 'Returned an unsuccessful exit code.'
+      if config.verbose?
+        message += "\nXcode output: \n#{output}\n"
+      else
+        message += ' You can use `--verbose` for more information.'
+      end
+      error('xcodebuild', message)
+    end
+  end
+end
diff --git a/SQLiteTests/FTS4Tests.swift b/SQLiteTests/FTS4Tests.swift
index a94d9073..7f889955 100644
--- a/SQLiteTests/FTS4Tests.swift
+++ b/SQLiteTests/FTS4Tests.swift
@@ -45,7 +45,7 @@ class FTS4Tests : XCTestCase {
 }
 
 class FTS4IntegrationTests : SQLiteTestCase {
-
+#if !SQLITE_SWIFT_STANDALONE
     func test_registerTokenizer_registersTokenizer() {
         let emails = VirtualTable("emails")
         let subject = Expression<String?>("subject")
@@ -73,5 +73,5 @@ class FTS4IntegrationTests : SQLiteTestCase {
         try! db.run(emails.insert(subject <- "Aún más cáfe!"))
         XCTAssertEqual(1, db.scalar(emails.filter(emails.match("aun")).count))
     }
-
+#endif
 }

From 77a0f8ea116db5526702acf33b4ce4bb12c1ece0 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 19 May 2016 22:16:59 +0100
Subject: [PATCH 028/685] Full FTS4/5 configuration

---
 Documentation/Index.md           |  32 +++++
 SQLite.xcodeproj/project.pbxproj |  16 +++
 SQLite/Extensions/FTS4.swift     | 196 ++++++++++++++++++++++++++++++-
 SQLite/Extensions/FTS5.swift     |  97 +++++++++++++++
 SQLiteTests/FTS4Tests.swift      | 131 +++++++++++++++++++++
 SQLiteTests/FTS5Tests.swift      | 124 +++++++++++++++++++
 6 files changed, 590 insertions(+), 6 deletions(-)
 create mode 100644 SQLite/Extensions/FTS5.swift
 create mode 100644 SQLiteTests/FTS5Tests.swift

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 700deb9f..2c64fdad 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1399,6 +1399,22 @@ try db.run(emails.create(.FTS4([subject, body], tokenize: .Porter)))
 // CREATE VIRTUAL TABLE "emails" USING fts4("subject", "body", tokenize=porter)
 ```
 
+We can set the full range of parameters by creating a `FTS4Config` object.
+
+``` swift
+let emails = VirtualTable("emails")
+let subject = Expression<String>("subject")
+let body = Expression<String>("body")
+let config = FTS4Config()
+    .column(subject)
+    .column(body, indexed: false)
+    .languageId("lid")
+    .order(.Desc)
+
+try db.run(emails.create(.FTS4(config))
+// CREATE VIRTUAL TABLE "emails" USING fts4("subject", "body", notindexed="body", languageid="lid", order="desc")
+```
+
 Once we insert a few rows, we can search using the `match` function, which takes a table or column as its first argument and a query string as its second.
 
 ``` swift
@@ -1414,6 +1430,22 @@ let replies = emails.filter(subject.match("Re:*"))
 // SELECT * FROM "emails" WHERE "subject" MATCH 'Re:*'
 ```
 
+### FTS5
+
+When linking against a version of SQLite with [FTS5](http://www.sqlite.org/fts5.html) enabled we can create the virtual table
+in a similar fashion.
+
+```swift
+let emails = VirtualTable("emails")
+let subject = Expression<String>("subject")
+let body = Expression<String>("body")
+let config = FTS5Config()
+    .column(subject)
+    .column(body, indexed: false)
+
+try db.run(emails.create(.FTS5(config))
+// CREATE VIRTUAL TABLE "emails" USING fts5("subject", "body" UNINDEXED)
+```
 
 ## Executing Arbitrary SQL
 
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 786c2c77..88d74dc4 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -46,6 +46,12 @@
 		03A65E941C6BB3030062603F /* ValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B331C3F142E00AE3E12 /* ValueTests.swift */; };
 		03A65E951C6BB3030062603F /* TestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B161C3F127200AE3E12 /* TestHelpers.swift */; };
 		03A65E971C6BB3210062603F /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 03A65E961C6BB3210062603F /* libsqlite3.tbd */; };
+		19A1717B10CC941ACB5533D6 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
+		19A171E6FA242F72A308C594 /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
+		19A17254FBA7894891F7297B /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
+		19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
+		19A1750CEE9B05267995CF3D /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
+		19A17EC0D68BA8C03288ADF7 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
 		EE247AD71C3F04ED00AE3E12 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		EE247ADE1C3F04ED00AE3E12 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE247AD31C3F04ED00AE3E12 /* SQLite.framework */; };
 		EE247B031C3F06E900AE3E12 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
@@ -154,6 +160,8 @@
 		03A65E5A1C6BB0F50062603F /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		03A65E631C6BB0F60062603F /* SQLiteTests tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SQLiteTests tvOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
 		03A65E961C6BB3210062603F /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
+		19A1721B8984686B9963B45D /* FTS5Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5Tests.swift; sourceTree = "<group>"; };
+		19A1730E4390C775C25677D1 /* FTS5.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5.swift; sourceTree = "<group>"; };
 		39548A631CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
 		39548A651CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
 		39548A671CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
@@ -406,6 +414,7 @@
 				EE247B331C3F142E00AE3E12 /* ValueTests.swift */,
 				EE247B161C3F127200AE3E12 /* TestHelpers.swift */,
 				EE247AE41C3F04ED00AE3E12 /* Info.plist */,
+				19A1721B8984686B9963B45D /* FTS5Tests.swift */,
 			);
 			path = SQLiteTests;
 			sourceTree = "<group>";
@@ -429,6 +438,7 @@
 			children = (
 				EE247AF51C3F06E900AE3E12 /* FTS4.swift */,
 				EE247AF61C3F06E900AE3E12 /* R*Tree.swift */,
+				19A1730E4390C775C25677D1 /* FTS5.swift */,
 			);
 			path = Extensions;
 			sourceTree = "<group>";
@@ -786,6 +796,7 @@
 				03A65E7C1C6BB2F70062603F /* FTS4.swift in Sources */,
 				03A65E771C6BB2E60062603F /* Connection.swift in Sources */,
 				03A65E7E1C6BB2FB0062603F /* AggregateFunctions.swift in Sources */,
+				19A17EC0D68BA8C03288ADF7 /* FTS5.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -808,6 +819,7 @@
 				03A65E8C1C6BB3030062603F /* ExpressionTests.swift in Sources */,
 				03A65E8E1C6BB3030062603F /* OperatorsTests.swift in Sources */,
 				03A65E951C6BB3030062603F /* TestHelpers.swift in Sources */,
+				19A17254FBA7894891F7297B /* FTS5Tests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -840,6 +852,7 @@
 				EE247B061C3F06E900AE3E12 /* SQLite-Bridging.m in Sources */,
 				EE247B071C3F06E900AE3E12 /* Statement.swift in Sources */,
 				EE247B0D1C3F06E900AE3E12 /* AggregateFunctions.swift in Sources */,
+				19A1717B10CC941ACB5533D6 /* FTS5.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -862,6 +875,7 @@
 				EE247B221C3F137700AE3E12 /* AggregateFunctionsTests.swift in Sources */,
 				EE247B2E1C3F141E00AE3E12 /* OperatorsTests.swift in Sources */,
 				EE247B251C3F137700AE3E12 /* ConnectionTests.swift in Sources */,
+				19A171E6FA242F72A308C594 /* FTS5Tests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -887,6 +901,7 @@
 				EE247B6B1C3F3FEC00AE3E12 /* FTS4.swift in Sources */,
 				EE247B661C3F3FEC00AE3E12 /* Connection.swift in Sources */,
 				EE247B6D1C3F3FEC00AE3E12 /* AggregateFunctions.swift in Sources */,
+				19A1750CEE9B05267995CF3D /* FTS5.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -909,6 +924,7 @@
 				EE247B581C3F3FC700AE3E12 /* ExpressionTests.swift in Sources */,
 				EE247B5E1C3F3FC700AE3E12 /* SetterTests.swift in Sources */,
 				EE247B5B1C3F3FC700AE3E12 /* QueryTests.swift in Sources */,
+				19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/SQLite/Extensions/FTS4.swift b/SQLite/Extensions/FTS4.swift
index e5a1d815..fc71124a 100644
--- a/SQLite/Extensions/FTS4.swift
+++ b/SQLite/Extensions/FTS4.swift
@@ -29,14 +29,12 @@ extension Module {
     }
 
     @warn_unused_result public static func FTS4(columns: [Expressible] = [], tokenize tokenizer: Tokenizer? = nil) -> Module {
-        var columns = columns
-        
-        if let tokenizer = tokenizer {
-            columns.append("=".join([Expression<Void>(literal: "tokenize"), Expression<Void>(literal: tokenizer.description)]))
-        }
-        return Module(name: "fts4", arguments: columns)
+        return FTS4(FTS4Config().columns(columns).tokenizer(tokenizer))
     }
 
+    @warn_unused_result public static func FTS4(config: FTS4Config) -> Module {
+        return Module(name: "fts4", arguments: config.arguments())
+    }
 }
 
 extension VirtualTable {
@@ -156,3 +154,189 @@ extension Connection {
     }
 
 }
+
+/// Configuration options shared between the [FTS4](https://www.sqlite.org/fts3.html) and
+/// [FTS5](https://www.sqlite.org/fts5.html) extensions.
+public class FTSConfig {
+    typealias ColumnDefinition = (Expressible, Bool)
+    var columnDefinitions = [ColumnDefinition]()
+    var tokenizer: Tokenizer?
+    var prefixes = [Int]()
+    var externalContentSchema: SchemaType?
+    var isContentless: Bool = false
+
+    /// Adds an indexed column definition
+    public func column(column: Expressible) -> Self {
+        return self.column(column, indexed: true)
+    }
+
+    /// Adds a column definition
+    public func column(column: Expressible, indexed: Bool) -> Self {
+        self.columnDefinitions.append((column, indexed))
+        return self
+    }
+
+    public func columns(columns: [Expressible]) -> Self {
+        for column in columns {
+            self.column(column)
+        }
+        return self
+    }
+
+    /// [Tokenizers](https://www.sqlite.org/fts3.html#tokenizer)
+    public func tokenizer(tokenizer: Tokenizer?) -> Self {
+        self.tokenizer = tokenizer
+        return self
+    }
+
+    /// [The prefix= option](https://www.sqlite.org/fts3.html#section_6_6)
+    public func prefix(prefix: [Int]) -> Self {
+        self.prefixes += prefix
+        return self
+    }
+
+    /// [The content= option](https://www.sqlite.org/fts3.html#section_6_2)
+    public func externalContent(schema: SchemaType) -> Self {
+        self.externalContentSchema = schema
+        return self
+    }
+
+    /// [Contentless FTS4 Tables](https://www.sqlite.org/fts3.html#section_6_2_1)
+    public func contentless() -> Self {
+        self.isContentless = true
+        return self
+    }
+
+    func formatColumnDefinitions() -> [Expressible] {
+        return columnDefinitions.map { $0.0 }
+    }
+
+    func arguments() -> [Expressible] {
+        return options().arguments
+    }
+
+    func options() -> Options {
+        var options = Options()
+        options.append(formatColumnDefinitions())
+        if let tokenizer = tokenizer {
+            options.append("tokenize", value: Expression<Void>(literal: tokenizer.description))
+        }
+        options.appendCommaSeparated("prefix", values:prefixes.sort().map { String($0) })
+        if isContentless {
+            options.append("content", value: "")
+        } else if let externalContentSchema = externalContentSchema {
+            options.append("content", value: externalContentSchema.tableName())
+        }
+        return options
+    }
+
+    struct Options {
+        var arguments = [Expressible]()
+
+        mutating func append(columns: [Expressible]) -> Options {
+            arguments.appendContentsOf(columns)
+            return self
+        }
+
+        mutating func appendCommaSeparated(key: String, values: [String]) -> Options {
+            if values.isEmpty {
+                return self
+            } else {
+                return append(key, value: values.joinWithSeparator(","))
+            }
+        }
+
+        mutating func append(key: String, value: CustomStringConvertible?) -> Options {
+            return append(key, value: value?.description)
+        }
+
+        mutating func append(key: String, value: String?) -> Options {
+            return append(key, value: value.map { Expression<String>($0) })
+        }
+
+        mutating func append(key: String, value: Expressible?) -> Options {
+            if let value = value {
+                arguments.append("=".join([Expression<Void>(literal: key), value]))
+            }
+            return self
+        }
+    }
+}
+
+/// Configuration for the [FTS4](https://www.sqlite.org/fts3.html) extension.
+public class FTS4Config : FTSConfig {
+    /// [The matchinfo= option](https://www.sqlite.org/fts3.html#section_6_4)
+    public enum MatchInfo : CustomStringConvertible {
+        case FTS3
+        public var description: String {
+            return "fts3"
+        }
+    }
+
+    /// [FTS4 options](https://www.sqlite.org/fts3.html#fts4_options)
+    public enum Order : CustomStringConvertible {
+        /// Data structures are optimized for returning results in ascending order by docid (default)
+        case Asc
+        /// FTS4 stores its data in such a way as to optimize returning results in descending order by docid.
+        case Desc
+
+        public var description: String {
+            switch self {
+            case Asc: return "asc"
+            case Desc: return "desc"
+            }
+        }
+    }
+
+    var compressFunction: String?
+    var uncompressFunction: String?
+    var languageId: String?
+    var matchInfo: MatchInfo?
+    var order: Order?
+
+    override public init() {
+    }
+
+    /// [The compress= and uncompress= options](https://www.sqlite.org/fts3.html#section_6_1)
+    public func compress(functionName: String) -> Self {
+        self.compressFunction = functionName
+        return self
+    }
+
+    /// [The compress= and uncompress= options](https://www.sqlite.org/fts3.html#section_6_1)
+    public func uncompress(functionName: String) -> Self {
+        self.uncompressFunction = functionName
+        return self
+    }
+
+    /// [The languageid= option](https://www.sqlite.org/fts3.html#section_6_3)
+    public func languageId(columnName: String) -> Self {
+        self.languageId = columnName
+        return self
+    }
+
+    /// [The matchinfo= option](https://www.sqlite.org/fts3.html#section_6_4)
+    public func matchInfo(matchInfo: MatchInfo) -> Self {
+        self.matchInfo = matchInfo
+        return self
+    }
+
+    /// [FTS4 options](https://www.sqlite.org/fts3.html#fts4_options)
+    public func order(order: Order) -> Self {
+        self.order = order
+        return self
+    }
+
+    override func options() -> Options {
+        var options = super.options()
+        for notIndexedColumn in (columnDefinitions.filter { !$0.1 }.map { $0.0 }) {
+            options.append("notindexed", value: notIndexedColumn)
+        }
+        options.append("languageid", value: languageId)
+        options.append("compress", value: compressFunction)
+        options.append("uncompress", value: uncompressFunction)
+        options.append("matchinfo", value: matchInfo)
+        options.append("order", value: order)
+        return options
+    }
+}
diff --git a/SQLite/Extensions/FTS5.swift b/SQLite/Extensions/FTS5.swift
new file mode 100644
index 00000000..e7e21403
--- /dev/null
+++ b/SQLite/Extensions/FTS5.swift
@@ -0,0 +1,97 @@
+//
+// SQLite.swift
+// https://github.com/stephencelis/SQLite.swift
+// Copyright © 2014-2015 Stephen Celis.
+//
+// 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.
+//
+
+extension Module {
+    @warn_unused_result public static func FTS5(config: FTS5Config) -> Module {
+        return Module(name: "fts5", arguments: config.arguments())
+    }
+}
+
+/// Configuration for the [FTS5](https://www.sqlite.org/fts5.html) extension.
+///
+/// **Note:** this is currently only applicable when using SQLite.swift together with a FTS5-enabled version
+/// of SQLite.
+public class FTS5Config : FTSConfig {
+    public enum Detail : CustomStringConvertible {
+        /// store rowid, column number, term offset
+        case Full
+        /// store rowid, column number
+        case Column
+        /// store rowid
+        case None
+
+        public var description: String {
+            switch self {
+            case Full: return "full"
+            case Column: return "column"
+            case None: return "none"
+            }
+        }
+    }
+
+    var detail: Detail?
+    var contentRowId: Expressible?
+    var columnSize: Int?
+
+    override public init() {
+    }
+
+    /// [External Content Tables](https://www.sqlite.org/fts5.html#section_4_4_2)
+    public func contentRowId(column: Expressible) -> Self {
+        self.contentRowId = column
+        return self
+    }
+
+    /// [The Columnsize Option](https://www.sqlite.org/fts5.html#section_4_5)
+    public func columnSize(size: Int) -> Self {
+        self.columnSize = size
+        return self
+    }
+
+    /// [The Detail Option](https://www.sqlite.org/fts5.html#section_4_6)
+    public func detail(detail: Detail) -> Self {
+        self.detail = detail
+        return self
+    }
+
+    override func options() -> Options {
+        var options = super.options()
+        options.append("content_rowid", value: contentRowId)
+        if let columnSize = columnSize {
+            options.append("columnsize", value: Expression<Int>(value: columnSize))
+        }
+        options.append("detail", value: detail)
+        return options
+    }
+
+    override func formatColumnDefinitions() -> [Expressible] {
+        return columnDefinitions.map { definition in
+            if definition.1 {
+                return definition.0
+            } else {
+                return " ".join([definition.0, Expression<Void>(literal: "UNINDEXED")])
+            }
+        }
+    }
+}
diff --git a/SQLiteTests/FTS4Tests.swift b/SQLiteTests/FTS4Tests.swift
index 7f889955..ca46aa13 100644
--- a/SQLiteTests/FTS4Tests.swift
+++ b/SQLiteTests/FTS4Tests.swift
@@ -44,6 +44,137 @@ class FTS4Tests : XCTestCase {
 
 }
 
+class FTS4ConfigTests : XCTestCase {
+    var config: FTS4Config!
+
+    override func setUp() {
+        super.setUp()
+        config = FTS4Config()
+    }
+
+    func test_empty_config() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4()",
+            sql(config))
+    }
+
+    func test_config_column() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(\"string\")",
+            sql(config.column(string)))
+    }
+
+    func test_config_columns() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(\"string\", \"int\")",
+            sql(config.columns([string, int])))
+    }
+
+    func test_config_unindexed_column() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(\"string\", notindexed=\"string\")",
+            sql(config.column(string, indexed: false)))
+    }
+
+    func test_external_content_view() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(content=\"view\")",
+            sql(config.externalContent(_view )))
+    }
+
+    func test_external_content_virtual_table() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(content=\"virtual_table\")",
+            sql(config.externalContent(virtualTable)))
+    }
+
+    func test_tokenizer_simple() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(tokenize=simple)",
+            sql(config.tokenizer(.Simple)))
+    }
+
+    func test_tokenizer_porter() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(tokenize=porter)",
+            sql(config.tokenizer(.Porter)))
+    }
+
+    func test_tokenizer_unicode61() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(tokenize=unicode61)",
+            sql(config.tokenizer(.Unicode61())))
+    }
+
+    func test_tokenizer_unicode61_with_options() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(tokenize=unicode61 \"removeDiacritics=1\" \"tokenchars=.\" \"separators=X\")",
+            sql(config.tokenizer(.Unicode61(removeDiacritics: true, tokenchars: ["."], separators: ["X"]))))
+    }
+
+    func test_content_less() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(content=\"\")",
+            sql(config.contentless()))
+    }
+
+    func test_config_matchinfo() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(matchinfo=\"fts3\")",
+            sql(config.matchInfo(.FTS3)))
+    }
+
+    func test_config_order_asc() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(order=\"asc\")",
+            sql(config.order(.Asc)))
+    }
+
+    func test_config_order_desc() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(order=\"desc\")",
+            sql(config.order(.Desc)))
+    }
+
+    func test_config_compress() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(compress=\"compress_foo\")",
+            sql(config.compress("compress_foo")))
+    }
+
+    func test_config_uncompress() {
+        XCTAssertEqual(
+           "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(uncompress=\"uncompress_foo\")",
+            sql(config.uncompress("uncompress_foo")))
+    }
+
+    func test_config_languageId() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(languageid=\"lid\")",
+            sql(config.languageId("lid")))
+    }
+
+    func test_config_all() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(\"int\", \"string\", \"date\", tokenize=porter, prefix=\"2,4\", content=\"table\", notindexed=\"string\", notindexed=\"date\", languageid=\"lid\", matchinfo=\"fts3\", order=\"desc\")",
+            sql(config
+                .tokenizer(.Porter)
+                .column(int)
+                .column(string, indexed: false)
+                .column(date, indexed: false)
+                .externalContent(table)
+                .matchInfo(.FTS3)
+                .languageId("lid")
+                .order(.Desc)
+                .prefix([2, 4]))
+        )
+    }
+
+    func sql(config: FTS4Config) -> String {
+        return virtualTable.create(.FTS4(config))
+    }
+}
+
 class FTS4IntegrationTests : SQLiteTestCase {
 #if !SQLITE_SWIFT_STANDALONE
     func test_registerTokenizer_registersTokenizer() {
diff --git a/SQLiteTests/FTS5Tests.swift b/SQLiteTests/FTS5Tests.swift
new file mode 100644
index 00000000..c23b4726
--- /dev/null
+++ b/SQLiteTests/FTS5Tests.swift
@@ -0,0 +1,124 @@
+import XCTest
+import SQLite
+
+class FTS5Tests: XCTestCase {
+    var config: FTS5Config!
+
+    override func setUp() {
+        super.setUp()
+        config = FTS5Config()
+    }
+
+    func test_empty_config() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5()",
+            sql(config))
+    }
+
+    func test_config_column() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(\"string\")",
+            sql(config.column(string)))
+    }
+
+    func test_config_columns() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(\"string\", \"int\")",
+            sql(config.columns([string, int])))
+    }
+
+    func test_config_unindexed_column() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(\"string\" UNINDEXED)",
+            sql(config.column(string, indexed: false)))
+    }
+
+    func test_external_content_table() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(content=\"table\")",
+            sql(config.externalContent(table)))
+    }
+
+    func test_external_content_view() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(content=\"view\")",
+            sql(config.externalContent(_view)))
+    }
+
+    func test_external_content_virtual_table() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(content=\"virtual_table\")",
+            sql(config.externalContent(virtualTable)))
+    }
+
+    func test_content_less() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(content=\"\")",
+            sql(config.contentless()))
+    }
+
+    func test_content_rowid() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(content_rowid=\"string\")",
+            sql(config.contentRowId(string)))
+    }
+
+    func test_tokenizer_porter() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(tokenize=porter)",
+            sql(config.tokenizer(.Porter)))
+    }
+
+    func test_tokenizer_unicode61() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(tokenize=unicode61)",
+            sql(config.tokenizer(.Unicode61())))
+    }
+
+    func test_tokenizer_unicode61_with_options() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(tokenize=unicode61 \"removeDiacritics=1\" \"tokenchars=.\" \"separators=X\")",
+            sql(config.tokenizer(.Unicode61(removeDiacritics: true, tokenchars: ["."], separators: ["X"]))))
+    }
+
+    func test_column_size() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(columnsize=1)",
+            sql(config.columnSize(1)))
+    }
+
+    func test_detail_full() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(detail=\"full\")",
+            sql(config.detail(.Full)))
+    }
+
+    func test_detail_column() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(detail=\"column\")",
+            sql(config.detail(.Column)))
+    }
+
+    func test_detail_none() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(detail=\"none\")",
+            sql(config.detail(.None)))
+    }
+
+    func test_fts5_config_all() {
+        XCTAssertEqual(
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(\"int\", \"string\" UNINDEXED, \"date\" UNINDEXED, tokenize=porter, prefix=\"2,4\", content=\"table\")",
+            sql(config
+                .tokenizer(.Porter)
+                .column(int)
+                .column(string, indexed: false)
+                .column(date, indexed: false)
+                .externalContent(table)
+                .prefix([2, 4]))
+        )
+    }
+
+    func sql(config: FTS5Config) -> String {
+        return virtualTable.create(.FTS5(config))
+    }
+}

From f4b9bc619b8cf9c2f670e3fdba5813cacceda224 Mon Sep 17 00:00:00 2001
From: Pascal Pfiffner <phase.of.matter@gmail.com>
Date: Wed, 25 May 2016 17:50:57 +0200
Subject: [PATCH 029/685] Add missing imports

---
 SQLite/Core/Connection.swift     | 1 +
 SQLite/Typed/CoreFunctions.swift | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index f4be7983..f83ab812 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -22,6 +22,7 @@
 // THE SOFTWARE.
 //
 
+import Foundation
 import Dispatch
 #if SQLITE_SWIFT_STANDALONE
 import sqlite3
diff --git a/SQLite/Typed/CoreFunctions.swift b/SQLite/Typed/CoreFunctions.swift
index b929e40a..5332556d 100644
--- a/SQLite/Typed/CoreFunctions.swift
+++ b/SQLite/Typed/CoreFunctions.swift
@@ -22,6 +22,9 @@
 // THE SOFTWARE.
 //
 
+import Foundation
+
+
 extension ExpressionType where UnderlyingType : Number {
 
     /// Builds a copy of the expression wrapped with the `abs` function.

From fa5626e90441e40ed1d6358db9745c0ba463d4de Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 28 May 2016 11:41:43 +0100
Subject: [PATCH 030/685] Change column config to `.column(body, [.unindexed])`
 syntax

---
 Documentation/Index.md       |  2 +-
 SQLite/Extensions/FTS4.swift | 20 ++++++++++----------
 SQLite/Extensions/FTS5.swift |  6 +++---
 SQLiteTests/FTS4Tests.swift  |  6 +++---
 SQLiteTests/FTS5Tests.swift  |  6 +++---
 5 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 2c64fdad..41e1c382 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1407,7 +1407,7 @@ let subject = Expression<String>("subject")
 let body = Expression<String>("body")
 let config = FTS4Config()
     .column(subject)
-    .column(body, indexed: false)
+    .column(body, [.unindexed])
     .languageId("lid")
     .order(.Desc)
 
diff --git a/SQLite/Extensions/FTS4.swift b/SQLite/Extensions/FTS4.swift
index fc71124a..466c42c7 100644
--- a/SQLite/Extensions/FTS4.swift
+++ b/SQLite/Extensions/FTS4.swift
@@ -158,21 +158,21 @@ extension Connection {
 /// Configuration options shared between the [FTS4](https://www.sqlite.org/fts3.html) and
 /// [FTS5](https://www.sqlite.org/fts5.html) extensions.
 public class FTSConfig {
-    typealias ColumnDefinition = (Expressible, Bool)
+    public enum ColumnOption {
+        /// [The notindexed= option](https://www.sqlite.org/fts3.html#section_6_5)
+        case unindexed
+    }
+
+    typealias ColumnDefinition = (Expressible, options: [ColumnOption])
     var columnDefinitions = [ColumnDefinition]()
     var tokenizer: Tokenizer?
     var prefixes = [Int]()
     var externalContentSchema: SchemaType?
     var isContentless: Bool = false
 
-    /// Adds an indexed column definition
-    public func column(column: Expressible) -> Self {
-        return self.column(column, indexed: true)
-    }
-
     /// Adds a column definition
-    public func column(column: Expressible, indexed: Bool) -> Self {
-        self.columnDefinitions.append((column, indexed))
+    public func column(column: Expressible, _ options: [ColumnOption] = []) -> Self {
+        self.columnDefinitions.append((column, options))
         return self
     }
 
@@ -329,8 +329,8 @@ public class FTS4Config : FTSConfig {
 
     override func options() -> Options {
         var options = super.options()
-        for notIndexedColumn in (columnDefinitions.filter { !$0.1 }.map { $0.0 }) {
-            options.append("notindexed", value: notIndexedColumn)
+        for (column, _) in (columnDefinitions.filter { $0.options.contains(.unindexed) }) {
+            options.append("notindexed", value: column)
         }
         options.append("languageid", value: languageId)
         options.append("compress", value: compressFunction)
diff --git a/SQLite/Extensions/FTS5.swift b/SQLite/Extensions/FTS5.swift
index e7e21403..97056819 100644
--- a/SQLite/Extensions/FTS5.swift
+++ b/SQLite/Extensions/FTS5.swift
@@ -87,10 +87,10 @@ public class FTS5Config : FTSConfig {
 
     override func formatColumnDefinitions() -> [Expressible] {
         return columnDefinitions.map { definition in
-            if definition.1 {
-                return definition.0
-            } else {
+            if definition.options.contains(.unindexed) {
                 return " ".join([definition.0, Expression<Void>(literal: "UNINDEXED")])
+            } else {
+                return definition.0
             }
         }
     }
diff --git a/SQLiteTests/FTS4Tests.swift b/SQLiteTests/FTS4Tests.swift
index ca46aa13..c1071972 100644
--- a/SQLiteTests/FTS4Tests.swift
+++ b/SQLiteTests/FTS4Tests.swift
@@ -73,7 +73,7 @@ class FTS4ConfigTests : XCTestCase {
     func test_config_unindexed_column() {
         XCTAssertEqual(
             "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(\"string\", notindexed=\"string\")",
-            sql(config.column(string, indexed: false)))
+            sql(config.column(string, [.unindexed])))
     }
 
     func test_external_content_view() {
@@ -160,8 +160,8 @@ class FTS4ConfigTests : XCTestCase {
             sql(config
                 .tokenizer(.Porter)
                 .column(int)
-                .column(string, indexed: false)
-                .column(date, indexed: false)
+                .column(string, [.unindexed])
+                .column(date, [.unindexed])
                 .externalContent(table)
                 .matchInfo(.FTS3)
                 .languageId("lid")
diff --git a/SQLiteTests/FTS5Tests.swift b/SQLiteTests/FTS5Tests.swift
index c23b4726..aa3965bd 100644
--- a/SQLiteTests/FTS5Tests.swift
+++ b/SQLiteTests/FTS5Tests.swift
@@ -30,7 +30,7 @@ class FTS5Tests: XCTestCase {
     func test_config_unindexed_column() {
         XCTAssertEqual(
             "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(\"string\" UNINDEXED)",
-            sql(config.column(string, indexed: false)))
+            sql(config.column(string, [.unindexed])))
     }
 
     func test_external_content_table() {
@@ -111,8 +111,8 @@ class FTS5Tests: XCTestCase {
             sql(config
                 .tokenizer(.Porter)
                 .column(int)
-                .column(string, indexed: false)
-                .column(date, indexed: false)
+                .column(string, [.unindexed])
+                .column(date, [.unindexed])
                 .externalContent(table)
                 .prefix([2, 4]))
         )

From b3a7e6c5815ad3d0979006a12c67800f6bc34444 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 28 May 2016 21:49:58 +0100
Subject: [PATCH 031/685] Update documentation

---
 Documentation/Index.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 41e1c382..0579e6f3 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1441,7 +1441,7 @@ let subject = Expression<String>("subject")
 let body = Expression<String>("body")
 let config = FTS5Config()
     .column(subject)
-    .column(body, indexed: false)
+    .column(body, [.unindexed])
 
 try db.run(emails.create(.FTS5(config))
 // CREATE VIRTUAL TABLE "emails" USING fts5("subject", "body" UNINDEXED)

From 341ecec8eb6fab7a26fc0b414b5c23d341154d11 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 30 May 2016 10:32:35 +0100
Subject: [PATCH 032/685] Add GRDB to list of alternatives

---
 README.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/README.md b/README.md
index 56d4374d..242567f0 100644
--- a/README.md
+++ b/README.md
@@ -231,6 +231,7 @@ Looking for something else? Try another Swift wrapper (or [FMDB][]):
 
  - [Camembert](https://github.com/remirobert/Camembert)
  - [EonilSQLite3](https://github.com/Eonil/SQLite3)
+ - [GRDB](https://github.com/groue/GRDB.swift)
  - [SQLiteDB](https://github.com/FahimF/SQLiteDB)
  - [Squeal](https://github.com/nerdyc/Squeal)
  - [SwiftData](https://github.com/ryanfowler/SwiftData)

From c85fe382d67dc664a0675edb601d377364a4e740 Mon Sep 17 00:00:00 2001
From: FrainL <frainl@vip.qq.com>
Date: Mon, 30 May 2016 22:54:15 +0800
Subject: [PATCH 033/685] prevent from crash when lastInsertRowId is negative

---
 SQLite/Core/Connection.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index f4be7983..85817025 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -107,7 +107,7 @@ public final class Connection {
     /// The last rowid inserted into the database via this connection.
     public var lastInsertRowid: Int64? {
         let rowid = sqlite3_last_insert_rowid(handle)
-        return rowid > 0 ? rowid : nil
+        return rowid != 0 ? rowid : nil
     }
 
     /// The last number of changes (inserts, updates, or deletes) made to the

From f52bdc2fa499636d090d29aa4f88c5f5b0498399 Mon Sep 17 00:00:00 2001
From: Stephen Celis <stephen@stephencelis.com>
Date: Wed, 1 Jun 2016 15:26:09 -0400
Subject: [PATCH 034/685] Remove stale recommendation

Will re-add if updated for a modern version of Swift.

Signed-off-by: Stephen Celis <stephen@stephencelis.com>
---
 README.md | 1 -
 1 file changed, 1 deletion(-)

diff --git a/README.md b/README.md
index 242567f0..850d3374 100644
--- a/README.md
+++ b/README.md
@@ -230,7 +230,6 @@ These projects enhance or use SQLite.swift:
 Looking for something else? Try another Swift wrapper (or [FMDB][]):
 
  - [Camembert](https://github.com/remirobert/Camembert)
- - [EonilSQLite3](https://github.com/Eonil/SQLite3)
  - [GRDB](https://github.com/groue/GRDB.swift)
  - [SQLiteDB](https://github.com/FahimF/SQLiteDB)
  - [Squeal](https://github.com/nerdyc/Squeal)

From ee06b9661af3097cb9e7de3bfeecefe0a0b1ee5a Mon Sep 17 00:00:00 2001
From: Pascal Pfiffner <phase.of.matter@gmail.com>
Date: Mon, 13 Jun 2016 08:59:09 +0200
Subject: [PATCH 035/685] More precise Foundation imports

---
 SQLite/Core/Connection.swift     | 2 +-
 SQLite/Typed/CoreFunctions.swift | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index f83ab812..58c5a7ab 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -22,7 +22,7 @@
 // THE SOFTWARE.
 //
 
-import Foundation
+import Foundation.NSUUID
 import Dispatch
 #if SQLITE_SWIFT_STANDALONE
 import sqlite3
diff --git a/SQLite/Typed/CoreFunctions.swift b/SQLite/Typed/CoreFunctions.swift
index 5332556d..b597f3ba 100644
--- a/SQLite/Typed/CoreFunctions.swift
+++ b/SQLite/Typed/CoreFunctions.swift
@@ -22,7 +22,7 @@
 // THE SOFTWARE.
 //
 
-import Foundation
+import Foundation.NSData
 
 
 extension ExpressionType where UnderlyingType : Number {

From 960309eb02724ae0f18f721942fb22473bb4b602 Mon Sep 17 00:00:00 2001
From: Nick Shelley <nickmshelley@gmail.com>
Date: Thu, 16 Jun 2016 15:48:36 -0600
Subject: [PATCH 036/685] Implement connection limit.

---
 SQLite/Core/ConnectionPool.swift      | 55 +++++++++++++--------------
 SQLiteTests/ConnectionPoolTests.swift | 21 +++++-----
 2 files changed, 37 insertions(+), 39 deletions(-)

diff --git a/SQLite/Core/ConnectionPool.swift b/SQLite/Core/ConnectionPool.swift
index dd644304..77cf047e 100644
--- a/SQLite/Core/ConnectionPool.swift
+++ b/SQLite/Core/ConnectionPool.swift
@@ -39,6 +39,7 @@ public final class ConnectionPool {
     private var unavailableReadConnections = [DirectConnection]()
     private let lockQueue : dispatch_queue_t
     private var writeConnection : DirectConnection!
+    private let connectionSemaphore = dispatch_semaphore_create(5)
     
     public var foreignKeys : Bool {
         get {
@@ -91,6 +92,7 @@ public final class ConnectionPool {
                     self.pool.unavailableReadConnections.removeAtIndex(index)
                 }
                 self.pool.availableReadConnections.append(self.connection)
+                dispatch_semaphore_signal(self.pool.connectionSemaphore)
             }
         }
 
@@ -151,44 +153,41 @@ public final class ConnectionPool {
         
         var borrowed : BorrowedConnection!
         
-        repeat {
+        dispatch_semaphore_wait(connectionSemaphore, DISPATCH_TIME_FOREVER)
+        dispatch_sync(lockQueue) {
             
-            dispatch_sync(lockQueue) {
-                
-                // Ensure database is open
-                self.writable
+            // Ensure database is open
+            self.writable
+            
+            let connection : DirectConnection
+            
+            if let availableConnection = self.availableReadConnections.popLast() {
+                connection = availableConnection
+            }
+            else {
                 
-                let connection : DirectConnection
+                let flags = SQLITE_OPEN_READONLY | SQLITE_OPEN_WAL | SQLITE_OPEN_NOMUTEX
                 
-                if let availableConnection = self.availableReadConnections.popLast() {
-                    connection = availableConnection
-                }
-                else {
-        
-                    let flags = SQLITE_OPEN_READONLY | SQLITE_OPEN_WAL | SQLITE_OPEN_NOMUTEX
-                    
-                    connection = try! DirectConnection(self.location, flags: flags, dispatcher: ImmediateDispatcher(), vfsName: vfsName)
-                    connection.busyTimeout = 2
+                connection = try! DirectConnection(self.location, flags: flags, dispatcher: ImmediateDispatcher(), vfsName: vfsName)
+                connection.busyTimeout = 2
                 
-                    for (type, setupProcessor) in self.internalSetup {
-                        if type == .WriteAheadLogging {
-                            continue
-                        }
-                        try! setupProcessor(connection)
-                    }
-                    
-                    for setupProcessor in self.setup {
-                        try! setupProcessor(connection)
+                for (type, setupProcessor) in self.internalSetup {
+                    if type == .WriteAheadLogging {
+                        continue
                     }
-                    
+                    try! setupProcessor(connection)
                 }
                 
-                self.unavailableReadConnections.append(connection)
+                for setupProcessor in self.setup {
+                    try! setupProcessor(connection)
+                }
                 
-                borrowed = BorrowedConnection(pool: self, connection: connection)
             }
             
-        } while borrowed == nil
+            self.unavailableReadConnections.append(connection)
+            
+            borrowed = BorrowedConnection(pool: self, connection: connection)
+        }
         
         return borrowed
     }
diff --git a/SQLiteTests/ConnectionPoolTests.swift b/SQLiteTests/ConnectionPoolTests.swift
index 74351527..b7f15171 100644
--- a/SQLiteTests/ConnectionPoolTests.swift
+++ b/SQLiteTests/ConnectionPoolTests.swift
@@ -22,33 +22,32 @@ class ConnectionPoolTests : SQLiteTestCase {
 
     func testConcurrentAccess2() {
         
+        let threadCount = 20
         let conn = pool.writable
         try! conn.execute("DROP TABLE IF EXISTS test; CREATE TABLE test(id INTEGER PRIMARY KEY, name TEXT);")
         try! conn.execute("DELETE FROM test")
-        try! conn.execute("INSERT INTO test(id,name) VALUES(0, 'test0')")
-        try! conn.execute("INSERT INTO test(id,name) VALUES(1, 'test1')")
-        try! conn.execute("INSERT INTO test(id,name) VALUES(2, 'test2')")
-        try! conn.execute("INSERT INTO test(id,name) VALUES(3, 'test3')")
-        try! conn.execute("INSERT INTO test(id,name) VALUES(4, 'test4')")
+        for threadNumber in 0..<threadCount {
+            try! conn.execute("INSERT INTO test(id,name) VALUES(\(threadNumber), 'test\(threadNumber)')")
+        }
         
         var quit = false
         let queue = dispatch_queue_create("Readers", DISPATCH_QUEUE_CONCURRENT)
-        for x in 0..<5 {
+        for threadNumber in 0..<threadCount {
             var reads = 0
 
-            let ex = expectationWithDescription("thread" + String(x))
+            let ex = expectationWithDescription("thread" + String(threadNumber))
             
             dispatch_async(queue) {
                 
-                print("started", x)
+                print("started", threadNumber)
 
                 let conn = self.pool.readable
                 
                 let stmt = try! conn.prepare("SELECT name FROM test WHERE id = ?")
-                var curr = stmt.scalar(x) as! String
+                var curr = stmt.scalar(threadNumber) as! String
                 while !quit {
                     
-                    let now = stmt.scalar(x) as! String
+                    let now = stmt.scalar(threadNumber) as! String
                     if now != curr {
                         //print(now)
                         curr = now
@@ -90,7 +89,7 @@ class ConnectionPoolTests : SQLiteTestCase {
         let q = dispatch_queue_create("Readers/Writers", DISPATCH_QUEUE_CONCURRENT);
         var finished = false
         
-        for _ in 0..<5 {
+        for _ in 0..<20 {
             
             dispatch_async(q) {
                 

From 6052c31e79efedd42b15a838e819fbd313218663 Mon Sep 17 00:00:00 2001
From: Nick Shelley <nickmshelley@gmail.com>
Date: Wed, 22 Jun 2016 12:37:10 -0600
Subject: [PATCH 037/685] Fix import problem for standalone.

---
 SQLite/Core/ConnectionPool.swift | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/SQLite/Core/ConnectionPool.swift b/SQLite/Core/ConnectionPool.swift
index 77cf047e..3f4a01f4 100644
--- a/SQLite/Core/ConnectionPool.swift
+++ b/SQLite/Core/ConnectionPool.swift
@@ -23,7 +23,11 @@
 //
 
 import Dispatch
-import CSQLite
+#if SQLITE_SWIFT_STANDALONE
+    import sqlite3
+#else
+    import CSQLite
+#endif
 
 
 private let vfsName = "unix-excl"

From e32db0905f244a46a4c61957e6c69bf856c7b155 Mon Sep 17 00:00:00 2001
From: Nick Shelley <nickmshelley@gmail.com>
Date: Wed, 22 Jun 2016 16:04:46 -0600
Subject: [PATCH 038/685] Shorten testConcurrentAccess2 time as it is making
 the travis tests take too long.

---
 SQLiteTests/ConnectionPoolTests.swift | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/SQLiteTests/ConnectionPoolTests.swift b/SQLiteTests/ConnectionPoolTests.swift
index b7f15171..301f0482 100644
--- a/SQLiteTests/ConnectionPoolTests.swift
+++ b/SQLiteTests/ConnectionPoolTests.swift
@@ -62,10 +62,10 @@ class ConnectionPoolTests : SQLiteTestCase {
             
         }
         
-        for x in 10..<5000 {
+        for x in 10..<1000 {
             
             let name = "test" + String(x)
-            let idx = Int(rand()) % 5
+            let idx = Int(rand()) % threadCount
             
             do {
                 try conn.run("UPDATE test SET name=? WHERE id=?", name, idx)

From 2fd69b87211c10428e75dbc6cdbce647ff866194 Mon Sep 17 00:00:00 2001
From: Nick Shelley <nickmshelley@gmail.com>
Date: Thu, 23 Jun 2016 08:59:13 -0600
Subject: [PATCH 039/685] Tests are still taking too long.

---
 SQLite/Core/ConnectionPool.swift      | 4 ++--
 SQLiteTests/ConnectionPoolTests.swift | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/SQLite/Core/ConnectionPool.swift b/SQLite/Core/ConnectionPool.swift
index 3f4a01f4..1e6a4b44 100644
--- a/SQLite/Core/ConnectionPool.swift
+++ b/SQLite/Core/ConnectionPool.swift
@@ -24,9 +24,9 @@
 
 import Dispatch
 #if SQLITE_SWIFT_STANDALONE
-    import sqlite3
+import sqlite3
 #else
-    import CSQLite
+import CSQLite
 #endif
 
 
diff --git a/SQLiteTests/ConnectionPoolTests.swift b/SQLiteTests/ConnectionPoolTests.swift
index 301f0482..190b70a0 100644
--- a/SQLiteTests/ConnectionPoolTests.swift
+++ b/SQLiteTests/ConnectionPoolTests.swift
@@ -62,7 +62,7 @@ class ConnectionPoolTests : SQLiteTestCase {
             
         }
         
-        for x in 10..<1000 {
+        for x in 10..<100 {
             
             let name = "test" + String(x)
             let idx = Int(rand()) % threadCount

From 9bf4c06c184281c3c02c7118d5049d3b25364467 Mon Sep 17 00:00:00 2001
From: Nick Shelley <nickmshelley@gmail.com>
Date: Thu, 23 Jun 2016 14:09:03 -0600
Subject: [PATCH 040/685] Closes #457: Split up tests into more Travis jobs.

---
 .travis.yml                        | 13 ++++++++-----
 CocoaPodsTests/integration_test.rb |  6 ++++++
 run-tests.sh                       |  7 +++++++
 3 files changed, 21 insertions(+), 5 deletions(-)
 create mode 100644 run-tests.sh

diff --git a/.travis.yml b/.travis.yml
index ad0f18b9..b33f9af3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,10 +1,13 @@
 language: objective-c
-env:
-  - BUILD_SCHEME="SQLite iOS"
-  - BUILD_SCHEME="SQLite Mac"
+matrix:
+  include:
+    - env: BUILD_SCHEME="SQLite iOS"
+    - env: BUILD_SCHEME="SQLite Mac"
+    - env: VALIDATOR_SUBSPEC="none"
+    - env: VALIDATOR_SUBSPEC="standard"
+    - env: VALIDATOR_SUBSPEC="standalone"
 before_install:
   - gem install xcpretty --no-document
 script:
-  - make test
-  - cd CocoaPodsTests && make test
+  - ./run-tests.sh
 osx_image: xcode7.3
diff --git a/CocoaPodsTests/integration_test.rb b/CocoaPodsTests/integration_test.rb
index 325b8493..429a9c77 100755
--- a/CocoaPodsTests/integration_test.rb
+++ b/CocoaPodsTests/integration_test.rb
@@ -13,6 +13,7 @@ def test_validate_project
 
   def validator
     @validator ||= TestRunningValidator.new(podspec, []).tap do |validator|
+    	subspec = ENV["VALIDATOR_SUBSPEC"]
         validator.test_files = Dir["#{project_test_dir}/*.swift"]
         validator.config.verbose = true
         validator.no_clean = true
@@ -20,6 +21,11 @@ def validator
         validator.fail_fast = true
         validator.local = true
         validator.allow_warnings = true
+        if subspec == "none"
+          validator.no_subspecs = true
+        else
+          validator.only_subspec = subspec
+        end
     end
   end
 
diff --git a/run-tests.sh b/run-tests.sh
new file mode 100644
index 00000000..244828bf
--- /dev/null
+++ b/run-tests.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+set -ev
+if [ -n "$BUILD_SCHEME" ]; then
+    make test
+elif [ -n "$VALIDATOR_SUBSPEC" ]; then
+    cd CocoaPodsTests && make test
+fi 
\ No newline at end of file

From 38dd7e52cc50beb3521f3a2c77a98632040f6d26 Mon Sep 17 00:00:00 2001
From: Nick Shelley <nickmshelley@gmail.com>
Date: Thu, 23 Jun 2016 14:23:04 -0600
Subject: [PATCH 041/685] Make run-tests.sh executable.

---
 run-tests.sh | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 mode change 100644 => 100755 run-tests.sh

diff --git a/run-tests.sh b/run-tests.sh
old mode 100644
new mode 100755

From 6759aad915b5bfc39f9b6f733785690ab69ef5e0 Mon Sep 17 00:00:00 2001
From: Nick Shelley <nickmshelley@gmail.com>
Date: Thu, 23 Jun 2016 15:05:00 -0600
Subject: [PATCH 042/685] Run desired unit tests instead of only Mac.

---
 Makefile | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile
index 5a452b87..b6d844c6 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,9 @@
 BUILD_TOOL = xcodebuild
-BUILD_SCHEME = SQLite Mac
-BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)"
+ifeq ($(BUILD_SCHEME),SQLite iOS)
+	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -sdk iphonesimulator
+else
+	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)"
+endif
 
 XCPRETTY := $(shell command -v xcpretty)
 SWIFTCOV := $(shell command -v swiftcov)

From 0de26029a753713669775a21204fc18d30d3f845 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 10 Jul 2016 09:58:42 +0200
Subject: [PATCH 043/685] Makefile: re-add scheme default

---
 Makefile     | 1 +
 run-tests.sh | 4 ++--
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile
index b6d844c6..7257b9b1 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,5 @@
 BUILD_TOOL = xcodebuild
+BUILD_SCHEME = SQLite Mac
 ifeq ($(BUILD_SCHEME),SQLite iOS)
 	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -sdk iphonesimulator
 else
diff --git a/run-tests.sh b/run-tests.sh
index 244828bf..7a35fb02 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -1,7 +1,7 @@
 #!/bin/bash
 set -ev
 if [ -n "$BUILD_SCHEME" ]; then
-    make test
+    make test BUILD_SCHEME="$BUILD_SCHEME"
 elif [ -n "$VALIDATOR_SUBSPEC" ]; then
     cd CocoaPodsTests && make test
-fi 
\ No newline at end of file
+fi

From 403077f94f884dadc40f4f99deedb8cdaaba1ba0 Mon Sep 17 00:00:00 2001
From: tasanobu <tasanobu@gmail.com>
Date: Sat, 16 Jul 2016 11:52:17 +0900
Subject: [PATCH 044/685] Fix the error handling in Query.pluck()

---
 SQLite/Typed/Query.swift | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/SQLite/Typed/Query.swift b/SQLite/Typed/Query.swift
index e45034ca..b81c3372 100644
--- a/SQLite/Typed/Query.swift
+++ b/SQLite/Typed/Query.swift
@@ -955,7 +955,10 @@ extension Connection {
     }
 
     public func pluck(query: QueryType) -> Row? {
-        return try! prepare(query.limit(1, query.clauses.limit?.offset)).generate().next()
+        guard let rows = try? prepare(query.limit(1, query.clauses.limit?.offset)) else {
+            return nil
+        }
+        return rows.generate().next()
     }
 
     /// Runs an `Insert` query.

From a688d1841f3d88e49a122221c9de309b467965b7 Mon Sep 17 00:00:00 2001
From: Nick Shelley <nickmshelley@gmail.com>
Date: Mon, 18 Jul 2016 14:26:48 -0600
Subject: [PATCH 045/685] Clean up some spacing.

---
 SQLite/Core/Connection.swift     |  8 ++--
 SQLite/Core/ConnectionPool.swift | 26 +++++-----
 SQLite/Core/Dispatcher.swift     | 82 +++++++++++++++++++-------------
 SQLite/Typed/Query.swift         |  1 -
 4 files changed, 66 insertions(+), 51 deletions(-)

diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index 5071c7ae..f66fb064 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -50,14 +50,14 @@ public enum TransactionMode : String {
 public protocol Connection {
     
     /// Whether or not the database was opened in a read-only state.
-    var readonly : Bool { get }
+    var readonly: Bool { get }
     
     /// The last rowid inserted into the database via this connection.
-    var lastInsertRowid : Int64? { get }
+    var lastInsertRowid: Int64? { get }
     
     /// The last number of changes (inserts, updates, or deletes) made to the
     /// database via this connection.
-    var changes : Int { get }
+    var changes: Int { get }
     
     /// The total number of changes (inserts, updates, or deletes) made to the
     /// database via this connection.
@@ -808,7 +808,7 @@ public final class DirectConnection : Connection, Equatable {
         throw error
     }
   
-    private var dispatcher : Dispatcher
+    private var dispatcher: Dispatcher
 
 }
 
diff --git a/SQLite/Core/ConnectionPool.swift b/SQLite/Core/ConnectionPool.swift
index 1e6a4b44..035c706a 100644
--- a/SQLite/Core/ConnectionPool.swift
+++ b/SQLite/Core/ConnectionPool.swift
@@ -38,11 +38,11 @@ private let vfsName = "unix-excl"
 // WAL mode.
 public final class ConnectionPool {
 
-    private let location : DirectConnection.Location
+    private let location: DirectConnection.Location
     private var availableReadConnections = [DirectConnection]()
     private var unavailableReadConnections = [DirectConnection]()
-    private let lockQueue : dispatch_queue_t
-    private var writeConnection : DirectConnection!
+    private let lockQueue: dispatch_queue_t
+    private var writeConnection: DirectConnection!
     private let connectionSemaphore = dispatch_semaphore_create(5)
     
     public var foreignKeys : Bool {
@@ -82,8 +82,8 @@ public final class ConnectionPool {
     // to the pool when it goes out of scope
     private class BorrowedConnection : Connection, Equatable {
         
-        let pool : ConnectionPool
-        let connection : DirectConnection
+        let pool: ConnectionPool
+        let connection: DirectConnection
         
         init(pool: ConnectionPool, connection: DirectConnection) {
             self.pool = pool
@@ -100,10 +100,10 @@ public final class ConnectionPool {
             }
         }
 
-        var readonly : Bool { return connection.readonly }
-        var lastInsertRowid : Int64? { return connection.lastInsertRowid }
-        var changes : Int { return connection.changes }
-        var totalChanges : Int { return connection.totalChanges }
+        var readonly: Bool { return connection.readonly }
+        var lastInsertRowid: Int64? { return connection.lastInsertRowid }
+        var changes: Int { return connection.changes }
+        var totalChanges: Int { return connection.totalChanges }
         
         func execute(SQL: String) throws { return try connection.execute(SQL) }
         @warn_unused_result func prepare(statement: String, _ bindings: Binding?...) throws -> Statement { return try connection.prepare(statement, bindings) }
@@ -131,7 +131,7 @@ public final class ConnectionPool {
     
     var writeConnectionInit = dispatch_once_t()
     
-    public var writable : DirectConnection {
+    public var writable: DirectConnection {
 
         dispatch_once(&writeConnectionInit) {
         
@@ -153,9 +153,9 @@ public final class ConnectionPool {
     }
     
     // Acquires a read only connection to the database
-    public var readable : Connection {
+    public var readable: Connection {
         
-        var borrowed : BorrowedConnection!
+        var borrowed: BorrowedConnection!
         
         dispatch_semaphore_wait(connectionSemaphore, DISPATCH_TIME_FOREVER)
         dispatch_sync(lockQueue) {
@@ -163,7 +163,7 @@ public final class ConnectionPool {
             // Ensure database is open
             self.writable
             
-            let connection : DirectConnection
+            let connection: DirectConnection
             
             if let availableConnection = self.availableReadConnections.popLast() {
                 connection = availableConnection
diff --git a/SQLite/Core/Dispatcher.swift b/SQLite/Core/Dispatcher.swift
index b5010488..f6cff005 100644
--- a/SQLite/Core/Dispatcher.swift
+++ b/SQLite/Core/Dispatcher.swift
@@ -1,9 +1,25 @@
 //
-//  Dispatcher.swift
-//  SQLite
+// SQLite.swift
+// https://github.com/stephencelis/SQLite.swift
+// Copyright © 2014-2015 Stephen Celis.
 //
-//  Created by Kevin Wooten on 11/28/15.
-//  Copyright © 2015 stephencelis. 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.
 //
 
 import Foundation
@@ -11,45 +27,45 @@ import Foundation
 
 /// Block dispatch method
 public protocol Dispatcher {
-
-  /// Dispatches the provided block
-  func dispatch(block: dispatch_block_t)
-  
+    
+    /// Dispatches the provided block
+    func dispatch(block: dispatch_block_t)
+    
 }
 
 
 /// Dispatches block immediately on current thread
 public final class ImmediateDispatcher : Dispatcher {
-  
-  public func dispatch(block: dispatch_block_t) {
-    block()
-  }
-  
+    
+    public func dispatch(block: dispatch_block_t) {
+        block()
+    }
+    
 }
 
 
 /// Synchronously dispatches block on a serial
 /// queue. Specifically allows reentrant calls
 public final class ReentrantDispatcher : Dispatcher {
-  
-  static let queueKey = unsafeBitCast(ReentrantDispatcher.self, UnsafePointer<Void>.self)
-  
-  let queue : dispatch_queue_t
-  
-  let queueContext : UnsafeMutablePointer<Void>!
-  
-  public init(_ name: String) {
-    queue = dispatch_queue_create(name, DISPATCH_QUEUE_SERIAL)
-    queueContext = unsafeBitCast(queue, UnsafeMutablePointer<Void>.self)
-    dispatch_queue_set_specific(queue, ReentrantDispatcher.queueKey, queueContext, nil)
-  }
-  
-  public func dispatch(block: dispatch_block_t) {
-    if dispatch_get_specific(ReentrantDispatcher.queueKey) == self.queueContext {
-      block()
-    } else {
-      dispatch_sync(self.queue, block) // FIXME: rdar://problem/21389236
+    
+    static let queueKey = unsafeBitCast(ReentrantDispatcher.self, UnsafePointer<Void>.self)
+    
+    let queue : dispatch_queue_t
+    
+    let queueContext : UnsafeMutablePointer<Void>
+    
+    public init(_ name: String) {
+        queue = dispatch_queue_create(name, DISPATCH_QUEUE_SERIAL)
+        queueContext = unsafeBitCast(queue, UnsafeMutablePointer<Void>.self)
+        dispatch_queue_set_specific(queue, ReentrantDispatcher.queueKey, queueContext, nil)
+    }
+    
+    public func dispatch(block: dispatch_block_t) {
+        if dispatch_get_specific(ReentrantDispatcher.queueKey) == self.queueContext {
+            block()
+        } else {
+            dispatch_sync(self.queue, block) // FIXME: rdar://problem/21389236
+        }
     }
-  }
-  
+    
 }
diff --git a/SQLite/Typed/Query.swift b/SQLite/Typed/Query.swift
index 9f966250..30a57337 100644
--- a/SQLite/Typed/Query.swift
+++ b/SQLite/Typed/Query.swift
@@ -1051,7 +1051,6 @@ public struct Row {
     }
 
     // FIXME: rdar://problem/18673897 // subscript<T>…
-    
     public subscript(column: Expression<Blob>) -> Blob {
         return get(column)
     }

From a1121c42101483fd469f393eb63420e083e7cd60 Mon Sep 17 00:00:00 2001
From: Nick Shelley <nickmshelley@gmail.com>
Date: Mon, 18 Jul 2016 16:06:18 -0600
Subject: [PATCH 046/685] Change ConnectionPool API and get rid of Connection
 protocol.

---
 SQLite/Core/Connection.swift          | 215 ++------------------------
 SQLite/Core/ConnectionPool.swift      | 114 +++++++-------
 SQLite/Core/Statement.swift           |   4 +-
 SQLite/Extensions/FTS4.swift          |   2 +-
 SQLite/Typed/CustomFunctions.swift    |   2 +-
 SQLiteTests/ConnectionPoolTests.swift | 131 +++++++++++-----
 SQLiteTests/ConnectionTests.swift     |  12 +-
 SQLiteTests/TestHelpers.swift         |   2 +-
 8 files changed, 168 insertions(+), 314 deletions(-)

diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index f66fb064..d594a4f5 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -46,193 +46,8 @@ public enum TransactionMode : String {
 }
 
 
-/// Protocol to an SQLite connection
-public protocol Connection {
-    
-    /// Whether or not the database was opened in a read-only state.
-    var readonly: Bool { get }
-    
-    /// The last rowid inserted into the database via this connection.
-    var lastInsertRowid: Int64? { get }
-    
-    /// The last number of changes (inserts, updates, or deletes) made to the
-    /// database via this connection.
-    var changes: Int { get }
-    
-    /// The total number of changes (inserts, updates, or deletes) made to the
-    /// database via this connection.
-    var totalChanges : Int { get }
-    
-    // MARK: - Execute
-    
-    /// Executes a batch of SQL statements.
-    ///
-    /// - Parameter SQL: A batch of zero or more semicolon-separated SQL
-    ///   statements.
-    ///
-    /// - Throws: `Result.Error` if query execution fails.
-    func execute(SQL: String) throws
-    
-    // MARK: - Prepare
-    
-    /// Prepares a single SQL statement (with optional parameter bindings).
-    ///
-    /// - Parameters:
-    ///
-    ///   - statement: A single SQL statement.
-    ///
-    ///   - bindings: A list of parameters to bind to the statement.
-    ///
-    /// - Returns: A prepared statement.
-    @warn_unused_result func prepare(statement: String, _ bindings: Binding?...) throws -> Statement
-
-    /// Prepares a single SQL statement and binds parameters to it.
-    ///
-    /// - Parameters:
-    ///
-    ///   - statement: A single SQL statement.
-    ///
-    ///   - bindings: A list of parameters to bind to the statement.
-    ///
-    /// - Returns: A prepared statement.
-    @warn_unused_result func prepare(statement: String, _ bindings: [Binding?]) throws -> Statement
-
-    /// Prepares a single SQL statement and binds parameters to it.
-    ///
-    /// - Parameters:
-    ///
-    ///   - statement: A single SQL statement.
-    ///
-    ///   - bindings: A dictionary of named parameters to bind to the statement.
-    ///
-    /// - Returns: A prepared statement.
-    @warn_unused_result func prepare(statement: String, _ bindings: [String: Binding?]) throws -> Statement
-    
-    // MARK: - Run
-    
-    /// Runs a single SQL statement (with optional parameter bindings).
-    ///
-    /// - Parameters:
-    ///
-    ///   - statement: A single SQL statement.
-    ///
-    ///   - bindings: A list of parameters to bind to the statement.
-    ///
-    /// - Throws: `Result.Error` if query execution fails.
-    ///
-    /// - Returns: The statement.
-    func run(statement: String, _ bindings: Binding?...) throws -> Statement
-
-    /// Prepares, binds, and runs a single SQL statement.
-    ///
-    /// - Parameters:
-    ///
-    ///   - statement: A single SQL statement.
-    ///
-    ///   - bindings: A list of parameters to bind to the statement.
-    ///
-    /// - Throws: `Result.Error` if query execution fails.
-    ///
-    /// - Returns: The statement.
-    func run(statement: String, _ bindings: [Binding?]) throws -> Statement
-
-    /// Prepares, binds, and runs a single SQL statement.
-    ///
-    /// - Parameters:
-    ///
-    ///   - statement: A single SQL statement.
-    ///
-    ///   - bindings: A dictionary of named parameters to bind to the statement.
-    ///
-    /// - Throws: `Result.Error` if query execution fails.
-    ///
-    /// - Returns: The statement.
-    func run(statement: String, _ bindings: [String: Binding?]) throws -> Statement
-
-    // MARK: - Scalar
-    
-    /// Runs a single SQL statement (with optional parameter bindings),
-    /// returning the first value of the first row.
-    ///
-    /// - Parameters:
-    ///
-    ///   - statement: A single SQL statement.
-    ///
-    ///   - bindings: A list of parameters to bind to the statement.
-    ///
-    /// - Returns: The first value of the first row returned.
-    @warn_unused_result func scalar(statement: String, _ bindings: Binding?...) -> Binding?
-
-    /// Runs a single SQL statement (with optional parameter bindings),
-    /// returning the first value of the first row.
-    ///
-    /// - Parameters:
-    ///
-    ///   - statement: A single SQL statement.
-    ///
-    ///   - bindings: A list of parameters to bind to the statement.
-    ///
-    /// - Returns: The first value of the first row returned.
-    @warn_unused_result func scalar(statement: String, _ bindings: [Binding?]) -> Binding?
-
-    /// Runs a single SQL statement (with optional parameter bindings),
-    /// returning the first value of the first row.
-    ///
-    /// - Parameters:
-    ///
-    ///   - statement: A single SQL statement.
-    ///
-    ///   - bindings: A dictionary of named parameters to bind to the statement.
-    ///
-    /// - Returns: The first value of the first row returned.
-    @warn_unused_result func scalar(statement: String, _ bindings: [String: Binding?]) -> Binding?
-
-    // MARK: - Transactions
-    
-    // TODO: Consider not requiring a throw to roll back?
-    /// Runs a transaction with the given mode.
-    ///
-    /// - Note: Transactions cannot be nested. To nest transactions, see
-    ///   `savepoint()`, instead.
-    ///
-    /// - Parameters:
-    ///
-    ///   - mode: The mode in which a transaction acquires a lock.
-    ///
-    ///     Default: `.Deferred`
-    ///
-    ///   - block: A closure to run SQL statements within the transaction.
-    ///     The transaction will be committed when the block returns. The block
-    ///     must throw to roll the transaction back.
-    ///
-    /// - Throws: `Result.Error`, and rethrows.
-    func transaction(mode: TransactionMode, block: (Connection) throws -> Void) throws
-    
-    // TODO: Consider not requiring a throw to roll back?
-    // TODO: Consider removing ability to set a name?
-    /// Runs a transaction with the given savepoint name (if omitted, it will
-    /// generate a UUID).
-    ///
-    /// - SeeAlso: `transaction()`.
-    ///
-    /// - Parameters:
-    ///
-    ///   - savepointName: A unique identifier for the savepoint (optional).
-    ///
-    ///   - block: A closure to run SQL statements within the transaction.
-    ///     The savepoint will be released (committed) when the block returns.
-    ///     The block must throw to roll the savepoint back.
-    ///
-    /// - Throws: `SQLite.Result.Error`, and rethrows.
-    func savepoint(name: String, block: (Connection) throws -> Void) throws
-    
-    func sync<T>(block: () throws -> T) rethrows -> T
-
-}
-
-
 /// A connection to SQLite.
-public final class DirectConnection : Connection, Equatable {
+public final class Connection : Equatable {
 
     /// The location of a SQLite database.
     public enum Location {
@@ -273,24 +88,12 @@ public final class DirectConnection : Connection, Equatable {
     ///     Default: `false`.
     ///
     /// - Returns: A new database connection.
-    public convenience init(_ location: Location = .InMemory, readonly: Bool = false, vfsName: String? = nil) throws {
+    public convenience init(_ location: Location = .InMemory, readonly: Bool = false) throws {
         let flags = readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE
-        try self.init(location, flags: flags, dispatcher: ReentrantDispatcher("SQLite.Connection"), vfsName: vfsName)
+        try self.init(location, flags: flags, dispatcher: ReentrantDispatcher("SQLite.Connection"), vfsName: nil)
     }
-  
-    /// Initializes a new SQLite connection.
-    ///
-    /// - Parameters:
-    ///
-    ///   - location: The location of the database. Creates a new database if it
-    ///     doesn’t already exist (unless in read-only mode).
-    ///
-    ///   - flags: SQLite open flags
-    ///
-    ///   - dispatcher: Dispatcher synchronization blocks
-    ///
-    /// - Returns: A new database connection.
-    public init(_ location: Location, flags: Int32, dispatcher: Dispatcher, vfsName: String? = nil) throws {
+    
+    init(_ location: Location, flags: Int32, dispatcher: Dispatcher, vfsName: String? = nil) throws {
         self.dispatcher = dispatcher
         if let vfsName = vfsName {
             try check(sqlite3_open_v2(location.description, &_handle, flags, vfsName))
@@ -812,7 +615,7 @@ public final class DirectConnection : Connection, Equatable {
 
 }
 
-extension DirectConnection : CustomStringConvertible {
+extension Connection : CustomStringConvertible {
 
     public var description: String {
         return String.fromCString(sqlite3_db_filename(handle, nil))!
@@ -820,7 +623,7 @@ extension DirectConnection : CustomStringConvertible {
 
 }
 
-extension DirectConnection.Location : CustomStringConvertible {
+extension Connection.Location : CustomStringConvertible {
 
     public var description: String {
         switch self {
@@ -835,7 +638,7 @@ extension DirectConnection.Location : CustomStringConvertible {
 
 }
 
-public func ==(lhs: DirectConnection, rhs: DirectConnection) -> Bool {
+public func == (lhs: Connection, rhs: Connection) -> Bool {
     return lhs === rhs
 }
 
@@ -872,7 +675,7 @@ public enum Result : ErrorType {
 
     case Error(message: String, code: Int32, statement: Statement?)
 
-    init?(errorCode: Int32, connection: DirectConnection, statement: Statement? = nil) {
+    init?(errorCode: Int32, connection: Connection, statement: Statement? = nil) {
         guard !Result.successCodes.contains(errorCode) else { return nil }
 
         let message = String.fromCString(sqlite3_errmsg(connection.handle))!
diff --git a/SQLite/Core/ConnectionPool.swift b/SQLite/Core/ConnectionPool.swift
index 035c706a..91c3e366 100644
--- a/SQLite/Core/ConnectionPool.swift
+++ b/SQLite/Core/ConnectionPool.swift
@@ -38,11 +38,11 @@ private let vfsName = "unix-excl"
 // WAL mode.
 public final class ConnectionPool {
 
-    private let location: DirectConnection.Location
-    private var availableReadConnections = [DirectConnection]()
-    private var unavailableReadConnections = [DirectConnection]()
+    private let location: Connection.Location
+    private var availableReadConnections = [Connection]()
+    private var unavailableReadConnections = [Connection]()
     private let lockQueue: dispatch_queue_t
-    private var writeConnection: DirectConnection!
+    private var writeConnection: Connection!
     private let connectionSemaphore = dispatch_semaphore_create(5)
     
     public var foreignKeys : Bool {
@@ -64,12 +64,38 @@ public final class ConnectionPool {
     
     private var internalSetup = [InternalOption: ConnectionProcessor]()
     
-    public init(_ location: DirectConnection.Location) throws {
+    /// Initializes a new SQLite connection pool.
+    ///
+    /// - Parameters:
+    ///
+    ///   - location: The location of the database. Creates a new database if it
+    ///     doesn’t already exist.
+    ///
+    ///     Default: `.InMemory`.
+    ///
+    /// - Throws: `Result.Error` iff a connection cannot be established.
+    ///
+    /// - Returns: A new connection pool.
+    public init(_ location: Connection.Location = .InMemory) throws {
         self.location = location
         self.lockQueue = dispatch_queue_create("SQLite.ConnectionPool.Lock", DISPATCH_QUEUE_SERIAL)
         self.internalSetup[.WriteAheadLogging] = { try $0.execute("PRAGMA journal_mode = WAL;") }
     }
     
+    /// Initializes a new connection to a database.
+    ///
+    /// - Parameters:
+    ///
+    ///   - filename: The location of the database. Creates a new database if
+    ///     it doesn’t already exist (unless in read-only mode).
+    ///
+    /// - Throws: `Result.Error` iff a connection cannot be established.
+    ///
+    /// - Returns: A new database connection pool.
+    public convenience init(_ filename: String) throws {
+        try self.init(.URI(filename))
+    }
+    
     public var totalReadableConnectionCount : Int {
         return availableReadConnections.count + unavailableReadConnections.count
     }
@@ -78,65 +104,36 @@ public final class ConnectionPool {
         return availableReadConnections.count
     }
     
-    // Connection that automatically returns itself
-    // to the pool when it goes out of scope
-    private class BorrowedConnection : Connection, Equatable {
-        
-        let pool: ConnectionPool
-        let connection: DirectConnection
-        
-        init(pool: ConnectionPool, connection: DirectConnection) {
-            self.pool = pool
-            self.connection = connection
-        }
+    /// Calls `readBlock` with an available read connection from the connection pool,
+    /// after which the connection is made available again.
+    public func read(readBlock: (connection: Connection) -> Void) {
+        let connection = readable
+        readBlock(connection: connection)
         
-        deinit {
-            dispatch_sync(pool.lockQueue) {
-                if let index = self.pool.unavailableReadConnections.indexOf(self.connection) {
-                    self.pool.unavailableReadConnections.removeAtIndex(index)
-                }
-                self.pool.availableReadConnections.append(self.connection)
-                dispatch_semaphore_signal(self.pool.connectionSemaphore)
+        dispatch_sync(lockQueue) {
+            if let index = self.unavailableReadConnections.indexOf(connection) {
+                self.unavailableReadConnections.removeAtIndex(index)
             }
+            self.availableReadConnections.append(connection)
+            dispatch_semaphore_signal(self.connectionSemaphore)
         }
-
-        var readonly: Bool { return connection.readonly }
-        var lastInsertRowid: Int64? { return connection.lastInsertRowid }
-        var changes: Int { return connection.changes }
-        var totalChanges: Int { return connection.totalChanges }
-        
-        func execute(SQL: String) throws { return try connection.execute(SQL) }
-        @warn_unused_result func prepare(statement: String, _ bindings: Binding?...) throws -> Statement { return try connection.prepare(statement, bindings) }
-        @warn_unused_result func prepare(statement: String, _ bindings: [Binding?]) throws -> Statement { return try connection.prepare(statement, bindings) }
-        @warn_unused_result func prepare(statement: String, _ bindings: [String: Binding?]) throws -> Statement { return try connection.prepare(statement, bindings) }
-        
-        func run(statement: String, _ bindings: Binding?...) throws -> Statement { return try connection.run(statement, bindings) }
-        func run(statement: String, _ bindings: [Binding?]) throws -> Statement { return try connection.run(statement, bindings) }
-        func run(statement: String, _ bindings: [String: Binding?]) throws -> Statement { return try connection.run(statement, bindings) }
-        
-        @warn_unused_result func scalar(statement: String, _ bindings: Binding?...) -> Binding? { return connection.scalar(statement, bindings) }
-        @warn_unused_result func scalar(statement: String, _ bindings: [Binding?]) -> Binding? { return connection.scalar(statement, bindings) }
-        @warn_unused_result func scalar(statement: String, _ bindings: [String: Binding?]) -> Binding? { return connection.scalar(statement, bindings) }
-        
-        func transaction(mode: TransactionMode, block: (Connection) throws -> Void) throws { return try connection.transaction(mode, block: block) }
-        func savepoint(name: String, block: (Connection) throws -> Void) throws { return try connection.savepoint(name, block: block) }
-
-        func sync<T>(block: () throws -> T) rethrows -> T { return try connection.sync(block) }
-        func check(resultCode: Int32, statement: Statement? = nil) throws -> Int32 { return try connection.check(resultCode, statement: statement) }
-        
     }
     
+    /// Calls `readWriteBlock` with a writeable connection
+    public func readWrite(readWriteBlock: (connection: Connection) -> Void) {
+        let connection = writable
+        readWriteBlock(connection: connection)
+    }
     
     // Acquires a read/write connection to the database
-    
     var writeConnectionInit = dispatch_once_t()
     
-    public var writable: DirectConnection {
+    private var writable: Connection {
 
         dispatch_once(&writeConnectionInit) {
         
             let flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_WAL | SQLITE_OPEN_NOMUTEX
-            self.writeConnection = try! DirectConnection(self.location, flags: flags, dispatcher: ReentrantDispatcher("SQLite.ConnectionPool.Write"), vfsName: vfsName)
+            self.writeConnection = try! Connection(self.location, flags: flags, dispatcher: ReentrantDispatcher("SQLite.ConnectionPool.Write"), vfsName: vfsName)
             self.writeConnection.busyTimeout = 2
             
             for setupProcessor in self.internalSetup.values {
@@ -153,9 +150,9 @@ public final class ConnectionPool {
     }
     
     // Acquires a read only connection to the database
-    public var readable: Connection {
+    private var readable: Connection {
         
-        var borrowed: BorrowedConnection!
+        var borrowed: Connection!
         
         dispatch_semaphore_wait(connectionSemaphore, DISPATCH_TIME_FOREVER)
         dispatch_sync(lockQueue) {
@@ -163,7 +160,7 @@ public final class ConnectionPool {
             // Ensure database is open
             self.writable
             
-            let connection: DirectConnection
+            let connection: Connection
             
             if let availableConnection = self.availableReadConnections.popLast() {
                 connection = availableConnection
@@ -172,7 +169,7 @@ public final class ConnectionPool {
                 
                 let flags = SQLITE_OPEN_READONLY | SQLITE_OPEN_WAL | SQLITE_OPEN_NOMUTEX
                 
-                connection = try! DirectConnection(self.location, flags: flags, dispatcher: ImmediateDispatcher(), vfsName: vfsName)
+                connection = try! Connection(self.location, flags: flags, dispatcher: ImmediateDispatcher(), vfsName: vfsName)
                 connection.busyTimeout = 2
                 
                 for (type, setupProcessor) in self.internalSetup {
@@ -190,15 +187,10 @@ public final class ConnectionPool {
             
             self.unavailableReadConnections.append(connection)
             
-            borrowed = BorrowedConnection(pool: self, connection: connection)
+            borrowed = connection
         }
         
         return borrowed
     }
     
 }
-
-    
-private func ==(lhs: ConnectionPool.BorrowedConnection, rhs: ConnectionPool.BorrowedConnection) -> Bool {
-    return lhs.connection == rhs.connection
-}
diff --git a/SQLite/Core/Statement.swift b/SQLite/Core/Statement.swift
index 876eab0f..9a4bfa1e 100644
--- a/SQLite/Core/Statement.swift
+++ b/SQLite/Core/Statement.swift
@@ -33,9 +33,9 @@ public final class Statement {
 
     private var handle: COpaquePointer = nil
 
-    private let connection: DirectConnection
+    private let connection: Connection
 
-    init(_ connection: DirectConnection, _ SQL: String) throws {
+    init(_ connection: Connection, _ SQL: String) throws {
         self.connection = connection
         try connection.check(sqlite3_prepare_v2(connection.handle, SQL, -1, &handle, nil))
     }
diff --git a/SQLite/Extensions/FTS4.swift b/SQLite/Extensions/FTS4.swift
index 7224cde9..466c42c7 100644
--- a/SQLite/Extensions/FTS4.swift
+++ b/SQLite/Extensions/FTS4.swift
@@ -138,7 +138,7 @@ extension Tokenizer : CustomStringConvertible {
 
 }
 
-extension DirectConnection {
+extension Connection {
 
     public func registerTokenizer(submoduleName: String, next: String -> (String, Range<String.Index>)?) throws {
         try check(_SQLiteRegisterTokenizer(handle, Tokenizer.moduleName, submoduleName) { input, offset, length in
diff --git a/SQLite/Typed/CustomFunctions.swift b/SQLite/Typed/CustomFunctions.swift
index d004f75e..068d0340 100644
--- a/SQLite/Typed/CustomFunctions.swift
+++ b/SQLite/Typed/CustomFunctions.swift
@@ -22,7 +22,7 @@
 // THE SOFTWARE.
 //
 
-public extension DirectConnection {
+public extension Connection {
 
     /// Creates or redefines a custom SQL function.
     ///
diff --git a/SQLiteTests/ConnectionPoolTests.swift b/SQLiteTests/ConnectionPoolTests.swift
index 190b70a0..14632713 100644
--- a/SQLiteTests/ConnectionPoolTests.swift
+++ b/SQLiteTests/ConnectionPoolTests.swift
@@ -7,54 +7,55 @@ class ConnectionPoolTests : SQLiteTestCase {
     
     override func setUp() {
         let _ = try? NSFileManager.defaultManager().removeItemAtPath("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite")
-        pool = try! ConnectionPool(.URI("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite"))
+        pool = try! ConnectionPool("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite")
     }
     
     func testConnectionSetupClosures() {
         
         pool.foreignKeys = true
         pool.setup.append { try $0.execute("CREATE TABLE IF NOT EXISTS test(value INT)") }
+        pool.read { conn in
+            XCTAssertTrue(conn.scalar("PRAGMA foreign_keys") as! Int64 == 1)
+        }
+        
+        pool.readWrite { conn in
+            try! conn.execute("INSERT INTO test(value) VALUES (1)")
+            try! conn.execute("SELECT value FROM test")
+        }
         
-        XCTAssertTrue(pool.readable.scalar("PRAGMA foreign_keys") as! Int64 == 1)
-        try! pool.writable.execute("INSERT INTO test(value) VALUES (1)")
-        try! pool.readable.execute("SELECT value FROM test")
     }
 
     func testConcurrentAccess2() {
         
         let threadCount = 20
-        let conn = pool.writable
-        try! conn.execute("DROP TABLE IF EXISTS test; CREATE TABLE test(id INTEGER PRIMARY KEY, name TEXT);")
-        try! conn.execute("DELETE FROM test")
-        for threadNumber in 0..<threadCount {
-            try! conn.execute("INSERT INTO test(id,name) VALUES(\(threadNumber), 'test\(threadNumber)')")
+        pool.readWrite { conn in
+            try! conn.execute("DROP TABLE IF EXISTS test; CREATE TABLE test(id INTEGER PRIMARY KEY, name TEXT);")
+            try! conn.execute("DELETE FROM test")
+            for threadNumber in 0..<threadCount {
+                try! conn.execute("INSERT INTO test(id,name) VALUES(\(threadNumber), 'test\(threadNumber)')")
+            }
         }
         
+        
         var quit = false
         let queue = dispatch_queue_create("Readers", DISPATCH_QUEUE_CONCURRENT)
         for threadNumber in 0..<threadCount {
             var reads = 0
-
+            
             let ex = expectationWithDescription("thread" + String(threadNumber))
             
             dispatch_async(queue) {
                 
                 print("started", threadNumber)
-
-                let conn = self.pool.readable
                 
-                let stmt = try! conn.prepare("SELECT name FROM test WHERE id = ?")
-                var curr = stmt.scalar(threadNumber) as! String
                 while !quit {
-                    
-                    let now = stmt.scalar(threadNumber) as! String
-                    if now != curr {
-                        //print(now)
-                        curr = now
+                    self.pool.read { conn in
+                        let _ = try! conn.prepare("SELECT name FROM test WHERE id = ?").scalar(threadNumber) as! String
+                        reads += 1
                     }
-                    reads += 1
                 }
                 
+                XCTAssertTrue(reads > 0, "Thread \(threadNumber) did not read.")
                 print("ended at", reads, "reads")
                 
                 ex.fulfill()
@@ -67,11 +68,13 @@ class ConnectionPoolTests : SQLiteTestCase {
             let name = "test" + String(x)
             let idx = Int(rand()) % threadCount
             
-            do {
-                try conn.run("UPDATE test SET name=? WHERE id=?", name, idx)
-            }
-            catch let error {
-                XCTFail((error as? CustomStringConvertible)?.description ?? "Unknown")
+            pool.readWrite { conn in
+                do {
+                    try conn.run("UPDATE test SET name=? WHERE id=?", name, idx)
+                }
+                catch let error {
+                    XCTFail((error as? CustomStringConvertible)?.description ?? "Unknown")
+                }
             }
             
             usleep(500)
@@ -82,9 +85,10 @@ class ConnectionPoolTests : SQLiteTestCase {
     }
     
     func testConcurrentAccess() throws {
-        
-        try! pool.writable.execute("DROP TABLE IF EXISTS test; CREATE TABLE test(value);")
-        try! pool.writable.run("INSERT INTO test(value) VALUES(?)", 0)
+        pool.readWrite { conn in
+            try! conn.execute("DROP TABLE IF EXISTS test; CREATE TABLE test(value);")
+            try! conn.run("INSERT INTO test(value) VALUES(?)", 0)
+        }
         
         let q = dispatch_queue_create("Readers/Writers", DISPATCH_QUEUE_CONCURRENT);
         var finished = false
@@ -94,10 +98,11 @@ class ConnectionPoolTests : SQLiteTestCase {
             dispatch_async(q) {
                 
                 while !finished {
-                    
-                    let val = self.pool.readable.scalar("SELECT value FROM test")
+                    var val: Binding?
+                    self.pool.read { conn in
+                        val = conn.scalar("SELECT value FROM test")
+                    }
                     assert(val != nil, "DB query returned nil result set")
-                    
                 }
                 
             }
@@ -105,8 +110,9 @@ class ConnectionPoolTests : SQLiteTestCase {
         }
         
         for c in 0..<5000 {
-            
-            try pool.writable.run("INSERT INTO test(value) VALUES(?)", c)
+            pool.readWrite { conn in
+                try! conn.run("INSERT INTO test(value) VALUES(?)", c)
+            }
             
             usleep(100);
             
@@ -120,10 +126,63 @@ class ConnectionPoolTests : SQLiteTestCase {
         
     }
     
-    func testAutoRelease() {
+    func testMultiplePools() {
+        let pool2 = try! ConnectionPool("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite")
+        pool.readWrite { conn in
+            try! conn.execute("DROP TABLE IF EXISTS test; CREATE TABLE test(value);")
+            try! conn.run("INSERT INTO test(value) VALUES(?)", 0)
+        }
+        
+        let q = dispatch_queue_create("Readers/Writers", DISPATCH_QUEUE_CONCURRENT);
+        var finished = false
         
-        do {
-            try! pool.readable.execute("SELECT 1")
+        for _ in 0..<20 {
+            dispatch_async(q) {
+                while !finished {
+                    var val: Binding?
+                    self.pool.read { conn in
+                        val = conn.scalar("SELECT value FROM test")
+                    }
+                    assert(val != nil, "DB query returned nil result set")
+                }
+            }
+        }
+        
+        for _ in 0..<20 {
+            dispatch_async(q) {
+                while !finished {
+                    var val: Binding?
+                    pool2.read { conn in
+                        val = conn.scalar("SELECT value FROM test")
+                    }
+                    assert(val != nil, "DB query returned nil result set")
+                }
+            }
+        }
+        
+        for c in 0..<5000 {
+            pool.readWrite { conn in
+                try! conn.run("INSERT INTO test(value) VALUES(?)", c)
+            }
+            
+            pool2.readWrite { conn in
+                try! conn.run("INSERT INTO test(value) VALUES(?)", c + 5000)
+            }
+            
+            usleep(100);
+        }
+        
+        finished = true
+        
+        // Wait for readers to finish
+        dispatch_barrier_sync(q) {
+        }
+        
+    }
+    
+    func testAutoRelease() {
+        pool.read { conn in
+            try! conn.execute("SELECT 1")
         }
         
         XCTAssertEqual(pool.totalReadableConnectionCount, pool.availableReadableConnectionCount)
diff --git a/SQLiteTests/ConnectionTests.swift b/SQLiteTests/ConnectionTests.swift
index bbad19a8..62203362 100644
--- a/SQLiteTests/ConnectionTests.swift
+++ b/SQLiteTests/ConnectionTests.swift
@@ -10,27 +10,27 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_init_withInMemory_returnsInMemoryConnection() {
-        let db = try! DirectConnection(.InMemory)
+        let db = try! Connection(.InMemory)
         XCTAssertEqual("", db.description)
     }
 
     func test_init_returnsInMemoryByDefault() {
-        let db = try! DirectConnection()
+        let db = try! Connection()
         XCTAssertEqual("", db.description)
     }
 
     func test_init_withTemporary_returnsTemporaryConnection() {
-        let db = try! DirectConnection(.Temporary)
+        let db = try! Connection(.Temporary)
         XCTAssertEqual("", db.description)
     }
 
     func test_init_withURI_returnsURIConnection() {
-        let db = try! DirectConnection(.URI("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3"))
+        let db = try! Connection(.URI("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3"))
         XCTAssertEqual("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3", db.description)
     }
 
     func test_init_withString_returnsURIConnection() {
-        let db = try! DirectConnection("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3")
+        let db = try! Connection("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3")
         XCTAssertEqual("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3", db.description)
     }
 
@@ -39,7 +39,7 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_readonly_returnsTrueOnReadOnlyConnections() {
-        let db = try! DirectConnection(readonly: true)
+        let db = try! Connection(readonly: true)
         XCTAssertTrue(db.readonly)
     }
 
diff --git a/SQLiteTests/TestHelpers.swift b/SQLiteTests/TestHelpers.swift
index 855bf7bd..464b9c27 100644
--- a/SQLiteTests/TestHelpers.swift
+++ b/SQLiteTests/TestHelpers.swift
@@ -5,7 +5,7 @@ class SQLiteTestCase : XCTestCase {
 
     var trace = [String: Int]()
 
-    let db = try! DirectConnection()
+    let db = try! Connection()
 
     let users = Table("users")
 

From 476cdc550430cbda86626d50af1a47c8d678f138 Mon Sep 17 00:00:00 2001
From: Nick Shelley <nickmshelley@gmail.com>
Date: Mon, 18 Jul 2016 16:52:13 -0600
Subject: [PATCH 047/685] Make sure every thread has at least one read.

---
 SQLiteTests/ConnectionPoolTests.swift | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/SQLiteTests/ConnectionPoolTests.swift b/SQLiteTests/ConnectionPoolTests.swift
index 14632713..5a20485b 100644
--- a/SQLiteTests/ConnectionPoolTests.swift
+++ b/SQLiteTests/ConnectionPoolTests.swift
@@ -48,14 +48,13 @@ class ConnectionPoolTests : SQLiteTestCase {
                 
                 print("started", threadNumber)
                 
-                while !quit {
+                while !quit || reads <= 0 {
                     self.pool.read { conn in
                         let _ = try! conn.prepare("SELECT name FROM test WHERE id = ?").scalar(threadNumber) as! String
                         reads += 1
                     }
                 }
                 
-                XCTAssertTrue(reads > 0, "Thread \(threadNumber) did not read.")
                 print("ended at", reads, "reads")
                 
                 ex.fulfill()

From c7db9198cdd3afbb4801d0652588b8b5e7752f06 Mon Sep 17 00:00:00 2001
From: Nick Shelley <nickmshelley@gmail.com>
Date: Tue, 19 Jul 2016 12:45:51 -0600
Subject: [PATCH 048/685] Add connection pool documentation.

---
 Documentation/Index.md | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 0579e6f3..6ea09026 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -11,6 +11,7 @@
       - [Read-Only Databases](#read-only-databases)
       - [In-Memory Databases](#in-memory-databases)
       - [Thread-Safety](#thread-safety)
+    - [Connection Pools](#connection-pools)
   - [Building Type-Safe SQL](#building-type-safe-sql)
     - [Expressions](#expressions)
       - [Compound Expressions](#compound-expressions)
@@ -251,7 +252,7 @@ Every Connection comes equipped with its own serial queue for statement executio
 
 If you maintain multiple connections for a single database, consider setting a timeout (in seconds) and/or a busy handler:
 
-```swift
+``` swift
 db.busyTimeout = 5
 
 db.busyHandler({ tries in
@@ -265,6 +266,33 @@ db.busyHandler({ tries in
 > _Note:_ The default timeout is 0, so if you see `database is locked` errors, you may be trying to access the same database simultaneously from multiple connections.
 
 
+### Connection Pools
+
+Connection pools use SQLite WAL mode to allow concurrent reads and writes, which can increase performance. Connection pools are created similar to connections:
+
+``` swift
+let pool = try ConnectionPool("path/to/db.sqlite3")
+```
+
+Writes are done inside of a readWrite block:
+
+``` swift
+pool.readWrite { connection in
+    try db.run(users.insert(email <- "alice@mac.com", name <- "Alice"))
+}
+```
+
+Reads are done inside of a read block:
+
+``` swift
+pool.read { connection in
+    for user in try db.prepare(users) {
+        print("id: \(user[id]), email: \(user[email]), name: \(user[name])")
+    }
+}
+```
+
+
 ## Building Type-Safe SQL
 
 SQLite.swift comes with a typed expression layer that directly maps [Swift types](https://developer.apple.com/library/prerelease/ios/documentation/General/Reference/SwiftStandardLibraryReference/) to their [SQLite counterparts](https://www.sqlite.org/datatype3.html).

From 66b61ddacc04576744decdafef6485f57f7a0d2e Mon Sep 17 00:00:00 2001
From: Nick Shelley <nickmshelley@gmail.com>
Date: Tue, 19 Jul 2016 12:47:36 -0600
Subject: [PATCH 049/685] Use the right variable names.

---
 Documentation/Index.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 6ea09026..a33000e8 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -278,7 +278,7 @@ Writes are done inside of a readWrite block:
 
 ``` swift
 pool.readWrite { connection in
-    try db.run(users.insert(email <- "alice@mac.com", name <- "Alice"))
+    try connection.run(users.insert(email <- "alice@mac.com", name <- "Alice"))
 }
 ```
 
@@ -286,7 +286,7 @@ Reads are done inside of a read block:
 
 ``` swift
 pool.read { connection in
-    for user in try db.prepare(users) {
+    for user in try connection.prepare(users) {
         print("id: \(user[id]), email: \(user[email]), name: \(user[name])")
     }
 }

From 20fa6ca68de34d71668c0fe24101af3c5943005d Mon Sep 17 00:00:00 2001
From: Nick Shelley <nickmshelley@gmail.com>
Date: Tue, 19 Jul 2016 15:50:14 -0600
Subject: [PATCH 050/685] Revert "Implement connection pool."

---
 Documentation/Index.md                |  30 +---
 SQLite.xcodeproj/project.pbxproj      |  38 +----
 SQLite/Core/Connection.swift          |  84 +++++------
 SQLite/Core/ConnectionPool.swift      | 196 --------------------------
 SQLite/Core/Dispatcher.swift          |  71 ----------
 SQLite/Typed/Query.swift              |   1 +
 SQLiteTests/ConnectionPoolTests.swift | 190 -------------------------
 SQLiteTests/ConnectionTests.swift     |  26 ++--
 8 files changed, 58 insertions(+), 578 deletions(-)
 delete mode 100644 SQLite/Core/ConnectionPool.swift
 delete mode 100644 SQLite/Core/Dispatcher.swift
 delete mode 100644 SQLiteTests/ConnectionPoolTests.swift

diff --git a/Documentation/Index.md b/Documentation/Index.md
index a33000e8..0579e6f3 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -11,7 +11,6 @@
       - [Read-Only Databases](#read-only-databases)
       - [In-Memory Databases](#in-memory-databases)
       - [Thread-Safety](#thread-safety)
-    - [Connection Pools](#connection-pools)
   - [Building Type-Safe SQL](#building-type-safe-sql)
     - [Expressions](#expressions)
       - [Compound Expressions](#compound-expressions)
@@ -252,7 +251,7 @@ Every Connection comes equipped with its own serial queue for statement executio
 
 If you maintain multiple connections for a single database, consider setting a timeout (in seconds) and/or a busy handler:
 
-``` swift
+```swift
 db.busyTimeout = 5
 
 db.busyHandler({ tries in
@@ -266,33 +265,6 @@ db.busyHandler({ tries in
 > _Note:_ The default timeout is 0, so if you see `database is locked` errors, you may be trying to access the same database simultaneously from multiple connections.
 
 
-### Connection Pools
-
-Connection pools use SQLite WAL mode to allow concurrent reads and writes, which can increase performance. Connection pools are created similar to connections:
-
-``` swift
-let pool = try ConnectionPool("path/to/db.sqlite3")
-```
-
-Writes are done inside of a readWrite block:
-
-``` swift
-pool.readWrite { connection in
-    try connection.run(users.insert(email <- "alice@mac.com", name <- "Alice"))
-}
-```
-
-Reads are done inside of a read block:
-
-``` swift
-pool.read { connection in
-    for user in try connection.prepare(users) {
-        print("id: \(user[id]), email: \(user[email]), name: \(user[name])")
-    }
-}
-```
-
-
 ## Building Type-Safe SQL
 
 SQLite.swift comes with a typed expression layer that directly maps [Swift types](https://developer.apple.com/library/prerelease/ios/documentation/General/Reference/SwiftStandardLibraryReference/) to their [SQLite counterparts](https://www.sqlite.org/datatype3.html).
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index ec4cdfad..88d74dc4 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -46,17 +46,6 @@
 		03A65E941C6BB3030062603F /* ValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B331C3F142E00AE3E12 /* ValueTests.swift */; };
 		03A65E951C6BB3030062603F /* TestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B161C3F127200AE3E12 /* TestHelpers.swift */; };
 		03A65E971C6BB3210062603F /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 03A65E961C6BB3210062603F /* libsqlite3.tbd */; };
-		AA780B3D1CC201A700E0E95E /* ConnectionPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA780B3B1CC201A700E0E95E /* ConnectionPool.swift */; };
-		AA780B3E1CC201A700E0E95E /* Dispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA780B3C1CC201A700E0E95E /* Dispatcher.swift */; };
-		AA780B411CC202C800E0E95E /* ConnectionPoolTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA780B3F1CC202B000E0E95E /* ConnectionPoolTests.swift */; };
-		AA780B421CC202C900E0E95E /* ConnectionPoolTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA780B3F1CC202B000E0E95E /* ConnectionPoolTests.swift */; };
-		AA780B431CC202CA00E0E95E /* ConnectionPoolTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA780B3F1CC202B000E0E95E /* ConnectionPoolTests.swift */; };
-		AA780B441CC202F300E0E95E /* ConnectionPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA780B3B1CC201A700E0E95E /* ConnectionPool.swift */; };
-		AA780B451CC202F300E0E95E /* Dispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA780B3C1CC201A700E0E95E /* Dispatcher.swift */; };
-		AA780B461CC202F400E0E95E /* ConnectionPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA780B3B1CC201A700E0E95E /* ConnectionPool.swift */; };
-		AA780B471CC202F400E0E95E /* Dispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA780B3C1CC201A700E0E95E /* Dispatcher.swift */; };
-		AA780B481CC202F500E0E95E /* ConnectionPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA780B3B1CC201A700E0E95E /* ConnectionPool.swift */; };
-		AA780B491CC202F500E0E95E /* Dispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA780B3C1CC201A700E0E95E /* Dispatcher.swift */; };
 		19A1717B10CC941ACB5533D6 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
 		19A171E6FA242F72A308C594 /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
 		19A17254FBA7894891F7297B /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
@@ -181,28 +170,25 @@
 		39548A6D1CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
 		39548A6F1CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
 		A121AC451CA35C79005A31D1 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
-		AA780B3B1CC201A700E0E95E /* ConnectionPool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ConnectionPool.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
-		AA780B3C1CC201A700E0E95E /* Dispatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Dispatcher.swift; sourceTree = "<group>"; };
-		AA780B3F1CC202B000E0E95E /* ConnectionPoolTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectionPoolTests.swift; sourceTree = "<group>"; };
 		EE247AD31C3F04ED00AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AD61C3F04ED00AE3E12 /* SQLite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLite.h; sourceTree = "<group>"; };
 		EE247AD81C3F04ED00AE3E12 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		EE247ADD1C3F04ED00AE3E12 /* SQLiteTests iOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SQLiteTests iOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AE41C3F04ED00AE3E12 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		EE247AEE1C3F06E900AE3E12 /* Blob.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Blob.swift; sourceTree = "<group>"; };
-		EE247AEF1C3F06E900AE3E12 /* Connection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Connection.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
+		EE247AEF1C3F06E900AE3E12 /* Connection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Connection.swift; sourceTree = "<group>"; };
 		EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fts3_tokenizer.h; sourceTree = "<group>"; };
 		EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "SQLite-Bridging.m"; sourceTree = "<group>"; };
-		EE247AF21C3F06E900AE3E12 /* Statement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Statement.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
+		EE247AF21C3F06E900AE3E12 /* Statement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Statement.swift; sourceTree = "<group>"; };
 		EE247AF31C3F06E900AE3E12 /* Value.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Value.swift; sourceTree = "<group>"; };
-		EE247AF51C3F06E900AE3E12 /* FTS4.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = FTS4.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
+		EE247AF51C3F06E900AE3E12 /* FTS4.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS4.swift; sourceTree = "<group>"; };
 		EE247AF61C3F06E900AE3E12 /* R*Tree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "R*Tree.swift"; sourceTree = "<group>"; };
 		EE247AF71C3F06E900AE3E12 /* Foundation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Foundation.swift; sourceTree = "<group>"; };
 		EE247AF81C3F06E900AE3E12 /* Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = "<group>"; };
 		EE247AFA1C3F06E900AE3E12 /* AggregateFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AggregateFunctions.swift; sourceTree = "<group>"; };
 		EE247AFB1C3F06E900AE3E12 /* Collation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Collation.swift; sourceTree = "<group>"; };
 		EE247AFC1C3F06E900AE3E12 /* CoreFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreFunctions.swift; sourceTree = "<group>"; };
-		EE247AFD1C3F06E900AE3E12 /* CustomFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = CustomFunctions.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
+		EE247AFD1C3F06E900AE3E12 /* CustomFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomFunctions.swift; sourceTree = "<group>"; };
 		EE247AFE1C3F06E900AE3E12 /* Expression.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Expression.swift; sourceTree = "<group>"; };
 		EE247AFF1C3F06E900AE3E12 /* Operators.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Operators.swift; sourceTree = "<group>"; };
 		EE247B001C3F06E900AE3E12 /* Query.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Query.swift; sourceTree = "<group>"; };
@@ -212,7 +198,7 @@
 		EE247B181C3F134A00AE3E12 /* SetterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetterTests.swift; sourceTree = "<group>"; };
 		EE247B1A1C3F137700AE3E12 /* AggregateFunctionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AggregateFunctionsTests.swift; sourceTree = "<group>"; };
 		EE247B1B1C3F137700AE3E12 /* BlobTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlobTests.swift; sourceTree = "<group>"; };
-		EE247B1D1C3F137700AE3E12 /* ConnectionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ConnectionTests.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
+		EE247B1D1C3F137700AE3E12 /* ConnectionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectionTests.swift; sourceTree = "<group>"; };
 		EE247B1E1C3F137700AE3E12 /* CoreFunctionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreFunctionsTests.swift; sourceTree = "<group>"; };
 		EE247B1F1C3F137700AE3E12 /* CustomFunctionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomFunctionsTests.swift; sourceTree = "<group>"; };
 		EE247B201C3F137700AE3E12 /* ExpressionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExpressionTests.swift; sourceTree = "<group>"; };
@@ -412,7 +398,6 @@
 		EE247AE11C3F04ED00AE3E12 /* SQLiteTests */ = {
 			isa = PBXGroup;
 			children = (
-				AA780B3F1CC202B000E0E95E /* ConnectionPoolTests.swift */,
 				EE247B1A1C3F137700AE3E12 /* AggregateFunctionsTests.swift */,
 				EE247B1B1C3F137700AE3E12 /* BlobTests.swift */,
 				EE247B1D1C3F137700AE3E12 /* ConnectionTests.swift */,
@@ -437,8 +422,6 @@
 		EE247AED1C3F06E900AE3E12 /* Core */ = {
 			isa = PBXGroup;
 			children = (
-				AA780B3B1CC201A700E0E95E /* ConnectionPool.swift */,
-				AA780B3C1CC201A700E0E95E /* Dispatcher.swift */,
 				EE91808D1C46E5230038162A /* SQLite-Bridging.h */,
 				EE247AEE1C3F06E900AE3E12 /* Blob.swift */,
 				EE247AEF1C3F06E900AE3E12 /* Connection.swift */,
@@ -809,11 +792,9 @@
 				03A65E741C6BB2DA0062603F /* Helpers.swift in Sources */,
 				03A65E831C6BB2FB0062603F /* Operators.swift in Sources */,
 				03A65E851C6BB2FB0062603F /* Schema.swift in Sources */,
-				AA780B471CC202F400E0E95E /* Dispatcher.swift in Sources */,
 				03A65E841C6BB2FB0062603F /* Query.swift in Sources */,
 				03A65E7C1C6BB2F70062603F /* FTS4.swift in Sources */,
 				03A65E771C6BB2E60062603F /* Connection.swift in Sources */,
-				AA780B461CC202F400E0E95E /* ConnectionPool.swift in Sources */,
 				03A65E7E1C6BB2FB0062603F /* AggregateFunctions.swift in Sources */,
 				19A17EC0D68BA8C03288ADF7 /* FTS5.swift in Sources */,
 			);
@@ -824,7 +805,6 @@
 			buildActionMask = 2147483647;
 			files = (
 				03A65E881C6BB3030062603F /* BlobTests.swift in Sources */,
-				AA780B431CC202CA00E0E95E /* ConnectionPoolTests.swift in Sources */,
 				03A65E901C6BB3030062603F /* R*TreeTests.swift in Sources */,
 				03A65E941C6BB3030062603F /* ValueTests.swift in Sources */,
 				03A65E8F1C6BB3030062603F /* QueryTests.swift in Sources */,
@@ -847,8 +827,6 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				AA780B491CC202F500E0E95E /* Dispatcher.swift in Sources */,
-				AA780B481CC202F500E0E95E /* ConnectionPool.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -870,11 +848,9 @@
 				EE247B081C3F06E900AE3E12 /* Value.swift in Sources */,
 				EE247B121C3F06E900AE3E12 /* Operators.swift in Sources */,
 				EE247B141C3F06E900AE3E12 /* Schema.swift in Sources */,
-				AA780B3E1CC201A700E0E95E /* Dispatcher.swift in Sources */,
 				EE247B131C3F06E900AE3E12 /* Query.swift in Sources */,
 				EE247B061C3F06E900AE3E12 /* SQLite-Bridging.m in Sources */,
 				EE247B071C3F06E900AE3E12 /* Statement.swift in Sources */,
-				AA780B3D1CC201A700E0E95E /* ConnectionPool.swift in Sources */,
 				EE247B0D1C3F06E900AE3E12 /* AggregateFunctions.swift in Sources */,
 				19A1717B10CC941ACB5533D6 /* FTS5.swift in Sources */,
 			);
@@ -885,7 +861,6 @@
 			buildActionMask = 2147483647;
 			files = (
 				EE247B261C3F137700AE3E12 /* CoreFunctionsTests.swift in Sources */,
-				AA780B411CC202C800E0E95E /* ConnectionPoolTests.swift in Sources */,
 				EE247B291C3F137700AE3E12 /* FTS4Tests.swift in Sources */,
 				EE247B191C3F134A00AE3E12 /* SetterTests.swift in Sources */,
 				EE247B311C3F141E00AE3E12 /* SchemaTests.swift in Sources */,
@@ -922,11 +897,9 @@
 				EE247B641C3F3FDB00AE3E12 /* Helpers.swift in Sources */,
 				EE247B721C3F3FEC00AE3E12 /* Operators.swift in Sources */,
 				EE247B741C3F3FEC00AE3E12 /* Schema.swift in Sources */,
-				AA780B451CC202F300E0E95E /* Dispatcher.swift in Sources */,
 				EE247B731C3F3FEC00AE3E12 /* Query.swift in Sources */,
 				EE247B6B1C3F3FEC00AE3E12 /* FTS4.swift in Sources */,
 				EE247B661C3F3FEC00AE3E12 /* Connection.swift in Sources */,
-				AA780B441CC202F300E0E95E /* ConnectionPool.swift in Sources */,
 				EE247B6D1C3F3FEC00AE3E12 /* AggregateFunctions.swift in Sources */,
 				19A1750CEE9B05267995CF3D /* FTS5.swift in Sources */,
 			);
@@ -937,7 +910,6 @@
 			buildActionMask = 2147483647;
 			files = (
 				EE247B561C3F3FC700AE3E12 /* CoreFunctionsTests.swift in Sources */,
-				AA780B421CC202C900E0E95E /* ConnectionPoolTests.swift in Sources */,
 				EE247B5A1C3F3FC700AE3E12 /* OperatorsTests.swift in Sources */,
 				EE247B541C3F3FC700AE3E12 /* BlobTests.swift in Sources */,
 				EE247B5D1C3F3FC700AE3E12 /* SchemaTests.swift in Sources */,
diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index d594a4f5..866ed1bf 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -30,24 +30,8 @@ import sqlite3
 import CSQLite
 #endif
 
-
-/// The mode in which a transaction acquires a lock.
-public enum TransactionMode : String {
-    
-    /// Defers locking the database till the first read/write executes.
-    case Deferred = "DEFERRED"
-    
-    /// Immediately acquires a reserved lock on the database.
-    case Immediate = "IMMEDIATE"
-    
-    /// Immediately acquires an exclusive lock on all databases.
-    case Exclusive = "EXCLUSIVE"
-    
-}
-
-
 /// A connection to SQLite.
-public final class Connection : Equatable {
+public final class Connection {
 
     /// The location of a SQLite database.
     public enum Location {
@@ -88,20 +72,10 @@ public final class Connection : Equatable {
     ///     Default: `false`.
     ///
     /// - Returns: A new database connection.
-    public convenience init(_ location: Location = .InMemory, readonly: Bool = false) throws {
+    public init(_ location: Location = .InMemory, readonly: Bool = false) throws {
         let flags = readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE
-        try self.init(location, flags: flags, dispatcher: ReentrantDispatcher("SQLite.Connection"), vfsName: nil)
-    }
-    
-    init(_ location: Location, flags: Int32, dispatcher: Dispatcher, vfsName: String? = nil) throws {
-        self.dispatcher = dispatcher
-        if let vfsName = vfsName {
-            try check(sqlite3_open_v2(location.description, &_handle, flags, vfsName))
-        }
-        else {
-            try check(sqlite3_open_v2(location.description, &_handle, flags, nil))
-        }
-        try check(sqlite3_extended_result_codes(handle, 1))
+        try check(sqlite3_open_v2(location.description, &_handle, flags | SQLITE_OPEN_FULLMUTEX, nil))
+        dispatch_queue_set_specific(queue, Connection.queueKey, queueContext, nil)
     }
 
     /// Initializes a new connection to a database.
@@ -296,6 +270,20 @@ public final class Connection : Equatable {
 
     // MARK: - Transactions
 
+    /// The mode in which a transaction acquires a lock.
+    public enum TransactionMode : String {
+
+        /// Defers locking the database till the first read/write executes.
+        case Deferred = "DEFERRED"
+
+        /// Immediately acquires a reserved lock on the database.
+        case Immediate = "IMMEDIATE"
+
+        /// Immediately acquires an exclusive lock on all databases.
+        case Exclusive = "EXCLUSIVE"
+
+    }
+
     // TODO: Consider not requiring a throw to roll back?
     /// Runs a transaction with the given mode.
     ///
@@ -313,10 +301,10 @@ public final class Connection : Equatable {
     ///     must throw to roll the transaction back.
     ///
     /// - Throws: `Result.Error`, and rethrows.
-    public func transaction(mode: TransactionMode = .Deferred, block: (Connection) throws -> Void) throws {
+    public func transaction(mode: TransactionMode = .Deferred, block: () throws -> Void) throws {
         try transaction("BEGIN \(mode.rawValue) TRANSACTION", block, "COMMIT TRANSACTION", or: "ROLLBACK TRANSACTION")
     }
-    
+
     // TODO: Consider not requiring a throw to roll back?
     // TODO: Consider removing ability to set a name?
     /// Runs a transaction with the given savepoint name (if omitted, it will
@@ -333,18 +321,18 @@ public final class Connection : Equatable {
     ///     The block must throw to roll the savepoint back.
     ///
     /// - Throws: `SQLite.Result.Error`, and rethrows.
-    public func savepoint(name: String = NSUUID().UUIDString, block: (Connection) throws -> Void) throws {
+    public func savepoint(name: String = NSUUID().UUIDString, block: () throws -> Void) throws {
         let name = name.quote("'")
         let savepoint = "SAVEPOINT \(name)"
-        
+
         try transaction(savepoint, block, "RELEASE \(savepoint)", or: "ROLLBACK TO \(savepoint)")
     }
-    
-    private func transaction(begin: String, _ block: (Connection) throws -> Void, _ commit: String, or rollback: String) throws {
+
+    private func transaction(begin: String, _ block: () throws -> Void, _ commit: String, or rollback: String) throws {
         return try sync {
             try self.run(begin)
             do {
-                try block(self)
+                try block()
             } catch {
                 try self.run(rollback)
                 throw error
@@ -352,7 +340,7 @@ public final class Connection : Equatable {
             try self.run(commit)
         }
     }
-    
+
     /// Interrupts any long-running queries.
     public func interrupt() {
         sqlite3_interrupt(handle)
@@ -582,7 +570,7 @@ public final class Connection : Equatable {
 
     // MARK: - Error Handling
 
-    public func sync<T>(block: () throws -> T) rethrows -> T {
+    func sync<T>(block: () throws -> T) rethrows -> T {
         var success: T?
         var failure: ErrorType?
 
@@ -594,7 +582,11 @@ public final class Connection : Equatable {
             }
         }
 
-        dispatcher.dispatch(box)
+        if dispatch_get_specific(Connection.queueKey) == queueContext {
+            box()
+        } else {
+            dispatch_sync(queue, box) // FIXME: rdar://problem/21389236
+        }
 
         if let failure = failure {
             try { () -> Void in throw failure }()
@@ -610,8 +602,12 @@ public final class Connection : Equatable {
 
         throw error
     }
-  
-    private var dispatcher: Dispatcher
+
+    private var queue = dispatch_queue_create("SQLite.Database", DISPATCH_QUEUE_SERIAL)
+
+    private static let queueKey = unsafeBitCast(Connection.self, UnsafePointer<Void>.self)
+
+    private lazy var queueContext: UnsafeMutablePointer<Void> = unsafeBitCast(self, UnsafeMutablePointer<Void>.self)
 
 }
 
@@ -638,10 +634,6 @@ extension Connection.Location : CustomStringConvertible {
 
 }
 
-public func == (lhs: Connection, rhs: Connection) -> Bool {
-    return lhs === rhs
-}
-
 /// An SQL operation passed to update callbacks.
 public enum Operation {
 
diff --git a/SQLite/Core/ConnectionPool.swift b/SQLite/Core/ConnectionPool.swift
deleted file mode 100644
index 91c3e366..00000000
--- a/SQLite/Core/ConnectionPool.swift
+++ /dev/null
@@ -1,196 +0,0 @@
-//
-// SQLite.swift
-// https://github.com/stephencelis/SQLite.swift
-// Copyright © 2014-2015 Stephen Celis.
-//
-// 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.
-//
-
-import Dispatch
-#if SQLITE_SWIFT_STANDALONE
-import sqlite3
-#else
-import CSQLite
-#endif
-
-
-private let vfsName = "unix-excl"
-
-
-// Connection pool for accessing an SQLite database
-// with multiple readers & a single writer. Utilizes
-// WAL mode.
-public final class ConnectionPool {
-
-    private let location: Connection.Location
-    private var availableReadConnections = [Connection]()
-    private var unavailableReadConnections = [Connection]()
-    private let lockQueue: dispatch_queue_t
-    private var writeConnection: Connection!
-    private let connectionSemaphore = dispatch_semaphore_create(5)
-    
-    public var foreignKeys : Bool {
-        get {
-            return internalSetup[.ForeignKeys] != nil
-        }
-        set {
-            internalSetup[.ForeignKeys] = newValue ? { try $0.execute("PRAGMA foreign_keys = ON;") } : nil
-        }
-    }
-    
-    public typealias ConnectionProcessor = Connection throws -> Void
-    public var setup = [ConnectionProcessor]()
-    
-    private enum InternalOption {
-        case WriteAheadLogging
-        case ForeignKeys
-    }
-    
-    private var internalSetup = [InternalOption: ConnectionProcessor]()
-    
-    /// Initializes a new SQLite connection pool.
-    ///
-    /// - Parameters:
-    ///
-    ///   - location: The location of the database. Creates a new database if it
-    ///     doesn’t already exist.
-    ///
-    ///     Default: `.InMemory`.
-    ///
-    /// - Throws: `Result.Error` iff a connection cannot be established.
-    ///
-    /// - Returns: A new connection pool.
-    public init(_ location: Connection.Location = .InMemory) throws {
-        self.location = location
-        self.lockQueue = dispatch_queue_create("SQLite.ConnectionPool.Lock", DISPATCH_QUEUE_SERIAL)
-        self.internalSetup[.WriteAheadLogging] = { try $0.execute("PRAGMA journal_mode = WAL;") }
-    }
-    
-    /// Initializes a new connection to a database.
-    ///
-    /// - Parameters:
-    ///
-    ///   - filename: The location of the database. Creates a new database if
-    ///     it doesn’t already exist (unless in read-only mode).
-    ///
-    /// - Throws: `Result.Error` iff a connection cannot be established.
-    ///
-    /// - Returns: A new database connection pool.
-    public convenience init(_ filename: String) throws {
-        try self.init(.URI(filename))
-    }
-    
-    public var totalReadableConnectionCount : Int {
-        return availableReadConnections.count + unavailableReadConnections.count
-    }
-    
-    public var availableReadableConnectionCount : Int {
-        return availableReadConnections.count
-    }
-    
-    /// Calls `readBlock` with an available read connection from the connection pool,
-    /// after which the connection is made available again.
-    public func read(readBlock: (connection: Connection) -> Void) {
-        let connection = readable
-        readBlock(connection: connection)
-        
-        dispatch_sync(lockQueue) {
-            if let index = self.unavailableReadConnections.indexOf(connection) {
-                self.unavailableReadConnections.removeAtIndex(index)
-            }
-            self.availableReadConnections.append(connection)
-            dispatch_semaphore_signal(self.connectionSemaphore)
-        }
-    }
-    
-    /// Calls `readWriteBlock` with a writeable connection
-    public func readWrite(readWriteBlock: (connection: Connection) -> Void) {
-        let connection = writable
-        readWriteBlock(connection: connection)
-    }
-    
-    // Acquires a read/write connection to the database
-    var writeConnectionInit = dispatch_once_t()
-    
-    private var writable: Connection {
-
-        dispatch_once(&writeConnectionInit) {
-        
-            let flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_WAL | SQLITE_OPEN_NOMUTEX
-            self.writeConnection = try! Connection(self.location, flags: flags, dispatcher: ReentrantDispatcher("SQLite.ConnectionPool.Write"), vfsName: vfsName)
-            self.writeConnection.busyTimeout = 2
-            
-            for setupProcessor in self.internalSetup.values {
-                try! setupProcessor(self.writeConnection)
-            }
-            
-            for setupProcessor in self.setup {
-                try! setupProcessor(self.writeConnection)
-            }
-            
-        }
-        
-        return writeConnection
-    }
-    
-    // Acquires a read only connection to the database
-    private var readable: Connection {
-        
-        var borrowed: Connection!
-        
-        dispatch_semaphore_wait(connectionSemaphore, DISPATCH_TIME_FOREVER)
-        dispatch_sync(lockQueue) {
-            
-            // Ensure database is open
-            self.writable
-            
-            let connection: Connection
-            
-            if let availableConnection = self.availableReadConnections.popLast() {
-                connection = availableConnection
-            }
-            else {
-                
-                let flags = SQLITE_OPEN_READONLY | SQLITE_OPEN_WAL | SQLITE_OPEN_NOMUTEX
-                
-                connection = try! Connection(self.location, flags: flags, dispatcher: ImmediateDispatcher(), vfsName: vfsName)
-                connection.busyTimeout = 2
-                
-                for (type, setupProcessor) in self.internalSetup {
-                    if type == .WriteAheadLogging {
-                        continue
-                    }
-                    try! setupProcessor(connection)
-                }
-                
-                for setupProcessor in self.setup {
-                    try! setupProcessor(connection)
-                }
-                
-            }
-            
-            self.unavailableReadConnections.append(connection)
-            
-            borrowed = connection
-        }
-        
-        return borrowed
-    }
-    
-}
diff --git a/SQLite/Core/Dispatcher.swift b/SQLite/Core/Dispatcher.swift
deleted file mode 100644
index f6cff005..00000000
--- a/SQLite/Core/Dispatcher.swift
+++ /dev/null
@@ -1,71 +0,0 @@
-//
-// SQLite.swift
-// https://github.com/stephencelis/SQLite.swift
-// Copyright © 2014-2015 Stephen Celis.
-//
-// 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.
-//
-
-import Foundation
-
-
-/// Block dispatch method
-public protocol Dispatcher {
-    
-    /// Dispatches the provided block
-    func dispatch(block: dispatch_block_t)
-    
-}
-
-
-/// Dispatches block immediately on current thread
-public final class ImmediateDispatcher : Dispatcher {
-    
-    public func dispatch(block: dispatch_block_t) {
-        block()
-    }
-    
-}
-
-
-/// Synchronously dispatches block on a serial
-/// queue. Specifically allows reentrant calls
-public final class ReentrantDispatcher : Dispatcher {
-    
-    static let queueKey = unsafeBitCast(ReentrantDispatcher.self, UnsafePointer<Void>.self)
-    
-    let queue : dispatch_queue_t
-    
-    let queueContext : UnsafeMutablePointer<Void>
-    
-    public init(_ name: String) {
-        queue = dispatch_queue_create(name, DISPATCH_QUEUE_SERIAL)
-        queueContext = unsafeBitCast(queue, UnsafeMutablePointer<Void>.self)
-        dispatch_queue_set_specific(queue, ReentrantDispatcher.queueKey, queueContext, nil)
-    }
-    
-    public func dispatch(block: dispatch_block_t) {
-        if dispatch_get_specific(ReentrantDispatcher.queueKey) == self.queueContext {
-            block()
-        } else {
-            dispatch_sync(self.queue, block) // FIXME: rdar://problem/21389236
-        }
-    }
-    
-}
diff --git a/SQLite/Typed/Query.swift b/SQLite/Typed/Query.swift
index 30a57337..e45034ca 100644
--- a/SQLite/Typed/Query.swift
+++ b/SQLite/Typed/Query.swift
@@ -1051,6 +1051,7 @@ public struct Row {
     }
 
     // FIXME: rdar://problem/18673897 // subscript<T>…
+
     public subscript(column: Expression<Blob>) -> Blob {
         return get(column)
     }
diff --git a/SQLiteTests/ConnectionPoolTests.swift b/SQLiteTests/ConnectionPoolTests.swift
deleted file mode 100644
index 5a20485b..00000000
--- a/SQLiteTests/ConnectionPoolTests.swift
+++ /dev/null
@@ -1,190 +0,0 @@
-import XCTest
-import SQLite
-
-class ConnectionPoolTests : SQLiteTestCase {
-
-    var pool : ConnectionPool!
-    
-    override func setUp() {
-        let _ = try? NSFileManager.defaultManager().removeItemAtPath("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite")
-        pool = try! ConnectionPool("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite")
-    }
-    
-    func testConnectionSetupClosures() {
-        
-        pool.foreignKeys = true
-        pool.setup.append { try $0.execute("CREATE TABLE IF NOT EXISTS test(value INT)") }
-        pool.read { conn in
-            XCTAssertTrue(conn.scalar("PRAGMA foreign_keys") as! Int64 == 1)
-        }
-        
-        pool.readWrite { conn in
-            try! conn.execute("INSERT INTO test(value) VALUES (1)")
-            try! conn.execute("SELECT value FROM test")
-        }
-        
-    }
-
-    func testConcurrentAccess2() {
-        
-        let threadCount = 20
-        pool.readWrite { conn in
-            try! conn.execute("DROP TABLE IF EXISTS test; CREATE TABLE test(id INTEGER PRIMARY KEY, name TEXT);")
-            try! conn.execute("DELETE FROM test")
-            for threadNumber in 0..<threadCount {
-                try! conn.execute("INSERT INTO test(id,name) VALUES(\(threadNumber), 'test\(threadNumber)')")
-            }
-        }
-        
-        
-        var quit = false
-        let queue = dispatch_queue_create("Readers", DISPATCH_QUEUE_CONCURRENT)
-        for threadNumber in 0..<threadCount {
-            var reads = 0
-            
-            let ex = expectationWithDescription("thread" + String(threadNumber))
-            
-            dispatch_async(queue) {
-                
-                print("started", threadNumber)
-                
-                while !quit || reads <= 0 {
-                    self.pool.read { conn in
-                        let _ = try! conn.prepare("SELECT name FROM test WHERE id = ?").scalar(threadNumber) as! String
-                        reads += 1
-                    }
-                }
-                
-                print("ended at", reads, "reads")
-                
-                ex.fulfill()
-            }
-            
-        }
-        
-        for x in 10..<100 {
-            
-            let name = "test" + String(x)
-            let idx = Int(rand()) % threadCount
-            
-            pool.readWrite { conn in
-                do {
-                    try conn.run("UPDATE test SET name=? WHERE id=?", name, idx)
-                }
-                catch let error {
-                    XCTFail((error as? CustomStringConvertible)?.description ?? "Unknown")
-                }
-            }
-            
-            usleep(500)
-        }
-        
-        quit = true
-        waitForExpectationsWithTimeout(1000, handler: nil)
-    }
-    
-    func testConcurrentAccess() throws {
-        pool.readWrite { conn in
-            try! conn.execute("DROP TABLE IF EXISTS test; CREATE TABLE test(value);")
-            try! conn.run("INSERT INTO test(value) VALUES(?)", 0)
-        }
-        
-        let q = dispatch_queue_create("Readers/Writers", DISPATCH_QUEUE_CONCURRENT);
-        var finished = false
-        
-        for _ in 0..<20 {
-            
-            dispatch_async(q) {
-                
-                while !finished {
-                    var val: Binding?
-                    self.pool.read { conn in
-                        val = conn.scalar("SELECT value FROM test")
-                    }
-                    assert(val != nil, "DB query returned nil result set")
-                }
-                
-            }
-            
-        }
-        
-        for c in 0..<5000 {
-            pool.readWrite { conn in
-                try! conn.run("INSERT INTO test(value) VALUES(?)", c)
-            }
-            
-            usleep(100);
-            
-        }
-        
-        finished = true
-        
-        // Wait for readers to finish
-        dispatch_barrier_sync(q) {
-        }
-        
-    }
-    
-    func testMultiplePools() {
-        let pool2 = try! ConnectionPool("\(NSTemporaryDirectory())/SQLite.swift Pool Tests.sqlite")
-        pool.readWrite { conn in
-            try! conn.execute("DROP TABLE IF EXISTS test; CREATE TABLE test(value);")
-            try! conn.run("INSERT INTO test(value) VALUES(?)", 0)
-        }
-        
-        let q = dispatch_queue_create("Readers/Writers", DISPATCH_QUEUE_CONCURRENT);
-        var finished = false
-        
-        for _ in 0..<20 {
-            dispatch_async(q) {
-                while !finished {
-                    var val: Binding?
-                    self.pool.read { conn in
-                        val = conn.scalar("SELECT value FROM test")
-                    }
-                    assert(val != nil, "DB query returned nil result set")
-                }
-            }
-        }
-        
-        for _ in 0..<20 {
-            dispatch_async(q) {
-                while !finished {
-                    var val: Binding?
-                    pool2.read { conn in
-                        val = conn.scalar("SELECT value FROM test")
-                    }
-                    assert(val != nil, "DB query returned nil result set")
-                }
-            }
-        }
-        
-        for c in 0..<5000 {
-            pool.readWrite { conn in
-                try! conn.run("INSERT INTO test(value) VALUES(?)", c)
-            }
-            
-            pool2.readWrite { conn in
-                try! conn.run("INSERT INTO test(value) VALUES(?)", c + 5000)
-            }
-            
-            usleep(100);
-        }
-        
-        finished = true
-        
-        // Wait for readers to finish
-        dispatch_barrier_sync(q) {
-        }
-        
-    }
-    
-    func testAutoRelease() {
-        pool.read { conn in
-            try! conn.execute("SELECT 1")
-        }
-        
-        XCTAssertEqual(pool.totalReadableConnectionCount, pool.availableReadableConnectionCount)
-    }
-    
-}
diff --git a/SQLiteTests/ConnectionTests.swift b/SQLiteTests/ConnectionTests.swift
index 62203362..aeec9b72 100644
--- a/SQLiteTests/ConnectionTests.swift
+++ b/SQLiteTests/ConnectionTests.swift
@@ -95,19 +95,19 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_transaction_executesBeginDeferred() {
-        try! db.transaction(.Deferred) {_ in }
+        try! db.transaction(.Deferred) {}
 
         AssertSQL("BEGIN DEFERRED TRANSACTION")
     }
 
     func test_transaction_executesBeginImmediate() {
-        try! db.transaction(.Immediate) {_ in }
+        try! db.transaction(.Immediate) {}
 
         AssertSQL("BEGIN IMMEDIATE TRANSACTION")
     }
 
     func test_transaction_executesBeginExclusive() {
-        try! db.transaction(.Exclusive) {_ in }
+        try! db.transaction(.Exclusive) {}
 
         AssertSQL("BEGIN EXCLUSIVE TRANSACTION")
     }
@@ -115,7 +115,7 @@ class ConnectionTests : SQLiteTestCase {
     func test_transaction_beginsAndCommitsTransactions() {
         let stmt = try! db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com")
 
-        try! db.transaction {_ in 
+        try! db.transaction {
             try stmt.run()
         }
 
@@ -129,7 +129,7 @@ class ConnectionTests : SQLiteTestCase {
         let stmt = try! db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com")
 
         do {
-            try db.transaction {_ in 
+            try db.transaction {
                 try stmt.run()
                 try stmt.run()
             }
@@ -145,8 +145,8 @@ class ConnectionTests : SQLiteTestCase {
     func test_savepoint_beginsAndCommitsSavepoints() {
         let db = self.db
 
-        try! db.savepoint("1") {_ in 
-            try db.savepoint("2") {_ in 
+        try! db.savepoint("1") {
+            try db.savepoint("2") {
                 try db.run("INSERT INTO users (email) VALUES (?)", "alice@example.com")
             }
         }
@@ -165,13 +165,13 @@ class ConnectionTests : SQLiteTestCase {
         let stmt = try! db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com")
 
         do {
-            try db.savepoint("1") {_ in 
-                try db.savepoint("2") {_ in 
+            try db.savepoint("1") {
+                try db.savepoint("2") {
                     try stmt.run()
                     try stmt.run()
                     try stmt.run()
                 }
-                try db.savepoint("2") {_ in 
+                try db.savepoint("2") {
                     try stmt.run()
                     try stmt.run()
                     try stmt.run()
@@ -235,7 +235,7 @@ class ConnectionTests : SQLiteTestCase {
             db.commitHook {
                 done()
             }
-            try! db.transaction {_ in 
+            try! db.transaction {
                 try self.InsertUser("alice")
             }
             XCTAssertEqual(1, db.scalar("SELECT count(*) FROM users") as? Int64)
@@ -246,7 +246,7 @@ class ConnectionTests : SQLiteTestCase {
         async { done in
             db.rollbackHook(done)
             do {
-                try db.transaction {_ in 
+                try db.transaction {
                     try self.InsertUser("alice")
                     try self.InsertUser("alice") // throw
                 }
@@ -263,7 +263,7 @@ class ConnectionTests : SQLiteTestCase {
             }
             db.rollbackHook(done)
             do {
-                try db.transaction {_ in 
+                try db.transaction {
                     try self.InsertUser("alice")
                 }
             } catch {

From 1b2d648784152f2c998c3e118524fcfc305d90d0 Mon Sep 17 00:00:00 2001
From: Nick Shelley <nickmshelley@gmail.com>
Date: Tue, 19 Jul 2016 16:05:15 -0600
Subject: [PATCH 051/685] Add test for single connection across multiple
 threads.

---
 SQLiteTests/ConnectionTests.swift | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/SQLiteTests/ConnectionTests.swift b/SQLiteTests/ConnectionTests.swift
index 62203362..4ec50c8a 100644
--- a/SQLiteTests/ConnectionTests.swift
+++ b/SQLiteTests/ConnectionTests.swift
@@ -313,5 +313,26 @@ class ConnectionTests : SQLiteTestCase {
         dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(10 * NSEC_PER_MSEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), db.interrupt)
         AssertThrows(try stmt.run())
     }
+    
+    func test_concurrent_access_single_connection() {
+        let conn = try! Connection("\(NSTemporaryDirectory())/SQLite.swift Connection Tests.sqlite")
+        try! conn.execute("DROP TABLE IF EXISTS test; CREATE TABLE test(value);")
+        try! conn.run("INSERT INTO test(value) VALUES(?)", 0)
+        
+        let q = dispatch_queue_create("Readers", DISPATCH_QUEUE_CONCURRENT);
+        var finished = false
+        
+        for _ in 0..<100 {
+            dispatch_async(q) {
+                while !finished {
+                    _ = try! conn.prepare("SELECT value FROM test")
+                }
+            }
+        }
+        
+        // Give the threads some time to conflict
+        sleep(5)
+        finished = true
+    }
 
 }

From dd97747529cc8bc1940425a63fb240e7cd90b54e Mon Sep 17 00:00:00 2001
From: Will Richardson <william.hamish@gmail.com>
Date: Wed, 20 Jul 2016 10:11:45 +1200
Subject: [PATCH 052/685] Added try! to connection pool tests

---
 SQLiteTests/ConnectionPoolTests.swift | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/SQLiteTests/ConnectionPoolTests.swift b/SQLiteTests/ConnectionPoolTests.swift
index 5a20485b..9c243379 100644
--- a/SQLiteTests/ConnectionPoolTests.swift
+++ b/SQLiteTests/ConnectionPoolTests.swift
@@ -15,7 +15,7 @@ class ConnectionPoolTests : SQLiteTestCase {
         pool.foreignKeys = true
         pool.setup.append { try $0.execute("CREATE TABLE IF NOT EXISTS test(value INT)") }
         pool.read { conn in
-            XCTAssertTrue(conn.scalar("PRAGMA foreign_keys") as! Int64 == 1)
+            XCTAssertTrue(try! conn.scalar("PRAGMA foreign_keys") as! Int64 == 1)
         }
         
         pool.readWrite { conn in
@@ -99,7 +99,7 @@ class ConnectionPoolTests : SQLiteTestCase {
                 while !finished {
                     var val: Binding?
                     self.pool.read { conn in
-                        val = conn.scalar("SELECT value FROM test")
+                        val = try! conn.scalar("SELECT value FROM test")
                     }
                     assert(val != nil, "DB query returned nil result set")
                 }
@@ -140,7 +140,7 @@ class ConnectionPoolTests : SQLiteTestCase {
                 while !finished {
                     var val: Binding?
                     self.pool.read { conn in
-                        val = conn.scalar("SELECT value FROM test")
+                        val = try! conn.scalar("SELECT value FROM test")
                     }
                     assert(val != nil, "DB query returned nil result set")
                 }
@@ -152,7 +152,7 @@ class ConnectionPoolTests : SQLiteTestCase {
                 while !finished {
                     var val: Binding?
                     pool2.read { conn in
-                        val = conn.scalar("SELECT value FROM test")
+                        val = try! conn.scalar("SELECT value FROM test")
                     }
                     assert(val != nil, "DB query returned nil result set")
                 }

From aec65643b92023bc38d8440ba2a5aa38e3f35056 Mon Sep 17 00:00:00 2001
From: tasanobu <tasanobu@gmail.com>
Date: Wed, 20 Jul 2016 12:06:50 +0900
Subject: [PATCH 053/685] Propagate error thrown in Query.pluck()

---
 SQLite/Typed/Query.swift     | 7 ++-----
 SQLiteTests/QueryTests.swift | 2 +-
 2 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/SQLite/Typed/Query.swift b/SQLite/Typed/Query.swift
index b81c3372..8eedf2d5 100644
--- a/SQLite/Typed/Query.swift
+++ b/SQLite/Typed/Query.swift
@@ -954,11 +954,8 @@ extension Connection {
         return V.fromDatatypeValue(value)
     }
 
-    public func pluck(query: QueryType) -> Row? {
-        guard let rows = try? prepare(query.limit(1, query.clauses.limit?.offset)) else {
-            return nil
-        }
-        return rows.generate().next()
+    public func pluck(query: QueryType) throws -> Row? {
+        return try prepare(query.limit(1, query.clauses.limit?.offset)).generate().next()
     }
 
     /// Runs an `Insert` query.
diff --git a/SQLiteTests/QueryTests.swift b/SQLiteTests/QueryTests.swift
index b76da61e..e1ef1344 100644
--- a/SQLiteTests/QueryTests.swift
+++ b/SQLiteTests/QueryTests.swift
@@ -315,7 +315,7 @@ class QueryIntegrationTests : SQLiteTestCase {
 
     func test_pluck() {
         let rowid = try! db.run(users.insert(email <- "alice@example.com"))
-        XCTAssertEqual(rowid, db.pluck(users)![id])
+        XCTAssertEqual(rowid, try! db.pluck(users)![id])
     }
 
     func test_insert() {

From ce1d0f1e5c463b63b5d92f97773429a29e117548 Mon Sep 17 00:00:00 2001
From: Nick Shelley <nickmshelley@gmail.com>
Date: Wed, 20 Jul 2016 10:45:25 -0600
Subject: [PATCH 054/685] Update test.

---
 SQLiteTests/ConnectionTests.swift | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/SQLiteTests/ConnectionTests.swift b/SQLiteTests/ConnectionTests.swift
index 4ec50c8a..a00ab388 100644
--- a/SQLiteTests/ConnectionTests.swift
+++ b/SQLiteTests/ConnectionTests.swift
@@ -320,19 +320,22 @@ class ConnectionTests : SQLiteTestCase {
         try! conn.run("INSERT INTO test(value) VALUES(?)", 0)
         
         let q = dispatch_queue_create("Readers", DISPATCH_QUEUE_CONCURRENT);
-        var finished = false
         
-        for _ in 0..<100 {
+        var reads = [0, 0, 0, 0, 0]
+        var finished = false
+        for index in 0..<5 {
             dispatch_async(q) {
                 while !finished {
                     _ = try! conn.prepare("SELECT value FROM test")
+                    reads[index] += 1
                 }
             }
         }
         
-        // Give the threads some time to conflict
-        sleep(5)
-        finished = true
+        while !finished {
+            sleep(1)
+            finished = reads.reduce(true) { $0 && ($1 > 500) }
+        }
     }
 
 }

From 72ee02cd8536c95a7e09604e2a85614a44efb386 Mon Sep 17 00:00:00 2001
From: Nick Shelley <nickmshelley@gmail.com>
Date: Wed, 20 Jul 2016 11:06:46 -0600
Subject: [PATCH 055/685] Whitespace change to retrigger build.

---
 SQLiteTests/ConnectionTests.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/SQLiteTests/ConnectionTests.swift b/SQLiteTests/ConnectionTests.swift
index a00ab388..c49e99e3 100644
--- a/SQLiteTests/ConnectionTests.swift
+++ b/SQLiteTests/ConnectionTests.swift
@@ -336,6 +336,6 @@ class ConnectionTests : SQLiteTestCase {
             sleep(1)
             finished = reads.reduce(true) { $0 && ($1 > 500) }
         }
-    }
+    } 
 
 }

From 68210d61ed95e8222a8dcef1c2ab3a079722827e Mon Sep 17 00:00:00 2001
From: David Potter <dpotter@tableau.com>
Date: Thu, 28 Jul 2016 15:56:01 -0700
Subject: [PATCH 056/685] Allow the framework to be included in app extensions
 for tvOS

---
 SQLite.xcodeproj/project.pbxproj | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 88d74dc4..b5179c09 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -952,6 +952,7 @@
 		03A65E6B1C6BB0F60062603F /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				APPLICATION_EXTENSION_API_ONLY = YES;
 				DEFINES_MODULE = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
@@ -972,6 +973,7 @@
 		03A65E6C1C6BB0F60062603F /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				APPLICATION_EXTENSION_API_ONLY = YES;
 				DEFINES_MODULE = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;

From 9279fc6e5e927575af956557dd16477d0f0f7fa9 Mon Sep 17 00:00:00 2001
From: Tim Spears <tspears@ultramain.com>
Date: Thu, 11 Aug 2016 12:24:48 -0600
Subject: [PATCH 057/685] Renamed R*Tree.swift to RTree.swift and
 R*TreeTests.swift to RTreeTests.swift. Made the necessary changes to the
 project.pbxproj file.

Verified tests still pass. No new tests since no functionality is changed.
---
 SQLite.xcodeproj/project.pbxproj              | 32 +++++++++----------
 .../Extensions/{R*Tree.swift => RTree.swift}  |  0
 .../{R*TreeTests.swift => RTreeTests.swift}   |  0
 3 files changed, 16 insertions(+), 16 deletions(-)
 rename SQLite/Extensions/{R*Tree.swift => RTree.swift} (100%)
 rename SQLiteTests/{R*TreeTests.swift => RTreeTests.swift} (100%)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 88d74dc4..ec5b5882 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -20,7 +20,7 @@
 		03A65E7A1C6BB2F70062603F /* Statement.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF21C3F06E900AE3E12 /* Statement.swift */; };
 		03A65E7B1C6BB2F70062603F /* Value.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF31C3F06E900AE3E12 /* Value.swift */; };
 		03A65E7C1C6BB2F70062603F /* FTS4.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF51C3F06E900AE3E12 /* FTS4.swift */; };
-		03A65E7D1C6BB2F70062603F /* R*Tree.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF61C3F06E900AE3E12 /* R*Tree.swift */; };
+		03A65E7D1C6BB2F70062603F /* RTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF61C3F06E900AE3E12 /* RTree.swift */; };
 		03A65E7E1C6BB2FB0062603F /* AggregateFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFA1C3F06E900AE3E12 /* AggregateFunctions.swift */; };
 		03A65E7F1C6BB2FB0062603F /* Collation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFB1C3F06E900AE3E12 /* Collation.swift */; };
 		03A65E801C6BB2FB0062603F /* CoreFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFC1C3F06E900AE3E12 /* CoreFunctions.swift */; };
@@ -39,7 +39,7 @@
 		03A65E8D1C6BB3030062603F /* FTS4Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B211C3F137700AE3E12 /* FTS4Tests.swift */; };
 		03A65E8E1C6BB3030062603F /* OperatorsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2A1C3F141E00AE3E12 /* OperatorsTests.swift */; };
 		03A65E8F1C6BB3030062603F /* QueryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2B1C3F141E00AE3E12 /* QueryTests.swift */; };
-		03A65E901C6BB3030062603F /* R*TreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2C1C3F141E00AE3E12 /* R*TreeTests.swift */; };
+		03A65E901C6BB3030062603F /* RTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2C1C3F141E00AE3E12 /* RTreeTests.swift */; };
 		03A65E911C6BB3030062603F /* SchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2D1C3F141E00AE3E12 /* SchemaTests.swift */; };
 		03A65E921C6BB3030062603F /* SetterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B181C3F134A00AE3E12 /* SetterTests.swift */; };
 		03A65E931C6BB3030062603F /* StatementTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B321C3F142E00AE3E12 /* StatementTests.swift */; };
@@ -61,7 +61,7 @@
 		EE247B071C3F06E900AE3E12 /* Statement.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF21C3F06E900AE3E12 /* Statement.swift */; };
 		EE247B081C3F06E900AE3E12 /* Value.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF31C3F06E900AE3E12 /* Value.swift */; };
 		EE247B091C3F06E900AE3E12 /* FTS4.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF51C3F06E900AE3E12 /* FTS4.swift */; };
-		EE247B0A1C3F06E900AE3E12 /* R*Tree.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF61C3F06E900AE3E12 /* R*Tree.swift */; };
+		EE247B0A1C3F06E900AE3E12 /* RTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF61C3F06E900AE3E12 /* RTree.swift */; };
 		EE247B0B1C3F06E900AE3E12 /* Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF71C3F06E900AE3E12 /* Foundation.swift */; };
 		EE247B0C1C3F06E900AE3E12 /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF81C3F06E900AE3E12 /* Helpers.swift */; };
 		EE247B0D1C3F06E900AE3E12 /* AggregateFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFA1C3F06E900AE3E12 /* AggregateFunctions.swift */; };
@@ -84,7 +84,7 @@
 		EE247B291C3F137700AE3E12 /* FTS4Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B211C3F137700AE3E12 /* FTS4Tests.swift */; };
 		EE247B2E1C3F141E00AE3E12 /* OperatorsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2A1C3F141E00AE3E12 /* OperatorsTests.swift */; };
 		EE247B2F1C3F141E00AE3E12 /* QueryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2B1C3F141E00AE3E12 /* QueryTests.swift */; };
-		EE247B301C3F141E00AE3E12 /* R*TreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2C1C3F141E00AE3E12 /* R*TreeTests.swift */; };
+		EE247B301C3F141E00AE3E12 /* RTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2C1C3F141E00AE3E12 /* RTreeTests.swift */; };
 		EE247B311C3F141E00AE3E12 /* SchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2D1C3F141E00AE3E12 /* SchemaTests.swift */; };
 		EE247B341C3F142E00AE3E12 /* StatementTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B321C3F142E00AE3E12 /* StatementTests.swift */; };
 		EE247B351C3F142E00AE3E12 /* ValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B331C3F142E00AE3E12 /* ValueTests.swift */; };
@@ -98,7 +98,7 @@
 		EE247B591C3F3FC700AE3E12 /* FTS4Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B211C3F137700AE3E12 /* FTS4Tests.swift */; };
 		EE247B5A1C3F3FC700AE3E12 /* OperatorsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2A1C3F141E00AE3E12 /* OperatorsTests.swift */; };
 		EE247B5B1C3F3FC700AE3E12 /* QueryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2B1C3F141E00AE3E12 /* QueryTests.swift */; };
-		EE247B5C1C3F3FC700AE3E12 /* R*TreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2C1C3F141E00AE3E12 /* R*TreeTests.swift */; };
+		EE247B5C1C3F3FC700AE3E12 /* RTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2C1C3F141E00AE3E12 /* RTreeTests.swift */; };
 		EE247B5D1C3F3FC700AE3E12 /* SchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2D1C3F141E00AE3E12 /* SchemaTests.swift */; };
 		EE247B5E1C3F3FC700AE3E12 /* SetterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B181C3F134A00AE3E12 /* SetterTests.swift */; };
 		EE247B5F1C3F3FC700AE3E12 /* StatementTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B321C3F142E00AE3E12 /* StatementTests.swift */; };
@@ -114,7 +114,7 @@
 		EE247B691C3F3FEC00AE3E12 /* Statement.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF21C3F06E900AE3E12 /* Statement.swift */; };
 		EE247B6A1C3F3FEC00AE3E12 /* Value.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF31C3F06E900AE3E12 /* Value.swift */; };
 		EE247B6B1C3F3FEC00AE3E12 /* FTS4.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF51C3F06E900AE3E12 /* FTS4.swift */; };
-		EE247B6C1C3F3FEC00AE3E12 /* R*Tree.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF61C3F06E900AE3E12 /* R*Tree.swift */; };
+		EE247B6C1C3F3FEC00AE3E12 /* RTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF61C3F06E900AE3E12 /* RTree.swift */; };
 		EE247B6D1C3F3FEC00AE3E12 /* AggregateFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFA1C3F06E900AE3E12 /* AggregateFunctions.swift */; };
 		EE247B6E1C3F3FEC00AE3E12 /* Collation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFB1C3F06E900AE3E12 /* Collation.swift */; };
 		EE247B6F1C3F3FEC00AE3E12 /* CoreFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFC1C3F06E900AE3E12 /* CoreFunctions.swift */; };
@@ -182,7 +182,7 @@
 		EE247AF21C3F06E900AE3E12 /* Statement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Statement.swift; sourceTree = "<group>"; };
 		EE247AF31C3F06E900AE3E12 /* Value.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Value.swift; sourceTree = "<group>"; };
 		EE247AF51C3F06E900AE3E12 /* FTS4.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS4.swift; sourceTree = "<group>"; };
-		EE247AF61C3F06E900AE3E12 /* R*Tree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "R*Tree.swift"; sourceTree = "<group>"; };
+		EE247AF61C3F06E900AE3E12 /* RTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "RTree.swift"; sourceTree = "<group>"; };
 		EE247AF71C3F06E900AE3E12 /* Foundation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Foundation.swift; sourceTree = "<group>"; };
 		EE247AF81C3F06E900AE3E12 /* Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = "<group>"; };
 		EE247AFA1C3F06E900AE3E12 /* AggregateFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AggregateFunctions.swift; sourceTree = "<group>"; };
@@ -205,7 +205,7 @@
 		EE247B211C3F137700AE3E12 /* FTS4Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS4Tests.swift; sourceTree = "<group>"; };
 		EE247B2A1C3F141E00AE3E12 /* OperatorsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperatorsTests.swift; sourceTree = "<group>"; };
 		EE247B2B1C3F141E00AE3E12 /* QueryTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryTests.swift; sourceTree = "<group>"; };
-		EE247B2C1C3F141E00AE3E12 /* R*TreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "R*TreeTests.swift"; sourceTree = "<group>"; };
+		EE247B2C1C3F141E00AE3E12 /* RTreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "RTreeTests.swift"; sourceTree = "<group>"; };
 		EE247B2D1C3F141E00AE3E12 /* SchemaTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaTests.swift; sourceTree = "<group>"; };
 		EE247B321C3F142E00AE3E12 /* StatementTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatementTests.swift; sourceTree = "<group>"; };
 		EE247B331C3F142E00AE3E12 /* ValueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValueTests.swift; sourceTree = "<group>"; };
@@ -407,7 +407,7 @@
 				EE247B211C3F137700AE3E12 /* FTS4Tests.swift */,
 				EE247B2A1C3F141E00AE3E12 /* OperatorsTests.swift */,
 				EE247B2B1C3F141E00AE3E12 /* QueryTests.swift */,
-				EE247B2C1C3F141E00AE3E12 /* R*TreeTests.swift */,
+				EE247B2C1C3F141E00AE3E12 /* RTreeTests.swift */,
 				EE247B2D1C3F141E00AE3E12 /* SchemaTests.swift */,
 				EE247B181C3F134A00AE3E12 /* SetterTests.swift */,
 				EE247B321C3F142E00AE3E12 /* StatementTests.swift */,
@@ -437,7 +437,7 @@
 			isa = PBXGroup;
 			children = (
 				EE247AF51C3F06E900AE3E12 /* FTS4.swift */,
-				EE247AF61C3F06E900AE3E12 /* R*Tree.swift */,
+				EE247AF61C3F06E900AE3E12 /* RTree.swift */,
 				19A1730E4390C775C25677D1 /* FTS5.swift */,
 			);
 			path = Extensions;
@@ -780,7 +780,7 @@
 			files = (
 				03A65E801C6BB2FB0062603F /* CoreFunctions.swift in Sources */,
 				03A65E761C6BB2E60062603F /* Blob.swift in Sources */,
-				03A65E7D1C6BB2F70062603F /* R*Tree.swift in Sources */,
+				03A65E7D1C6BB2F70062603F /* RTree.swift in Sources */,
 				03A65E791C6BB2EF0062603F /* SQLite-Bridging.m in Sources */,
 				03A65E7B1C6BB2F70062603F /* Value.swift in Sources */,
 				03A65E821C6BB2FB0062603F /* Expression.swift in Sources */,
@@ -805,7 +805,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				03A65E881C6BB3030062603F /* BlobTests.swift in Sources */,
-				03A65E901C6BB3030062603F /* R*TreeTests.swift in Sources */,
+				03A65E901C6BB3030062603F /* RTreeTests.swift in Sources */,
 				03A65E941C6BB3030062603F /* ValueTests.swift in Sources */,
 				03A65E8F1C6BB3030062603F /* QueryTests.swift in Sources */,
 				03A65E8B1C6BB3030062603F /* CustomFunctionsTests.swift in Sources */,
@@ -835,7 +835,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				EE247B0F1C3F06E900AE3E12 /* CoreFunctions.swift in Sources */,
-				EE247B0A1C3F06E900AE3E12 /* R*Tree.swift in Sources */,
+				EE247B0A1C3F06E900AE3E12 /* RTree.swift in Sources */,
 				EE247B031C3F06E900AE3E12 /* Blob.swift in Sources */,
 				EE247B0B1C3F06E900AE3E12 /* Foundation.swift in Sources */,
 				EE247B041C3F06E900AE3E12 /* Connection.swift in Sources */,
@@ -868,7 +868,7 @@
 				EE247B281C3F137700AE3E12 /* ExpressionTests.swift in Sources */,
 				EE247B271C3F137700AE3E12 /* CustomFunctionsTests.swift in Sources */,
 				EE247B341C3F142E00AE3E12 /* StatementTests.swift in Sources */,
-				EE247B301C3F141E00AE3E12 /* R*TreeTests.swift in Sources */,
+				EE247B301C3F141E00AE3E12 /* RTreeTests.swift in Sources */,
 				EE247B231C3F137700AE3E12 /* BlobTests.swift in Sources */,
 				EE247B351C3F142E00AE3E12 /* ValueTests.swift in Sources */,
 				EE247B2F1C3F141E00AE3E12 /* QueryTests.swift in Sources */,
@@ -885,7 +885,7 @@
 			files = (
 				EE247B6F1C3F3FEC00AE3E12 /* CoreFunctions.swift in Sources */,
 				EE247B651C3F3FEC00AE3E12 /* Blob.swift in Sources */,
-				EE247B6C1C3F3FEC00AE3E12 /* R*Tree.swift in Sources */,
+				EE247B6C1C3F3FEC00AE3E12 /* RTree.swift in Sources */,
 				EE247B681C3F3FEC00AE3E12 /* SQLite-Bridging.m in Sources */,
 				EE247B6A1C3F3FEC00AE3E12 /* Value.swift in Sources */,
 				EE247B711C3F3FEC00AE3E12 /* Expression.swift in Sources */,
@@ -916,7 +916,7 @@
 				EE247B591C3F3FC700AE3E12 /* FTS4Tests.swift in Sources */,
 				EE247B531C3F3FC700AE3E12 /* AggregateFunctionsTests.swift in Sources */,
 				EE247B5F1C3F3FC700AE3E12 /* StatementTests.swift in Sources */,
-				EE247B5C1C3F3FC700AE3E12 /* R*TreeTests.swift in Sources */,
+				EE247B5C1C3F3FC700AE3E12 /* RTreeTests.swift in Sources */,
 				EE247B571C3F3FC700AE3E12 /* CustomFunctionsTests.swift in Sources */,
 				EE247B601C3F3FC700AE3E12 /* ValueTests.swift in Sources */,
 				EE247B551C3F3FC700AE3E12 /* ConnectionTests.swift in Sources */,
diff --git a/SQLite/Extensions/R*Tree.swift b/SQLite/Extensions/RTree.swift
similarity index 100%
rename from SQLite/Extensions/R*Tree.swift
rename to SQLite/Extensions/RTree.swift
diff --git a/SQLiteTests/R*TreeTests.swift b/SQLiteTests/RTreeTests.swift
similarity index 100%
rename from SQLiteTests/R*TreeTests.swift
rename to SQLiteTests/RTreeTests.swift

From d5ede257ecba3281272e32232c4306641b2c3629 Mon Sep 17 00:00:00 2001
From: Daniel Alm <Daniel.Alm@ForumD.net>
Date: Mon, 9 May 2016 16:43:57 +0200
Subject: [PATCH 058/685] Fix transactions not being rolled back when the
 individual statements succeed, but the committing the transaction fails.

---
 SQLite/Core/Connection.swift      |  2 +-
 SQLiteTests/ConnectionTests.swift | 27 +++++++++++++++++++++++++++
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index 04fdd901..62a2b812 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -333,11 +333,11 @@ public final class Connection {
             try self.run(begin)
             do {
                 try block()
+                try self.run(commit)
             } catch {
                 try self.run(rollback)
                 throw error
             }
-            try self.run(commit)
         }
     }
 
diff --git a/SQLiteTests/ConnectionTests.swift b/SQLiteTests/ConnectionTests.swift
index 3d7dd3eb..eda4677a 100644
--- a/SQLiteTests/ConnectionTests.swift
+++ b/SQLiteTests/ConnectionTests.swift
@@ -125,6 +125,33 @@ class ConnectionTests : SQLiteTestCase {
         AssertSQL("ROLLBACK TRANSACTION", 0)
     }
 
+    func test_transaction_rollsBackTransactionsIfCommitsFail() {
+        // This test case needs to emulate an environment where the individual statements succeed, but committing the
+        // transactuin fails. Using deferred foreign keys is one option to achieve this.
+        try! db.execute("PRAGMA foreign_keys = ON;")
+        try! db.execute("PRAGMA defer_foreign_keys = ON;")
+        let stmt = try! db.prepare("INSERT INTO users (email, manager_id) VALUES (?, ?)", "alice@example.com", 100)
+
+        do {
+            try db.transaction {
+                try stmt.run()
+            }
+        } catch {
+        }
+
+        AssertSQL("BEGIN DEFERRED TRANSACTION")
+        AssertSQL("INSERT INTO users (email, manager_id) VALUES ('alice@example.com', 100)")
+        AssertSQL("COMMIT TRANSACTION")
+        AssertSQL("ROLLBACK TRANSACTION")
+
+        // Run another transaction to ensure that a subsequent transaction does not fail with an "cannot start a
+        // transaction within a transaction" error.
+        let stmt2 = try! db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com")
+        try! db.transaction {
+            try stmt2.run()
+        }
+    }
+
     func test_transaction_beginsAndRollsTransactionsBack() {
         let stmt = try! db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com")
 

From 39a065ce458ece86c815b9b7b3a30a51bb863ba4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mustafa=20Hast=C3=BCrk?= <mustafa.hasturk@yandex.com>
Date: Thu, 28 Jul 2016 11:53:24 +0300
Subject: [PATCH 059/685] remove --pre argument

Cocoapods 1.0.1 is now stable so we dont need to pass --pre argument
---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 850d3374..53d654fb 100644
--- a/README.md
+++ b/README.md
@@ -149,7 +149,7 @@ SQLite.swift with CocoaPods:
     ``` sh
     # Using the default Ruby install will require you to use sudo when
     # installing and updating gems.
-    sudo gem install --pre cocoapods
+    [sudo] gem install cocoapods
     ```
 
  2. Update your Podfile to include the following:

From 4ff05c6018435aecd238809ddb2f0e36d697002f Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 21 Jul 2016 15:12:12 +0100
Subject: [PATCH 060/685] Run tests on Xcode8-beta

---
 .travis.yml                                    |  7 +++++++
 CocoaPods/iphoneos-10.0/module.modulemap       |  4 ++++
 .../iphonesimulator-10.0/module.modulemap      |  4 ++++
 CocoaPods/macosx-10.12/module.modulemap        |  4 ++++
 Makefile                                       |  2 +-
 SQLite.xcodeproj/project.pbxproj               | 18 ++++++++++++++++++
 6 files changed, 38 insertions(+), 1 deletion(-)
 create mode 100644 CocoaPods/iphoneos-10.0/module.modulemap
 create mode 100644 CocoaPods/iphonesimulator-10.0/module.modulemap
 create mode 100644 CocoaPods/macosx-10.12/module.modulemap

diff --git a/.travis.yml b/.travis.yml
index b33f9af3..e4d9fe7b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,13 @@
 language: objective-c
 matrix:
+
   include:
+    - os: osx
+      osx_image: xcode8
+      env: BUILD_SCHEME="SQLite iOS"
+    - os: osx
+      osx_image: xcode8
+      env: BUILD_SCHEME="SQLite Mac"
     - env: BUILD_SCHEME="SQLite iOS"
     - env: BUILD_SCHEME="SQLite Mac"
     - env: VALIDATOR_SUBSPEC="none"
diff --git a/CocoaPods/iphoneos-10.0/module.modulemap b/CocoaPods/iphoneos-10.0/module.modulemap
new file mode 100644
index 00000000..67a6c203
--- /dev/null
+++ b/CocoaPods/iphoneos-10.0/module.modulemap
@@ -0,0 +1,4 @@
+module CSQLite [system] {
+    header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.sdk/usr/include/sqlite3.h"
+    export *
+}
diff --git a/CocoaPods/iphonesimulator-10.0/module.modulemap b/CocoaPods/iphonesimulator-10.0/module.modulemap
new file mode 100644
index 00000000..c8b84ab8
--- /dev/null
+++ b/CocoaPods/iphonesimulator-10.0/module.modulemap
@@ -0,0 +1,4 @@
+module CSQLite [system] {
+    header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator10.0.sdk/usr/include/sqlite3.h"
+    export *
+}
diff --git a/CocoaPods/macosx-10.12/module.modulemap b/CocoaPods/macosx-10.12/module.modulemap
new file mode 100644
index 00000000..8fc958e6
--- /dev/null
+++ b/CocoaPods/macosx-10.12/module.modulemap
@@ -0,0 +1,4 @@
+module CSQLite [system] {
+    header "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/include/sqlite3.h"
+    export *
+}
diff --git a/Makefile b/Makefile
index 7257b9b1..059a20b1 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 BUILD_TOOL = xcodebuild
 BUILD_SCHEME = SQLite Mac
 ifeq ($(BUILD_SCHEME),SQLite iOS)
-	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -sdk iphonesimulator
+	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -destination "platform=iOS Simulator,name=iPhone 6"
 else
 	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)"
 endif
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index d431ff3c..59bce055 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -686,15 +686,19 @@
 					};
 					EE247AD21C3F04ED00AE3E12 = {
 						CreatedOnToolsVersion = 7.2;
+						LastSwiftMigration = 0800;
 					};
 					EE247ADC1C3F04ED00AE3E12 = {
 						CreatedOnToolsVersion = 7.2;
+						LastSwiftMigration = 0800;
 					};
 					EE247B3B1C3F3ED000AE3E12 = {
 						CreatedOnToolsVersion = 7.2;
+						LastSwiftMigration = 0800;
 					};
 					EE247B441C3F3ED000AE3E12 = {
 						CreatedOnToolsVersion = 7.2;
+						LastSwiftMigration = 0800;
 					};
 				};
 			};
@@ -1167,8 +1171,11 @@
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
 				"SWIFT_INCLUDE_PATHS[sdk=iphoneos*]" = "$(SRCROOT)/CocoaPods/iphoneos";
+				"SWIFT_INCLUDE_PATHS[sdk=iphoneos10.0]" = "$(SRCROOT)/CocoaPods/iphoneos-10.0";
 				"SWIFT_INCLUDE_PATHS[sdk=iphonesimulator*]" = "$(SRCROOT)/CocoaPods/iphonesimulator";
+				"SWIFT_INCLUDE_PATHS[sdk=iphonesimulator10.0]" = "$(SRCROOT)/CocoaPods/iphonesimulator-10.0";
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+				SWIFT_VERSION = 2.3;
 			};
 			name = Debug;
 		};
@@ -1189,7 +1196,10 @@
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
 				"SWIFT_INCLUDE_PATHS[sdk=iphoneos*]" = "$(SRCROOT)/CocoaPods/iphoneos";
+				"SWIFT_INCLUDE_PATHS[sdk=iphoneos10.0]" = "$(SRCROOT)/CocoaPods/iphoneos-10.0";
 				"SWIFT_INCLUDE_PATHS[sdk=iphonesimulator*]" = "$(SRCROOT)/CocoaPods/iphonesimulator";
+				"SWIFT_INCLUDE_PATHS[sdk=iphonesimulator10.0]" = "$(SRCROOT)/CocoaPods/iphonesimulator-10.0";
+				SWIFT_VERSION = 2.3;
 			};
 			name = Release;
 		};
@@ -1200,6 +1210,7 @@
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_VERSION = 2.3;
 			};
 			name = Debug;
 		};
@@ -1210,6 +1221,7 @@
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_VERSION = 2.3;
 			};
 			name = Release;
 		};
@@ -1234,6 +1246,8 @@
 				SKIP_INSTALL = YES;
 				SWIFT_INCLUDE_PATHS = "";
 				"SWIFT_INCLUDE_PATHS[sdk=macosx*]" = "$(SRCROOT)/CocoaPods/macosx";
+				"SWIFT_INCLUDE_PATHS[sdk=macosx10.12]" = "$(SRCROOT)/CocoaPods/macosx-10.12";
+				SWIFT_VERSION = 2.3;
 			};
 			name = Debug;
 		};
@@ -1258,6 +1272,8 @@
 				SKIP_INSTALL = YES;
 				SWIFT_INCLUDE_PATHS = "";
 				"SWIFT_INCLUDE_PATHS[sdk=macosx*]" = "$(SRCROOT)/CocoaPods/macosx";
+				"SWIFT_INCLUDE_PATHS[sdk=macosx10.12]" = "$(SRCROOT)/CocoaPods/macosx-10.12";
+				SWIFT_VERSION = 2.3;
 			};
 			name = Release;
 		};
@@ -1272,6 +1288,7 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = macosx;
+				SWIFT_VERSION = 2.3;
 			};
 			name = Debug;
 		};
@@ -1286,6 +1303,7 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = macosx;
+				SWIFT_VERSION = 2.3;
 			};
 			name = Release;
 		};

From 4cdfd69bf405bf5eb91bc31203af3fd536097851 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 24 Aug 2016 12:12:51 +0100
Subject: [PATCH 061/685] Validate pod on xcode8

---
 .travis.yml | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/.travis.yml b/.travis.yml
index e4d9fe7b..c40d8e39 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,6 +8,15 @@ matrix:
     - os: osx
       osx_image: xcode8
       env: BUILD_SCHEME="SQLite Mac"
+    - os: osx
+      osx_image: xcode8
+      env: VALIDATOR_SUBSPEC="none"
+    - os: osx
+      osx_image: xcode8
+      env: VALIDATOR_SUBSPEC="standard"
+    - os: osx
+      osx_image: xcode8
+      env: VALIDATOR_SUBSPEC="standalone"
     - env: BUILD_SCHEME="SQLite iOS"
     - env: BUILD_SCHEME="SQLite Mac"
     - env: VALIDATOR_SUBSPEC="none"

From ed8980cf35b1756a1a4453378bb0bcebddc6890b Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 24 Aug 2016 12:57:44 +0100
Subject: [PATCH 062/685] Run tests on iPhone 6

---
 CocoaPodsTests/test_running_validator.rb | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/CocoaPodsTests/test_running_validator.rb b/CocoaPodsTests/test_running_validator.rb
index 10f4db61..ab0e12ed 100644
--- a/CocoaPodsTests/test_running_validator.rb
+++ b/CocoaPodsTests/test_running_validator.rb
@@ -7,6 +7,14 @@ class TestRunningValidator < Pod::Validator
   TEST_TARGET = 'Tests'
 
   attr_accessor :test_files
+  attr_accessor :iphone_simulator
+  attr_accessor :tvos_simulator
+
+  def initialize(spec_or_path, source_urls)
+    super(spec_or_path, source_urls)
+    self.iphone_simulator = 'iPhone 6'
+    self.tvos_simulator = 'Apple TV 1080p'
+  end
 
   def create_app_project
     super.tap do
@@ -67,12 +75,12 @@ def run_tests
     case consumer.platform_name
     when :ios
       command += %w(CODE_SIGN_IDENTITY=- -sdk iphonesimulator)
-      command += Fourflusher::SimControl.new.destination('iPhone 4s', deployment_target)
+      command += Fourflusher::SimControl.new.destination(iphone_simulator, deployment_target)
     when :osx
       command += %w(LD_RUNPATH_SEARCH_PATHS=@loader_path/../Frameworks)
     when :tvos
       command += %w(CODE_SIGN_IDENTITY=- -sdk appletvsimulator)
-      command += Fourflusher::SimControl.new.destination('Apple TV 1080p', deployment_target)
+      command += Fourflusher::SimControl.new.destination(tvos_simulator, deployment_target)
     else
       return # skip watchos
     end

From 775a26c542cfe21026e9038460669fe6d3df66be Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 24 Aug 2016 13:17:27 +0100
Subject: [PATCH 063/685] =?UTF-8?q?Don=E2=80=99t=20hardcode=20simulator=20?=
 =?UTF-8?q?version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 CocoaPodsTests/Gemfile                   |  2 +-
 CocoaPodsTests/Gemfile.lock              | 39 +++++++++++++-----------
 CocoaPodsTests/test_running_validator.rb |  8 ++---
 3 files changed, 27 insertions(+), 22 deletions(-)

diff --git a/CocoaPodsTests/Gemfile b/CocoaPodsTests/Gemfile
index 0a6af5c8..995a10e4 100644
--- a/CocoaPodsTests/Gemfile
+++ b/CocoaPodsTests/Gemfile
@@ -1,4 +1,4 @@
 source 'https://rubygems.org'
 
-gem 'cocoapods'
+gem 'cocoapods', '~> 1.1.0.beta1'
 gem 'minitest'
diff --git a/CocoaPodsTests/Gemfile.lock b/CocoaPodsTests/Gemfile.lock
index 7173e2c4..36f2a982 100644
--- a/CocoaPodsTests/Gemfile.lock
+++ b/CocoaPodsTests/Gemfile.lock
@@ -1,36 +1,37 @@
 GEM
   remote: https://rubygems.org/
   specs:
-    activesupport (4.2.6)
+    activesupport (4.2.7.1)
       i18n (~> 0.7)
       json (~> 1.7, >= 1.7.7)
       minitest (~> 5.1)
       thread_safe (~> 0.3, >= 0.3.4)
       tzinfo (~> 1.1)
     claide (1.0.0)
-    cocoapods (1.0.0)
-      activesupport (>= 4.0.2)
+    cocoapods (1.1.0.beta.1)
+      activesupport (>= 4.0.2, < 5)
       claide (>= 1.0.0, < 2.0)
-      cocoapods-core (= 1.0.0)
+      cocoapods-core (= 1.1.0.beta.1)
       cocoapods-deintegrate (>= 1.0.0, < 2.0)
-      cocoapods-downloader (>= 1.0.0, < 2.0)
+      cocoapods-downloader (>= 1.1.0, < 2.0)
       cocoapods-plugins (>= 1.0.0, < 2.0)
       cocoapods-search (>= 1.0.0, < 2.0)
       cocoapods-stats (>= 1.0.0, < 2.0)
       cocoapods-trunk (>= 1.0.0, < 2.0)
-      cocoapods-try (>= 1.0.0, < 2.0)
+      cocoapods-try (>= 1.1.0, < 2.0)
       colored (~> 1.2)
       escape (~> 0.0.4)
-      fourflusher (~> 0.3.0)
-      molinillo (~> 0.4.5)
+      fourflusher (~> 1.0.1)
+      gh_inspector (~> 1.0)
+      molinillo (~> 0.5.0)
       nap (~> 1.0)
-      xcodeproj (>= 1.0.0, < 2.0)
-    cocoapods-core (1.0.0)
+      xcodeproj (>= 1.2.0, < 2.0)
+    cocoapods-core (1.1.0.beta.1)
       activesupport (>= 4.0.2)
       fuzzy_match (~> 2.0.4)
       nap (~> 1.0)
     cocoapods-deintegrate (1.0.0)
-    cocoapods-downloader (1.0.0)
+    cocoapods-downloader (1.1.0)
     cocoapods-plugins (1.0.0)
       nap
     cocoapods-search (1.0.0)
@@ -38,21 +39,22 @@ GEM
     cocoapods-trunk (1.0.0)
       nap (>= 0.8, < 2.0)
       netrc (= 0.7.8)
-    cocoapods-try (1.0.0)
+    cocoapods-try (1.1.0)
     colored (1.2)
     escape (0.0.4)
-    fourflusher (0.3.0)
+    fourflusher (1.0.1)
     fuzzy_match (2.0.4)
+    gh_inspector (1.0.2)
     i18n (0.7.0)
     json (1.8.3)
-    minitest (5.8.4)
-    molinillo (0.4.5)
+    minitest (5.9.0)
+    molinillo (0.5.0)
     nap (1.1.0)
     netrc (0.7.8)
     thread_safe (0.3.5)
     tzinfo (1.2.2)
       thread_safe (~> 0.1)
-    xcodeproj (1.0.0)
+    xcodeproj (1.2.0)
       activesupport (>= 3)
       claide (>= 1.0.0, < 2.0)
       colored (~> 1.2)
@@ -61,5 +63,8 @@ PLATFORMS
   ruby
 
 DEPENDENCIES
-  cocoapods
+  cocoapods (~> 1.1.0.beta1)
   minitest
+
+BUNDLED WITH
+   1.10.6
diff --git a/CocoaPodsTests/test_running_validator.rb b/CocoaPodsTests/test_running_validator.rb
index ab0e12ed..e866d873 100644
--- a/CocoaPodsTests/test_running_validator.rb
+++ b/CocoaPodsTests/test_running_validator.rb
@@ -12,8 +12,8 @@ class TestRunningValidator < Pod::Validator
 
   def initialize(spec_or_path, source_urls)
     super(spec_or_path, source_urls)
-    self.iphone_simulator = 'iPhone 6'
-    self.tvos_simulator = 'Apple TV 1080p'
+    self.iphone_simulator = :oldest
+    self.tvos_simulator = :oldest
   end
 
   def create_app_project
@@ -75,12 +75,12 @@ def run_tests
     case consumer.platform_name
     when :ios
       command += %w(CODE_SIGN_IDENTITY=- -sdk iphonesimulator)
-      command += Fourflusher::SimControl.new.destination(iphone_simulator, deployment_target)
+      command += Fourflusher::SimControl.new.destination(iphone_simulator, 'iOS', deployment_target)
     when :osx
       command += %w(LD_RUNPATH_SEARCH_PATHS=@loader_path/../Frameworks)
     when :tvos
       command += %w(CODE_SIGN_IDENTITY=- -sdk appletvsimulator)
-      command += Fourflusher::SimControl.new.destination(tvos_simulator, deployment_target)
+      command += Fourflusher::SimControl.new.destination(tvos_simulator, 'tvOS', deployment_target)
     else
       return # skip watchos
     end

From 1cc0a535732cd5000a3d23ae703a25d6b58de8ef Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 13 Sep 2016 14:36:00 +0100
Subject: [PATCH 064/685] Bump cocoapods

---
 CocoaPodsTests/Gemfile      |  2 +-
 CocoaPodsTests/Gemfile.lock | 24 ++++++++++++------------
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/CocoaPodsTests/Gemfile b/CocoaPodsTests/Gemfile
index 995a10e4..86c90369 100644
--- a/CocoaPodsTests/Gemfile
+++ b/CocoaPodsTests/Gemfile
@@ -1,4 +1,4 @@
 source 'https://rubygems.org'
 
-gem 'cocoapods', '~> 1.1.0.beta1'
+gem 'cocoapods', '~> 1.1.0.rc.1'
 gem 'minitest'
diff --git a/CocoaPodsTests/Gemfile.lock b/CocoaPodsTests/Gemfile.lock
index 36f2a982..4252e155 100644
--- a/CocoaPodsTests/Gemfile.lock
+++ b/CocoaPodsTests/Gemfile.lock
@@ -8,12 +8,12 @@ GEM
       thread_safe (~> 0.3, >= 0.3.4)
       tzinfo (~> 1.1)
     claide (1.0.0)
-    cocoapods (1.1.0.beta.1)
+    cocoapods (1.1.0.rc.1)
       activesupport (>= 4.0.2, < 5)
       claide (>= 1.0.0, < 2.0)
-      cocoapods-core (= 1.1.0.beta.1)
-      cocoapods-deintegrate (>= 1.0.0, < 2.0)
-      cocoapods-downloader (>= 1.1.0, < 2.0)
+      cocoapods-core (= 1.1.0.rc.1)
+      cocoapods-deintegrate (>= 1.0.1, < 2.0)
+      cocoapods-downloader (>= 1.1.1, < 2.0)
       cocoapods-plugins (>= 1.0.0, < 2.0)
       cocoapods-search (>= 1.0.0, < 2.0)
       cocoapods-stats (>= 1.0.0, < 2.0)
@@ -25,13 +25,13 @@ GEM
       gh_inspector (~> 1.0)
       molinillo (~> 0.5.0)
       nap (~> 1.0)
-      xcodeproj (>= 1.2.0, < 2.0)
-    cocoapods-core (1.1.0.beta.1)
-      activesupport (>= 4.0.2)
+      xcodeproj (>= 1.3.1, < 2.0)
+    cocoapods-core (1.1.0.rc.1)
+      activesupport (>= 4.0.2, < 5)
       fuzzy_match (~> 2.0.4)
       nap (~> 1.0)
-    cocoapods-deintegrate (1.0.0)
-    cocoapods-downloader (1.1.0)
+    cocoapods-deintegrate (1.0.1)
+    cocoapods-downloader (1.1.1)
     cocoapods-plugins (1.0.0)
       nap
     cocoapods-search (1.0.0)
@@ -48,13 +48,13 @@ GEM
     i18n (0.7.0)
     json (1.8.3)
     minitest (5.9.0)
-    molinillo (0.5.0)
+    molinillo (0.5.1)
     nap (1.1.0)
     netrc (0.7.8)
     thread_safe (0.3.5)
     tzinfo (1.2.2)
       thread_safe (~> 0.1)
-    xcodeproj (1.2.0)
+    xcodeproj (1.3.1)
       activesupport (>= 3)
       claide (>= 1.0.0, < 2.0)
       colored (~> 1.2)
@@ -63,7 +63,7 @@ PLATFORMS
   ruby
 
 DEPENDENCIES
-  cocoapods (~> 1.1.0.beta1)
+  cocoapods (~> 1.1.0.rc.1)
   minitest
 
 BUNDLED WITH

From 0aaf650f4f1530e6d97e39ed454619ce5e9c8aed Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 13 Sep 2016 15:27:18 +0100
Subject: [PATCH 065/685] Set Swift version to 2.3

---
 CocoaPodsTests/test_running_validator.rb | 17 ++++++++++++++++-
 SQLite.xcodeproj/project.pbxproj         |  2 ++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/CocoaPodsTests/test_running_validator.rb b/CocoaPodsTests/test_running_validator.rb
index e866d873..0c21e90c 100644
--- a/CocoaPodsTests/test_running_validator.rb
+++ b/CocoaPodsTests/test_running_validator.rb
@@ -20,6 +20,8 @@ def create_app_project
     super.tap do
       project = Xcodeproj::Project.open(validation_dir + "#{APP_TARGET}.xcodeproj")
       create_test_target(project)
+      set_swift_version(project, '2.3')
+      project.save
     end
   end
 
@@ -45,6 +47,14 @@ def build_pod
   end
 
   private
+  def set_swift_version(project, version)
+    project.targets.each do |target|
+      target.build_configuration_list.build_configurations.each do |configuration|
+        configuration.build_settings['SWIFT_VERSION'] = version
+      end
+    end
+  end
+
   def create_test_target(project)
     test_target = project.new_target(:unit_test_bundle, TEST_TARGET, consumer.platform_name, deployment_target)
     group = project.new_group(TEST_TARGET)
@@ -71,7 +81,12 @@ def add_test_target(pod_file)
   end
 
   def run_tests
-    command = %W(clean test -workspace #{APP_TARGET}.xcworkspace -scheme #{TEST_TARGET} -configuration Debug)
+    command = [
+      'clean', 'test',
+      '-workspace', File.join(validation_dir, "#{APP_TARGET}.xcworkspace"),
+      '-scheme', TEST_TARGET,
+      '-configuration', 'Debug'
+    ]
     case consumer.platform_name
     when :ios
       command += %w(CODE_SIGN_IDENTITY=- -sdk iphonesimulator)
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 59bce055..03d27cd8 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -970,6 +970,7 @@
 				SKIP_INSTALL = YES;
 				"SWIFT_INCLUDE_PATHS[sdk=appletvos*]" = "$(SRCROOT)/CocoaPods/appletvos";
 				"SWIFT_INCLUDE_PATHS[sdk=appletvsimulator*]" = "$(SRCROOT)/CocoaPods/appletvsimulator";
+				SWIFT_VERSION = 2.3;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
 			name = Debug;
@@ -991,6 +992,7 @@
 				SKIP_INSTALL = YES;
 				"SWIFT_INCLUDE_PATHS[sdk=appletvos*]" = "$(SRCROOT)/CocoaPods/appletvos";
 				"SWIFT_INCLUDE_PATHS[sdk=appletvsimulator*]" = "$(SRCROOT)/CocoaPods/appletvsimulator";
+				SWIFT_VERSION = 2.3;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
 			name = Release;

From 2588c4440bc9aa36ba52189e5be0fceab46e641f Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 13 Sep 2016 17:32:33 +0100
Subject: [PATCH 066/685] Xcode8 compat changes

* Add modulemap for MacOSX 10.11
* Update modulemap
* Use iPhone SE simulator to fix test failures
  (https://github.com/travis-ci/travis-ci/issues/6422)
---
 .travis.yml                              | 21 ++++++++++++++++-----
 CocoaPods/macosx-10.11/module.modulemap  |  4 ++++
 CocoaPods/macosx/module.modulemap        |  2 +-
 CocoaPodsTests/integration_test.rb       |  7 +++++--
 CocoaPodsTests/test_running_validator.rb | 12 +++++++-----
 Makefile                                 |  3 ++-
 SQLite.swift.podspec                     | 18 +++++++++++-------
 SQLite.xcodeproj/project.pbxproj         |  6 ++++--
 run-tests.sh                             |  6 +++++-
 9 files changed, 55 insertions(+), 24 deletions(-)
 create mode 100644 CocoaPods/macosx-10.11/module.modulemap

diff --git a/.travis.yml b/.travis.yml
index c40d8e39..7deffc04 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,22 +1,30 @@
 language: objective-c
+rvm: 2.2
 matrix:
-
   include:
     - os: osx
       osx_image: xcode8
-      env: BUILD_SCHEME="SQLite iOS"
+      env:
+        - BUILD_SCHEME="SQLite iOS"
+        - IOS_SIMULATOR="iPhone SE"
     - os: osx
       osx_image: xcode8
       env: BUILD_SCHEME="SQLite Mac"
     - os: osx
       osx_image: xcode8
-      env: VALIDATOR_SUBSPEC="none"
+      env:
+        - VALIDATOR_SUBSPEC="none"
+        - IOS_SIMULATOR="iPhone SE"
     - os: osx
       osx_image: xcode8
-      env: VALIDATOR_SUBSPEC="standard"
+      env:
+        - VALIDATOR_SUBSPEC="standard"
+        - IOS_SIMULATOR="iPhone SE"
     - os: osx
       osx_image: xcode8
-      env: VALIDATOR_SUBSPEC="standalone"
+      env:
+        - VALIDATOR_SUBSPEC="standalone"
+        - IOS_SIMULATOR="iPhone SE"
     - env: BUILD_SCHEME="SQLite iOS"
     - env: BUILD_SCHEME="SQLite Mac"
     - env: VALIDATOR_SUBSPEC="none"
@@ -26,4 +34,7 @@ before_install:
   - gem install xcpretty --no-document
 script:
   - ./run-tests.sh
+after_failure:
+  - find $HOME/Library/Developer/Xcode/DerivedData/ -name '*.log' -print0 | xargs -0 cat
+  - cat /var/log/system.log
 osx_image: xcode7.3
diff --git a/CocoaPods/macosx-10.11/module.modulemap b/CocoaPods/macosx-10.11/module.modulemap
new file mode 100644
index 00000000..9e091297
--- /dev/null
+++ b/CocoaPods/macosx-10.11/module.modulemap
@@ -0,0 +1,4 @@
+module CSQLite [system] {
+    header "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/sqlite3.h"
+    export *
+}
diff --git a/CocoaPods/macosx/module.modulemap b/CocoaPods/macosx/module.modulemap
index 9e091297..cc8370ec 100644
--- a/CocoaPods/macosx/module.modulemap
+++ b/CocoaPods/macosx/module.modulemap
@@ -1,4 +1,4 @@
 module CSQLite [system] {
-    header "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/sqlite3.h"
+    header "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sqlite3.h"
     export *
 }
diff --git a/CocoaPodsTests/integration_test.rb b/CocoaPodsTests/integration_test.rb
index 429a9c77..c62e066e 100755
--- a/CocoaPodsTests/integration_test.rb
+++ b/CocoaPodsTests/integration_test.rb
@@ -13,7 +13,6 @@ def test_validate_project
 
   def validator
     @validator ||= TestRunningValidator.new(podspec, []).tap do |validator|
-    	subspec = ENV["VALIDATOR_SUBSPEC"]
         validator.test_files = Dir["#{project_test_dir}/*.swift"]
         validator.config.verbose = true
         validator.no_clean = true
@@ -21,11 +20,15 @@ def validator
         validator.fail_fast = true
         validator.local = true
         validator.allow_warnings = true
-        if subspec == "none"
+        subspec = ENV['VALIDATOR_SUBSPEC']
+        if subspec == 'none'
           validator.no_subspecs = true
         else
           validator.only_subspec = subspec
         end
+        if ENV['IOS_SIMULATOR']
+          validator.ios_simulator = ENV['IOS_SIMULATOR']
+        end
     end
   end
 
diff --git a/CocoaPodsTests/test_running_validator.rb b/CocoaPodsTests/test_running_validator.rb
index 0c21e90c..17fd88d7 100644
--- a/CocoaPodsTests/test_running_validator.rb
+++ b/CocoaPodsTests/test_running_validator.rb
@@ -7,12 +7,12 @@ class TestRunningValidator < Pod::Validator
   TEST_TARGET = 'Tests'
 
   attr_accessor :test_files
-  attr_accessor :iphone_simulator
+  attr_accessor :ios_simulator
   attr_accessor :tvos_simulator
 
   def initialize(spec_or_path, source_urls)
     super(spec_or_path, source_urls)
-    self.iphone_simulator = :oldest
+    self.ios_simulator = :oldest
     self.tvos_simulator = :oldest
   end
 
@@ -61,7 +61,7 @@ def create_test_target(project)
     test_target.add_file_references(test_files.map { |file| group.new_file(file) })
     project.save
     create_test_scheme(project, test_target)
-    project
+    test_target
   end
 
   def create_test_scheme(project, test_target)
@@ -90,7 +90,7 @@ def run_tests
     case consumer.platform_name
     when :ios
       command += %w(CODE_SIGN_IDENTITY=- -sdk iphonesimulator)
-      command += Fourflusher::SimControl.new.destination(iphone_simulator, 'iOS', deployment_target)
+      command += Fourflusher::SimControl.new.destination(ios_simulator, 'iOS', deployment_target)
     when :osx
       command += %w(LD_RUNPATH_SEARCH_PATHS=@loader_path/../Frameworks)
     when :tvos
@@ -100,7 +100,8 @@ def run_tests
       return # skip watchos
     end
 
-    output, status = Dir.chdir(validation_dir) { _xcodebuild(command) }
+    output, status = _xcodebuild(command)
+
     unless status.success?
       message = 'Returned an unsuccessful exit code.'
       if config.verbose?
@@ -110,5 +111,6 @@ def run_tests
       end
       error('xcodebuild', message)
     end
+    output
   end
 end
diff --git a/Makefile b/Makefile
index 059a20b1..35edf493 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,8 @@
 BUILD_TOOL = xcodebuild
 BUILD_SCHEME = SQLite Mac
+IOS_SIMULATOR = iPhone 6
 ifeq ($(BUILD_SCHEME),SQLite iOS)
-	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -destination "platform=iOS Simulator,name=iPhone 6"
+	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -destination "platform=iOS Simulator,name=$(IOS_SIMULATOR)"
 else
 	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)"
 endif
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 6e5e25d5..b0fb7965 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -33,13 +33,17 @@ Pod::Spec.new do |s|
     ss.library = 'sqlite3'
     ss.preserve_paths = 'CocoaPods/**/*'
     ss.pod_target_xcconfig = {
-      'SWIFT_INCLUDE_PATHS[sdk=macosx*]'           => '$(SRCROOT)/SQLite.swift/CocoaPods/macosx',
-      'SWIFT_INCLUDE_PATHS[sdk=iphoneos*]'         => '$(SRCROOT)/SQLite.swift/CocoaPods/iphoneos',
-      'SWIFT_INCLUDE_PATHS[sdk=iphonesimulator*]'  => '$(SRCROOT)/SQLite.swift/CocoaPods/iphonesimulator',
-      'SWIFT_INCLUDE_PATHS[sdk=appletvos*]'        => '$(SRCROOT)/SQLite.swift/CocoaPods/appletvos',
-      'SWIFT_INCLUDE_PATHS[sdk=appletvsimulator*]' => '$(SRCROOT)/SQLite.swift/CocoaPods/appletvsimulator',
-      'SWIFT_INCLUDE_PATHS[sdk=watchos*]'          => '$(SRCROOT)/SQLite.swift/CocoaPods/watchos',
-      'SWIFT_INCLUDE_PATHS[sdk=watchsimulator*]'   => '$(SRCROOT)/SQLite.swift/CocoaPods/watchsimulator'
+      'SWIFT_INCLUDE_PATHS[sdk=macosx*]'             => '$(SRCROOT)/SQLite.swift/CocoaPods/macosx',
+      'SWIFT_INCLUDE_PATHS[sdk=macosx10.11]'         => '$(SRCROOT)/SQLite.swift/CocoaPods/macosx-10.11',
+      'SWIFT_INCLUDE_PATHS[sdk=macosx10.12]'         => '$(SRCROOT)/SQLite.swift/CocoaPods/macosx-10.12',
+      'SWIFT_INCLUDE_PATHS[sdk=iphoneos*]'           => '$(SRCROOT)/SQLite.swift/CocoaPods/iphoneos',
+      'SWIFT_INCLUDE_PATHS[sdk=iphoneos10.0]'        => '$(SRCROOT)/SQLite.swift/CocoaPods/iphoneos-10.0',
+      'SWIFT_INCLUDE_PATHS[sdk=iphonesimulator*]'    => '$(SRCROOT)/SQLite.swift/CocoaPods/iphonesimulator',
+      'SWIFT_INCLUDE_PATHS[sdk=iphonesimulator10.0]' => '$(SRCROOT)/SQLite.swift/CocoaPods/iphonesimulator-10.0',
+      'SWIFT_INCLUDE_PATHS[sdk=appletvos*]'          => '$(SRCROOT)/SQLite.swift/CocoaPods/appletvos',
+      'SWIFT_INCLUDE_PATHS[sdk=appletvsimulator*]'   => '$(SRCROOT)/SQLite.swift/CocoaPods/appletvsimulator',
+      'SWIFT_INCLUDE_PATHS[sdk=watchos*]'            => '$(SRCROOT)/SQLite.swift/CocoaPods/watchos',
+      'SWIFT_INCLUDE_PATHS[sdk=watchsimulator*]'     => '$(SRCROOT)/SQLite.swift/CocoaPods/watchsimulator'
     }
   end
 
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 03d27cd8..f7450bd2 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -182,7 +182,7 @@
 		EE247AF21C3F06E900AE3E12 /* Statement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Statement.swift; sourceTree = "<group>"; };
 		EE247AF31C3F06E900AE3E12 /* Value.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Value.swift; sourceTree = "<group>"; };
 		EE247AF51C3F06E900AE3E12 /* FTS4.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS4.swift; sourceTree = "<group>"; };
-		EE247AF61C3F06E900AE3E12 /* RTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "RTree.swift"; sourceTree = "<group>"; };
+		EE247AF61C3F06E900AE3E12 /* RTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RTree.swift; sourceTree = "<group>"; };
 		EE247AF71C3F06E900AE3E12 /* Foundation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Foundation.swift; sourceTree = "<group>"; };
 		EE247AF81C3F06E900AE3E12 /* Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = "<group>"; };
 		EE247AFA1C3F06E900AE3E12 /* AggregateFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AggregateFunctions.swift; sourceTree = "<group>"; };
@@ -205,7 +205,7 @@
 		EE247B211C3F137700AE3E12 /* FTS4Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS4Tests.swift; sourceTree = "<group>"; };
 		EE247B2A1C3F141E00AE3E12 /* OperatorsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperatorsTests.swift; sourceTree = "<group>"; };
 		EE247B2B1C3F141E00AE3E12 /* QueryTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryTests.swift; sourceTree = "<group>"; };
-		EE247B2C1C3F141E00AE3E12 /* RTreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "RTreeTests.swift"; sourceTree = "<group>"; };
+		EE247B2C1C3F141E00AE3E12 /* RTreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RTreeTests.swift; sourceTree = "<group>"; };
 		EE247B2D1C3F141E00AE3E12 /* SchemaTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaTests.swift; sourceTree = "<group>"; };
 		EE247B321C3F142E00AE3E12 /* StatementTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatementTests.swift; sourceTree = "<group>"; };
 		EE247B331C3F142E00AE3E12 /* ValueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValueTests.swift; sourceTree = "<group>"; };
@@ -1248,6 +1248,7 @@
 				SKIP_INSTALL = YES;
 				SWIFT_INCLUDE_PATHS = "";
 				"SWIFT_INCLUDE_PATHS[sdk=macosx*]" = "$(SRCROOT)/CocoaPods/macosx";
+				"SWIFT_INCLUDE_PATHS[sdk=macosx10.11]" = "$(SRCROOT)/CocoaPods/macosx-10.11";
 				"SWIFT_INCLUDE_PATHS[sdk=macosx10.12]" = "$(SRCROOT)/CocoaPods/macosx-10.12";
 				SWIFT_VERSION = 2.3;
 			};
@@ -1274,6 +1275,7 @@
 				SKIP_INSTALL = YES;
 				SWIFT_INCLUDE_PATHS = "";
 				"SWIFT_INCLUDE_PATHS[sdk=macosx*]" = "$(SRCROOT)/CocoaPods/macosx";
+				"SWIFT_INCLUDE_PATHS[sdk=macosx10.11]" = "$(SRCROOT)/CocoaPods/macosx-10.11";
 				"SWIFT_INCLUDE_PATHS[sdk=macosx10.12]" = "$(SRCROOT)/CocoaPods/macosx-10.12";
 				SWIFT_VERSION = 2.3;
 			};
diff --git a/run-tests.sh b/run-tests.sh
index 7a35fb02..bc8cd773 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -1,7 +1,11 @@
 #!/bin/bash
 set -ev
 if [ -n "$BUILD_SCHEME" ]; then
-    make test BUILD_SCHEME="$BUILD_SCHEME"
+    if [ -n "$IOS_SIMULATOR" ]; then
+        make test BUILD_SCHEME="$BUILD_SCHEME" IOS_SIMULATOR="$IOS_SIMULATOR"
+    else
+        make test BUILD_SCHEME="$BUILD_SCHEME"
+    fi
 elif [ -n "$VALIDATOR_SUBSPEC" ]; then
     cd CocoaPodsTests && make test
 fi

From b62880efe87ccb19eb2f44fc39212179c7b908da Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 14 Sep 2016 22:24:03 +0100
Subject: [PATCH 067/685] Update CocoaPods, update repo

---
 CocoaPodsTests/Gemfile      |  2 +-
 CocoaPodsTests/Gemfile.lock | 10 +++++-----
 CocoaPodsTests/Makefile     |  5 ++++-
 3 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/CocoaPodsTests/Gemfile b/CocoaPodsTests/Gemfile
index 86c90369..287dcbfc 100644
--- a/CocoaPodsTests/Gemfile
+++ b/CocoaPodsTests/Gemfile
@@ -1,4 +1,4 @@
 source 'https://rubygems.org'
 
-gem 'cocoapods', '~> 1.1.0.rc.1'
+gem 'cocoapods', '~> 1.1.0.rc.2'
 gem 'minitest'
diff --git a/CocoaPodsTests/Gemfile.lock b/CocoaPodsTests/Gemfile.lock
index 4252e155..93a54bb9 100644
--- a/CocoaPodsTests/Gemfile.lock
+++ b/CocoaPodsTests/Gemfile.lock
@@ -8,10 +8,10 @@ GEM
       thread_safe (~> 0.3, >= 0.3.4)
       tzinfo (~> 1.1)
     claide (1.0.0)
-    cocoapods (1.1.0.rc.1)
+    cocoapods (1.1.0.rc.2)
       activesupport (>= 4.0.2, < 5)
       claide (>= 1.0.0, < 2.0)
-      cocoapods-core (= 1.1.0.rc.1)
+      cocoapods-core (= 1.1.0.rc.2)
       cocoapods-deintegrate (>= 1.0.1, < 2.0)
       cocoapods-downloader (>= 1.1.1, < 2.0)
       cocoapods-plugins (>= 1.0.0, < 2.0)
@@ -23,10 +23,10 @@ GEM
       escape (~> 0.0.4)
       fourflusher (~> 1.0.1)
       gh_inspector (~> 1.0)
-      molinillo (~> 0.5.0)
+      molinillo (~> 0.5.1)
       nap (~> 1.0)
       xcodeproj (>= 1.3.1, < 2.0)
-    cocoapods-core (1.1.0.rc.1)
+    cocoapods-core (1.1.0.rc.2)
       activesupport (>= 4.0.2, < 5)
       fuzzy_match (~> 2.0.4)
       nap (~> 1.0)
@@ -63,7 +63,7 @@ PLATFORMS
   ruby
 
 DEPENDENCIES
-  cocoapods (~> 1.1.0.rc.1)
+  cocoapods (~> 1.1.0.rc.2)
   minitest
 
 BUNDLED WITH
diff --git a/CocoaPodsTests/Makefile b/CocoaPodsTests/Makefile
index c9a3182e..26163fdb 100644
--- a/CocoaPodsTests/Makefile
+++ b/CocoaPodsTests/Makefile
@@ -1,9 +1,12 @@
-test: install
+test: install repo_update
 	@set -e; \
 	for test in *_test.rb; do \
 		bundle exec ./$$test; \
 	done
 
+repo_update:
+	@bundle exec pod repo update --silent
+
 install:
 	@bundle install --path gems
 

From 9fa5b908ae67e033a9bc7d498735c237b7c198b5 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 14 Sep 2016 23:11:26 +0100
Subject: [PATCH 068/685] Use recommended Xcode8 project settings

---
 SQLite.xcodeproj/project.pbxproj                | 17 ++++++++++++++---
 .../xcshareddata/xcschemes/SQLite Mac.xcscheme  |  2 +-
 .../xcshareddata/xcschemes/SQLite iOS.xcscheme  |  2 +-
 .../xcshareddata/xcschemes/SQLite tvOS.xcscheme |  2 +-
 4 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index f7450bd2..a69730d4 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -673,7 +673,7 @@
 			isa = PBXProject;
 			attributes = {
 				LastSwiftUpdateCheck = 0720;
-				LastUpgradeCheck = 0720;
+				LastUpgradeCheck = 0800;
 				TargetAttributes = {
 					03A65E591C6BB0F50062603F = {
 						CreatedOnToolsVersion = 7.2;
@@ -957,6 +957,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				APPLICATION_EXTENSION_API_ONLY = YES;
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
 				DEFINES_MODULE = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
@@ -979,6 +980,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				APPLICATION_EXTENSION_API_ONLY = YES;
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
 				DEFINES_MODULE = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
@@ -1026,6 +1028,7 @@
 			buildSettings = {
 				APPLICATION_EXTENSION_API_ONLY = YES;
 				CLANG_ANALYZER_NONNULL = YES;
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
 				DEFINES_MODULE = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
@@ -1047,6 +1050,7 @@
 			buildSettings = {
 				APPLICATION_EXTENSION_API_ONLY = YES;
 				CLANG_ANALYZER_NONNULL = YES;
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
 				DEFINES_MODULE = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
@@ -1076,8 +1080,10 @@
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
 				CLANG_WARN_EMPTY_BODY = YES;
 				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
 				CLANG_WARN_INT_CONVERSION = YES;
 				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
 				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
@@ -1126,8 +1132,10 @@
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
 				CLANG_WARN_EMPTY_BODY = YES;
 				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
 				CLANG_WARN_INT_CONVERSION = YES;
 				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
 				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
@@ -1149,6 +1157,7 @@
 				MTL_ENABLE_DEBUG_INFO = NO;
 				PRODUCT_NAME = "";
 				SDKROOT = iphoneos;
+				SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
 				TARGETED_DEVICE_FAMILY = "1,2,3";
 				VALIDATE_PRODUCT = YES;
 				VERSIONING_SYSTEM = "apple-generic";
@@ -1161,6 +1170,7 @@
 			buildSettings = {
 				APPLICATION_EXTENSION_API_ONLY = YES;
 				CLANG_ENABLE_MODULES = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
 				DEFINES_MODULE = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
@@ -1186,6 +1196,7 @@
 			buildSettings = {
 				APPLICATION_EXTENSION_API_ONLY = YES;
 				CLANG_ENABLE_MODULES = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
 				DEFINES_MODULE = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
@@ -1231,7 +1242,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				APPLICATION_EXTENSION_API_ONLY = YES;
-				CODE_SIGN_IDENTITY = "-";
+				CODE_SIGN_IDENTITY = "";
 				COMBINE_HIDPI_IMAGES = YES;
 				DEFINES_MODULE = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
@@ -1258,7 +1269,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				APPLICATION_EXTENSION_API_ONLY = YES;
-				CODE_SIGN_IDENTITY = "-";
+				CODE_SIGN_IDENTITY = "";
 				COMBINE_HIDPI_IMAGES = YES;
 				DEFINES_MODULE = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme
index fa91858e..606b5a10 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme	
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0720"
+   LastUpgradeVersion = "0800"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme
index 534df7df..64f32011 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme	
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0720"
+   LastUpgradeVersion = "0800"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme
index f500a2ae..71ba5f16 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme	
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0720"
+   LastUpgradeVersion = "0800"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"

From 3df6b05361dd318f5fd483de9f57892e71cdebc5 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 14 Sep 2016 22:00:53 +0100
Subject: [PATCH 069/685] travis: use xcode8 as default image

---
 .travis.yml | 42 +++++++++++++++++++++---------------------
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 7deffc04..d855fb3c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,35 +1,36 @@
 language: objective-c
 rvm: 2.2
+osx_image: xcode8
 matrix:
   include:
-    - os: osx
-      osx_image: xcode8
-      env:
+    - env:
         - BUILD_SCHEME="SQLite iOS"
         - IOS_SIMULATOR="iPhone SE"
-    - os: osx
-      osx_image: xcode8
-      env: BUILD_SCHEME="SQLite Mac"
-    - os: osx
-      osx_image: xcode8
-      env:
+    - env: BUILD_SCHEME="SQLite Mac"
+    - env:
         - VALIDATOR_SUBSPEC="none"
         - IOS_SIMULATOR="iPhone SE"
-    - os: osx
-      osx_image: xcode8
-      env:
+    - env:
         - VALIDATOR_SUBSPEC="standard"
         - IOS_SIMULATOR="iPhone SE"
-    - os: osx
-      osx_image: xcode8
-      env:
+    - env:
         - VALIDATOR_SUBSPEC="standalone"
         - IOS_SIMULATOR="iPhone SE"
-    - env: BUILD_SCHEME="SQLite iOS"
-    - env: BUILD_SCHEME="SQLite Mac"
-    - env: VALIDATOR_SUBSPEC="none"
-    - env: VALIDATOR_SUBSPEC="standard"
-    - env: VALIDATOR_SUBSPEC="standalone"
+    - os: osx
+      osx_image: xcode7.3
+      env: BUILD_SCHEME="SQLite iOS"
+    - os: osx
+      osx_image: xcode7.3
+      env: BUILD_SCHEME="SQLite Mac"
+    - os: osx
+      osx_image: xcode7.3
+      env: VALIDATOR_SUBSPEC="none"
+    - os: osx
+      osx_image: xcode7.3
+      env: VALIDATOR_SUBSPEC="standard"
+    - os: osx
+      osx_image: xcode7.3
+      env: VALIDATOR_SUBSPEC="standalone"
 before_install:
   - gem install xcpretty --no-document
 script:
@@ -37,4 +38,3 @@ script:
 after_failure:
   - find $HOME/Library/Developer/Xcode/DerivedData/ -name '*.log' -print0 | xargs -0 cat
   - cat /var/log/system.log
-osx_image: xcode7.3

From 90e662e1e9e502b66d60d658ab076482d1251e3a Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 16 Sep 2016 16:38:55 +0100
Subject: [PATCH 070/685] Add Swift version to xcconfig

---
 SQLite.swift.podspec | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index b0fb7965..89cffff1 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -25,6 +25,9 @@ Pod::Spec.new do |s|
   s.osx.deployment_target = "10.9"
   s.watchos.deployment_target = "2.0"
   s.default_subspec  = 'standard'
+  s.pod_target_xcconfig = {
+    'SWIFT_VERSION' => '2.3',
+  }
 
   s.subspec 'standard' do |ss|
     ss.source_files = 'SQLite/**/*.{c,h,m,swift}'

From 494f3c4e8810dc06e9c71b825cc14eb3571d2cc7 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 16 Sep 2016 16:39:30 +0100
Subject: [PATCH 071/685] use Pod::Validator#add_swift_version

---
 .swift-version                           |  1 +
 CocoaPodsTests/test_running_validator.rb | 39 +++++++++++-------------
 2 files changed, 18 insertions(+), 22 deletions(-)
 create mode 100644 .swift-version

diff --git a/.swift-version b/.swift-version
new file mode 100644
index 00000000..bb576dbd
--- /dev/null
+++ b/.swift-version
@@ -0,0 +1 @@
+2.3
diff --git a/CocoaPodsTests/test_running_validator.rb b/CocoaPodsTests/test_running_validator.rb
index 17fd88d7..1eefa4b8 100644
--- a/CocoaPodsTests/test_running_validator.rb
+++ b/CocoaPodsTests/test_running_validator.rb
@@ -17,19 +17,26 @@ def initialize(spec_or_path, source_urls)
   end
 
   def create_app_project
-    super.tap do
-      project = Xcodeproj::Project.open(validation_dir + "#{APP_TARGET}.xcodeproj")
-      create_test_target(project)
-      set_swift_version(project, '2.3')
-      project.save
-    end
+    super
+    project = Xcodeproj::Project.open(validation_dir + "#{APP_TARGET}.xcodeproj")
+    create_test_target(project)
+    project.save
+  end
+
+  def add_app_project_import
+    super
+    project = Xcodeproj::Project.open(validation_dir + 'App.xcodeproj')
+    group = project.new_group(TEST_TARGET)
+    test_target = project.targets.last
+    test_target.add_file_references(test_files.map { |file| group.new_file(file) })
+    add_swift_version(test_target)
+    project.save
   end
 
   def install_pod
-    super.tap do
-      if local?
-        FileUtils.ln_s file.dirname, validation_dir + "Pods/#{spec.name}"
-      end
+    super
+    if local?
+      FileUtils.ln_s file.dirname, validation_dir + "Pods/#{spec.name}"
     end
   end
 
@@ -47,21 +54,9 @@ def build_pod
   end
 
   private
-  def set_swift_version(project, version)
-    project.targets.each do |target|
-      target.build_configuration_list.build_configurations.each do |configuration|
-        configuration.build_settings['SWIFT_VERSION'] = version
-      end
-    end
-  end
-
   def create_test_target(project)
     test_target = project.new_target(:unit_test_bundle, TEST_TARGET, consumer.platform_name, deployment_target)
-    group = project.new_group(TEST_TARGET)
-    test_target.add_file_references(test_files.map { |file| group.new_file(file) })
-    project.save
     create_test_scheme(project, test_target)
-    test_target
   end
 
   def create_test_scheme(project, test_target)

From 8f9b8a855f9d473c8389d2927b4321217e5622cc Mon Sep 17 00:00:00 2001
From: Mariotaku Lee <mariotaku.lee@gmail.com>
Date: Fri, 16 Sep 2016 17:45:29 +0800
Subject: [PATCH 072/685] migrating to swift 3

---
 SQLite.xcodeproj/project.pbxproj      |  20 +-
 SQLite/Core/Blob.swift                |  10 +-
 SQLite/Core/Connection.swift          | 198 ++++++++++---------
 SQLite/Core/Statement.swift           |  60 +++---
 SQLite/Core/Value.swift               |  14 +-
 SQLite/Extensions/FTS4.swift          | 114 +++++------
 SQLite/Extensions/FTS5.swift          |  28 +--
 SQLite/Extensions/RTree.swift         |   4 +-
 SQLite/Foundation.swift               |  46 ++---
 SQLite/Helpers.swift                  |  32 +--
 SQLite/Typed/AggregateFunctions.swift |   4 +-
 SQLite/Typed/Collation.swift          |  16 +-
 SQLite/Typed/CoreFunctions.swift      |  68 +++----
 SQLite/Typed/CustomFunctions.swift    |  32 +--
 SQLite/Typed/Expression.swift         |   4 +-
 SQLite/Typed/Operators.swift          | 272 +++++++++++++-------------
 SQLite/Typed/Query.swift              | 130 ++++++------
 SQLite/Typed/Schema.swift             | 164 ++++++++--------
 SQLite/Typed/Setter.swift             | 128 ++++++------
 SQLiteTests/ConnectionTests.swift     |  76 +++----
 SQLiteTests/CoreFunctionsTests.swift  |  18 +-
 SQLiteTests/FTS4Tests.swift           |  26 +--
 SQLiteTests/FTS5Tests.swift           |   8 +-
 SQLiteTests/OperatorsTests.swift      |   2 +-
 SQLiteTests/QueryTests.swift          |   4 +-
 SQLiteTests/SchemaTests.swift         | 106 +++++-----
 SQLiteTests/TestHelpers.swift         |  30 +--
 27 files changed, 811 insertions(+), 803 deletions(-)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index a69730d4..2f13a35f 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -971,7 +971,7 @@
 				SKIP_INSTALL = YES;
 				"SWIFT_INCLUDE_PATHS[sdk=appletvos*]" = "$(SRCROOT)/CocoaPods/appletvos";
 				"SWIFT_INCLUDE_PATHS[sdk=appletvsimulator*]" = "$(SRCROOT)/CocoaPods/appletvsimulator";
-				SWIFT_VERSION = 2.3;
+				SWIFT_VERSION = 3.0;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
 			name = Debug;
@@ -994,7 +994,7 @@
 				SKIP_INSTALL = YES;
 				"SWIFT_INCLUDE_PATHS[sdk=appletvos*]" = "$(SRCROOT)/CocoaPods/appletvos";
 				"SWIFT_INCLUDE_PATHS[sdk=appletvsimulator*]" = "$(SRCROOT)/CocoaPods/appletvsimulator";
-				SWIFT_VERSION = 2.3;
+				SWIFT_VERSION = 3.0;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
 			name = Release;
@@ -1187,7 +1187,7 @@
 				"SWIFT_INCLUDE_PATHS[sdk=iphonesimulator*]" = "$(SRCROOT)/CocoaPods/iphonesimulator";
 				"SWIFT_INCLUDE_PATHS[sdk=iphonesimulator10.0]" = "$(SRCROOT)/CocoaPods/iphonesimulator-10.0";
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
-				SWIFT_VERSION = 2.3;
+				SWIFT_VERSION = 3.0;
 			};
 			name = Debug;
 		};
@@ -1212,7 +1212,7 @@
 				"SWIFT_INCLUDE_PATHS[sdk=iphoneos10.0]" = "$(SRCROOT)/CocoaPods/iphoneos-10.0";
 				"SWIFT_INCLUDE_PATHS[sdk=iphonesimulator*]" = "$(SRCROOT)/CocoaPods/iphonesimulator";
 				"SWIFT_INCLUDE_PATHS[sdk=iphonesimulator10.0]" = "$(SRCROOT)/CocoaPods/iphonesimulator-10.0";
-				SWIFT_VERSION = 2.3;
+				SWIFT_VERSION = 3.0;
 			};
 			name = Release;
 		};
@@ -1223,7 +1223,7 @@
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
-				SWIFT_VERSION = 2.3;
+				SWIFT_VERSION = 3.0;
 			};
 			name = Debug;
 		};
@@ -1234,7 +1234,7 @@
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
-				SWIFT_VERSION = 2.3;
+				SWIFT_VERSION = 3.0;
 			};
 			name = Release;
 		};
@@ -1261,7 +1261,7 @@
 				"SWIFT_INCLUDE_PATHS[sdk=macosx*]" = "$(SRCROOT)/CocoaPods/macosx";
 				"SWIFT_INCLUDE_PATHS[sdk=macosx10.11]" = "$(SRCROOT)/CocoaPods/macosx-10.11";
 				"SWIFT_INCLUDE_PATHS[sdk=macosx10.12]" = "$(SRCROOT)/CocoaPods/macosx-10.12";
-				SWIFT_VERSION = 2.3;
+				SWIFT_VERSION = 3.0;
 			};
 			name = Debug;
 		};
@@ -1288,7 +1288,7 @@
 				"SWIFT_INCLUDE_PATHS[sdk=macosx*]" = "$(SRCROOT)/CocoaPods/macosx";
 				"SWIFT_INCLUDE_PATHS[sdk=macosx10.11]" = "$(SRCROOT)/CocoaPods/macosx-10.11";
 				"SWIFT_INCLUDE_PATHS[sdk=macosx10.12]" = "$(SRCROOT)/CocoaPods/macosx-10.12";
-				SWIFT_VERSION = 2.3;
+				SWIFT_VERSION = 3.0;
 			};
 			name = Release;
 		};
@@ -1303,7 +1303,7 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = macosx;
-				SWIFT_VERSION = 2.3;
+				SWIFT_VERSION = 3.0;
 			};
 			name = Debug;
 		};
@@ -1318,7 +1318,7 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = macosx;
-				SWIFT_VERSION = 2.3;
+				SWIFT_VERSION = 3.0;
 			};
 			name = Release;
 		};
diff --git a/SQLite/Core/Blob.swift b/SQLite/Core/Blob.swift
index 1b30ffa1..45d6604a 100644
--- a/SQLite/Core/Blob.swift
+++ b/SQLite/Core/Blob.swift
@@ -30,16 +30,16 @@ public struct Blob {
         self.bytes = bytes
     }
 
-    public init(bytes: UnsafePointer<Void>, length: Int) {
-        self.init(bytes: [UInt8](UnsafeBufferPointer(
-            start: UnsafePointer(bytes), count: length
-        )))
+    public init(bytes: UnsafeRawPointer, length: Int) {
+        // TODO correct count
+        let i8bufptr = UnsafeBufferPointer(start: bytes.assumingMemoryBound(to: UInt8.self), count: length)
+        self.init(bytes: [UInt8](i8bufptr))
     }
 
     public func toHex() -> String {
         return bytes.map {
             ($0 < 16 ? "0" : "") + String($0, radix: 16, uppercase: false)
-        }.joinWithSeparator("")
+        }.joined(separator: "")
     }
 
 }
diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index 04fdd901..832910ba 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -39,24 +39,24 @@ public final class Connection {
         /// An in-memory database (equivalent to `.URI(":memory:")`).
         ///
         /// See: <https://www.sqlite.org/inmemorydb.html#sharedmemdb>
-        case InMemory
+        case inMemory
 
         /// A temporary, file-backed database (equivalent to `.URI("")`).
         ///
         /// See: <https://www.sqlite.org/inmemorydb.html#temp_db>
-        case Temporary
+        case temporary
 
         /// A database located at the given URI filename (or path).
         ///
         /// See: <https://www.sqlite.org/uri.html>
         ///
         /// - Parameter filename: A URI filename
-        case URI(String)
+        case uri(String)
     }
 
-    public var handle: COpaquePointer { return _handle }
+    public var handle: OpaquePointer { return _handle! }
 
-    private var _handle: COpaquePointer = nil
+    fileprivate var _handle: OpaquePointer? = nil
 
     /// Initializes a new SQLite connection.
     ///
@@ -72,10 +72,10 @@ public final class Connection {
     ///     Default: `false`.
     ///
     /// - Returns: A new database connection.
-    public init(_ location: Location = .InMemory, readonly: Bool = false) throws {
+    public init(_ location: Location = .inMemory, readonly: Bool = false) throws {
         let flags = readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE
-        try check(sqlite3_open_v2(location.description, &_handle, flags | SQLITE_OPEN_FULLMUTEX, nil))
-        dispatch_queue_set_specific(queue, Connection.queueKey, queueContext, nil)
+        _ = try check(sqlite3_open_v2(location.description, &_handle, flags | SQLITE_OPEN_FULLMUTEX, nil))
+        queue.setSpecific(key: /*Migrator FIXME: Use a variable of type DispatchSpecificKey*/ Connection.queueKey, value: queueContext)
     }
 
     /// Initializes a new connection to a database.
@@ -93,7 +93,7 @@ public final class Connection {
     ///
     /// - Returns: A new database connection.
     public convenience init(_ filename: String, readonly: Bool = false) throws {
-        try self.init(.URI(filename), readonly: readonly)
+        try self.init(.uri(filename), readonly: readonly)
     }
 
     deinit {
@@ -131,8 +131,8 @@ public final class Connection {
     ///   statements.
     ///
     /// - Throws: `Result.Error` if query execution fails.
-    public func execute(SQL: String) throws {
-        try sync { try self.check(sqlite3_exec(self.handle, SQL, nil, nil, nil)) }
+    public func execute(_ SQL: String) throws {
+        _ = try sync { try self.check(sqlite3_exec(self.handle, SQL, nil, nil, nil)) }
     }
 
     // MARK: - Prepare
@@ -146,7 +146,7 @@ public final class Connection {
     ///   - bindings: A list of parameters to bind to the statement.
     ///
     /// - Returns: A prepared statement.
-    @warn_unused_result public func prepare(statement: String, _ bindings: Binding?...) throws -> Statement {
+    public func prepare(_ statement: String, _ bindings: Binding?...) throws -> Statement {
         if !bindings.isEmpty { return try prepare(statement, bindings) }
         return try Statement(self, statement)
     }
@@ -160,7 +160,7 @@ public final class Connection {
     ///   - bindings: A list of parameters to bind to the statement.
     ///
     /// - Returns: A prepared statement.
-    @warn_unused_result public func prepare(statement: String, _ bindings: [Binding?]) throws -> Statement {
+    public func prepare(_ statement: String, _ bindings: [Binding?]) throws -> Statement {
         return try prepare(statement).bind(bindings)
     }
 
@@ -173,7 +173,7 @@ public final class Connection {
     ///   - bindings: A dictionary of named parameters to bind to the statement.
     ///
     /// - Returns: A prepared statement.
-    @warn_unused_result public func prepare(statement: String, _ bindings: [String: Binding?]) throws -> Statement {
+    public func prepare(_ statement: String, _ bindings: [String: Binding?]) throws -> Statement {
         return try prepare(statement).bind(bindings)
     }
 
@@ -190,7 +190,7 @@ public final class Connection {
     /// - Throws: `Result.Error` if query execution fails.
     ///
     /// - Returns: The statement.
-    public func run(statement: String, _ bindings: Binding?...) throws -> Statement {
+    public func run(_ statement: String, _ bindings: Binding?...) throws -> Statement {
         return try run(statement, bindings)
     }
 
@@ -205,7 +205,7 @@ public final class Connection {
     /// - Throws: `Result.Error` if query execution fails.
     ///
     /// - Returns: The statement.
-    public func run(statement: String, _ bindings: [Binding?]) throws -> Statement {
+    public func run(_ statement: String, _ bindings: [Binding?]) throws -> Statement {
         return try prepare(statement).run(bindings)
     }
 
@@ -220,7 +220,7 @@ public final class Connection {
     /// - Throws: `Result.Error` if query execution fails.
     ///
     /// - Returns: The statement.
-    public func run(statement: String, _ bindings: [String: Binding?]) throws -> Statement {
+    public func run(_ statement: String, _ bindings: [String: Binding?]) throws -> Statement {
         return try prepare(statement).run(bindings)
     }
 
@@ -236,7 +236,7 @@ public final class Connection {
     ///   - bindings: A list of parameters to bind to the statement.
     ///
     /// - Returns: The first value of the first row returned.
-    @warn_unused_result public func scalar(statement: String, _ bindings: Binding?...) throws -> Binding? {
+    public func scalar(_ statement: String, _ bindings: Binding?...) throws -> Binding? {
         return try scalar(statement, bindings)
     }
 
@@ -250,7 +250,7 @@ public final class Connection {
     ///   - bindings: A list of parameters to bind to the statement.
     ///
     /// - Returns: The first value of the first row returned.
-    @warn_unused_result public func scalar(statement: String, _ bindings: [Binding?]) throws -> Binding? {
+    public func scalar(_ statement: String, _ bindings: [Binding?]) throws -> Binding? {
         return try prepare(statement).scalar(bindings)
     }
 
@@ -264,7 +264,7 @@ public final class Connection {
     ///   - bindings: A dictionary of named parameters to bind to the statement.
     ///
     /// - Returns: The first value of the first row returned.
-    @warn_unused_result public func scalar(statement: String, _ bindings: [String: Binding?]) throws -> Binding? {
+    public func scalar(_ statement: String, _ bindings: [String: Binding?]) throws -> Binding? {
         return try prepare(statement).scalar(bindings)
     }
 
@@ -301,7 +301,7 @@ public final class Connection {
     ///     must throw to roll the transaction back.
     ///
     /// - Throws: `Result.Error`, and rethrows.
-    public func transaction(mode: TransactionMode = .Deferred, block: () throws -> Void) throws {
+    public func transaction(_ mode: TransactionMode = .Deferred, block: @escaping () throws -> Void) throws {
         try transaction("BEGIN \(mode.rawValue) TRANSACTION", block, "COMMIT TRANSACTION", or: "ROLLBACK TRANSACTION")
     }
 
@@ -321,23 +321,23 @@ public final class Connection {
     ///     The block must throw to roll the savepoint back.
     ///
     /// - Throws: `SQLite.Result.Error`, and rethrows.
-    public func savepoint(name: String = NSUUID().UUIDString, block: () throws -> Void) throws {
+    public func savepoint(_ name: String = UUID().uuidString, block: @escaping () throws -> Void) throws {
         let name = name.quote("'")
         let savepoint = "SAVEPOINT \(name)"
 
         try transaction(savepoint, block, "RELEASE \(savepoint)", or: "ROLLBACK TO \(savepoint)")
     }
 
-    private func transaction(begin: String, _ block: () throws -> Void, _ commit: String, or rollback: String) throws {
+    fileprivate func transaction(_ begin: String, _ block: @escaping () throws -> Void, _ commit: String, or rollback: String) throws {
         return try sync {
-            try self.run(begin)
+            _ = try self.run(begin)
             do {
                 try block()
             } catch {
-                try self.run(rollback)
+                _ = try self.run(rollback)
                 throw error
             }
-            try self.run(commit)
+            _ = try self.run(commit)
         }
     }
 
@@ -362,21 +362,21 @@ public final class Connection {
     ///   busy error would otherwise be returned. It’s passed the number of
     ///   times it’s been called for this lock. If it returns `true`, it will
     ///   try again. If it returns `false`, no further attempts will be made.
-    public func busyHandler(callback: ((tries: Int) -> Bool)?) {
+    public func busyHandler(_ callback: ((_ tries: Int) -> Bool)?) {
         guard let callback = callback else {
             sqlite3_busy_handler(handle, nil, nil)
             busyHandler = nil
             return
         }
 
-        let box: BusyHandler = { callback(tries: Int($0)) ? 1 : 0 }
+        let box: BusyHandler = { callback(Int($0)) ? 1 : 0 }
         sqlite3_busy_handler(handle, { callback, tries in
-            unsafeBitCast(callback, BusyHandler.self)(tries)
-        }, unsafeBitCast(box, UnsafeMutablePointer<Void>.self))
+            unsafeBitCast(callback, to: BusyHandler.self)(tries)
+        }, unsafeBitCast(box, to: UnsafeMutableRawPointer.self))
         busyHandler = box
     }
-    private typealias BusyHandler = @convention(block) Int32 -> Int32
-    private var busyHandler: BusyHandler?
+    fileprivate typealias BusyHandler = @convention(block) (Int32) -> Int32
+    fileprivate var busyHandler: BusyHandler?
 
     /// Sets a handler to call when a statement is executed with the compiled
     /// SQL.
@@ -385,21 +385,21 @@ public final class Connection {
     ///   with the compiled SQL as its argument.
     ///
     ///       db.trace { SQL in print(SQL) }
-    public func trace(callback: (String -> Void)?) {
+    public func trace(_ callback: ((String) -> Void)?) {
         guard let callback = callback else {
             sqlite3_trace(handle, nil, nil)
             trace = nil
             return
         }
 
-        let box: Trace = { callback(String.fromCString($0)!) }
+        let box: Trace = { callback(String(cString: $0)) }
         sqlite3_trace(handle, { callback, SQL in
-            unsafeBitCast(callback, Trace.self)(SQL)
-        }, unsafeBitCast(box, UnsafeMutablePointer<Void>.self))
+            unsafeBitCast(callback, to: Trace.self)(SQL!)
+        }, unsafeBitCast(box, to: UnsafeMutableRawPointer.self))
         trace = box
     }
-    private typealias Trace = @convention(block) UnsafePointer<Int8> -> Void
-    private var trace: Trace?
+    fileprivate typealias Trace = @convention(block) (UnsafePointer<Int8>) -> Void
+    fileprivate var trace: Trace?
 
     /// Registers a callback to be invoked whenever a row is inserted, updated,
     /// or deleted in a rowid table.
@@ -407,7 +407,7 @@ public final class Connection {
     /// - Parameter callback: A callback invoked with the `Operation` (one of
     ///   `.Insert`, `.Update`, or `.Delete`), database name, table name, and
     ///   rowid.
-    public func updateHook(callback: ((operation: Operation, db: String, table: String, rowid: Int64) -> Void)?) {
+    public func updateHook(_ callback: ((_ operation: Operation, _ db: String, _ table: String, _ rowid: Int64) -> Void)?) {
         guard let callback = callback else {
             sqlite3_update_hook(handle, nil, nil)
             updateHook = nil
@@ -416,26 +416,26 @@ public final class Connection {
 
         let box: UpdateHook = {
             callback(
-                operation: Operation(rawValue: $0),
-                db: String.fromCString($1)!,
-                table: String.fromCString($2)!,
-                rowid: $3
+                Operation(rawValue: $0),
+                String(cString: $1),
+                String(cString: $2),
+                $3
             )
         }
         sqlite3_update_hook(handle, { callback, operation, db, table, rowid in
-            unsafeBitCast(callback, UpdateHook.self)(operation, db, table, rowid)
-        }, unsafeBitCast(box, UnsafeMutablePointer<Void>.self))
+            unsafeBitCast(callback, to: UpdateHook.self)(operation, db!, table!, rowid)
+        }, unsafeBitCast(box, to: UnsafeMutableRawPointer.self))
         updateHook = box
     }
-    private typealias UpdateHook = @convention(block) (Int32, UnsafePointer<Int8>, UnsafePointer<Int8>, Int64) -> Void
-    private var updateHook: UpdateHook?
+    fileprivate typealias UpdateHook = @convention(block) (Int32, UnsafePointer<Int8>, UnsafePointer<Int8>, Int64) -> Void
+    fileprivate var updateHook: UpdateHook?
 
     /// Registers a callback to be invoked whenever a transaction is committed.
     ///
     /// - Parameter callback: A callback invoked whenever a transaction is
     ///   committed. If this callback throws, the transaction will be rolled
     ///   back.
-    public func commitHook(callback: (() throws -> Void)?) {
+    public func commitHook(_ callback: (() throws -> Void)?) {
         guard let callback = callback else {
             sqlite3_commit_hook(handle, nil, nil)
             commitHook = nil
@@ -451,18 +451,18 @@ public final class Connection {
             return 0
         }
         sqlite3_commit_hook(handle, { callback in
-            unsafeBitCast(callback, CommitHook.self)()
-        }, unsafeBitCast(box, UnsafeMutablePointer<Void>.self))
+            unsafeBitCast(callback, to: CommitHook.self)()
+        }, unsafeBitCast(box, to: UnsafeMutableRawPointer.self))
         commitHook = box
     }
-    private typealias CommitHook = @convention(block) () -> Int32
-    private var commitHook: CommitHook?
+    fileprivate typealias CommitHook = @convention(block) () -> Int32
+    fileprivate var commitHook: CommitHook?
 
     /// Registers a callback to be invoked whenever a transaction rolls back.
     ///
     /// - Parameter callback: A callback invoked when a transaction is rolled
     ///   back.
-    public func rollbackHook(callback: (() -> Void)?) {
+    public func rollbackHook(_ callback: (() -> Void)?) {
         guard let callback = callback else {
             sqlite3_rollback_hook(handle, nil, nil)
             rollbackHook = nil
@@ -471,12 +471,12 @@ public final class Connection {
 
         let box: RollbackHook = { callback() }
         sqlite3_rollback_hook(handle, { callback in
-            unsafeBitCast(callback, RollbackHook.self)()
-        }, unsafeBitCast(box, UnsafeMutablePointer<Void>.self))
+            unsafeBitCast(callback, to: RollbackHook.self)()
+        }, unsafeBitCast(box, to: UnsafeMutableRawPointer.self))
         rollbackHook = box
     }
-    private typealias RollbackHook = @convention(block) () -> Void
-    private var rollbackHook: RollbackHook?
+    fileprivate typealias RollbackHook = @convention(block) () -> Void
+    fileprivate var rollbackHook: RollbackHook?
 
     /// Creates or redefines a custom SQL function.
     ///
@@ -497,11 +497,11 @@ public final class Connection {
     ///   - block: A block of code to run when the function is called. The block
     ///     is called with an array of raw SQL values mapped to the function’s
     ///     parameters and should return a raw SQL value (or nil).
-    public func createFunction(function: String, argumentCount: UInt? = nil, deterministic: Bool = false, _ block: (args: [Binding?]) -> Binding?) {
+    public func createFunction(_ function: String, argumentCount: UInt? = nil, deterministic: Bool = false, _ block: @escaping (_ args: [Binding?]) -> Binding?) {
         let argc = argumentCount.map { Int($0) } ?? -1
         let box: Function = { context, argc, argv in
             let arguments: [Binding?] = (0..<Int(argc)).map { idx in
-                let value = argv[idx]
+                let value = argv![idx]
                 switch sqlite3_value_type(value) {
                 case SQLITE_BLOB:
                     return Blob(bytes: sqlite3_value_blob(value), length: Int(sqlite3_value_bytes(value)))
@@ -512,12 +512,12 @@ public final class Connection {
                 case SQLITE_NULL:
                     return nil
                 case SQLITE_TEXT:
-                    return String.fromCString(UnsafePointer(sqlite3_value_text(value)))!
+                    return String(cString: UnsafePointer(sqlite3_value_text(value)))
                 case let type:
                     fatalError("unsupported value type: \(type)")
                 }
             }
-            let result = block(args: arguments)
+            let result = block(arguments)
             if let result = result as? Blob {
                 sqlite3_result_blob(context, result.bytes, Int32(result.bytes.count), nil)
             } else if let result = result as? Double {
@@ -536,17 +536,18 @@ public final class Connection {
         if deterministic {
             flags |= SQLITE_DETERMINISTIC
         }
-        sqlite3_create_function_v2(handle, function, Int32(argc), flags, unsafeBitCast(box, UnsafeMutablePointer<Void>.self), { context, argc, value in
-            unsafeBitCast(sqlite3_user_data(context), Function.self)(context, argc, value)
+        sqlite3_create_function_v2(handle, function, Int32(argc), flags, unsafeBitCast(box, to: UnsafeMutableRawPointer.self), { context, argc, value in
+            let function = unsafeBitCast(sqlite3_user_data(context), to: Function.self)
+            function(context, argc, value)
         }, nil, nil, nil)
         if functions[function] == nil { self.functions[function] = [:] }
         functions[function]?[argc] = box
     }
-    private typealias Function = @convention(block) (COpaquePointer, Int32, UnsafeMutablePointer<COpaquePointer>) -> Void
-    private var functions = [String: [Int: Function]]()
+    fileprivate typealias Function = @convention(block) (OpaquePointer?, Int32, UnsafeMutablePointer<OpaquePointer?>?) -> Void
+    fileprivate var functions = [String: [Int: Function]]()
 
     /// The return type of a collation comparison function.
-    public typealias ComparisonResult = NSComparisonResult
+    public typealias ComparisonResult = Foundation.ComparisonResult
 
     /// Defines a new collating sequence.
     ///
@@ -556,23 +557,26 @@ public final class Connection {
     ///
     ///   - block: A collation function that takes two strings and returns the
     ///     comparison result.
-    public func createCollation(collation: String, _ block: (lhs: String, rhs: String) -> ComparisonResult) throws {
+    public func createCollation(_ collation: String, _ block: @escaping (_ lhs: String, _ rhs: String) -> ComparisonResult) throws {
+        // TODO correct capacity
         let box: Collation = { lhs, rhs in
-            Int32(block(lhs: String.fromCString(UnsafePointer<Int8>(lhs))!, rhs: String.fromCString(UnsafePointer<Int8>(rhs))!).rawValue)
+            let lstr = String(cString: lhs.bindMemory(to: UInt8.self, capacity: 0))
+            let rstr = String(cString: rhs.bindMemory(to: UInt8.self, capacity: 0))
+            return Int32(Int(block(lstr, rstr).rawValue))
         }
-        try check(sqlite3_create_collation_v2(handle, collation, SQLITE_UTF8, unsafeBitCast(box, UnsafeMutablePointer<Void>.self), { callback, _, lhs, _, rhs in
-            unsafeBitCast(callback, Collation.self)(lhs, rhs)
+        _ = try check(sqlite3_create_collation_v2(handle, collation, SQLITE_UTF8, unsafeBitCast(box, to: UnsafeMutableRawPointer.self), { callback, _, lhs, _, rhs in
+            unsafeBitCast(callback, to: Collation.self)(lhs!, rhs!)
         }, nil))
         collations[collation] = box
     }
-    private typealias Collation = @convention(block) (UnsafePointer<Void>, UnsafePointer<Void>) -> Int32
-    private var collations = [String: Collation]()
+    fileprivate typealias Collation = @convention(block) (UnsafeRawPointer, UnsafeRawPointer) -> Int32
+    fileprivate var collations = [String: Collation]()
 
     // MARK: - Error Handling
 
-    func sync<T>(block: () throws -> T) rethrows -> T {
+    func sync<T>(_ block: @escaping () throws -> T) rethrows -> T {
         var success: T?
-        var failure: ErrorType?
+        var failure: Error?
 
         let box: () -> Void = {
             do {
@@ -582,10 +586,10 @@ public final class Connection {
             }
         }
 
-        if dispatch_get_specific(Connection.queueKey) == queueContext {
+        if DispatchQueue.getSpecific(key: Connection.queueKey) == queueContext {
             box()
         } else {
-            dispatch_sync(queue, box) // FIXME: rdar://problem/21389236
+            queue.sync(execute: box) // FIXME: rdar://problem/21389236
         }
 
         if let failure = failure {
@@ -595,7 +599,7 @@ public final class Connection {
         return success!
     }
 
-    func check(resultCode: Int32, statement: Statement? = nil) throws -> Int32 {
+    func check(_ resultCode: Int32, statement: Statement? = nil) throws -> Int32 {
         guard let error = Result(errorCode: resultCode, connection: self, statement: statement) else {
             return resultCode
         }
@@ -603,18 +607,18 @@ public final class Connection {
         throw error
     }
 
-    private var queue = dispatch_queue_create("SQLite.Database", DISPATCH_QUEUE_SERIAL)
+    fileprivate var queue = DispatchQueue(label: "SQLite.Database", attributes: [])
 
-    private static let queueKey = unsafeBitCast(Connection.self, UnsafePointer<Void>.self)
+    fileprivate static let queueKey = DispatchSpecificKey<Int>()
 
-    private lazy var queueContext: UnsafeMutablePointer<Void> = unsafeBitCast(self, UnsafeMutablePointer<Void>.self)
+    fileprivate lazy var queueContext: Int = unsafeBitCast(self, to: Int.self)
 
 }
 
 extension Connection : CustomStringConvertible {
 
     public var description: String {
-        return String.fromCString(sqlite3_db_filename(handle, nil))!
+        return String(cString: sqlite3_db_filename(handle, nil))
     }
 
 }
@@ -623,11 +627,11 @@ extension Connection.Location : CustomStringConvertible {
 
     public var description: String {
         switch self {
-        case .InMemory:
+        case .inMemory:
             return ":memory:"
-        case .Temporary:
+        case .temporary:
             return ""
-        case .URI(let URI):
+        case .uri(let URI):
             return URI
         }
     }
@@ -638,22 +642,22 @@ extension Connection.Location : CustomStringConvertible {
 public enum Operation {
 
     /// An INSERT operation.
-    case Insert
+    case insert
 
     /// An UPDATE operation.
-    case Update
+    case update
 
     /// A DELETE operation.
-    case Delete
+    case delete
 
-    private init(rawValue: Int32) {
+    fileprivate init(rawValue: Int32) {
         switch rawValue {
         case SQLITE_INSERT:
-            self = .Insert
+            self = .insert
         case SQLITE_UPDATE:
-            self = .Update
+            self = .update
         case SQLITE_DELETE:
-            self = .Delete
+            self = .delete
         default:
             fatalError("unhandled operation code: \(rawValue)")
         }
@@ -661,17 +665,17 @@ public enum Operation {
 
 }
 
-public enum Result : ErrorType {
+public enum Result : Error {
 
-    private static let successCodes: Set = [SQLITE_OK, SQLITE_ROW, SQLITE_DONE]
+    fileprivate static let successCodes: Set = [SQLITE_OK, SQLITE_ROW, SQLITE_DONE]
 
-    case Error(message: String, code: Int32, statement: Statement?)
+    case error(message: String, code: Int32, statement: Statement?)
 
     init?(errorCode: Int32, connection: Connection, statement: Statement? = nil) {
         guard !Result.successCodes.contains(errorCode) else { return nil }
 
-        let message = String.fromCString(sqlite3_errmsg(connection.handle))!
-        self = Error(message: message, code: errorCode, statement: statement)
+        let message = String(cString: sqlite3_errmsg(connection.handle))
+        self = .error(message: message, code: errorCode, statement: statement)
     }
 
 }
@@ -680,7 +684,7 @@ extension Result : CustomStringConvertible {
 
     public var description: String {
         switch self {
-        case let .Error(message, _, statement):
+        case let .error(message, _, statement):
             guard let statement = statement else { return message }
 
             return "\(message) (\(statement))"
diff --git a/SQLite/Core/Statement.swift b/SQLite/Core/Statement.swift
index 5e172b68..01720433 100644
--- a/SQLite/Core/Statement.swift
+++ b/SQLite/Core/Statement.swift
@@ -31,13 +31,13 @@ import CSQLite
 /// A single SQL statement.
 public final class Statement {
 
-    private var handle: COpaquePointer = nil
+    fileprivate var handle: OpaquePointer? = nil
 
-    private let connection: Connection
+    fileprivate let connection: Connection
 
     init(_ connection: Connection, _ SQL: String) throws {
         self.connection = connection
-        try connection.check(sqlite3_prepare_v2(connection.handle, SQL, -1, &handle, nil))
+        _ = try connection.check(sqlite3_prepare_v2(connection.handle, SQL, -1, &handle, nil))
     }
 
     deinit {
@@ -47,7 +47,7 @@ public final class Statement {
     public lazy var columnCount: Int = Int(sqlite3_column_count(self.handle))
 
     public lazy var columnNames: [String] = (0..<Int32(self.columnCount)).map {
-        String.fromCString(sqlite3_column_name(self.handle, $0))!
+        String(cString: sqlite3_column_name(self.handle, $0))
     }
 
     /// A cursor pointing to the current row.
@@ -58,7 +58,7 @@ public final class Statement {
     /// - Parameter values: A list of parameters to bind to the statement.
     ///
     /// - Returns: The statement object (useful for chaining).
-    public func bind(values: Binding?...) -> Statement {
+    public func bind(_ values: Binding?...) -> Statement {
         return bind(values)
     }
 
@@ -67,7 +67,7 @@ public final class Statement {
     /// - Parameter values: A list of parameters to bind to the statement.
     ///
     /// - Returns: The statement object (useful for chaining).
-    public func bind(values: [Binding?]) -> Statement {
+    public func bind(_ values: [Binding?]) -> Statement {
         if values.isEmpty { return self }
         reset()
         guard values.count == Int(sqlite3_bind_parameter_count(handle)) else {
@@ -83,7 +83,7 @@ public final class Statement {
     ///   statement.
     ///
     /// - Returns: The statement object (useful for chaining).
-    public func bind(values: [String: Binding?]) -> Statement {
+    public func bind(_ values: [String: Binding?]) -> Statement {
         reset()
         for (name, value) in values {
             let idx = sqlite3_bind_parameter_index(handle, name)
@@ -95,7 +95,7 @@ public final class Statement {
         return self
     }
 
-    private func bind(value: Binding?, atIndex idx: Int) {
+    fileprivate func bind(_ value: Binding?, atIndex idx: Int) {
         if value == nil {
             sqlite3_bind_null(handle, Int32(idx))
         } else if let value = value as? Blob {
@@ -120,7 +120,7 @@ public final class Statement {
     /// - Throws: `Result.Error` if query execution fails.
     ///
     /// - Returns: The statement object (useful for chaining).
-    public func run(bindings: Binding?...) throws -> Statement {
+    public func run(_ bindings: Binding?...) throws -> Statement {
         guard bindings.isEmpty else {
             return try run(bindings)
         }
@@ -135,7 +135,7 @@ public final class Statement {
     /// - Throws: `Result.Error` if query execution fails.
     ///
     /// - Returns: The statement object (useful for chaining).
-    public func run(bindings: [Binding?]) throws -> Statement {
+    public func run(_ bindings: [Binding?]) throws -> Statement {
         return try bind(bindings).run()
     }
 
@@ -145,27 +145,27 @@ public final class Statement {
     /// - Throws: `Result.Error` if query execution fails.
     ///
     /// - Returns: The statement object (useful for chaining).
-    public func run(bindings: [String: Binding?]) throws -> Statement {
+    public func run(_ bindings: [String: Binding?]) throws -> Statement {
         return try bind(bindings).run()
     }
 
     /// - Parameter bindings: A list of parameters to bind to the statement.
     ///
     /// - Returns: The first value of the first row returned.
-    @warn_unused_result public func scalar(bindings: Binding?...) throws -> Binding? {
+    public func scalar(_ bindings: Binding?...) throws -> Binding? {
         guard bindings.isEmpty else {
             return try scalar(bindings)
         }
 
         reset(clearBindings: false)
-        try step()
+        _ = try step()
         return row[0]
     }
 
     /// - Parameter bindings: A list of parameters to bind to the statement.
     ///
     /// - Returns: The first value of the first row returned.
-    @warn_unused_result public func scalar(bindings: [Binding?]) throws -> Binding? {
+    public func scalar(_ bindings: [Binding?]) throws -> Binding? {
         return try bind(bindings).scalar()
     }
 
@@ -174,7 +174,7 @@ public final class Statement {
     ///   statement.
     ///
     /// - Returns: The first value of the first row returned.
-    @warn_unused_result public func scalar(bindings: [String: Binding?]) throws -> Binding? {
+    public func scalar(_ bindings: [String: Binding?]) throws -> Binding? {
         return try bind(bindings).scalar()
     }
 
@@ -182,23 +182,23 @@ public final class Statement {
         return try connection.sync { try self.connection.check(sqlite3_step(self.handle)) == SQLITE_ROW }
     }
 
-    private func reset(clearBindings shouldClear: Bool = true) {
+    fileprivate func reset(clearBindings shouldClear: Bool = true) {
         sqlite3_reset(handle)
         if (shouldClear) { sqlite3_clear_bindings(handle) }
     }
 
 }
 
-extension Statement : SequenceType {
+extension Statement : Sequence {
 
-    public func generate() -> Statement {
+    public func makeIterator() -> Statement {
         reset(clearBindings: false)
         return self
     }
 
 }
 
-extension Statement : GeneratorType {
+extension Statement : IteratorProtocol {
 
     public func next() -> [Binding?]? {
         return try! step() ? Array(row) : nil
@@ -209,19 +209,19 @@ extension Statement : GeneratorType {
 extension Statement : CustomStringConvertible {
 
     public var description: String {
-        return String.fromCString(sqlite3_sql(handle))!
+        return String(cString: sqlite3_sql(handle))
     }
 
 }
 
 public struct Cursor {
 
-    private let handle: COpaquePointer
+    fileprivate let handle: OpaquePointer
 
-    private let columnCount: Int
+    fileprivate let columnCount: Int
 
-    private init(_ statement: Statement) {
-        handle = statement.handle
+    fileprivate init(_ statement: Statement) {
+        handle = statement.handle!
         columnCount = statement.columnCount
     }
 
@@ -234,13 +234,13 @@ public struct Cursor {
     }
 
     public subscript(idx: Int) -> String {
-        return String.fromCString(UnsafePointer(sqlite3_column_text(handle, Int32(idx)))) ?? ""
+        return String(cString: UnsafePointer(sqlite3_column_text(handle, Int32(idx))))
     }
 
     public subscript(idx: Int) -> Blob {
         let bytes = sqlite3_column_blob(handle, Int32(idx))
         let length = Int(sqlite3_column_bytes(handle, Int32(idx)))
-        return Blob(bytes: bytes, length: length)
+        return Blob(bytes: bytes!, length: length)
     }
 
     // MARK: -
@@ -256,7 +256,7 @@ public struct Cursor {
 }
 
 /// Cursors provide direct access to a statement’s current row.
-extension Cursor : SequenceType {
+extension Cursor : Sequence {
 
     public subscript(idx: Int) -> Binding? {
         switch sqlite3_column_type(handle, Int32(idx)) {
@@ -275,11 +275,11 @@ extension Cursor : SequenceType {
         }
     }
 
-    public func generate() -> AnyGenerator<Binding?> {
+    public func makeIterator() -> AnyIterator<Binding?> {
         var idx = 0
-        return AnyGenerator {
+        return AnyIterator {
             if idx >= self.columnCount {
-                return Optional<Binding?>.None
+                return Optional<Binding?>.none
             } else {
                 idx += 1
                 return self[idx - 1]
diff --git a/SQLite/Core/Value.swift b/SQLite/Core/Value.swift
index 2cfb45ed..608f0ce6 100644
--- a/SQLite/Core/Value.swift
+++ b/SQLite/Core/Value.swift
@@ -39,7 +39,7 @@ public protocol Value : Expressible { // extensions cannot have inheritance clau
 
     static var declaredDatatype: String { get }
 
-    static func fromDatatypeValue(datatypeValue: Datatype) -> ValueType
+    static func fromDatatypeValue(_ datatypeValue: Datatype) -> ValueType
 
     var datatypeValue: Datatype { get }
 
@@ -49,7 +49,7 @@ extension Double : Number, Value {
 
     public static let declaredDatatype = "REAL"
 
-    public static func fromDatatypeValue(datatypeValue: Double) -> Double {
+    public static func fromDatatypeValue(_ datatypeValue: Double) -> Double {
         return datatypeValue
     }
 
@@ -63,7 +63,7 @@ extension Int64 : Number, Value {
 
     public static let declaredDatatype = "INTEGER"
 
-    public static func fromDatatypeValue(datatypeValue: Int64) -> Int64 {
+    public static func fromDatatypeValue(_ datatypeValue: Int64) -> Int64 {
         return datatypeValue
     }
 
@@ -77,7 +77,7 @@ extension String : Binding, Value {
 
     public static let declaredDatatype = "TEXT"
 
-    public static func fromDatatypeValue(datatypeValue: String) -> String {
+    public static func fromDatatypeValue(_ datatypeValue: String) -> String {
         return datatypeValue
     }
 
@@ -91,7 +91,7 @@ extension Blob : Binding, Value {
 
     public static let declaredDatatype = "BLOB"
 
-    public static func fromDatatypeValue(datatypeValue: Blob) -> Blob {
+    public static func fromDatatypeValue(_ datatypeValue: Blob) -> Blob {
         return datatypeValue
     }
 
@@ -107,7 +107,7 @@ extension Bool : Binding, Value {
 
     public static var declaredDatatype = Int64.declaredDatatype
 
-    public static func fromDatatypeValue(datatypeValue: Int64) -> Bool {
+    public static func fromDatatypeValue(_ datatypeValue: Int64) -> Bool {
         return datatypeValue != 0
     }
 
@@ -121,7 +121,7 @@ extension Int : Number, Value {
 
     public static var declaredDatatype = Int64.declaredDatatype
 
-    public static func fromDatatypeValue(datatypeValue: Int64) -> Int {
+    public static func fromDatatypeValue(_ datatypeValue: Int64) -> Int {
         return Int(datatypeValue)
     }
 
diff --git a/SQLite/Extensions/FTS4.swift b/SQLite/Extensions/FTS4.swift
index 466c42c7..52de47bf 100644
--- a/SQLite/Extensions/FTS4.swift
+++ b/SQLite/Extensions/FTS4.swift
@@ -24,15 +24,15 @@
 
 extension Module {
 
-    @warn_unused_result public static func FTS4(column: Expressible, _ more: Expressible...) -> Module {
+    public static func FTS4(_ column: Expressible, _ more: Expressible...) -> Module {
         return FTS4([column] + more)
     }
 
-    @warn_unused_result public static func FTS4(columns: [Expressible] = [], tokenize tokenizer: Tokenizer? = nil) -> Module {
+    public static func FTS4(_ columns: [Expressible] = [], tokenize tokenizer: Tokenizer? = nil) -> Module {
         return FTS4(FTS4Config().columns(columns).tokenizer(tokenizer))
     }
 
-    @warn_unused_result public static func FTS4(config: FTS4Config) -> Module {
+    public static func FTS4(_ config: FTS4Config) -> Module {
         return Module(name: "fts4", arguments: config.arguments())
     }
 }
@@ -51,15 +51,15 @@ extension VirtualTable {
     ///
     /// - Returns: An expression appended with a `MATCH` query against the given
     ///   pattern.
-    @warn_unused_result public func match(pattern: String) -> Expression<Bool> {
+    public func match(_ pattern: String) -> Expression<Bool> {
         return "MATCH".infix(tableName(), pattern)
     }
 
-    @warn_unused_result public func match(pattern: Expression<String>) -> Expression<Bool> {
+    public func match(_ pattern: Expression<String>) -> Expression<Bool> {
         return "MATCH".infix(tableName(), pattern)
     }
 
-    @warn_unused_result public func match(pattern: Expression<String?>) -> Expression<Bool?> {
+    public func match(_ pattern: Expression<String?>) -> Expression<Bool?> {
         return "MATCH".infix(tableName(), pattern)
     }
 
@@ -73,15 +73,15 @@ extension VirtualTable {
     /// - Parameter pattern: A pattern to match.
     ///
     /// - Returns: A query with the given `WHERE … MATCH` clause applied.
-    @warn_unused_result public func match(pattern: String) -> QueryType {
+    public func match(_ pattern: String) -> QueryType {
         return filter(match(pattern))
     }
 
-    @warn_unused_result public func match(pattern: Expression<String>) -> QueryType {
+    public func match(_ pattern: Expression<String>) -> QueryType {
         return filter(match(pattern))
     }
 
-    @warn_unused_result public func match(pattern: Expression<String?>) -> QueryType {
+    public func match(_ pattern: Expression<String?>) -> QueryType {
         return filter(match(pattern))
     }
 
@@ -93,7 +93,7 @@ public struct Tokenizer {
 
     public static let Porter = Tokenizer("porter")
 
-    @warn_unused_result public static func Unicode61(removeDiacritics removeDiacritics: Bool? = nil, tokenchars: Set<Character> = [], separators: Set<Character> = []) -> Tokenizer {
+    public static func Unicode61(removeDiacritics: Bool? = nil, tokenchars: Set<Character> = [], separators: Set<Character> = []) -> Tokenizer {
         var arguments = [String]()
 
         if let removeDiacritics = removeDiacritics {
@@ -101,19 +101,19 @@ public struct Tokenizer {
         }
 
         if !tokenchars.isEmpty {
-            let joined = tokenchars.map { String($0) }.joinWithSeparator("")
+            let joined = tokenchars.map { String($0) }.joined(separator: "")
             arguments.append("tokenchars=\(joined)".quote())
         }
 
         if !separators.isEmpty {
-            let joined = separators.map { String($0) }.joinWithSeparator("")
+            let joined = separators.map { String($0) }.joined(separator: "")
             arguments.append("separators=\(joined)".quote())
         }
 
         return Tokenizer("unicode61", arguments)
     }
 
-    @warn_unused_result public static func Custom(name: String) -> Tokenizer {
+    public static func Custom(_ name: String) -> Tokenizer {
         return Tokenizer(Tokenizer.moduleName.quote(), [name.quote()])
     }
 
@@ -121,34 +121,34 @@ public struct Tokenizer {
 
     public let arguments: [String]
 
-    private init(_ name: String, _ arguments: [String] = []) {
+    fileprivate init(_ name: String, _ arguments: [String] = []) {
         self.name = name
         self.arguments = arguments
     }
 
-    private static let moduleName = "SQLite.swift"
+    fileprivate static let moduleName = "SQLite.swift"
 
 }
 
 extension Tokenizer : CustomStringConvertible {
 
     public var description: String {
-        return ([name] + arguments).joinWithSeparator(" ")
+        return ([name] + arguments).joined(separator: " ")
     }
 
 }
 
 extension Connection {
 
-    public func registerTokenizer(submoduleName: String, next: String -> (String, Range<String.Index>)?) throws {
-        try check(_SQLiteRegisterTokenizer(handle, Tokenizer.moduleName, submoduleName) { input, offset, length in
-            let string = String.fromCString(input)!
+    public func registerTokenizer(_ submoduleName: String, next: @escaping (String) -> (String, Range<String.Index>)?) throws {
+        _ = try check(_SQLiteRegisterTokenizer(handle, Tokenizer.moduleName, submoduleName) { input, offset, length in
+            let string = String(cString: input)
 
             guard let (token, range) = next(string) else { return nil }
 
             let view = string.utf8
-            offset.memory += string.substringToIndex(range.startIndex).utf8.count
-            length.memory = Int32(range.startIndex.samePositionIn(view).distanceTo(range.endIndex.samePositionIn(view)))
+            offset.pointee += string.substring(to: range.lowerBound).utf8.count
+            length.pointee = Int32(view.distance(from: range.lowerBound.samePosition(in: view), to: range.lowerBound.samePosition(in: view)))
             return token
         })
     }
@@ -157,7 +157,7 @@ extension Connection {
 
 /// Configuration options shared between the [FTS4](https://www.sqlite.org/fts3.html) and
 /// [FTS5](https://www.sqlite.org/fts5.html) extensions.
-public class FTSConfig {
+open class FTSConfig {
     public enum ColumnOption {
         /// [The notindexed= option](https://www.sqlite.org/fts3.html#section_6_5)
         case unindexed
@@ -171,38 +171,38 @@ public class FTSConfig {
     var isContentless: Bool = false
 
     /// Adds a column definition
-    public func column(column: Expressible, _ options: [ColumnOption] = []) -> Self {
+    open func column(_ column: Expressible, _ options: [ColumnOption] = []) -> Self {
         self.columnDefinitions.append((column, options))
         return self
     }
 
-    public func columns(columns: [Expressible]) -> Self {
+    open func columns(_ columns: [Expressible]) -> Self {
         for column in columns {
-            self.column(column)
+            _ = self.column(column)
         }
         return self
     }
 
     /// [Tokenizers](https://www.sqlite.org/fts3.html#tokenizer)
-    public func tokenizer(tokenizer: Tokenizer?) -> Self {
+    open func tokenizer(_ tokenizer: Tokenizer?) -> Self {
         self.tokenizer = tokenizer
         return self
     }
 
     /// [The prefix= option](https://www.sqlite.org/fts3.html#section_6_6)
-    public func prefix(prefix: [Int]) -> Self {
+    open func prefix(_ prefix: [Int]) -> Self {
         self.prefixes += prefix
         return self
     }
 
     /// [The content= option](https://www.sqlite.org/fts3.html#section_6_2)
-    public func externalContent(schema: SchemaType) -> Self {
+    open func externalContent(_ schema: SchemaType) -> Self {
         self.externalContentSchema = schema
         return self
     }
 
     /// [Contentless FTS4 Tables](https://www.sqlite.org/fts3.html#section_6_2_1)
-    public func contentless() -> Self {
+    open func contentless() -> Self {
         self.isContentless = true
         return self
     }
@@ -217,15 +217,15 @@ public class FTSConfig {
 
     func options() -> Options {
         var options = Options()
-        options.append(formatColumnDefinitions())
+        _ = options.append(formatColumnDefinitions())
         if let tokenizer = tokenizer {
-            options.append("tokenize", value: Expression<Void>(literal: tokenizer.description))
+            _ = options.append("tokenize", value: Expression<Void>(literal: tokenizer.description))
         }
-        options.appendCommaSeparated("prefix", values:prefixes.sort().map { String($0) })
+        _ = options.appendCommaSeparated("prefix", values:prefixes.sorted().map { String($0) })
         if isContentless {
-            options.append("content", value: "")
+            _ = options.append("content", value: "")
         } else if let externalContentSchema = externalContentSchema {
-            options.append("content", value: externalContentSchema.tableName())
+            _ = options.append("content", value: externalContentSchema.tableName())
         }
         return options
     }
@@ -233,28 +233,28 @@ public class FTSConfig {
     struct Options {
         var arguments = [Expressible]()
 
-        mutating func append(columns: [Expressible]) -> Options {
-            arguments.appendContentsOf(columns)
+        mutating func append(_ columns: [Expressible]) -> Options {
+            arguments.append(contentsOf: columns)
             return self
         }
 
-        mutating func appendCommaSeparated(key: String, values: [String]) -> Options {
+        mutating func appendCommaSeparated(_ key: String, values: [String]) -> Options {
             if values.isEmpty {
                 return self
             } else {
-                return append(key, value: values.joinWithSeparator(","))
+                return append(key, value: values.joined(separator: ","))
             }
         }
 
-        mutating func append(key: String, value: CustomStringConvertible?) -> Options {
+        mutating func append(_ key: String, value: CustomStringConvertible?) -> Options {
             return append(key, value: value?.description)
         }
 
-        mutating func append(key: String, value: String?) -> Options {
+        mutating func append(_ key: String, value: String?) -> Options {
             return append(key, value: value.map { Expression<String>($0) })
         }
 
-        mutating func append(key: String, value: Expressible?) -> Options {
+        mutating func append(_ key: String, value: Expressible?) -> Options {
             if let value = value {
                 arguments.append("=".join([Expression<Void>(literal: key), value]))
             }
@@ -264,10 +264,10 @@ public class FTSConfig {
 }
 
 /// Configuration for the [FTS4](https://www.sqlite.org/fts3.html) extension.
-public class FTS4Config : FTSConfig {
+open class FTS4Config : FTSConfig {
     /// [The matchinfo= option](https://www.sqlite.org/fts3.html#section_6_4)
     public enum MatchInfo : CustomStringConvertible {
-        case FTS3
+        case fts3
         public var description: String {
             return "fts3"
         }
@@ -276,14 +276,14 @@ public class FTS4Config : FTSConfig {
     /// [FTS4 options](https://www.sqlite.org/fts3.html#fts4_options)
     public enum Order : CustomStringConvertible {
         /// Data structures are optimized for returning results in ascending order by docid (default)
-        case Asc
+        case asc
         /// FTS4 stores its data in such a way as to optimize returning results in descending order by docid.
-        case Desc
+        case desc
 
         public var description: String {
             switch self {
-            case Asc: return "asc"
-            case Desc: return "desc"
+            case .asc: return "asc"
+            case .desc: return "desc"
             }
         }
     }
@@ -298,31 +298,31 @@ public class FTS4Config : FTSConfig {
     }
 
     /// [The compress= and uncompress= options](https://www.sqlite.org/fts3.html#section_6_1)
-    public func compress(functionName: String) -> Self {
+    open func compress(_ functionName: String) -> Self {
         self.compressFunction = functionName
         return self
     }
 
     /// [The compress= and uncompress= options](https://www.sqlite.org/fts3.html#section_6_1)
-    public func uncompress(functionName: String) -> Self {
+    open func uncompress(_ functionName: String) -> Self {
         self.uncompressFunction = functionName
         return self
     }
 
     /// [The languageid= option](https://www.sqlite.org/fts3.html#section_6_3)
-    public func languageId(columnName: String) -> Self {
+    open func languageId(_ columnName: String) -> Self {
         self.languageId = columnName
         return self
     }
 
     /// [The matchinfo= option](https://www.sqlite.org/fts3.html#section_6_4)
-    public func matchInfo(matchInfo: MatchInfo) -> Self {
+    open func matchInfo(_ matchInfo: MatchInfo) -> Self {
         self.matchInfo = matchInfo
         return self
     }
 
     /// [FTS4 options](https://www.sqlite.org/fts3.html#fts4_options)
-    public func order(order: Order) -> Self {
+    open func order(_ order: Order) -> Self {
         self.order = order
         return self
     }
@@ -332,11 +332,11 @@ public class FTS4Config : FTSConfig {
         for (column, _) in (columnDefinitions.filter { $0.options.contains(.unindexed) }) {
             options.append("notindexed", value: column)
         }
-        options.append("languageid", value: languageId)
-        options.append("compress", value: compressFunction)
-        options.append("uncompress", value: uncompressFunction)
-        options.append("matchinfo", value: matchInfo)
-        options.append("order", value: order)
+        _ = options.append("languageid", value: languageId)
+        _ = options.append("compress", value: compressFunction)
+        _ = options.append("uncompress", value: uncompressFunction)
+        _ = options.append("matchinfo", value: matchInfo)
+        _ = options.append("order", value: order)
         return options
     }
 }
diff --git a/SQLite/Extensions/FTS5.swift b/SQLite/Extensions/FTS5.swift
index 97056819..9204d5b2 100644
--- a/SQLite/Extensions/FTS5.swift
+++ b/SQLite/Extensions/FTS5.swift
@@ -23,7 +23,7 @@
 //
 
 extension Module {
-    @warn_unused_result public static func FTS5(config: FTS5Config) -> Module {
+    public static func FTS5(_ config: FTS5Config) -> Module {
         return Module(name: "fts5", arguments: config.arguments())
     }
 }
@@ -32,20 +32,20 @@ extension Module {
 ///
 /// **Note:** this is currently only applicable when using SQLite.swift together with a FTS5-enabled version
 /// of SQLite.
-public class FTS5Config : FTSConfig {
+open class FTS5Config : FTSConfig {
     public enum Detail : CustomStringConvertible {
         /// store rowid, column number, term offset
-        case Full
+        case full
         /// store rowid, column number
-        case Column
+        case column
         /// store rowid
-        case None
+        case none
 
         public var description: String {
             switch self {
-            case Full: return "full"
-            case Column: return "column"
-            case None: return "none"
+            case .full: return "full"
+            case .column: return "column"
+            case .none: return "none"
             }
         }
     }
@@ -58,30 +58,30 @@ public class FTS5Config : FTSConfig {
     }
 
     /// [External Content Tables](https://www.sqlite.org/fts5.html#section_4_4_2)
-    public func contentRowId(column: Expressible) -> Self {
+    open func contentRowId(_ column: Expressible) -> Self {
         self.contentRowId = column
         return self
     }
 
     /// [The Columnsize Option](https://www.sqlite.org/fts5.html#section_4_5)
-    public func columnSize(size: Int) -> Self {
+    open func columnSize(_ size: Int) -> Self {
         self.columnSize = size
         return self
     }
 
     /// [The Detail Option](https://www.sqlite.org/fts5.html#section_4_6)
-    public func detail(detail: Detail) -> Self {
+    open func detail(_ detail: Detail) -> Self {
         self.detail = detail
         return self
     }
 
     override func options() -> Options {
         var options = super.options()
-        options.append("content_rowid", value: contentRowId)
+        _ = options.append("content_rowid", value: contentRowId)
         if let columnSize = columnSize {
-            options.append("columnsize", value: Expression<Int>(value: columnSize))
+            _ = options.append("columnsize", value: Expression<Int>(value: columnSize))
         }
-        options.append("detail", value: detail)
+        _ = options.append("detail", value: detail)
         return options
     }
 
diff --git a/SQLite/Extensions/RTree.swift b/SQLite/Extensions/RTree.swift
index a5571ea6..4fc1a235 100644
--- a/SQLite/Extensions/RTree.swift
+++ b/SQLite/Extensions/RTree.swift
@@ -24,11 +24,11 @@
 
 extension Module {
 
-    @warn_unused_result public static func RTree<T : Value, U : Value where T.Datatype == Int64, U.Datatype == Double>(primaryKey: Expression<T>, _ pairs: (Expression<U>, Expression<U>)...) -> Module {
+    public static func RTree<T : Value, U : Value>(_ primaryKey: Expression<T>, _ pairs: (Expression<U>, Expression<U>)...) -> Module where T.Datatype == Int64, U.Datatype == Double {
         var arguments: [Expressible] = [primaryKey]
 
         for pair in pairs {
-            arguments.appendContentsOf([pair.0, pair.1] as [Expressible])
+            arguments.append(contentsOf: [pair.0, pair.1] as [Expressible])
         }
 
         return Module(name: "rtree", arguments: arguments)
diff --git a/SQLite/Foundation.swift b/SQLite/Foundation.swift
index 52b2ea02..5c266a05 100644
--- a/SQLite/Foundation.swift
+++ b/SQLite/Foundation.swift
@@ -24,34 +24,36 @@
 
 import Foundation
 
-extension NSData : Value {
+extension Data : Value {
 
-    public class var declaredDatatype: String {
+    public static var declaredDatatype: String {
         return Blob.declaredDatatype
     }
 
-    public class func fromDatatypeValue(dataValue: Blob) -> NSData {
-        return NSData(bytes: dataValue.bytes, length: dataValue.bytes.count)
+    public static func fromDatatypeValue(_ dataValue: Blob) -> Data {
+        return Data(bytes: UnsafePointer<UInt8>(dataValue.bytes), count: dataValue.bytes.count)
     }
 
     public var datatypeValue: Blob {
-        return Blob(bytes: bytes, length: length)
+        return withUnsafeBytes { ptr -> Blob in
+            return Blob(bytes: ptr, length: count)
+        }
     }
 
 }
 
-extension NSDate : Value {
+extension Date : Value {
 
-    public class var declaredDatatype: String {
+    public static var declaredDatatype: String {
         return String.declaredDatatype
     }
 
-    public class func fromDatatypeValue(stringValue: String) -> NSDate {
-        return dateFormatter.dateFromString(stringValue)!
+    public static func fromDatatypeValue(_ stringValue: String) -> Date {
+        return dateFormatter.date(from: stringValue)!
     }
 
     public var datatypeValue: String {
-        return dateFormatter.stringFromDate(self)
+        return dateFormatter.string(from: self)
     }
 
 }
@@ -59,11 +61,11 @@ extension NSDate : Value {
 /// A global date formatter used to serialize and deserialize `NSDate` objects.
 /// If multiple date formats are used in an application’s database(s), use a
 /// custom `Value` type per additional format.
-public var dateFormatter: NSDateFormatter = {
-    let formatter = NSDateFormatter()
+public var dateFormatter: DateFormatter = {
+    let formatter = DateFormatter()
     formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"
-    formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
-    formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0)
+    formatter.locale = Locale(identifier: "en_US_POSIX")
+    formatter.timeZone = TimeZone(secondsFromGMT: 0)
     return formatter
 }()
 
@@ -71,17 +73,17 @@ public var dateFormatter: NSDateFormatter = {
 
 extension QueryType {
 
-    public subscript(column: Expression<NSData>) -> Expression<NSData> {
+    public subscript(column: Expression<Data>) -> Expression<Data> {
         return namespace(column)
     }
-    public subscript(column: Expression<NSData?>) -> Expression<NSData?> {
+    public subscript(column: Expression<Data?>) -> Expression<Data?> {
         return namespace(column)
     }
 
-    public subscript(column: Expression<NSDate>) -> Expression<NSDate> {
+    public subscript(column: Expression<Date>) -> Expression<Date> {
         return namespace(column)
     }
-    public subscript(column: Expression<NSDate?>) -> Expression<NSDate?> {
+    public subscript(column: Expression<Date?>) -> Expression<Date?> {
         return namespace(column)
     }
 
@@ -89,17 +91,17 @@ extension QueryType {
 
 extension Row {
 
-    public subscript(column: Expression<NSData>) -> NSData {
+    public subscript(column: Expression<Data>) -> Data {
         return get(column)
     }
-    public subscript(column: Expression<NSData?>) -> NSData? {
+    public subscript(column: Expression<Data?>) -> Data? {
         return get(column)
     }
 
-    public subscript(column: Expression<NSDate>) -> NSDate {
+    public subscript(column: Expression<Date>) -> Date {
         return get(column)
     }
-    public subscript(column: Expression<NSDate?>) -> NSDate? {
+    public subscript(column: Expression<Date?>) -> Date? {
         return get(column)
     }
 
diff --git a/SQLite/Helpers.swift b/SQLite/Helpers.swift
index cc6da27c..e9a17ce6 100644
--- a/SQLite/Helpers.swift
+++ b/SQLite/Helpers.swift
@@ -47,28 +47,28 @@ extension Optional : _OptionalType {
 }
 
 // let SQLITE_STATIC = unsafeBitCast(0, sqlite3_destructor_type.self)
-let SQLITE_TRANSIENT = unsafeBitCast(-1, sqlite3_destructor_type.self)
+let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self)
 
 extension String {
 
-    @warn_unused_result func quote(mark: Character = "\"") -> String {
+    func quote(_ mark: Character = "\"") -> String {
         let escaped = characters.reduce("") { string, character in
             string + (character == mark ? "\(mark)\(mark)" : "\(character)")
         }
         return "\(mark)\(escaped)\(mark)"
     }
 
-    @warn_unused_result func join(expressions: [Expressible]) -> Expressible {
+    func join(_ expressions: [Expressible]) -> Expressible {
         var (template, bindings) = ([String](), [Binding?]())
         for expressible in expressions {
             let expression = expressible.expression
             template.append(expression.template)
-            bindings.appendContentsOf(expression.bindings)
+            bindings.append(contentsOf: expression.bindings)
         }
-        return Expression<Void>(template.joinWithSeparator(self), bindings)
+        return Expression<Void>(template.joined(separator: self), bindings)
     }
 
-    @warn_unused_result func infix<T>(lhs: Expressible, _ rhs: Expressible, wrap: Bool = true) -> Expression<T> {
+    func infix<T>(_ lhs: Expressible, _ rhs: Expressible, wrap: Bool = true) -> Expression<T> {
         let expression = Expression<T>(" \(self) ".join([lhs, rhs]).expression)
         guard wrap else {
             return expression
@@ -76,37 +76,37 @@ extension String {
         return "".wrap(expression)
     }
 
-    @warn_unused_result func prefix(expressions: Expressible) -> Expressible {
+    func prefix(_ expressions: Expressible) -> Expressible {
         return "\(self) ".wrap(expressions) as Expression<Void>
     }
 
-    @warn_unused_result func prefix(expressions: [Expressible]) -> Expressible {
+    func prefix(_ expressions: [Expressible]) -> Expressible {
         return "\(self) ".wrap(expressions) as Expression<Void>
     }
 
-    @warn_unused_result func wrap<T>(expression: Expressible) -> Expression<T> {
+    func wrap<T>(_ expression: Expressible) -> Expression<T> {
         return Expression("\(self)(\(expression.expression.template))", expression.expression.bindings)
     }
 
-    @warn_unused_result func wrap<T>(expressions: [Expressible]) -> Expression<T> {
+    func wrap<T>(_ expressions: [Expressible]) -> Expression<T> {
         return wrap(", ".join(expressions))
     }
 
 }
 
-@warn_unused_result func infix<T>(lhs: Expressible, _ rhs: Expressible, wrap: Bool = true, function: String = #function) -> Expression<T> {
+func infix<T>(_ lhs: Expressible, _ rhs: Expressible, wrap: Bool = true, function: String = #function) -> Expression<T> {
     return function.infix(lhs, rhs, wrap: wrap)
 }
 
-@warn_unused_result func wrap<T>(expression: Expressible, function: String = #function) -> Expression<T> {
+func wrap<T>(_ expression: Expressible, function: String = #function) -> Expression<T> {
     return function.wrap(expression)
 }
 
-@warn_unused_result func wrap<T>(expressions: [Expressible], function: String = #function) -> Expression<T> {
+func wrap<T>(_ expressions: [Expressible], function: String = #function) -> Expression<T> {
     return function.wrap(", ".join(expressions))
 }
 
-@warn_unused_result func transcode(literal: Binding?) -> String {
+func transcode(_ literal: Binding?) -> String {
     guard let literal = literal else { return "NULL" }
 
     switch literal {
@@ -119,10 +119,10 @@ extension String {
     }
 }
 
-@warn_unused_result func value<A: Value>(v: Binding) -> A {
+func value<A: Value>(_ v: Binding) -> A {
     return A.fromDatatypeValue(v as! A.Datatype) as! A
 }
 
-@warn_unused_result func value<A: Value>(v: Binding?) -> A {
+func value<A: Value>(_ v: Binding?) -> A {
     return value(v!)
 }
diff --git a/SQLite/Typed/AggregateFunctions.swift b/SQLite/Typed/AggregateFunctions.swift
index 5775e0fe..249bbe60 100644
--- a/SQLite/Typed/AggregateFunctions.swift
+++ b/SQLite/Typed/AggregateFunctions.swift
@@ -232,7 +232,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
 
 extension ExpressionType where UnderlyingType == Int {
 
-    @warn_unused_result static func count(star: Star) -> Expression<UnderlyingType> {
+    static func count(_ star: Star) -> Expression<UnderlyingType> {
         return wrap(star(nil, nil))
     }
 
@@ -246,6 +246,6 @@ extension ExpressionType where UnderlyingType == Int {
 ///
 /// - Returns: An expression returning `count(*)` (when called with the `*`
 ///   function literal).
-@warn_unused_result public func count(star: Star) -> Expression<Int> {
+public func count(_ star: Star) -> Expression<Int> {
     return Expression.count(star)
 }
diff --git a/SQLite/Typed/Collation.swift b/SQLite/Typed/Collation.swift
index 5a632055..e2ff9d10 100644
--- a/SQLite/Typed/Collation.swift
+++ b/SQLite/Typed/Collation.swift
@@ -28,18 +28,18 @@
 public enum Collation {
 
     /// Compares string by raw data.
-    case Binary
+    case binary
 
     /// Like binary, but folds uppercase ASCII letters into their lowercase
     /// equivalents.
-    case Nocase
+    case nocase
 
     /// Like binary, but strips trailing space.
-    case Rtrim
+    case rtrim
 
     /// A custom collating sequence identified by the given string, registered
     /// using `Database.create(collation:…)`
-    case Custom(String)
+    case custom(String)
 
 }
 
@@ -55,13 +55,13 @@ extension Collation : CustomStringConvertible {
 
     public var description : String {
         switch self {
-        case Binary:
+        case .binary:
             return "BINARY"
-        case Nocase:
+        case .nocase:
             return "NOCASE"
-        case Rtrim:
+        case .rtrim:
             return "RTRIM"
-        case Custom(let collation):
+        case .custom(let collation):
             return collation.quote()
         }
     }
diff --git a/SQLite/Typed/CoreFunctions.swift b/SQLite/Typed/CoreFunctions.swift
index b597f3ba..9d17a326 100644
--- a/SQLite/Typed/CoreFunctions.swift
+++ b/SQLite/Typed/CoreFunctions.swift
@@ -66,7 +66,7 @@ extension ExpressionType where UnderlyingType == Double {
     ///     // round("salary", 2)
     ///
     /// - Returns: A copy of the expression wrapped with the `round` function.
-    @warn_unused_result public func round(precision: Int? = nil) -> Expression<UnderlyingType> {
+    public func round(_ precision: Int? = nil) -> Expression<UnderlyingType> {
         guard let precision = precision else {
             return wrap([self])
         }
@@ -86,7 +86,7 @@ extension ExpressionType where UnderlyingType == Double? {
     ///     // round("salary", 2)
     ///
     /// - Returns: A copy of the expression wrapped with the `round` function.
-    @warn_unused_result public func round(precision: Int? = nil) -> Expression<UnderlyingType> {
+    public func round(_ precision: Int? = nil) -> Expression<UnderlyingType> {
         guard let precision = precision else {
             return wrap(self)
         }
@@ -103,13 +103,13 @@ extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype =
     ///     // random()
     ///
     /// - Returns: An expression calling the `random` function.
-    @warn_unused_result public static func random() -> Expression<UnderlyingType> {
+    public static func random() -> Expression<UnderlyingType> {
         return "random".wrap([])
     }
 
 }
 
-extension ExpressionType where UnderlyingType == NSData {
+extension ExpressionType where UnderlyingType == Data {
 
     /// Builds an expression representing the `randomblob` function.
     ///
@@ -119,7 +119,7 @@ extension ExpressionType where UnderlyingType == NSData {
     /// - Parameter length: Length in bytes.
     ///
     /// - Returns: An expression calling the `randomblob` function.
-    @warn_unused_result public static func random(length: Int) -> Expression<UnderlyingType> {
+    public static func random(_ length: Int) -> Expression<UnderlyingType> {
         return "randomblob".wrap([])
     }
 
@@ -131,7 +131,7 @@ extension ExpressionType where UnderlyingType == NSData {
     /// - Parameter length: Length in bytes.
     ///
     /// - Returns: An expression calling the `zeroblob` function.
-    @warn_unused_result public static func allZeros(length: Int) -> Expression<UnderlyingType> {
+    public static func allZeros(_ length: Int) -> Expression<UnderlyingType> {
         return "zeroblob".wrap([])
     }
 
@@ -148,7 +148,7 @@ extension ExpressionType where UnderlyingType == NSData {
 
 }
 
-extension ExpressionType where UnderlyingType == NSData? {
+extension ExpressionType where UnderlyingType == Data? {
 
     /// Builds a copy of the expression wrapped with the `length` function.
     ///
@@ -216,7 +216,7 @@ extension ExpressionType where UnderlyingType == String {
     ///
     /// - Returns: A copy of the expression appended with a `LIKE` query against
     ///   the given pattern.
-    @warn_unused_result public func like(pattern: String, escape character: Character? = nil) -> Expression<Bool> {
+    public func like(_ pattern: String, escape character: Character? = nil) -> Expression<Bool> {
         guard let character = character else {
             return "LIKE".infix(self, pattern)
         }
@@ -234,7 +234,7 @@ extension ExpressionType where UnderlyingType == String {
     ///
     /// - Returns: A copy of the expression appended with a `GLOB` query against
     ///   the given pattern.
-    @warn_unused_result public func glob(pattern: String) -> Expression<Bool> {
+    public func glob(_ pattern: String) -> Expression<Bool> {
         return "GLOB".infix(self, pattern)
     }
 
@@ -249,7 +249,7 @@ extension ExpressionType where UnderlyingType == String {
     ///
     /// - Returns: A copy of the expression appended with a `MATCH` query
     ///   against the given pattern.
-    @warn_unused_result public func match(pattern: String) -> Expression<Bool> {
+    public func match(_ pattern: String) -> Expression<Bool> {
         return "MATCH".infix(self, pattern)
     }
 
@@ -260,7 +260,7 @@ extension ExpressionType where UnderlyingType == String {
     ///
     /// - Returns: A copy of the expression appended with a `REGEXP` query
     ///   against the given pattern.
-    @warn_unused_result public func regexp(pattern: String) -> Expression<Bool> {
+    public func regexp(_ pattern: String) -> Expression<Bool> {
         return "REGEXP".infix(self, pattern)
     }
 
@@ -275,7 +275,7 @@ extension ExpressionType where UnderlyingType == String {
     ///
     /// - Returns: A copy of the expression appended with a `COLLATE` clause
     ///   with the given sequence.
-    @warn_unused_result public func collate(collation: Collation) -> Expression<UnderlyingType> {
+    public func collate(_ collation: Collation) -> Expression<UnderlyingType> {
         return "COLLATE".infix(self, collation)
     }
 
@@ -290,7 +290,7 @@ extension ExpressionType where UnderlyingType == String {
     /// - Parameter characters: A set of characters to trim.
     ///
     /// - Returns: A copy of the expression wrapped with the `ltrim` function.
-    @warn_unused_result public func ltrim(characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
+    public func ltrim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
             return wrap(self)
         }
@@ -308,7 +308,7 @@ extension ExpressionType where UnderlyingType == String {
     /// - Parameter characters: A set of characters to trim.
     ///
     /// - Returns: A copy of the expression wrapped with the `rtrim` function.
-    @warn_unused_result public func rtrim(characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
+    public func rtrim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
             return wrap(self)
         }
@@ -326,7 +326,7 @@ extension ExpressionType where UnderlyingType == String {
     /// - Parameter characters: A set of characters to trim.
     ///
     /// - Returns: A copy of the expression wrapped with the `trim` function.
-    @warn_unused_result public func trim(characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
+    public func trim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
             return wrap([self])
         }
@@ -346,11 +346,11 @@ extension ExpressionType where UnderlyingType == String {
     ///   - replacement: The replacement string.
     ///
     /// - Returns: A copy of the expression wrapped with the `replace` function.
-    @warn_unused_result public func replace(pattern: String, with replacement: String) -> Expression<UnderlyingType> {
+    public func replace(_ pattern: String, with replacement: String) -> Expression<UnderlyingType> {
         return "replace".wrap([self, pattern, replacement])
     }
 
-    @warn_unused_result public func substring(location: Int, length: Int? = nil) -> Expression<UnderlyingType> {
+    public func substring(_ location: Int, length: Int? = nil) -> Expression<UnderlyingType> {
         guard let length = length else {
             return "substr".wrap([self, location])
         }
@@ -358,7 +358,7 @@ extension ExpressionType where UnderlyingType == String {
     }
 
     public subscript(range: Range<Int>) -> Expression<UnderlyingType> {
-        return substring(range.startIndex, length: range.endIndex - range.startIndex)
+        return substring(range.lowerBound, length: range.upperBound - range.lowerBound)
     }
 
 }
@@ -416,7 +416,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression appended with a `LIKE` query against
     ///   the given pattern.
-    @warn_unused_result public func like(pattern: String, escape character: Character? = nil) -> Expression<Bool?> {
+    public func like(_ pattern: String, escape character: Character? = nil) -> Expression<Bool?> {
         guard let character = character else {
             return "LIKE".infix(self, pattern)
         }
@@ -434,7 +434,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression appended with a `GLOB` query against
     ///   the given pattern.
-    @warn_unused_result public func glob(pattern: String) -> Expression<Bool?> {
+    public func glob(_ pattern: String) -> Expression<Bool?> {
         return "GLOB".infix(self, pattern)
     }
 
@@ -449,7 +449,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression appended with a `MATCH` query
     ///   against the given pattern.
-    @warn_unused_result public func match(pattern: String) -> Expression<Bool> {
+    public func match(_ pattern: String) -> Expression<Bool> {
         return "MATCH".infix(self, pattern)
     }
 
@@ -460,7 +460,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression appended with a `REGEXP` query
     ///   against the given pattern.
-    @warn_unused_result public func regexp(pattern: String) -> Expression<Bool?> {
+    public func regexp(_ pattern: String) -> Expression<Bool?> {
         return "REGEXP".infix(self, pattern)
     }
 
@@ -475,7 +475,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression appended with a `COLLATE` clause
     ///   with the given sequence.
-    @warn_unused_result public func collate(collation: Collation) -> Expression<UnderlyingType> {
+    public func collate(_ collation: Collation) -> Expression<UnderlyingType> {
         return "COLLATE".infix(self, collation)
     }
 
@@ -490,7 +490,7 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Parameter characters: A set of characters to trim.
     ///
     /// - Returns: A copy of the expression wrapped with the `ltrim` function.
-    @warn_unused_result public func ltrim(characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
+    public func ltrim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
             return wrap(self)
         }
@@ -508,7 +508,7 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Parameter characters: A set of characters to trim.
     ///
     /// - Returns: A copy of the expression wrapped with the `rtrim` function.
-    @warn_unused_result public func rtrim(characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
+    public func rtrim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
             return wrap(self)
         }
@@ -526,7 +526,7 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Parameter characters: A set of characters to trim.
     ///
     /// - Returns: A copy of the expression wrapped with the `trim` function.
-    @warn_unused_result public func trim(characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
+    public func trim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
             return wrap(self)
         }
@@ -546,7 +546,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///   - replacement: The replacement string.
     ///
     /// - Returns: A copy of the expression wrapped with the `replace` function.
-    @warn_unused_result public func replace(pattern: String, with replacement: String) -> Expression<UnderlyingType> {
+    public func replace(_ pattern: String, with replacement: String) -> Expression<UnderlyingType> {
         return "replace".wrap([self, pattern, replacement])
     }
 
@@ -565,7 +565,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///   - length: An optional substring length.
     ///
     /// - Returns: A copy of the expression wrapped with the `substr` function.
-    @warn_unused_result public func substring(location: Int, length: Int? = nil) -> Expression<UnderlyingType> {
+    public func substring(_ location: Int, length: Int? = nil) -> Expression<UnderlyingType> {
         guard let length = length else {
             return "substr".wrap([self, location])
         }
@@ -582,12 +582,12 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression wrapped with the `substr` function.
     public subscript(range: Range<Int>) -> Expression<UnderlyingType> {
-        return substring(range.startIndex, length: range.endIndex - range.startIndex)
+        return substring(range.lowerBound, length: range.upperBound - range.lowerBound)
     }
 
 }
 
-extension CollectionType where Generator.Element : Value, Index.Distance == Int {
+extension Collection where Iterator.Element : Value, IndexDistance == Int {
 
     /// Builds a copy of the expression prepended with an `IN` check against the
     /// collection.
@@ -600,8 +600,8 @@ extension CollectionType where Generator.Element : Value, Index.Distance == Int
     ///
     /// - Returns: A copy of the expression prepended with an `IN` check against
     ///   the collection.
-    @warn_unused_result public func contains(expression: Expression<Generator.Element>) -> Expression<Bool> {
-        let templates = [String](count: count, repeatedValue: "?").joinWithSeparator(", ")
+    public func contains(_ expression: Expression<Iterator.Element>) -> Expression<Bool> {
+        let templates = [String](repeating: "?", count: count).joined(separator: ", ")
         return "IN".infix(expression, Expression<Void>("(\(templates))", map { $0.datatypeValue }))
     }
 
@@ -616,8 +616,8 @@ extension CollectionType where Generator.Element : Value, Index.Distance == Int
     ///
     /// - Returns: A copy of the expression prepended with an `IN` check against
     ///   the collection.
-    @warn_unused_result public func contains(expression: Expression<Generator.Element?>) -> Expression<Bool?> {
-        let templates = [String](count: count, repeatedValue: "?").joinWithSeparator(", ")
+    public func contains(_ expression: Expression<Iterator.Element?>) -> Expression<Bool?> {
+        let templates = [String](repeating: "?", count: count).joined(separator: ", ")
         return "IN".infix(expression, Expression<Void>("(\(templates))", map { $0.datatypeValue }))
     }
 
diff --git a/SQLite/Typed/CustomFunctions.swift b/SQLite/Typed/CustomFunctions.swift
index 068d0340..64b54edb 100644
--- a/SQLite/Typed/CustomFunctions.swift
+++ b/SQLite/Typed/CustomFunctions.swift
@@ -39,83 +39,83 @@ public extension Connection {
     ///     The assigned types must be explicit.
     ///
     /// - Returns: A closure returning an SQL expression to call the function.
-    public func createFunction<Z : Value>(function: String, deterministic: Bool = false, _ block: () -> Z) throws -> (() -> Expression<Z>) {
+    public func createFunction<Z : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping () -> Z) throws -> (() -> Expression<Z>) {
         let fn = try createFunction(function, 0, deterministic) { _ in block() }
         return { fn([]) }
     }
 
-    public func createFunction<Z : Value>(function: String, deterministic: Bool = false, _ block: () -> Z?) throws -> (() -> Expression<Z?>) {
+    public func createFunction<Z : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping () -> Z?) throws -> (() -> Expression<Z?>) {
         let fn = try createFunction(function, 0, deterministic) { _ in block() }
         return { fn([]) }
     }
 
     // MARK: -
 
-    public func createFunction<Z : Value, A : Value>(function: String, deterministic: Bool = false, _ block: A -> Z) throws -> (Expression<A> -> Expression<Z>) {
+    public func createFunction<Z : Value, A : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A) -> Z) throws -> ((Expression<A>) -> Expression<Z>) {
         let fn = try createFunction(function, 1, deterministic) { args in block(value(args[0])) }
         return { arg in fn([arg]) }
     }
 
-    public func createFunction<Z : Value, A : Value>(function function: String, deterministic: Bool = false, _ block: A? -> Z) throws -> (Expression<A?> -> Expression<Z>) {
+    public func createFunction<Z : Value, A : Value>(function: String, deterministic: Bool = false, _ block: @escaping (A?) -> Z) throws -> ((Expression<A?>) -> Expression<Z>) {
         let fn = try createFunction(function, 1, deterministic) { args in block(args[0].map(value)) }
         return { arg in fn([arg]) }
     }
 
-    public func createFunction<Z : Value, A : Value>(function function: String, deterministic: Bool = false, _ block: A -> Z?) throws -> (Expression<A> -> Expression<Z?>) {
+    public func createFunction<Z : Value, A : Value>(function: String, deterministic: Bool = false, _ block: @escaping (A) -> Z?) throws -> ((Expression<A>) -> Expression<Z?>) {
         let fn = try createFunction(function, 1, deterministic) { args in block(value(args[0])) }
         return { arg in fn([arg]) }
     }
 
-    public func createFunction<Z : Value, A : Value>(function function: String, deterministic: Bool = false, _ block: A? -> Z?) throws -> (Expression<A?> -> Expression<Z?>) {
+    public func createFunction<Z : Value, A : Value>(function: String, deterministic: Bool = false, _ block: @escaping (A?) -> Z?) throws -> ((Expression<A?>) -> Expression<Z?>) {
         let fn = try createFunction(function, 1, deterministic) { args in block(args[0].map(value)) }
         return { arg in fn([arg]) }
     }
 
     // MARK: -
 
-    public func createFunction<Z : Value, A : Value, B : Value>(function: String, deterministic: Bool = false, _ block: (A, B) -> Z) throws -> (Expression<A>, Expression<B>) -> Expression<Z> {
+    public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B) -> Z) throws -> (Expression<A>, Expression<B>) -> Expression<Z> {
         let fn = try createFunction(function, 1, deterministic) { args in block(value(args[0]), value(args[1])) }
         return { a, b in fn([a, b]) }
     }
 
-    public func createFunction<Z : Value, A : Value, B : Value>(function: String, deterministic: Bool = false, _ block: (A?, B) -> Z) throws -> (Expression<A?>, Expression<B>) -> Expression<Z> {
+    public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B) -> Z) throws -> (Expression<A?>, Expression<B>) -> Expression<Z> {
         let fn = try createFunction(function, 1, deterministic) { args in block(args[0].map(value), value(args[1])) }
         return { a, b in fn([a, b]) }
     }
 
-    public func createFunction<Z : Value, A : Value, B : Value>(function: String, deterministic: Bool = false, _ block: (A, B?) -> Z) throws -> (Expression<A>, Expression<B?>) -> Expression<Z> {
+    public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B?) -> Z) throws -> (Expression<A>, Expression<B?>) -> Expression<Z> {
         let fn = try createFunction(function, 1, deterministic) { args in block(value(args[0]), args[1].map(value)) }
         return { a, b in fn([a, b]) }
     }
 
-    public func createFunction<Z : Value, A : Value, B : Value>(function: String, deterministic: Bool = false, _ block: (A, B) -> Z?) throws -> (Expression<A>, Expression<B>) -> Expression<Z?> {
+    public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B) -> Z?) throws -> (Expression<A>, Expression<B>) -> Expression<Z?> {
         let fn = try createFunction(function, 1, deterministic) { args in block(value(args[0]), value(args[1])) }
         return { a, b in fn([a, b]) }
     }
 
-    public func createFunction<Z : Value, A : Value, B : Value>(function: String, deterministic: Bool = false, _ block: (A?, B?) -> Z) throws -> (Expression<A?>, Expression<B?>) -> Expression<Z> {
+    public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B?) -> Z) throws -> (Expression<A?>, Expression<B?>) -> Expression<Z> {
         let fn = try createFunction(function, 1, deterministic) { args in block(args[0].map(value), args[1].map(value)) }
         return { a, b in fn([a, b]) }
     }
 
-    public func createFunction<Z : Value, A : Value, B : Value>(function: String, deterministic: Bool = false, _ block: (A?, B) -> Z?) throws -> (Expression<A?>, Expression<B>) -> Expression<Z?> {
+    public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B) -> Z?) throws -> (Expression<A?>, Expression<B>) -> Expression<Z?> {
         let fn = try createFunction(function, 1, deterministic) { args in block(args[0].map(value), value(args[1])) }
         return { a, b in fn([a, b]) }
     }
 
-    public func createFunction<Z : Value, A : Value, B : Value>(function: String, deterministic: Bool = false, _ block: (A, B?) -> Z?) throws -> (Expression<A>, Expression<B?>) -> Expression<Z?> {
+    public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B?) -> Z?) throws -> (Expression<A>, Expression<B?>) -> Expression<Z?> {
         let fn = try createFunction(function, 1, deterministic) { args in block(value(args[0]), args[1].map(value)) }
         return { a, b in fn([a, b]) }
     }
 
-    public func createFunction<Z : Value, A : Value, B : Value>(function: String, deterministic: Bool = false, _ block: (A?, B?) -> Z?) throws -> (Expression<A?>, Expression<B?>) -> Expression<Z?> {
+    public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B?) -> Z?) throws -> (Expression<A?>, Expression<B?>) -> Expression<Z?> {
         let fn = try createFunction(function, 1, deterministic) { args in block(args[0].map(value), args[1].map(value)) }
         return { a, b in fn([a, b]) }
     }
 
     // MARK: -
 
-    private func createFunction<Z : Value>(function: String, _ argumentCount: UInt, _ deterministic: Bool, _ block: [Binding?] -> Z) throws -> ([Expressible] -> Expression<Z>) {
+    fileprivate func createFunction<Z : Value>(_ function: String, _ argumentCount: UInt, _ deterministic: Bool, _ block: @escaping ([Binding?]) -> Z) throws -> (([Expressible]) -> Expression<Z>) {
         createFunction(function, argumentCount: argumentCount, deterministic: deterministic) { arguments in
             block(arguments).datatypeValue
         }
@@ -124,7 +124,7 @@ public extension Connection {
         }
     }
 
-    private func createFunction<Z : Value>(function: String, _ argumentCount: UInt, _ deterministic: Bool, _ block: [Binding?] -> Z?) throws -> ([Expressible] -> Expression<Z?>) {
+    fileprivate func createFunction<Z : Value>(_ function: String, _ argumentCount: UInt, _ deterministic: Bool, _ block: @escaping ([Binding?]) -> Z?) throws -> (([Expressible]) -> Expression<Z?>) {
         createFunction(function, argumentCount: argumentCount, deterministic: deterministic) { arguments in
             block(arguments)?.datatypeValue
         }
diff --git a/SQLite/Typed/Expression.swift b/SQLite/Typed/Expression.swift
index 2e71b970..3198901c 100644
--- a/SQLite/Typed/Expression.swift
+++ b/SQLite/Typed/Expression.swift
@@ -138,10 +138,10 @@ extension Value {
 
 public let rowid = Expression<Int64>("ROWID")
 
-public func cast<T: Value, U: Value>(expression: Expression<T>) -> Expression<U> {
+public func cast<T: Value, U: Value>(_ expression: Expression<T>) -> Expression<U> {
     return Expression("CAST (\(expression.template) AS \(U.declaredDatatype))", expression.bindings)
 }
 
-public func cast<T: Value, U: Value>(expression: Expression<T?>) -> Expression<U?> {
+public func cast<T: Value, U: Value>(_ expression: Expression<T?>) -> Expression<U?> {
     return Expression("CAST (\(expression.template) AS \(U.declaredDatatype))", expression.bindings)
 }
diff --git a/SQLite/Typed/Operators.swift b/SQLite/Typed/Operators.swift
index 816560a5..616015dc 100644
--- a/SQLite/Typed/Operators.swift
+++ b/SQLite/Typed/Operators.swift
@@ -52,433 +52,433 @@ public func +(lhs: String, rhs: Expression<String?>) -> Expression<String?> {
 
 // MARK: -
 
-public func +<V : Value where V.Datatype : Number>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> {
+public func +<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func +<V : Value where V.Datatype : Number>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> {
+public func +<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func +<V : Value where V.Datatype : Number>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> {
+public func +<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func +<V : Value where V.Datatype : Number>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> {
+public func +<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func +<V : Value where V.Datatype : Number>(lhs: Expression<V>, rhs: V) -> Expression<V> {
+public func +<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func +<V : Value where V.Datatype : Number>(lhs: Expression<V?>, rhs: V) -> Expression<V?> {
+public func +<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func +<V : Value where V.Datatype : Number>(lhs: V, rhs: Expression<V>) -> Expression<V> {
+public func +<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func +<V: Value where V.Datatype : Number>(lhs: V, rhs: Expression<V?>) -> Expression<V?> {
+public func +<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
 
-public func -<V : Value where V.Datatype : Number>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> {
+public func -<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func -<V : Value where V.Datatype : Number>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> {
+public func -<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func -<V : Value where V.Datatype : Number>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> {
+public func -<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func -<V : Value where V.Datatype : Number>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> {
+public func -<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func -<V : Value where V.Datatype : Number>(lhs: Expression<V>, rhs: V) -> Expression<V> {
+public func -<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func -<V : Value where V.Datatype : Number>(lhs: Expression<V?>, rhs: V) -> Expression<V?> {
+public func -<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func -<V : Value where V.Datatype : Number>(lhs: V, rhs: Expression<V>) -> Expression<V> {
+public func -<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func -<V: Value where V.Datatype : Number>(lhs: V, rhs: Expression<V?>) -> Expression<V?> {
+public func -<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
 
-public func *<V : Value where V.Datatype : Number>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> {
+public func *<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func *<V : Value where V.Datatype : Number>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> {
+public func *<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func *<V : Value where V.Datatype : Number>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> {
+public func *<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func *<V : Value where V.Datatype : Number>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> {
+public func *<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func *<V : Value where V.Datatype : Number>(lhs: Expression<V>, rhs: V) -> Expression<V> {
+public func *<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func *<V : Value where V.Datatype : Number>(lhs: Expression<V?>, rhs: V) -> Expression<V?> {
+public func *<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func *<V : Value where V.Datatype : Number>(lhs: V, rhs: Expression<V>) -> Expression<V> {
+public func *<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func *<V: Value where V.Datatype : Number>(lhs: V, rhs: Expression<V?>) -> Expression<V?> {
+public func *<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
 
-public func /<V : Value where V.Datatype : Number>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> {
+public func /<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func /<V : Value where V.Datatype : Number>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> {
+public func /<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func /<V : Value where V.Datatype : Number>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> {
+public func /<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func /<V : Value where V.Datatype : Number>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> {
+public func /<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func /<V : Value where V.Datatype : Number>(lhs: Expression<V>, rhs: V) -> Expression<V> {
+public func /<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func /<V : Value where V.Datatype : Number>(lhs: Expression<V?>, rhs: V) -> Expression<V?> {
+public func /<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func /<V : Value where V.Datatype : Number>(lhs: V, rhs: Expression<V>) -> Expression<V> {
+public func /<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
-public func /<V: Value where V.Datatype : Number>(lhs: V, rhs: Expression<V?>) -> Expression<V?> {
+public func /<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
     return infix(lhs, rhs)
 }
 
-public prefix func -<V : Value where V.Datatype : Number>(rhs: Expression<V>) -> Expression<V> {
+public prefix func -<V : Value>(rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
     return wrap(rhs)
 }
-public prefix func -<V : Value where V.Datatype : Number>(rhs: Expression<V?>) -> Expression<V?> {
+public prefix func -<V : Value>(rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
     return wrap(rhs)
 }
 
 // MARK: -
 
-public func %<V : Value where V.Datatype == Int64>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> {
+public func %<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func %<V : Value where V.Datatype == Int64>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> {
+public func %<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func %<V : Value where V.Datatype == Int64>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> {
+public func %<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func %<V : Value where V.Datatype == Int64>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> {
+public func %<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func %<V : Value where V.Datatype == Int64>(lhs: Expression<V>, rhs: V) -> Expression<V> {
+public func %<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func %<V : Value where V.Datatype == Int64>(lhs: Expression<V?>, rhs: V) -> Expression<V?> {
+public func %<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func %<V : Value where V.Datatype == Int64>(lhs: V, rhs: Expression<V>) -> Expression<V> {
+public func %<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func %<V : Value where V.Datatype == Int64>(lhs: V, rhs: Expression<V?>) -> Expression<V?> {
+public func %<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
 
-public func <<<V : Value where V.Datatype == Int64>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> {
+public func <<<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func <<<V : Value where V.Datatype == Int64>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> {
+public func <<<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func <<<V : Value where V.Datatype == Int64>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> {
+public func <<<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func <<<V : Value where V.Datatype == Int64>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> {
+public func <<<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func <<<V : Value where V.Datatype == Int64>(lhs: Expression<V>, rhs: V) -> Expression<V> {
+public func <<<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func <<<V : Value where V.Datatype == Int64>(lhs: Expression<V?>, rhs: V) -> Expression<V?> {
+public func <<<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func <<<V : Value where V.Datatype == Int64>(lhs: V, rhs: Expression<V>) -> Expression<V> {
+public func <<<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func <<<V : Value where V.Datatype == Int64>(lhs: V, rhs: Expression<V?>) -> Expression<V?> {
+public func <<<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
 
-public func >><V : Value where V.Datatype == Int64>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> {
+public func >><V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func >><V : Value where V.Datatype == Int64>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> {
+public func >><V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func >><V : Value where V.Datatype == Int64>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> {
+public func >><V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func >><V : Value where V.Datatype == Int64>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> {
+public func >><V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func >><V : Value where V.Datatype == Int64>(lhs: Expression<V>, rhs: V) -> Expression<V> {
+public func >><V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func >><V : Value where V.Datatype == Int64>(lhs: Expression<V?>, rhs: V) -> Expression<V?> {
+public func >><V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func >><V : Value where V.Datatype == Int64>(lhs: V, rhs: Expression<V>) -> Expression<V> {
+public func >><V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func >><V : Value where V.Datatype == Int64>(lhs: V, rhs: Expression<V?>) -> Expression<V?> {
+public func >><V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
 
-public func &<V : Value where V.Datatype == Int64>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> {
+public func &<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func &<V : Value where V.Datatype == Int64>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> {
+public func &<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func &<V : Value where V.Datatype == Int64>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> {
+public func &<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func &<V : Value where V.Datatype == Int64>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> {
+public func &<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func &<V : Value where V.Datatype == Int64>(lhs: Expression<V>, rhs: V) -> Expression<V> {
+public func &<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func &<V : Value where V.Datatype == Int64>(lhs: Expression<V?>, rhs: V) -> Expression<V?> {
+public func &<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func &<V : Value where V.Datatype == Int64>(lhs: V, rhs: Expression<V>) -> Expression<V> {
+public func &<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func &<V : Value where V.Datatype == Int64>(lhs: V, rhs: Expression<V?>) -> Expression<V?> {
+public func &<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
 
-public func |<V : Value where V.Datatype == Int64>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> {
+public func |<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func |<V : Value where V.Datatype == Int64>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> {
+public func |<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func |<V : Value where V.Datatype == Int64>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> {
+public func |<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func |<V : Value where V.Datatype == Int64>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> {
+public func |<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func |<V : Value where V.Datatype == Int64>(lhs: Expression<V>, rhs: V) -> Expression<V> {
+public func |<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func |<V : Value where V.Datatype == Int64>(lhs: Expression<V?>, rhs: V) -> Expression<V?> {
+public func |<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func |<V : Value where V.Datatype == Int64>(lhs: V, rhs: Expression<V>) -> Expression<V> {
+public func |<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
-public func |<V : Value where V.Datatype == Int64>(lhs: V, rhs: Expression<V?>) -> Expression<V?> {
+public func |<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return infix(lhs, rhs)
 }
 
-public func ^<V : Value where V.Datatype == Int64>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> {
+public func ^<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return (~(lhs & rhs)) & (lhs | rhs)
 }
-public func ^<V : Value where V.Datatype == Int64>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> {
+public func ^<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return (~(lhs & rhs)) & (lhs | rhs)
 }
-public func ^<V : Value where V.Datatype == Int64>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> {
+public func ^<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
     return (~(lhs & rhs)) & (lhs | rhs)
 }
-public func ^<V : Value where V.Datatype == Int64>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> {
+public func ^<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return (~(lhs & rhs)) & (lhs | rhs)
 }
-public func ^<V : Value where V.Datatype == Int64>(lhs: Expression<V>, rhs: V) -> Expression<V> {
+public func ^<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
     return (~(lhs & rhs)) & (lhs | rhs)
 }
-public func ^<V : Value where V.Datatype == Int64>(lhs: Expression<V?>, rhs: V) -> Expression<V?> {
+public func ^<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
     return (~(lhs & rhs)) & (lhs | rhs)
 }
-public func ^<V : Value where V.Datatype == Int64>(lhs: V, rhs: Expression<V>) -> Expression<V> {
+public func ^<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return (~(lhs & rhs)) & (lhs | rhs)
 }
-public func ^<V : Value where V.Datatype == Int64>(lhs: V, rhs: Expression<V?>) -> Expression<V?> {
+public func ^<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return (~(lhs & rhs)) & (lhs | rhs)
 }
 
-public prefix func ~<V : Value where V.Datatype == Int64>(rhs: Expression<V>) -> Expression<V> {
+public prefix func ~<V : Value>(rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return wrap(rhs)
 }
-public prefix func ~<V : Value where V.Datatype == Int64>(rhs: Expression<V?>) -> Expression<V?> {
+public prefix func ~<V : Value>(rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return wrap(rhs)
 }
 
 // MARK: -
 
-public func ==<V : Value where V.Datatype : Equatable>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> {
+public func ==<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
     return "=".infix(lhs, rhs)
 }
-public func ==<V : Value where V.Datatype : Equatable>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> {
+public func ==<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
     return "=".infix(lhs, rhs)
 }
-public func ==<V : Value where V.Datatype : Equatable>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> {
+public func ==<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Equatable {
     return "=".infix(lhs, rhs)
 }
-public func ==<V : Value where V.Datatype : Equatable>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> {
+public func ==<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
     return "=".infix(lhs, rhs)
 }
-public func ==<V : Value where V.Datatype : Equatable>(lhs: Expression<V>, rhs: V) -> Expression<Bool> {
+public func ==<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Equatable {
     return "=".infix(lhs, rhs)
 }
-public func ==<V : Value where V.Datatype : Equatable>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> {
+public func ==<V : Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype : Equatable {
     guard let rhs = rhs else { return "IS".infix(lhs, Expression<V?>(value: nil)) }
     return "=".infix(lhs, rhs)
 }
-public func ==<V : Value where V.Datatype : Equatable>(lhs: V, rhs: Expression<V>) -> Expression<Bool> {
+public func ==<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
     return "=".infix(lhs, rhs)
 }
-public func ==<V : Value where V.Datatype : Equatable>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> {
+public func ==<V : Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
     guard let lhs = lhs else { return "IS".infix(Expression<V?>(value: nil), rhs) }
     return "=".infix(lhs, rhs)
 }
 
-public func !=<V : Value where V.Datatype : Equatable>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> {
+public func !=<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
     return infix(lhs, rhs)
 }
-public func !=<V : Value where V.Datatype : Equatable>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> {
+public func !=<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
     return infix(lhs, rhs)
 }
-public func !=<V : Value where V.Datatype : Equatable>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> {
+public func !=<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Equatable {
     return infix(lhs, rhs)
 }
-public func !=<V : Value where V.Datatype : Equatable>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> {
+public func !=<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
     return infix(lhs, rhs)
 }
-public func !=<V : Value where V.Datatype : Equatable>(lhs: Expression<V>, rhs: V) -> Expression<Bool> {
+public func !=<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Equatable {
     return infix(lhs, rhs)
 }
-public func !=<V : Value where V.Datatype : Equatable>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> {
+public func !=<V : Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype : Equatable {
     guard let rhs = rhs else { return "IS NOT".infix(lhs, Expression<V?>(value: nil)) }
     return infix(lhs, rhs)
 }
-public func !=<V : Value where V.Datatype : Equatable>(lhs: V, rhs: Expression<V>) -> Expression<Bool> {
+public func !=<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
     return infix(lhs, rhs)
 }
-public func !=<V : Value where V.Datatype : Equatable>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> {
+public func !=<V : Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
     guard let lhs = lhs else { return "IS NOT".infix(Expression<V?>(value: nil), rhs) }
     return infix(lhs, rhs)
 }
 
-public func ><V : Value where V.Datatype : Comparable>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> {
+public func ><V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func ><V : Value where V.Datatype : Comparable>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> {
+public func ><V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func ><V : Value where V.Datatype : Comparable>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> {
+public func ><V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func ><V : Value where V.Datatype : Comparable>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> {
+public func ><V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func ><V : Value where V.Datatype : Comparable>(lhs: Expression<V>, rhs: V) -> Expression<Bool> {
+public func ><V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func ><V : Value where V.Datatype : Comparable>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> {
+public func ><V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func ><V : Value where V.Datatype : Comparable>(lhs: V, rhs: Expression<V>) -> Expression<Bool> {
+public func ><V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func ><V : Value where V.Datatype : Comparable>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> {
+public func ><V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
 
-public func >=<V : Value where V.Datatype : Comparable>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> {
+public func >=<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func >=<V : Value where V.Datatype : Comparable>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> {
+public func >=<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func >=<V : Value where V.Datatype : Comparable>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> {
+public func >=<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func >=<V : Value where V.Datatype : Comparable>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> {
+public func >=<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func >=<V : Value where V.Datatype : Comparable>(lhs: Expression<V>, rhs: V) -> Expression<Bool> {
+public func >=<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func >=<V : Value where V.Datatype : Comparable>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> {
+public func >=<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func >=<V : Value where V.Datatype : Comparable>(lhs: V, rhs: Expression<V>) -> Expression<Bool> {
+public func >=<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func >=<V : Value where V.Datatype : Comparable>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> {
+public func >=<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
 
-public func <<V : Value where V.Datatype : Comparable>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> {
+public func <<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func <<V : Value where V.Datatype : Comparable>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> {
+public func <<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func <<V : Value where V.Datatype : Comparable>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> {
+public func <<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func <<V : Value where V.Datatype : Comparable>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> {
+public func <<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func <<V : Value where V.Datatype : Comparable>(lhs: Expression<V>, rhs: V) -> Expression<Bool> {
+public func <<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func <<V : Value where V.Datatype : Comparable>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> {
+public func <<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func <<V : Value where V.Datatype : Comparable>(lhs: V, rhs: Expression<V>) -> Expression<Bool> {
+public func <<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func <<V : Value where V.Datatype : Comparable>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> {
+public func <<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
 
-public func <=<V : Value where V.Datatype : Comparable>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> {
+public func <=<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func <=<V : Value where V.Datatype : Comparable>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> {
+public func <=<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func <=<V : Value where V.Datatype : Comparable>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> {
+public func <=<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func <=<V : Value where V.Datatype : Comparable>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> {
+public func <=<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func <=<V : Value where V.Datatype : Comparable>(lhs: Expression<V>, rhs: V) -> Expression<Bool> {
+public func <=<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func <=<V : Value where V.Datatype : Comparable>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> {
+public func <=<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func <=<V : Value where V.Datatype : Comparable>(lhs: V, rhs: Expression<V>) -> Expression<Bool> {
+public func <=<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
-public func <=<V : Value where V.Datatype : Comparable>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> {
+public func <=<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
     return infix(lhs, rhs)
 }
 
-public func ~=<I : IntervalType, V : Value where V.Datatype : protocol<Binding, Comparable>, V.Datatype == I.Bound>(lhs: I, rhs: Expression<V>) -> Expression<Bool> {
-    return Expression("\(rhs.template) BETWEEN ? AND ?", rhs.bindings + [lhs.start, lhs.end])
+public func ~=<V : Value>(lhs: CountableClosedRange<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Binding & Comparable {
+    return Expression("\(rhs.template) BETWEEN ? AND ?", rhs.bindings + [lhs.lowerBound as? Binding, lhs.upperBound as? Binding])
 }
-public func ~=<I : IntervalType, V : Value where V.Datatype : protocol<Binding, Comparable>, V.Datatype == I.Bound>(lhs: I, rhs: Expression<V?>) -> Expression<Bool?> {
-    return Expression("\(rhs.template) BETWEEN ? AND ?", rhs.bindings + [lhs.start, lhs.end])
+public func ~=<V : Value>(lhs: CountableClosedRange<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Binding & Comparable {
+    return Expression("\(rhs.template) BETWEEN ? AND ?", rhs.bindings + [lhs.lowerBound as? Binding, lhs.upperBound as? Binding])
 }
 
 // MARK: -
diff --git a/SQLite/Typed/Query.swift b/SQLite/Typed/Query.swift
index 36b3b2e1..d0e4572d 100644
--- a/SQLite/Typed/Query.swift
+++ b/SQLite/Typed/Query.swift
@@ -50,7 +50,7 @@ extension SchemaType {
     /// - Parameter all: A list of expressions to select.
     ///
     /// - Returns: A query with the given `SELECT` clause applied.
-    public func select(column1: Expressible, _ more: Expressible...) -> Self {
+    public func select(_ column1: Expressible, _ more: Expressible...) -> Self {
         return select(false, [column1] + more)
     }
 
@@ -81,7 +81,7 @@ extension SchemaType {
     /// - Parameter all: A list of expressions to select.
     ///
     /// - Returns: A query with the given `SELECT` clause applied.
-    public func select(all: [Expressible]) -> Self {
+    public func select(_ all: [Expressible]) -> Self {
         return select(false, all)
     }
 
@@ -110,7 +110,7 @@ extension SchemaType {
     /// - Parameter star: A star literal.
     ///
     /// - Returns: A query with the given `SELECT *` clause applied.
-    public func select(star: Star) -> Self {
+    public func select(_ star: Star) -> Self {
         return select([star(nil, nil)])
     }
 
@@ -139,10 +139,10 @@ extension SchemaType {
     /// - Parameter all: A list of expressions to select.
     ///
     /// - Returns: A query with the given `SELECT` clause applied.
-    public func select<V : Value>(column: Expression<V>) -> ScalarQuery<V> {
+    public func select<V : Value>(_ column: Expression<V>) -> ScalarQuery<V> {
         return select(false, [column])
     }
-    public func select<V : Value>(column: Expression<V?>) -> ScalarQuery<V?> {
+    public func select<V : Value>(_ column: Expression<V?>) -> ScalarQuery<V?> {
         return select(false, [column])
     }
 
@@ -173,7 +173,7 @@ extension SchemaType {
 
 extension QueryType {
 
-    private func select<Q : QueryType>(distinct: Bool, _ columns: [Expressible]) -> Q {
+    fileprivate func select<Q : QueryType>(_ distinct: Bool, _ columns: [Expressible]) -> Q {
         var query = Q.init(clauses.from.name, database: clauses.from.database)
         query.clauses = clauses
         query.clauses.select = (distinct, columns)
@@ -199,7 +199,7 @@ extension QueryType {
     ///   - condition: A boolean expression describing the join condition.
     ///
     /// - Returns: A query with the given `JOIN` clause applied.
-    public func join(table: QueryType, on condition: Expression<Bool>) -> Self {
+    public func join(_ table: QueryType, on condition: Expression<Bool>) -> Self {
         return join(table, on: Expression<Bool?>(condition))
     }
 
@@ -220,7 +220,7 @@ extension QueryType {
     ///   - condition: A boolean expression describing the join condition.
     ///
     /// - Returns: A query with the given `JOIN` clause applied.
-    public func join(table: QueryType, on condition: Expression<Bool?>) -> Self {
+    public func join(_ table: QueryType, on condition: Expression<Bool?>) -> Self {
         return join(.Inner, table, on: condition)
     }
 
@@ -243,7 +243,7 @@ extension QueryType {
     ///   - condition: A boolean expression describing the join condition.
     ///
     /// - Returns: A query with the given `JOIN` clause applied.
-    public func join(type: JoinType, _ table: QueryType, on condition: Expression<Bool>) -> Self {
+    public func join(_ type: JoinType, _ table: QueryType, on condition: Expression<Bool>) -> Self {
         return join(type, table, on: Expression<Bool?>(condition))
     }
 
@@ -266,7 +266,7 @@ extension QueryType {
     ///   - condition: A boolean expression describing the join condition.
     ///
     /// - Returns: A query with the given `JOIN` clause applied.
-    public func join(type: JoinType, _ table: QueryType, on condition: Expression<Bool?>) -> Self {
+    public func join(_ type: JoinType, _ table: QueryType, on condition: Expression<Bool?>) -> Self {
         var query = self
         query.clauses.join.append((type: type, query: table, condition: table.clauses.filters.map { condition && $0 } ?? condition as Expressible))
         return query
@@ -285,7 +285,7 @@ extension QueryType {
     /// - Parameter condition: A boolean expression to filter on.
     ///
     /// - Returns: A query with the given `WHERE` clause applied.
-    public func filter(predicate: Expression<Bool>) -> Self {
+    public func filter(_ predicate: Expression<Bool>) -> Self {
         return filter(Expression<Bool?>(predicate))
     }
 
@@ -300,7 +300,7 @@ extension QueryType {
     /// - Parameter condition: A boolean expression to filter on.
     ///
     /// - Returns: A query with the given `WHERE` clause applied.
-    public func filter(predicate: Expression<Bool?>) -> Self {
+    public func filter(_ predicate: Expression<Bool?>) -> Self {
         var query = self
         query.clauses.filters = query.clauses.filters.map { $0 && predicate } ?? predicate
         return query
@@ -313,7 +313,7 @@ extension QueryType {
     /// - Parameter by: A list of columns to group by.
     ///
     /// - Returns: A query with the given `GROUP BY` clause applied.
-    public func group(by: Expressible...) -> Self {
+    public func group(_ by: Expressible...) -> Self {
         return group(by)
     }
 
@@ -322,7 +322,7 @@ extension QueryType {
     /// - Parameter by: A list of columns to group by.
     ///
     /// - Returns: A query with the given `GROUP BY` clause applied.
-    public func group(by: [Expressible]) -> Self {
+    public func group(_ by: [Expressible]) -> Self {
         return group(by, nil)
     }
 
@@ -335,7 +335,7 @@ extension QueryType {
     ///   - having: A condition determining which groups are returned.
     ///
     /// - Returns: A query with the given `GROUP BY`–`HAVING` clause applied.
-    public func group(by: Expressible, having: Expression<Bool>) -> Self {
+    public func group(_ by: Expressible, having: Expression<Bool>) -> Self {
         return group([by], having: having)
     }
 
@@ -348,7 +348,7 @@ extension QueryType {
     ///   - having: A condition determining which groups are returned.
     ///
     /// - Returns: A query with the given `GROUP BY`–`HAVING` clause applied.
-    public func group(by: Expressible, having: Expression<Bool?>) -> Self {
+    public func group(_ by: Expressible, having: Expression<Bool?>) -> Self {
         return group([by], having: having)
     }
 
@@ -361,7 +361,7 @@ extension QueryType {
     ///   - having: A condition determining which groups are returned.
     ///
     /// - Returns: A query with the given `GROUP BY`–`HAVING` clause applied.
-    public func group(by: [Expressible], having: Expression<Bool>) -> Self {
+    public func group(_ by: [Expressible], having: Expression<Bool>) -> Self {
         return group(by, Expression<Bool?>(having))
     }
 
@@ -374,11 +374,11 @@ extension QueryType {
     ///   - having: A condition determining which groups are returned.
     ///
     /// - Returns: A query with the given `GROUP BY`–`HAVING` clause applied.
-    public func group(by: [Expressible], having: Expression<Bool?>) -> Self {
+    public func group(_ by: [Expressible], having: Expression<Bool?>) -> Self {
         return group(by, having)
     }
 
-    private func group(by: [Expressible], _ having: Expression<Bool?>?) -> Self {
+    fileprivate func group(_ by: [Expressible], _ having: Expression<Bool?>?) -> Self {
         var query = self
         query.clauses.group = (by, having)
         return query
@@ -398,7 +398,7 @@ extension QueryType {
     /// - Parameter by: An ordered list of columns and directions to sort by.
     ///
     /// - Returns: A query with the given `ORDER BY` clause applied.
-    public func order(by: Expressible...) -> Self {
+    public func order(_ by: Expressible...) -> Self {
         return order(by)
     }
     
@@ -414,7 +414,7 @@ extension QueryType {
     /// - Parameter by: An ordered list of columns and directions to sort by.
     ///
     /// - Returns: A query with the given `ORDER BY` clause applied.
-    public func order(by: [Expressible]) -> Self {
+    public func order(_ by: [Expressible]) -> Self {
         var query = self
         query.clauses.order = by
         return query
@@ -433,7 +433,7 @@ extension QueryType {
     ///   return unlimited rows).
     ///
     /// - Returns: A query with the given LIMIT clause applied.
-    public func limit(length: Int?) -> Self {
+    public func limit(_ length: Int?) -> Self {
         return limit(length, nil)
     }
 
@@ -451,12 +451,12 @@ extension QueryType {
     ///   - offset: The number of rows to skip.
     ///
     /// - Returns: A query with the given LIMIT and OFFSET clauses applied.
-    public func limit(length: Int, offset: Int) -> Self {
+    public func limit(_ length: Int, offset: Int) -> Self {
         return limit(length, offset)
     }
 
     // prevents limit(nil, offset: 5)
-    private func limit(length: Int?, _ offset: Int?) -> Self {
+    fileprivate func limit(_ length: Int?, _ offset: Int?) -> Self {
         var query = self
         query.clauses.limit = length.map { ($0, offset) }
         return query
@@ -468,7 +468,7 @@ extension QueryType {
 
     // MARK: -
 
-    private var selectClause: Expressible {
+    fileprivate var selectClause: Expressible {
         return " ".join([
             Expression<Void>(literal: clauses.select.distinct ? "SELECT DISTINCT" : "SELECT"),
             ", ".join(clauses.select.columns),
@@ -477,7 +477,7 @@ extension QueryType {
         ])
     }
 
-    private var joinClause: Expressible? {
+    fileprivate var joinClause: Expressible? {
         guard !clauses.join.isEmpty else {
             return nil
         }
@@ -492,7 +492,7 @@ extension QueryType {
         })
     }
 
-    private var whereClause: Expressible? {
+    fileprivate var whereClause: Expressible? {
         guard let filters = clauses.filters else {
             return nil
         }
@@ -503,7 +503,7 @@ extension QueryType {
         ])
     }
 
-    private var groupByClause: Expressible? {
+    fileprivate var groupByClause: Expressible? {
         guard let group = clauses.group else {
             return nil
         }
@@ -526,7 +526,7 @@ extension QueryType {
         ])
     }
 
-    private var orderClause: Expressible? {
+    fileprivate var orderClause: Expressible? {
         guard !clauses.order.isEmpty else {
             return nil
         }
@@ -537,7 +537,7 @@ extension QueryType {
         ])
     }
 
-    private var limitOffsetClause: Expressible? {
+    fileprivate var limitOffsetClause: Expressible? {
         guard let limit = clauses.limit else {
             return nil
         }
@@ -556,7 +556,7 @@ extension QueryType {
 
     // MARK: -
 
-    public func alias(aliasName: String) -> Self {
+    public func alias(_ aliasName: String) -> Self {
         var query = self
         query.clauses.from = (clauses.from.name, aliasName, clauses.from.database)
         return query
@@ -566,11 +566,11 @@ extension QueryType {
     //
     // MARK: INSERT
 
-    public func insert(value: Setter, _ more: Setter...) -> Insert {
+    public func insert(_ value: Setter, _ more: Setter...) -> Insert {
         return insert([value] + more)
     }
 
-    public func insert(values: [Setter]) -> Insert {
+    public func insert(_ values: [Setter]) -> Insert {
         return insert(nil, values)
     }
 
@@ -582,7 +582,7 @@ extension QueryType {
         return insert(onConflict, values)
     }
 
-    private func insert(or: OnConflict?, _ values: [Setter]) -> Insert {
+    fileprivate func insert(_ or: OnConflict?, _ values: [Setter]) -> Insert {
         let insert = values.reduce((columns: [Expressible](), values: [Expressible]())) { insert, setter in
             (insert.columns + [setter.column], insert.values + [setter.value])
         }
@@ -616,7 +616,7 @@ extension QueryType {
     /// - Parameter query: A query to `SELECT` results from.
     ///
     /// - Returns: The number of updated rows and statement.
-    public func insert(query: QueryType) -> Update {
+    public func insert(_ query: QueryType) -> Update {
         return Update(" ".join([
             Expression<Void>(literal: "INSERT INTO"),
             tableName(),
@@ -626,11 +626,11 @@ extension QueryType {
 
     // MARK: UPDATE
 
-    public func update(values: Setter...) -> Update {
+    public func update(_ values: Setter...) -> Update {
         return update(values)
     }
 
-    public func update(values: [Setter]) -> Update {
+    public func update(_ values: [Setter]) -> Update {
         let clauses: [Expressible?] = [
             Expression<Void>(literal: "UPDATE"),
             tableName(),
@@ -671,7 +671,7 @@ extension QueryType {
     ///
     /// - Returns: A column expression namespaced with the query’s table name or
     ///   alias.
-    public func namespace<V>(column: Expression<V>) -> Expression<V> {
+    public func namespace<V>(_ column: Expression<V>) -> Expression<V> {
         return Expression(".".join([tableName(), column]).expression)
     }
 
@@ -733,7 +733,7 @@ extension QueryType {
 
     // TODO: alias support
     func tableName(alias aliased: Bool = false) -> Expressible {
-        guard let alias = clauses.from.alias where aliased else {
+        guard let alias = clauses.from.alias , aliased else {
             return database(namespace: clauses.from.alias ?? clauses.from.name)
         }
 
@@ -744,7 +744,7 @@ extension QueryType {
         ])
     }
 
-    func tableName(qualified qualified: Bool) -> Expressible {
+    func tableName(qualified: Bool) -> Expressible {
         if qualified {
             return tableName()
         }
@@ -880,7 +880,7 @@ public struct Delete : ExpressionType {
 
 extension Connection {
 
-    public func prepare(query: QueryType) throws -> AnySequence<Row> {
+    public func prepare(_ query: QueryType) throws -> AnySequence<Row> {
         let expression = query.expression
         let statement = try prepare(expression.template, expression.bindings)
 
@@ -889,11 +889,11 @@ extension Connection {
             column: for each in query.clauses.select.columns ?? [Expression<Void>(literal: "*")] {
                 var names = each.expression.template.characters.split { $0 == "." }.map(String.init)
                 let column = names.removeLast()
-                let namespace = names.joinWithSeparator(".")
+                let namespace = names.joined(separator: ".")
 
-                func expandGlob(namespace: Bool) -> (QueryType throws -> Void) {
+                func expandGlob(_ namespace: Bool) -> ((QueryType) throws -> Void) {
                     return { (query: QueryType) throws -> (Void) in
-                        var q = query.dynamicType.init(query.clauses.from.name, database: query.clauses.from.database)
+                        var q = type(of: query).init(query.clauses.from.name, database: query.clauses.from.database)
                         q.clauses.select = query.clauses.select
                         let e = q.expression
                         var names = try self.prepare(e.template, e.bindings).columnNames.map { $0.quote() }
@@ -928,34 +928,34 @@ extension Connection {
         }()
 
         return AnySequence {
-            AnyGenerator { statement.next().map { Row(columnNames, $0) } }
+            AnyIterator { statement.next().map { Row(columnNames, $0) } }
         }
     }
 
-    public func scalar<V : Value>(query: ScalarQuery<V>) throws -> V {
+    public func scalar<V : Value>(_ query: ScalarQuery<V>) throws -> V {
         let expression = query.expression
         return value(try scalar(expression.template, expression.bindings))
     }
 
-    public func scalar<V : Value>(query: ScalarQuery<V?>) throws -> V.ValueType? {
+    public func scalar<V : Value>(_ query: ScalarQuery<V?>) throws -> V.ValueType? {
         let expression = query.expression
         guard let value = try scalar(expression.template, expression.bindings) as? V.Datatype else { return nil }
         return V.fromDatatypeValue(value)
     }
 
-    public func scalar<V : Value>(query: Select<V>) throws -> V {
+    public func scalar<V : Value>(_ query: Select<V>) throws -> V {
         let expression = query.expression
         return value(try scalar(expression.template, expression.bindings))
     }
 
-    public func scalar<V : Value>(query: Select<V?>) throws ->  V.ValueType? {
+    public func scalar<V : Value>(_ query: Select<V?>) throws ->  V.ValueType? {
         let expression = query.expression
         guard let value = try scalar(expression.template, expression.bindings) as? V.Datatype else { return nil }
         return V.fromDatatypeValue(value)
     }
 
-    public func pluck(query: QueryType) throws -> Row? {
-        return try prepare(query.limit(1, query.clauses.limit?.offset)).generate().next()
+    public func pluck(_ query: QueryType) throws -> Row? {
+        return try prepare(query.limit(1, query.clauses.limit?.offset)).makeIterator().next()
     }
 
     /// Runs an `Insert` query.
@@ -968,10 +968,10 @@ extension Connection {
     /// - Parameter query: An insert query.
     ///
     /// - Returns: The insert’s rowid.
-    public func run(query: Insert) throws -> Int64 {
+    public func run(_ query: Insert) throws -> Int64 {
         let expression = query.expression
         return try sync {
-            try self.run(expression.template, expression.bindings)
+            _ = try self.run(expression.template, expression.bindings)
             return self.lastInsertRowid!
         }
     }
@@ -984,10 +984,10 @@ extension Connection {
     /// - Parameter query: An update query.
     ///
     /// - Returns: The number of updated rows.
-    public func run(query: Update) throws -> Int {
+    public func run(_ query: Update) throws -> Int {
         let expression = query.expression
         return try sync {
-            try self.run(expression.template, expression.bindings)
+            _ = try self.run(expression.template, expression.bindings)
             return self.changes
         }
     }
@@ -999,10 +999,10 @@ extension Connection {
     /// - Parameter query: A delete query.
     ///
     /// - Returns: The number of deleted rows.
-    public func run(query: Delete) throws -> Int {
+    public func run(_ query: Delete) throws -> Int {
         let expression = query.expression
         return try sync {
-            try self.run(expression.template, expression.bindings)
+            _ = try self.run(expression.template, expression.bindings)
             return self.changes
         }
     }
@@ -1011,11 +1011,11 @@ extension Connection {
 
 public struct Row {
 
-    private let columnNames: [String: Int]
+    fileprivate let columnNames: [String: Int]
 
-    private let values: [Binding?]
+    fileprivate let values: [Binding?]
 
-    private init(_ columnNames: [String: Int], _ values: [Binding?]) {
+    fileprivate init(_ columnNames: [String: Int], _ values: [Binding?]) {
         self.columnNames = columnNames
         self.values = values
     }
@@ -1025,11 +1025,11 @@ public struct Row {
     /// - Parameter column: An expression representing a column selected in a Query.
     ///
     /// - Returns: The value for the given column.
-    public func get<V: Value>(column: Expression<V>) -> V {
+    public func get<V: Value>(_ column: Expression<V>) -> V {
         return get(Expression<V?>(column))!
     }
-    public func get<V: Value>(column: Expression<V?>) -> V? {
-        func valueAtIndex(idx: Int) -> V? {
+    public func get<V: Value>(_ column: Expression<V?>) -> V? {
+        func valueAtIndex(_ idx: Int) -> V? {
             guard let value = values[idx] as? V.Datatype else { return nil }
             return (V.fromDatatypeValue(value) as? V)!
         }
@@ -1039,7 +1039,7 @@ public struct Row {
 
             switch similar.count {
             case 0:
-                fatalError("no such column '\(column.template)' in columns: \(columnNames.keys.sort())")
+                fatalError("no such column '\(column.template)' in columns: \(columnNames.keys.sorted())")
             case 1:
                 return valueAtIndex(columnNames[similar[0]]!)
             default:
@@ -1143,7 +1143,7 @@ public struct QueryClauses {
 
     var limit: (length: Int, offset: Int?)?
 
-    private init(_ name: String, alias: String?, database: String?) {
+    fileprivate init(_ name: String, alias: String?, database: String?) {
         self.from = (name, alias, database)
     }
 
diff --git a/SQLite/Typed/Schema.swift b/SQLite/Typed/Schema.swift
index 16e11c16..4c6862c0 100644
--- a/SQLite/Typed/Schema.swift
+++ b/SQLite/Typed/Schema.swift
@@ -26,7 +26,7 @@ extension SchemaType {
 
     // MARK: - DROP TABLE / VIEW / VIRTUAL TABLE
 
-    public func drop(ifExists ifExists: Bool = false) -> String {
+    public func drop(ifExists: Bool = false) -> String {
         return drop("TABLE", tableName(), ifExists)
     }
 
@@ -36,7 +36,7 @@ extension Table {
 
     // MARK: - CREATE TABLE
 
-    public func create(temporary temporary: Bool = false, ifNotExists: Bool = false, @noescape block: TableBuilder -> Void) -> String {
+    public func create(temporary: Bool = false, ifNotExists: Bool = false, block: (TableBuilder) -> Void) -> String {
         let builder = TableBuilder()
 
         block(builder)
@@ -49,7 +49,7 @@ extension Table {
         return " ".join(clauses.flatMap { $0 }).asSQL()
     }
 
-    public func create(query: QueryType, temporary: Bool = false, ifNotExists: Bool = false) -> String {
+    public func create(_ query: QueryType, temporary: Bool = false, ifNotExists: Bool = false) -> String {
         let clauses: [Expressible?] = [
             create(Table.identifier, tableName(), temporary ? .Temporary : nil, ifNotExists),
             Expression<Void>(literal: "AS"),
@@ -61,55 +61,55 @@ extension Table {
 
     // MARK: - ALTER TABLE … ADD COLUMN
 
-    public func addColumn<V : Value>(name: Expression<V>, check: Expression<Bool>? = nil, defaultValue: V) -> String {
+    public func addColumn<V : Value>(_ name: Expression<V>, check: Expression<Bool>? = nil, defaultValue: V) -> String {
         return addColumn(definition(name, V.declaredDatatype, nil, false, false, check, defaultValue, nil, nil))
     }
 
-    public func addColumn<V : Value>(name: Expression<V>, check: Expression<Bool?>, defaultValue: V) -> String {
+    public func addColumn<V : Value>(_ name: Expression<V>, check: Expression<Bool?>, defaultValue: V) -> String {
         return addColumn(definition(name, V.declaredDatatype, nil, false, false, check, defaultValue, nil, nil))
     }
 
-    public func addColumn<V : Value>(name: Expression<V?>, check: Expression<Bool>? = nil, defaultValue: V? = nil) -> String {
+    public func addColumn<V : Value>(_ name: Expression<V?>, check: Expression<Bool>? = nil, defaultValue: V? = nil) -> String {
         return addColumn(definition(name, V.declaredDatatype, nil, true, false, check, defaultValue, nil, nil))
     }
 
-    public func addColumn<V : Value>(name: Expression<V?>, check: Expression<Bool?>, defaultValue: V? = nil) -> String {
+    public func addColumn<V : Value>(_ name: Expression<V?>, check: Expression<Bool?>, defaultValue: V? = nil) -> String {
         return addColumn(definition(name, V.declaredDatatype, nil, true, false, check, defaultValue, nil, nil))
     }
 
-    public func addColumn<V : Value where V.Datatype == Int64>(name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil, references table: QueryType, _ other: Expression<V>) -> String {
+    public func addColumn<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil, references table: QueryType, _ other: Expression<V>) -> String where V.Datatype == Int64 {
         return addColumn(definition(name, V.declaredDatatype, nil, false, unique, check, nil, (table, other), nil))
     }
 
-    public func addColumn<V : Value where V.Datatype == Int64>(name: Expression<V>, unique: Bool = false, check: Expression<Bool?>, references table: QueryType, _ other: Expression<V>) -> String {
+    public func addColumn<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool?>, references table: QueryType, _ other: Expression<V>) -> String where V.Datatype == Int64 {
         return addColumn(definition(name, V.declaredDatatype, nil, false, unique, check, nil, (table, other), nil))
     }
 
-    public func addColumn<V : Value where V.Datatype == Int64>(name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, references table: QueryType, _ other: Expression<V>) -> String {
+    public func addColumn<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, references table: QueryType, _ other: Expression<V>) -> String where V.Datatype == Int64 {
         return addColumn(definition(name, V.declaredDatatype, nil, true, unique, check, nil, (table, other), nil))
     }
 
-    public func addColumn<V : Value where V.Datatype == Int64>(name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, references table: QueryType, _ other: Expression<V>) -> String {
+    public func addColumn<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, references table: QueryType, _ other: Expression<V>) -> String where V.Datatype == Int64 {
         return addColumn(definition(name, V.declaredDatatype, nil, true, unique, check, nil, (table, other), nil))
     }
 
-    public func addColumn<V : Value where V.Datatype == String>(name: Expression<V>, check: Expression<Bool>? = nil, defaultValue: V, collate: Collation) -> String {
+    public func addColumn<V : Value>(_ name: Expression<V>, check: Expression<Bool>? = nil, defaultValue: V, collate: Collation) -> String where V.Datatype == String {
         return addColumn(definition(name, V.declaredDatatype, nil, false, false, check, defaultValue, nil, collate))
     }
 
-    public func addColumn<V : Value where V.Datatype == String>(name: Expression<V>, check: Expression<Bool?>, defaultValue: V, collate: Collation) -> String {
+    public func addColumn<V : Value>(_ name: Expression<V>, check: Expression<Bool?>, defaultValue: V, collate: Collation) -> String where V.Datatype == String {
         return addColumn(definition(name, V.declaredDatatype, nil, false, false, check, defaultValue, nil, collate))
     }
 
-    public func addColumn<V : Value where V.Datatype == String>(name: Expression<V?>, check: Expression<Bool>? = nil, defaultValue: V? = nil, collate: Collation) -> String {
+    public func addColumn<V : Value>(_ name: Expression<V?>, check: Expression<Bool>? = nil, defaultValue: V? = nil, collate: Collation) -> String where V.Datatype == String {
         return addColumn(definition(name, V.declaredDatatype, nil, true, false, check, defaultValue, nil, collate))
     }
 
-    public func addColumn<V : Value where V.Datatype == String>(name: Expression<V?>, check: Expression<Bool?>, defaultValue: V? = nil, collate: Collation) -> String {
+    public func addColumn<V : Value>(_ name: Expression<V?>, check: Expression<Bool?>, defaultValue: V? = nil, collate: Collation) -> String where V.Datatype == String {
         return addColumn(definition(name, V.declaredDatatype, nil, true, false, check, defaultValue, nil, collate))
     }
 
-    private func addColumn(expression: Expressible) -> String {
+    fileprivate func addColumn(_ expression: Expressible) -> String {
         return " ".join([
             Expression<Void>(literal: "ALTER TABLE"),
             tableName(),
@@ -120,17 +120,17 @@ extension Table {
 
     // MARK: - ALTER TABLE … RENAME TO
 
-    public func rename(to: Table) -> String {
+    public func rename(_ to: Table) -> String {
         return rename(to: to)
     }
 
     // MARK: - CREATE INDEX
 
-    public func createIndex(columns: Expressible...) -> String {
+    public func createIndex(_ columns: Expressible...) -> String {
         return createIndex(columns)
     }
 
-    public func createIndex(columns: [Expressible], unique: Bool = false, ifNotExists: Bool = false) -> String {
+    public func createIndex(_ columns: [Expressible], unique: Bool = false, ifNotExists: Bool = false) -> String {
         let clauses: [Expressible?] = [
             create("INDEX", indexName(columns), unique ? .Unique : nil, ifNotExists),
             Expression<Void>(literal: "ON"),
@@ -143,16 +143,16 @@ extension Table {
 
     // MARK: - DROP INDEX
 
-    public func dropIndex(columns: Expressible...) -> String {
+    public func dropIndex(_ columns: Expressible...) -> String {
         return dropIndex(columns)
     }
 
-    public func dropIndex(columns: [Expressible], ifExists: Bool = false) -> String {
+    public func dropIndex(_ columns: [Expressible], ifExists: Bool = false) -> String {
         return drop("INDEX", indexName(columns), ifExists)
     }
 
-    private func indexName(columns: [Expressible]) -> Expressible {
-        let string = (["index", clauses.from.name, "on"] + columns.map { $0.expression.template }).joinWithSeparator(" ").lowercaseString
+    fileprivate func indexName(_ columns: [Expressible]) -> Expressible {
+        let string = (["index", clauses.from.name, "on"] + columns.map { $0.expression.template }).joined(separator: " ").lowercased()
 
         let index = string.characters.reduce("") { underscored, character in
             guard character != "\"" else {
@@ -173,7 +173,7 @@ extension View {
 
     // MARK: - CREATE VIEW
 
-    public func create(query: QueryType, temporary: Bool = false, ifNotExists: Bool = false) -> String {
+    public func create(_ query: QueryType, temporary: Bool = false, ifNotExists: Bool = false) -> String {
         let clauses: [Expressible?] = [
             create(View.identifier, tableName(), temporary ? .Temporary : nil, ifNotExists),
             Expression<Void>(literal: "AS"),
@@ -185,7 +185,7 @@ extension View {
 
     // MARK: - DROP VIEW
 
-    public func drop(ifExists ifExists: Bool = false) -> String {
+    public func drop(ifExists: Bool = false) -> String {
         return drop("VIEW", tableName(), ifExists)
     }
 
@@ -195,7 +195,7 @@ extension VirtualTable {
 
     // MARK: - CREATE VIRTUAL TABLE
 
-    public func create(using: Module, ifNotExists: Bool = false) -> String {
+    public func create(_ using: Module, ifNotExists: Bool = false) -> String {
         let clauses: [Expressible?] = [
             create(VirtualTable.identifier, tableName(), nil, ifNotExists),
             Expression<Void>(literal: "USING"),
@@ -207,7 +207,7 @@ extension VirtualTable {
 
     // MARK: - ALTER TABLE … RENAME TO
 
-    public func rename(to: VirtualTable) -> String {
+    public func rename(_ to: VirtualTable) -> String {
         return rename(to: to)
     }
 
@@ -215,155 +215,155 @@ extension VirtualTable {
 
 public final class TableBuilder {
 
-    private var definitions = [Expressible]()
+    fileprivate var definitions = [Expressible]()
 
-    public func column<V : Value>(name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: Expression<V>? = nil) {
+    public func column<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: Expression<V>? = nil) {
         column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value>(name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: V) {
+    public func column<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: V) {
         column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value>(name: Expression<V>, unique: Bool = false, check: Expression<Bool?>, defaultValue: Expression<V>? = nil) {
+    public func column<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool?>, defaultValue: Expression<V>? = nil) {
         column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value>(name: Expression<V>, unique: Bool = false, check: Expression<Bool?>, defaultValue: V) {
+    public func column<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool?>, defaultValue: V) {
         column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value>(name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: Expression<V>? = nil) {
+    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: Expression<V>? = nil) {
         column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value>(name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: Expression<V?>) {
+    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: Expression<V?>) {
         column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value>(name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: V) {
+    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: V) {
         column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value>(name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, defaultValue: Expression<V>? = nil) {
+    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, defaultValue: Expression<V>? = nil) {
         column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value>(name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, defaultValue: Expression<V?>) {
+    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, defaultValue: Expression<V?>) {
         column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value>(name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, defaultValue: V) {
+    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, defaultValue: V) {
         column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value>(name: Expression<V>, primaryKey: Bool, check: Expression<Bool>? = nil, defaultValue: Expression<V>? = nil) {
-        column(name, V.declaredDatatype, primaryKey ? .Default : nil, false, false, check, defaultValue, nil, nil)
+    public func column<V : Value>(_ name: Expression<V>, primaryKey: Bool, check: Expression<Bool>? = nil, defaultValue: Expression<V>? = nil) {
+        column(name, V.declaredDatatype, primaryKey ? .default : nil, false, false, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value>(name: Expression<V>, primaryKey: Bool, check: Expression<Bool?>, defaultValue: Expression<V>? = nil) {
-        column(name, V.declaredDatatype, primaryKey ? .Default : nil, false, false, check, defaultValue, nil, nil)
+    public func column<V : Value>(_ name: Expression<V>, primaryKey: Bool, check: Expression<Bool?>, defaultValue: Expression<V>? = nil) {
+        column(name, V.declaredDatatype, primaryKey ? .default : nil, false, false, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value where V.Datatype == Int64>(name: Expression<V>, primaryKey: PrimaryKey, check: Expression<Bool>? = nil) {
+    public func column<V : Value>(_ name: Expression<V>, primaryKey: PrimaryKey, check: Expression<Bool>? = nil) where V.Datatype == Int64 {
         column(name, V.declaredDatatype, primaryKey, false, false, check, nil, nil, nil)
     }
 
-    public func column<V : Value where V.Datatype == Int64>(name: Expression<V>, primaryKey: PrimaryKey, check: Expression<Bool?>) {
+    public func column<V : Value>(_ name: Expression<V>, primaryKey: PrimaryKey, check: Expression<Bool?>) where V.Datatype == Int64 {
         column(name, V.declaredDatatype, primaryKey, false, false, check, nil, nil, nil)
     }
 
-    public func column<V : Value where V.Datatype == Int64>(name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil, references table: QueryType, _ other: Expression<V>) {
+    public func column<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil, references table: QueryType, _ other: Expression<V>) where V.Datatype == Int64 {
         column(name, V.declaredDatatype, nil, false, unique, check, nil, (table, other), nil)
     }
 
-    public func column<V : Value where V.Datatype == Int64>(name: Expression<V>, unique: Bool = false, check: Expression<Bool?>, references table: QueryType, _ other: Expression<V>) {
+    public func column<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool?>, references table: QueryType, _ other: Expression<V>) where V.Datatype == Int64 {
         column(name, V.declaredDatatype, nil, false, unique, check, nil, (table, other), nil)
     }
 
-    public func column<V : Value where V.Datatype == Int64>(name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, references table: QueryType, _ other: Expression<V>) {
+    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, references table: QueryType, _ other: Expression<V>) where V.Datatype == Int64 {
         column(name, V.declaredDatatype, nil, true, unique, check, nil, (table, other), nil)
     }
 
-    public func column<V : Value where V.Datatype == Int64>(name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, references table: QueryType, _ other: Expression<V>) {
+    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, references table: QueryType, _ other: Expression<V>) where V.Datatype == Int64 {
         column(name, V.declaredDatatype, nil, true, unique, check, nil, (table, other), nil)
     }
 
-    public func column<V : Value where V.Datatype == String>(name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: Expression<V>? = nil, collate: Collation) {
+    public func column<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: Expression<V>? = nil, collate: Collation) where V.Datatype == String {
         column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate)
     }
 
-    public func column<V : Value where V.Datatype == String>(name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: V, collate: Collation) {
+    public func column<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: V, collate: Collation) where V.Datatype == String {
         column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate)
     }
 
-    public func column<V : Value where V.Datatype == String>(name: Expression<V>, unique: Bool = false, check: Expression<Bool?>, defaultValue: Expression<V>? = nil, collate: Collation) {
+    public func column<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool?>, defaultValue: Expression<V>? = nil, collate: Collation) where V.Datatype == String {
         column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate)
     }
 
-    public func column<V : Value where V.Datatype == String>(name: Expression<V>, unique: Bool = false, check: Expression<Bool?>, defaultValue: V, collate: Collation) {
+    public func column<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool?>, defaultValue: V, collate: Collation) where V.Datatype == String {
         column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate)
     }
 
-    public func column<V : Value where V.Datatype == String>(name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: Expression<V>? = nil, collate: Collation) {
+    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: Expression<V>? = nil, collate: Collation) where V.Datatype == String {
         column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate)
     }
 
-    public func column<V : Value where V.Datatype == String>(name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: Expression<V?>, collate: Collation) {
+    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: Expression<V?>, collate: Collation) where V.Datatype == String {
         column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate)
     }
 
-    public func column<V : Value where V.Datatype == String>(name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: V, collate: Collation) {
+    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: V, collate: Collation) where V.Datatype == String {
         column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate)
     }
 
-    public func column<V : Value where V.Datatype == String>(name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, defaultValue: Expression<V>? = nil, collate: Collation) {
+    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, defaultValue: Expression<V>? = nil, collate: Collation) where V.Datatype == String {
         column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate)
     }
 
-    public func column<V : Value where V.Datatype == String>(name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, defaultValue: Expression<V?>, collate: Collation) {
+    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, defaultValue: Expression<V?>, collate: Collation) where V.Datatype == String {
         column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate)
     }
 
-    public func column<V : Value where V.Datatype == String>(name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, defaultValue: V, collate: Collation) {
+    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, defaultValue: V, collate: Collation) where V.Datatype == String {
         column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate)
     }
 
-    private func column(name: Expressible, _ datatype: String, _ primaryKey: PrimaryKey?, _ null: Bool, _ unique: Bool, _ check: Expressible?, _ defaultValue: Expressible?, _ references: (QueryType, Expressible)?, _ collate: Collation?) {
+    fileprivate func column(_ name: Expressible, _ datatype: String, _ primaryKey: PrimaryKey?, _ null: Bool, _ unique: Bool, _ check: Expressible?, _ defaultValue: Expressible?, _ references: (QueryType, Expressible)?, _ collate: Collation?) {
         definitions.append(definition(name, datatype, primaryKey, null, unique, check, defaultValue, references, collate))
     }
 
     // MARK: -
 
-    public func primaryKey<T : Value>(column: Expression<T>) {
+    public func primaryKey<T : Value>(_ column: Expression<T>) {
         primaryKey([column])
     }
 
-    public func primaryKey<T : Value, U : Value>(compositeA: Expression<T>, _ b: Expression<U>) {
+    public func primaryKey<T : Value, U : Value>(_ compositeA: Expression<T>, _ b: Expression<U>) {
         primaryKey([compositeA, b])
     }
 
-    public func primaryKey<T : Value, U : Value, V : Value>(compositeA: Expression<T>, _ b: Expression<U>, _ c: Expression<V>) {
+    public func primaryKey<T : Value, U : Value, V : Value>(_ compositeA: Expression<T>, _ b: Expression<U>, _ c: Expression<V>) {
         primaryKey([compositeA, b, c])
     }
 
-    private func primaryKey(composite: [Expressible]) {
+    fileprivate func primaryKey(_ composite: [Expressible]) {
         definitions.append("PRIMARY KEY".prefix(composite))
     }
 
-    public func unique(columns: Expressible...) {
+    public func unique(_ columns: Expressible...) {
         unique(columns)
     }
 
-    public func unique(columns: [Expressible]) {
+    public func unique(_ columns: [Expressible]) {
         definitions.append("UNIQUE".prefix(columns))
     }
 
-    public func check(condition: Expression<Bool>) {
+    public func check(_ condition: Expression<Bool>) {
         check(Expression<Bool?>(condition))
     }
 
-    public func check(condition: Expression<Bool?>) {
+    public func check(_ condition: Expression<Bool?>) {
         definitions.append("CHECK".prefix(condition))
     }
 
@@ -381,29 +381,29 @@ public final class TableBuilder {
         
     }
 
-    public func foreignKey<T : Value>(column: Expression<T>, references table: QueryType, _ other: Expression<T>, update: Dependency? = nil, delete: Dependency? = nil) {
+    public func foreignKey<T : Value>(_ column: Expression<T>, references table: QueryType, _ other: Expression<T>, update: Dependency? = nil, delete: Dependency? = nil) {
         foreignKey(column, (table, other), update, delete)
     }
 
-    public func foreignKey<T : Value>(column: Expression<T?>, references table: QueryType, _ other: Expression<T>, update: Dependency? = nil, delete: Dependency? = nil) {
+    public func foreignKey<T : Value>(_ column: Expression<T?>, references table: QueryType, _ other: Expression<T>, update: Dependency? = nil, delete: Dependency? = nil) {
         foreignKey(column, (table, other), update, delete)
     }
 
-    public func foreignKey<T : Value, U : Value>(composite: (Expression<T>, Expression<U>), references table: QueryType, _ other: (Expression<T>, Expression<U>), update: Dependency? = nil, delete: Dependency? = nil) {
+    public func foreignKey<T : Value, U : Value>(_ composite: (Expression<T>, Expression<U>), references table: QueryType, _ other: (Expression<T>, Expression<U>), update: Dependency? = nil, delete: Dependency? = nil) {
         let composite = ", ".join([composite.0, composite.1])
         let references = (table, ", ".join([other.0, other.1]))
 
         foreignKey(composite, references, update, delete)
     }
 
-    public func foreignKey<T : Value, U : Value, V : Value>(composite: (Expression<T>, Expression<U>, Expression<V>), references table: QueryType, _ other: (Expression<T>, Expression<U>, Expression<V>), update: Dependency? = nil, delete: Dependency? = nil) {
+    public func foreignKey<T : Value, U : Value, V : Value>(_ composite: (Expression<T>, Expression<U>, Expression<V>), references table: QueryType, _ other: (Expression<T>, Expression<U>, Expression<V>), update: Dependency? = nil, delete: Dependency? = nil) {
         let composite = ", ".join([composite.0, composite.1, composite.2])
         let references = (table, ", ".join([other.0, other.1, other.2]))
 
         foreignKey(composite, references, update, delete)
     }
 
-    private func foreignKey(column: Expressible, _ references: (QueryType, Expressible), _ update: Dependency?, _ delete: Dependency?) {
+    fileprivate func foreignKey(_ column: Expressible, _ references: (QueryType, Expressible), _ update: Dependency?, _ delete: Dependency?) {
         let clauses: [Expressible?] = [
             "FOREIGN KEY".prefix(column),
             reference(references),
@@ -418,17 +418,17 @@ public final class TableBuilder {
 
 public enum PrimaryKey {
 
-    case Default
+    case `default`
 
-    case Autoincrement
+    case autoincrement
 
 }
 
 public struct Module {
 
-    private let name: String
+    fileprivate let name: String
 
-    private let arguments: [Expressible]
+    fileprivate let arguments: [Expressible]
 
     public init(_ name: String, _ arguments: [Expressible]) {
         self.init(name: name.quote(), arguments: arguments)
@@ -453,7 +453,7 @@ extension Module : Expressible {
 
 private extension QueryType {
 
-    func create(identifier: String, _ name: Expressible, _ modifier: Modifier?, _ ifNotExists: Bool) -> Expressible {
+    func create(_ identifier: String, _ name: Expressible, _ modifier: Modifier?, _ ifNotExists: Bool) -> Expressible {
         let clauses: [Expressible?] = [
             Expression<Void>(literal: "CREATE"),
             modifier.map { Expression<Void>(literal: $0.rawValue) },
@@ -465,7 +465,7 @@ private extension QueryType {
         return " ".join(clauses.flatMap { $0 })
     }
 
-    func rename(to to: Self) -> String {
+    func rename(to: Self) -> String {
         return " ".join([
             Expression<Void>(literal: "ALTER TABLE"),
             tableName(),
@@ -474,7 +474,7 @@ private extension QueryType {
         ]).asSQL()
     }
 
-    func drop(identifier: String, _ name: Expressible, _ ifExists: Bool) -> String {
+    func drop(_ identifier: String, _ name: Expressible, _ ifExists: Bool) -> String {
         let clauses: [Expressible?] = [
             Expression<Void>(literal: "DROP \(identifier)"),
             ifExists ? Expression<Void>(literal: "IF EXISTS") : nil,
@@ -486,11 +486,11 @@ private extension QueryType {
 
 }
 
-private func definition(column: Expressible, _ datatype: String, _ primaryKey: PrimaryKey?, _ null: Bool, _ unique: Bool, _ check: Expressible?, _ defaultValue: Expressible?, _ references: (QueryType, Expressible)?, _ collate: Collation?) -> Expressible {
+private func definition(_ column: Expressible, _ datatype: String, _ primaryKey: PrimaryKey?, _ null: Bool, _ unique: Bool, _ check: Expressible?, _ defaultValue: Expressible?, _ references: (QueryType, Expressible)?, _ collate: Collation?) -> Expressible {
     let clauses: [Expressible?] = [
         column,
         Expression<Void>(literal: datatype),
-        primaryKey.map { Expression<Void>(literal: $0 == .Autoincrement ? "PRIMARY KEY AUTOINCREMENT" : "PRIMARY KEY") },
+        primaryKey.map { Expression<Void>(literal: $0 == .autoincrement ? "PRIMARY KEY AUTOINCREMENT" : "PRIMARY KEY") },
         null ? nil : Expression<Void>(literal: "NOT NULL"),
         unique ? Expression<Void>(literal: "UNIQUE") : nil,
         check.map { " ".join([Expression<Void>(literal: "CHECK"), $0]) },
@@ -502,7 +502,7 @@ private func definition(column: Expressible, _ datatype: String, _ primaryKey: P
     return " ".join(clauses.flatMap { $0 })
 }
 
-private func reference(primary: (QueryType, Expressible)) -> Expressible {
+private func reference(_ primary: (QueryType, Expressible)) -> Expressible {
     return " ".join([
         Expression<Void>(literal: "REFERENCES"),
         primary.0.tableName(qualified: false),
diff --git a/SQLite/Typed/Setter.swift b/SQLite/Typed/Setter.swift
index d8bf775a..86f16fca 100644
--- a/SQLite/Typed/Setter.swift
+++ b/SQLite/Typed/Setter.swift
@@ -22,38 +22,40 @@
 // THE SOFTWARE.
 //
 
-infix operator <- {
-    associativity left
-    precedence 135
-    assignment
+precedencegroup ColumnAssignment {
+    associativity: left
+    assignment: true
+    lowerThan: AssignmentPrecedence
 }
 
+infix operator <- : ColumnAssignment
+
 public struct Setter {
 
     let column: Expressible
     let value: Expressible
 
-    private init<V : Value>(column: Expression<V>, value: Expression<V>) {
+    fileprivate init<V : Value>(column: Expression<V>, value: Expression<V>) {
         self.column = column
         self.value = value
     }
 
-    private init<V : Value>(column: Expression<V>, value: V) {
+    fileprivate init<V : Value>(column: Expression<V>, value: V) {
         self.column = column
         self.value = value
     }
 
-    private init<V : Value>(column: Expression<V?>, value: Expression<V>) {
+    fileprivate init<V : Value>(column: Expression<V?>, value: Expression<V>) {
         self.column = column
         self.value = value
     }
 
-    private init<V : Value>(column: Expression<V?>, value: Expression<V?>) {
+    fileprivate init<V : Value>(column: Expression<V?>, value: Expression<V?>) {
         self.column = column
         self.value = value
     }
 
-    private init<V : Value>(column: Expression<V?>, value: V?) {
+    fileprivate init<V : Value>(column: Expression<V?>, value: V?) {
         self.column = column
         self.value = Expression<V?>(value: value)
     }
@@ -100,176 +102,176 @@ public func +=(column: Expression<String?>, value: String) -> Setter {
     return column <- column + value
 }
 
-public func +=<V : Value where V.Datatype : Number>(column: Expression<V>, value: Expression<V>) -> Setter {
+public func +=<V : Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype : Number {
     return column <- column + value
 }
-public func +=<V : Value where V.Datatype : Number>(column: Expression<V>, value: V) -> Setter {
+public func +=<V : Value>(column: Expression<V>, value: V) -> Setter where V.Datatype : Number {
     return column <- column + value
 }
-public func +=<V : Value where V.Datatype : Number>(column: Expression<V?>, value: Expression<V>) -> Setter {
+public func +=<V : Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype : Number {
     return column <- column + value
 }
-public func +=<V : Value where V.Datatype : Number>(column: Expression<V?>, value: Expression<V?>) -> Setter {
+public func +=<V : Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype : Number {
     return column <- column + value
 }
-public func +=<V : Value where V.Datatype : Number>(column: Expression<V?>, value: V) -> Setter {
+public func +=<V : Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype : Number {
     return column <- column + value
 }
 
-public func -=<V : Value where V.Datatype : Number>(column: Expression<V>, value: Expression<V>) -> Setter {
+public func -=<V : Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype : Number {
     return column <- column - value
 }
-public func -=<V : Value where V.Datatype : Number>(column: Expression<V>, value: V) -> Setter {
+public func -=<V : Value>(column: Expression<V>, value: V) -> Setter where V.Datatype : Number {
     return column <- column - value
 }
-public func -=<V : Value where V.Datatype : Number>(column: Expression<V?>, value: Expression<V>) -> Setter {
+public func -=<V : Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype : Number {
     return column <- column - value
 }
-public func -=<V : Value where V.Datatype : Number>(column: Expression<V?>, value: Expression<V?>) -> Setter {
+public func -=<V : Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype : Number {
     return column <- column - value
 }
-public func -=<V : Value where V.Datatype : Number>(column: Expression<V?>, value: V) -> Setter {
+public func -=<V : Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype : Number {
     return column <- column - value
 }
 
-public func *=<V : Value where V.Datatype : Number>(column: Expression<V>, value: Expression<V>) -> Setter {
+public func *=<V : Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype : Number {
     return column <- column * value
 }
-public func *=<V : Value where V.Datatype : Number>(column: Expression<V>, value: V) -> Setter {
+public func *=<V : Value>(column: Expression<V>, value: V) -> Setter where V.Datatype : Number {
     return column <- column * value
 }
-public func *=<V : Value where V.Datatype : Number>(column: Expression<V?>, value: Expression<V>) -> Setter {
+public func *=<V : Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype : Number {
     return column <- column * value
 }
-public func *=<V : Value where V.Datatype : Number>(column: Expression<V?>, value: Expression<V?>) -> Setter {
+public func *=<V : Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype : Number {
     return column <- column * value
 }
-public func *=<V : Value where V.Datatype : Number>(column: Expression<V?>, value: V) -> Setter {
+public func *=<V : Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype : Number {
     return column <- column * value
 }
 
-public func /=<V : Value where V.Datatype : Number>(column: Expression<V>, value: Expression<V>) -> Setter {
+public func /=<V : Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype : Number {
     return column <- column / value
 }
-public func /=<V : Value where V.Datatype : Number>(column: Expression<V>, value: V) -> Setter {
+public func /=<V : Value>(column: Expression<V>, value: V) -> Setter where V.Datatype : Number {
     return column <- column / value
 }
-public func /=<V : Value where V.Datatype : Number>(column: Expression<V?>, value: Expression<V>) -> Setter {
+public func /=<V : Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype : Number {
     return column <- column / value
 }
-public func /=<V : Value where V.Datatype : Number>(column: Expression<V?>, value: Expression<V?>) -> Setter {
+public func /=<V : Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype : Number {
     return column <- column / value
 }
-public func /=<V : Value where V.Datatype : Number>(column: Expression<V?>, value: V) -> Setter {
+public func /=<V : Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype : Number {
     return column <- column / value
 }
 
-public func %=<V : Value where V.Datatype == Int64>(column: Expression<V>, value: Expression<V>) -> Setter {
+public func %=<V : Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column % value
 }
-public func %=<V : Value where V.Datatype == Int64>(column: Expression<V>, value: V) -> Setter {
+public func %=<V : Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column % value
 }
-public func %=<V : Value where V.Datatype == Int64>(column: Expression<V?>, value: Expression<V>) -> Setter {
+public func %=<V : Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column % value
 }
-public func %=<V : Value where V.Datatype == Int64>(column: Expression<V?>, value: Expression<V?>) -> Setter {
+public func %=<V : Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
     return column <- column % value
 }
-public func %=<V : Value where V.Datatype == Int64>(column: Expression<V?>, value: V) -> Setter {
+public func %=<V : Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column % value
 }
 
-public func <<=<V : Value where V.Datatype == Int64>(column: Expression<V>, value: Expression<V>) -> Setter {
+public func <<=<V : Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column << value
 }
-public func <<=<V : Value where V.Datatype == Int64>(column: Expression<V>, value: V) -> Setter {
+public func <<=<V : Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column << value
 }
-public func <<=<V : Value where V.Datatype == Int64>(column: Expression<V?>, value: Expression<V>) -> Setter {
+public func <<=<V : Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column << value
 }
-public func <<=<V : Value where V.Datatype == Int64>(column: Expression<V?>, value: Expression<V?>) -> Setter {
+public func <<=<V : Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
     return column <- column << value
 }
-public func <<=<V : Value where V.Datatype == Int64>(column: Expression<V?>, value: V) -> Setter {
+public func <<=<V : Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column << value
 }
 
-public func >>=<V : Value where V.Datatype == Int64>(column: Expression<V>, value: Expression<V>) -> Setter {
+public func >>=<V : Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column >> value
 }
-public func >>=<V : Value where V.Datatype == Int64>(column: Expression<V>, value: V) -> Setter {
+public func >>=<V : Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column >> value
 }
-public func >>=<V : Value where V.Datatype == Int64>(column: Expression<V?>, value: Expression<V>) -> Setter {
+public func >>=<V : Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column >> value
 }
-public func >>=<V : Value where V.Datatype == Int64>(column: Expression<V?>, value: Expression<V?>) -> Setter {
+public func >>=<V : Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
     return column <- column >> value
 }
-public func >>=<V : Value where V.Datatype == Int64>(column: Expression<V?>, value: V) -> Setter {
+public func >>=<V : Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column >> value
 }
 
-public func &=<V : Value where V.Datatype == Int64>(column: Expression<V>, value: Expression<V>) -> Setter {
+public func &=<V : Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column & value
 }
-public func &=<V : Value where V.Datatype == Int64>(column: Expression<V>, value: V) -> Setter {
+public func &=<V : Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column & value
 }
-public func &=<V : Value where V.Datatype == Int64>(column: Expression<V?>, value: Expression<V>) -> Setter {
+public func &=<V : Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column & value
 }
-public func &=<V : Value where V.Datatype == Int64>(column: Expression<V?>, value: Expression<V?>) -> Setter {
+public func &=<V : Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
     return column <- column & value
 }
-public func &=<V : Value where V.Datatype == Int64>(column: Expression<V?>, value: V) -> Setter {
+public func &=<V : Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column & value
 }
 
-public func |=<V : Value where V.Datatype == Int64>(column: Expression<V>, value: Expression<V>) -> Setter {
+public func |=<V : Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column | value
 }
-public func |=<V : Value where V.Datatype == Int64>(column: Expression<V>, value: V) -> Setter {
+public func |=<V : Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column | value
 }
-public func |=<V : Value where V.Datatype == Int64>(column: Expression<V?>, value: Expression<V>) -> Setter {
+public func |=<V : Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column | value
 }
-public func |=<V : Value where V.Datatype == Int64>(column: Expression<V?>, value: Expression<V?>) -> Setter {
+public func |=<V : Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
     return column <- column | value
 }
-public func |=<V : Value where V.Datatype == Int64>(column: Expression<V?>, value: V) -> Setter {
+public func |=<V : Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column | value
 }
 
-public func ^=<V : Value where V.Datatype == Int64>(column: Expression<V>, value: Expression<V>) -> Setter {
+public func ^=<V : Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column ^ value
 }
-public func ^=<V : Value where V.Datatype == Int64>(column: Expression<V>, value: V) -> Setter {
+public func ^=<V : Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column ^ value
 }
-public func ^=<V : Value where V.Datatype == Int64>(column: Expression<V?>, value: Expression<V>) -> Setter {
+public func ^=<V : Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column ^ value
 }
-public func ^=<V : Value where V.Datatype == Int64>(column: Expression<V?>, value: Expression<V?>) -> Setter {
+public func ^=<V : Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
     return column <- column ^ value
 }
-public func ^=<V : Value where V.Datatype == Int64>(column: Expression<V?>, value: V) -> Setter {
+public func ^=<V : Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column ^ value
 }
 
-public postfix func ++<V : Value where V.Datatype == Int64>(column: Expression<V>) -> Setter {
+public postfix func ++<V : Value>(column: Expression<V>) -> Setter where V.Datatype == Int64 {
     return Expression<Int>(column) += 1
 }
-public postfix func ++<V : Value where V.Datatype == Int64>(column: Expression<V?>) -> Setter {
+public postfix func ++<V : Value>(column: Expression<V?>) -> Setter where V.Datatype == Int64 {
     return Expression<Int>(column) += 1
 }
 
-public postfix func --<V : Value where V.Datatype == Int64>(column: Expression<V>) -> Setter {
+public postfix func --<V : Value>(column: Expression<V>) -> Setter where V.Datatype == Int64 {
     return Expression<Int>(column) -= 1
 }
-public postfix func --<V : Value where V.Datatype == Int64>(column: Expression<V?>) -> Setter {
+public postfix func --<V : Value>(column: Expression<V?>) -> Setter where V.Datatype == Int64 {
     return Expression<Int>(column) -= 1
 }
diff --git a/SQLiteTests/ConnectionTests.swift b/SQLiteTests/ConnectionTests.swift
index 3d7dd3eb..0e8ebea6 100644
--- a/SQLiteTests/ConnectionTests.swift
+++ b/SQLiteTests/ConnectionTests.swift
@@ -10,7 +10,7 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_init_withInMemory_returnsInMemoryConnection() {
-        let db = try! Connection(.InMemory)
+        let db = try! Connection(.inMemory)
         XCTAssertEqual("", db.description)
     }
 
@@ -20,12 +20,12 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_init_withTemporary_returnsTemporaryConnection() {
-        let db = try! Connection(.Temporary)
+        let db = try! Connection(.temporary)
         XCTAssertEqual("", db.description)
     }
 
     func test_init_withURI_returnsURIConnection() {
-        let db = try! Connection(.URI("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3"))
+        let db = try! Connection(.uri("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3"))
         XCTAssertEqual("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3", db.description)
     }
 
@@ -48,7 +48,7 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_lastInsertRowid_returnsLastIdAfterInserts() {
-        try! InsertUser("alice")
+        _ = try! InsertUser("alice")
         XCTAssertEqual(1, db.lastInsertRowid!)
     }
 
@@ -57,17 +57,17 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_changes_returnsNumberOfChanges() {
-        try! InsertUser("alice")
+        _ = try! InsertUser("alice")
         XCTAssertEqual(1, db.changes)
-        try! InsertUser("betsy")
+        _ = try! InsertUser("betsy")
         XCTAssertEqual(1, db.changes)
     }
 
     func test_totalChanges_returnsTotalNumberOfChanges() {
         XCTAssertEqual(0, db.totalChanges)
-        try! InsertUser("alice")
+        _ = try! InsertUser("alice")
         XCTAssertEqual(1, db.totalChanges)
-        try! InsertUser("betsy")
+        _ = try! InsertUser("betsy")
         XCTAssertEqual(2, db.totalChanges)
     }
 
@@ -79,10 +79,10 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_run_preparesRunsAndReturnsStatements() {
-        try! db.run("SELECT * FROM users WHERE admin = 0")
-        try! db.run("SELECT * FROM users WHERE admin = ?", 0)
-        try! db.run("SELECT * FROM users WHERE admin = ?", [0])
-        try! db.run("SELECT * FROM users WHERE admin = $admin", ["$admin": 0])
+        _ = try! db.run("SELECT * FROM users WHERE admin = 0")
+        _ = try! db.run("SELECT * FROM users WHERE admin = ?", 0)
+        _ = try! db.run("SELECT * FROM users WHERE admin = ?", [0])
+        _ = try! db.run("SELECT * FROM users WHERE admin = $admin", ["$admin": 0])
         AssertSQL("SELECT * FROM users WHERE admin = 0", 4)
     }
 
@@ -116,7 +116,7 @@ class ConnectionTests : SQLiteTestCase {
         let stmt = try! db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com")
 
         try! db.transaction {
-            try stmt.run()
+            _ = try stmt.run()
         }
 
         AssertSQL("BEGIN DEFERRED TRANSACTION")
@@ -130,8 +130,8 @@ class ConnectionTests : SQLiteTestCase {
 
         do {
             try db.transaction {
-                try stmt.run()
-                try stmt.run()
+                _ = try stmt.run()
+                _ = try stmt.run()
             }
         } catch {
         }
@@ -147,7 +147,7 @@ class ConnectionTests : SQLiteTestCase {
 
         try! db.savepoint("1") {
             try db.savepoint("2") {
-                try db.run("INSERT INTO users (email) VALUES (?)", "alice@example.com")
+                _ = try db.run("INSERT INTO users (email) VALUES (?)", "alice@example.com")
             }
         }
 
@@ -167,14 +167,14 @@ class ConnectionTests : SQLiteTestCase {
         do {
             try db.savepoint("1") {
                 try db.savepoint("2") {
-                    try stmt.run()
-                    try stmt.run()
-                    try stmt.run()
+                    _ = try stmt.run()
+                    _ = try stmt.run()
+                    _ = try stmt.run()
                 }
                 try db.savepoint("2") {
-                    try stmt.run()
-                    try stmt.run()
-                    try stmt.run()
+                    _ = try stmt.run()
+                    _ = try stmt.run()
+                    _ = try stmt.run()
                 }
             }
         } catch {
@@ -192,41 +192,41 @@ class ConnectionTests : SQLiteTestCase {
     func test_updateHook_setsUpdateHook_withInsert() {
         async { done in
             db.updateHook { operation, db, table, rowid in
-                XCTAssertEqual(Operation.Insert, operation)
+                XCTAssertEqual(Operation.insert, operation)
                 XCTAssertEqual("main", db)
                 XCTAssertEqual("users", table)
                 XCTAssertEqual(1, rowid)
                 done()
             }
-            try! InsertUser("alice")
+            _ = try! InsertUser("alice")
         }
     }
 
     func test_updateHook_setsUpdateHook_withUpdate() {
-        try! InsertUser("alice")
+        _ = try! InsertUser("alice")
         async { done in
             db.updateHook { operation, db, table, rowid in
-                XCTAssertEqual(Operation.Update, operation)
+                XCTAssertEqual(Operation.update, operation)
                 XCTAssertEqual("main", db)
                 XCTAssertEqual("users", table)
                 XCTAssertEqual(1, rowid)
                 done()
             }
-            try! db.run("UPDATE users SET email = 'alice@example.com'")
+            _ = try! db.run("UPDATE users SET email = 'alice@example.com'")
         }
     }
 
     func test_updateHook_setsUpdateHook_withDelete() {
-        try! InsertUser("alice")
+        _ = try! InsertUser("alice")
         async { done in
             db.updateHook { operation, db, table, rowid in
-                XCTAssertEqual(Operation.Delete, operation)
+                XCTAssertEqual(Operation.delete, operation)
                 XCTAssertEqual("main", db)
                 XCTAssertEqual("users", table)
                 XCTAssertEqual(1, rowid)
                 done()
             }
-            try! db.run("DELETE FROM users WHERE id = 1")
+            _ = try! db.run("DELETE FROM users WHERE id = 1")
         }
     }
 
@@ -236,7 +236,7 @@ class ConnectionTests : SQLiteTestCase {
                 done()
             }
             try! db.transaction {
-                try self.InsertUser("alice")
+                _ = try self.InsertUser("alice")
             }
             XCTAssertEqual(1, try! db.scalar("SELECT count(*) FROM users") as? Int64)
         }
@@ -247,8 +247,8 @@ class ConnectionTests : SQLiteTestCase {
             db.rollbackHook(done)
             do {
                 try db.transaction {
-                    try self.InsertUser("alice")
-                    try self.InsertUser("alice") // throw
+                    _ = try self.InsertUser("alice")
+                    _ = try self.InsertUser("alice") // throw
                 }
             } catch {
             }
@@ -264,7 +264,7 @@ class ConnectionTests : SQLiteTestCase {
             db.rollbackHook(done)
             do {
                 try db.transaction {
-                    try self.InsertUser("alice")
+                    _ = try self.InsertUser("alice")
                 }
             } catch {
             }
@@ -288,14 +288,14 @@ class ConnectionTests : SQLiteTestCase {
 
     func test_createCollation_createsCollation() {
         try! db.createCollation("NODIACRITIC") { lhs, rhs in
-            return lhs.compare(rhs, options: .DiacriticInsensitiveSearch)
+            return lhs.compare(rhs, options: .diacriticInsensitive)
         }
         XCTAssertEqual(1, try! db.scalar("SELECT ? = ? COLLATE NODIACRITIC", "cafe", "café") as? Int64)
     }
 
     func test_createCollation_createsQuotableCollation() {
         try! db.createCollation("NO DIACRITIC") { lhs, rhs in
-            return lhs.compare(rhs, options: .DiacriticInsensitiveSearch)
+            return lhs.compare(rhs, options: .diacriticInsensitive)
         }
         XCTAssertEqual(1, try! db.scalar("SELECT ? = ? COLLATE \"NO DIACRITIC\"", "cafe", "café") as? Int64)
     }
@@ -308,9 +308,9 @@ class ConnectionTests : SQLiteTestCase {
         }
 
         let stmt = try! db.prepare("SELECT *, sleep(?) FROM users", 0.1)
-        try! stmt.run()
+        _ = try! stmt.run()
 
-        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(10 * NSEC_PER_MSEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), db.interrupt)
+        _ = DispatchQueue.global(priority: DispatchQueue.GlobalQueuePriority.background).asyncAfter(deadline: DispatchTime.now() + Double(Int64(10 * NSEC_PER_MSEC)) / Double(NSEC_PER_SEC), execute: db.interrupt)
         AssertThrows(try stmt.run())
     }
 
diff --git a/SQLiteTests/CoreFunctionsTests.swift b/SQLiteTests/CoreFunctionsTests.swift
index 8f7460d5..db37ff7f 100644
--- a/SQLiteTests/CoreFunctionsTests.swift
+++ b/SQLiteTests/CoreFunctionsTests.swift
@@ -55,15 +55,15 @@ class CoreFunctionsTests : XCTestCase {
     }
 
     func test_collate_buildsExpressionWithCollateOperator() {
-        AssertSQL("(\"string\" COLLATE BINARY)", string.collate(.Binary))
-        AssertSQL("(\"string\" COLLATE NOCASE)", string.collate(.Nocase))
-        AssertSQL("(\"string\" COLLATE RTRIM)", string.collate(.Rtrim))
-        AssertSQL("(\"string\" COLLATE \"CUSTOM\")", string.collate(.Custom("CUSTOM")))
-
-        AssertSQL("(\"stringOptional\" COLLATE BINARY)", stringOptional.collate(.Binary))
-        AssertSQL("(\"stringOptional\" COLLATE NOCASE)", stringOptional.collate(.Nocase))
-        AssertSQL("(\"stringOptional\" COLLATE RTRIM)", stringOptional.collate(.Rtrim))
-        AssertSQL("(\"stringOptional\" COLLATE \"CUSTOM\")", stringOptional.collate(.Custom("CUSTOM")))
+        AssertSQL("(\"string\" COLLATE BINARY)", string.collate(.binary))
+        AssertSQL("(\"string\" COLLATE NOCASE)", string.collate(.nocase))
+        AssertSQL("(\"string\" COLLATE RTRIM)", string.collate(.rtrim))
+        AssertSQL("(\"string\" COLLATE \"CUSTOM\")", string.collate(.custom("CUSTOM")))
+
+        AssertSQL("(\"stringOptional\" COLLATE BINARY)", stringOptional.collate(.binary))
+        AssertSQL("(\"stringOptional\" COLLATE NOCASE)", stringOptional.collate(.nocase))
+        AssertSQL("(\"stringOptional\" COLLATE RTRIM)", stringOptional.collate(.rtrim))
+        AssertSQL("(\"stringOptional\" COLLATE \"CUSTOM\")", stringOptional.collate(.custom("CUSTOM")))
     }
 
     func test_ltrim_wrapsStringWithLtrimFunction() {
diff --git a/SQLiteTests/FTS4Tests.swift b/SQLiteTests/FTS4Tests.swift
index 8b4e4f96..37a773a6 100644
--- a/SQLiteTests/FTS4Tests.swift
+++ b/SQLiteTests/FTS4Tests.swift
@@ -121,19 +121,19 @@ class FTS4ConfigTests : XCTestCase {
     func test_config_matchinfo() {
         XCTAssertEqual(
             "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(matchinfo=\"fts3\")",
-            sql(config.matchInfo(.FTS3)))
+            sql(config.matchInfo(.fts3)))
     }
 
     func test_config_order_asc() {
         XCTAssertEqual(
             "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(order=\"asc\")",
-            sql(config.order(.Asc)))
+            sql(config.order(.asc)))
     }
 
     func test_config_order_desc() {
         XCTAssertEqual(
             "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(order=\"desc\")",
-            sql(config.order(.Desc)))
+            sql(config.order(.desc)))
     }
 
     func test_config_compress() {
@@ -163,14 +163,14 @@ class FTS4ConfigTests : XCTestCase {
                 .column(string, [.unindexed])
                 .column(date, [.unindexed])
                 .externalContent(table)
-                .matchInfo(.FTS3)
+                .matchInfo(.fts3)
                 .languageId("lid")
-                .order(.Desc)
+                .order(.desc)
                 .prefix([2, 4]))
         )
     }
 
-    func sql(config: FTS4Config) -> String {
+    func sql(_ config: FTS4Config) -> String {
         return virtualTable.create(.FTS4(config))
     }
 }
@@ -184,24 +184,24 @@ class FTS4IntegrationTests : SQLiteTestCase {
 
         let locale = CFLocaleCopyCurrent()
         let tokenizerName = "tokenizer"
-        let tokenizer = CFStringTokenizerCreate(nil, "", CFRangeMake(0, 0), UInt(kCFStringTokenizerUnitWord), locale)
+        let tokenizer = CFStringTokenizerCreate(nil, "" as CFString!, CFRangeMake(0, 0), UInt(kCFStringTokenizerUnitWord), locale)
         try! db.registerTokenizer(tokenizerName) { string in
-            CFStringTokenizerSetString(tokenizer, string, CFRangeMake(0, CFStringGetLength(string)))
-            if CFStringTokenizerAdvanceToNextToken(tokenizer) == .None {
+            CFStringTokenizerSetString(tokenizer, string as CFString, CFRangeMake(0, CFStringGetLength(string as CFString)))
+            if CFStringTokenizerAdvanceToNextToken(tokenizer) == .none {
                 return nil
             }
             let range = CFStringTokenizerGetCurrentTokenRange(tokenizer)
-            let input = CFStringCreateWithSubstring(kCFAllocatorDefault, string, range)
+            let input = CFStringCreateWithSubstring(kCFAllocatorDefault, string as CFString, range)
             let token = CFStringCreateMutableCopy(nil, range.length, input)
             CFStringLowercase(token, locale)
             CFStringTransform(token, nil, kCFStringTransformStripDiacritics, false)
-            return (token as String, string.rangeOfString(input as String)!)
+            return ((token as String?)!, string.range(of: (input as String?)!)!)
         }
 
-        try! db.run(emails.create(.FTS4([subject, body], tokenize: .Custom(tokenizerName))))
+        _ = try! db.run(emails.create(.FTS4([subject, body], tokenize: .Custom(tokenizerName))))
         AssertSQL("CREATE VIRTUAL TABLE \"emails\" USING fts4(\"subject\", \"body\", tokenize=\"SQLite.swift\" \"tokenizer\")")
 
-        try! db.run(emails.insert(subject <- "Aún más cáfe!"))
+        _ = try! db.run(emails.insert(subject <- "Aún más cáfe!"))
         XCTAssertEqual(1, try! db.scalar(emails.filter(emails.match("aun")).count))
     }
 #endif
diff --git a/SQLiteTests/FTS5Tests.swift b/SQLiteTests/FTS5Tests.swift
index aa3965bd..63d8dc40 100644
--- a/SQLiteTests/FTS5Tests.swift
+++ b/SQLiteTests/FTS5Tests.swift
@@ -90,19 +90,19 @@ class FTS5Tests: XCTestCase {
     func test_detail_full() {
         XCTAssertEqual(
             "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(detail=\"full\")",
-            sql(config.detail(.Full)))
+            sql(config.detail(.full)))
     }
 
     func test_detail_column() {
         XCTAssertEqual(
             "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(detail=\"column\")",
-            sql(config.detail(.Column)))
+            sql(config.detail(.column)))
     }
 
     func test_detail_none() {
         XCTAssertEqual(
             "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(detail=\"none\")",
-            sql(config.detail(.None)))
+            sql(config.detail(.none)))
     }
 
     func test_fts5_config_all() {
@@ -118,7 +118,7 @@ class FTS5Tests: XCTestCase {
         )
     }
 
-    func sql(config: FTS5Config) -> String {
+    func sql(_ config: FTS5Config) -> String {
         return virtualTable.create(.FTS5(config))
     }
 }
diff --git a/SQLiteTests/OperatorsTests.swift b/SQLiteTests/OperatorsTests.swift
index 86aa34ed..819cf292 100644
--- a/SQLiteTests/OperatorsTests.swift
+++ b/SQLiteTests/OperatorsTests.swift
@@ -283,4 +283,4 @@ class OperatorsTests : XCTestCase {
         AssertSQL("((1 = 1) AND ((1 = 1) OR (1 = 1)))", n == n && (n == n || n == n))
     }
 
-}
\ No newline at end of file
+}
diff --git a/SQLiteTests/QueryTests.swift b/SQLiteTests/QueryTests.swift
index f584bfcf..df2ff073 100644
--- a/SQLiteTests/QueryTests.swift
+++ b/SQLiteTests/QueryTests.swift
@@ -298,10 +298,10 @@ class QueryIntegrationTests : SQLiteTestCase {
         let managers = users.alias("managers")
 
         let alice = try! db.run(users.insert(email <- "alice@example.com"))
-        try! db.run(users.insert(email <- "betsy@example.com", managerId <- alice))
+        _ = try! db.run(users.insert(email <- "betsy@example.com", managerId <- alice))
 
         for user in try! db.prepare(users.join(managers, on: managers[id] == users[managerId])) {
-            user[users[managerId]]
+            _ = user[users[managerId]]
         }
     }
 
diff --git a/SQLiteTests/SchemaTests.swift b/SQLiteTests/SchemaTests.swift
index 416b3646..01bedda0 100644
--- a/SQLiteTests/SchemaTests.swift
+++ b/SQLiteTests/SchemaTests.swift
@@ -283,15 +283,15 @@ class SchemaTests : XCTestCase {
     func test_column_withIntegerExpression_compilesPrimaryKeyAutoincrementColumnDefinitionExpression() {
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"int64\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
-            table.create { t in t.column(int64, primaryKey: .Autoincrement) }
+            table.create { t in t.column(int64, primaryKey: .autoincrement) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"int64\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK (\"int64\" > 0))",
-            table.create { t in t.column(int64, primaryKey: .Autoincrement, check: int64 > 0) }
+            table.create { t in t.column(int64, primaryKey: .autoincrement, check: int64 > 0) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"int64\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK (\"int64Optional\" > 0))",
-            table.create { t in t.column(int64, primaryKey: .Autoincrement, check: int64Optional > 0) }
+            table.create { t in t.column(int64, primaryKey: .autoincrement, check: int64Optional > 0) }
         )
     }
 
@@ -354,172 +354,172 @@ class SchemaTests : XCTestCase {
     func test_column_withStringExpression_compilesCollatedColumnDefinitionExpression() {
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL COLLATE RTRIM)",
-            table.create { t in t.column(string, collate: .Rtrim) }
+            table.create { t in t.column(string, collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL UNIQUE COLLATE RTRIM)",
-            table.create { t in t.column(string, unique: true, collate: .Rtrim) }
+            table.create { t in t.column(string, unique: true, collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL CHECK (\"string\" != '') COLLATE RTRIM)",
-            table.create { t in t.column(string, check: string != "", collate: .Rtrim) }
+            table.create { t in t.column(string, check: string != "", collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL CHECK (\"stringOptional\" != '') COLLATE RTRIM)",
-            table.create { t in t.column(string, check: stringOptional != "", collate: .Rtrim) }
+            table.create { t in t.column(string, check: stringOptional != "", collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL DEFAULT (\"string\") COLLATE RTRIM)",
-            table.create { t in t.column(string, defaultValue: string, collate: .Rtrim) }
+            table.create { t in t.column(string, defaultValue: string, collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL DEFAULT ('string') COLLATE RTRIM)",
-            table.create { t in t.column(string, defaultValue: "string", collate: .Rtrim) }
+            table.create { t in t.column(string, defaultValue: "string", collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL UNIQUE CHECK (\"string\" != '') COLLATE RTRIM)",
-            table.create { t in t.column(string, unique: true, check: string != "", collate: .Rtrim) }
+            table.create { t in t.column(string, unique: true, check: string != "", collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL UNIQUE CHECK (\"stringOptional\" != '') COLLATE RTRIM)",
-            table.create { t in t.column(string, unique: true, check: stringOptional != "", collate: .Rtrim) }
+            table.create { t in t.column(string, unique: true, check: stringOptional != "", collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL UNIQUE DEFAULT (\"string\") COLLATE RTRIM)",
-            table.create { t in t.column(string, unique: true, defaultValue: string, collate: .Rtrim) }
+            table.create { t in t.column(string, unique: true, defaultValue: string, collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL UNIQUE DEFAULT ('string') COLLATE RTRIM)",
-            table.create { t in t.column(string, unique: true, defaultValue: "string", collate: .Rtrim) }
+            table.create { t in t.column(string, unique: true, defaultValue: "string", collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL UNIQUE CHECK (\"string\" != '') DEFAULT (\"string\") COLLATE RTRIM)",
-            table.create { t in t.column(string, unique: true, check: string != "", defaultValue: string, collate: .Rtrim) }
+            table.create { t in t.column(string, unique: true, check: string != "", defaultValue: string, collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL UNIQUE CHECK (\"stringOptional\" != '') DEFAULT (\"string\") COLLATE RTRIM)",
-            table.create { t in t.column(string, unique: true, check: stringOptional != "", defaultValue: string, collate: .Rtrim) }
+            table.create { t in t.column(string, unique: true, check: stringOptional != "", defaultValue: string, collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL UNIQUE CHECK (\"string\" != '') DEFAULT ('string') COLLATE RTRIM)",
-            table.create { t in t.column(string, unique: true, check: string != "", defaultValue: "string", collate: .Rtrim) }
+            table.create { t in t.column(string, unique: true, check: string != "", defaultValue: "string", collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL UNIQUE CHECK (\"stringOptional\" != '') DEFAULT ('string') COLLATE RTRIM)",
-            table.create { t in t.column(string, unique: true, check: stringOptional != "", defaultValue: "string", collate: .Rtrim) }
+            table.create { t in t.column(string, unique: true, check: stringOptional != "", defaultValue: "string", collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL CHECK (\"string\" != '') DEFAULT (\"string\") COLLATE RTRIM)",
-            table.create { t in t.column(string, check: string != "", defaultValue: string, collate: .Rtrim) }
+            table.create { t in t.column(string, check: string != "", defaultValue: string, collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL CHECK (\"stringOptional\" != '') DEFAULT (\"string\") COLLATE RTRIM)",
-            table.create { t in t.column(string, check: stringOptional != "", defaultValue: string, collate: .Rtrim) }
+            table.create { t in t.column(string, check: stringOptional != "", defaultValue: string, collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL CHECK (\"string\" != '') DEFAULT ('string') COLLATE RTRIM)",
-            table.create { t in t.column(string, check: string != "", defaultValue: "string", collate: .Rtrim) }
+            table.create { t in t.column(string, check: string != "", defaultValue: "string", collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL CHECK (\"stringOptional\" != '') DEFAULT ('string') COLLATE RTRIM)",
-            table.create { t in t.column(string, check: stringOptional != "", defaultValue: "string", collate: .Rtrim) }
+            table.create { t in t.column(string, check: stringOptional != "", defaultValue: "string", collate: .rtrim) }
         )
 
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, unique: true, collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, unique: true, collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL CHECK (\"string\" != '') COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, check: string != "", collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, check: string != "", collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL CHECK (\"stringOptional\" != '') COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, check: stringOptional != "", collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, check: stringOptional != "", collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL DEFAULT (\"string\") COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, defaultValue: string, collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, defaultValue: string, collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL DEFAULT (\"stringOptional\") COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, defaultValue: stringOptional, collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, defaultValue: stringOptional, collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL DEFAULT ('string') COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, defaultValue: "string", collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, defaultValue: "string", collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE CHECK (\"string\" != '') COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, unique: true, check: string != "", collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, unique: true, check: string != "", collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE CHECK (\"stringOptional\" != '') COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, unique: true, check: stringOptional != "", collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, unique: true, check: stringOptional != "", collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE DEFAULT (\"string\") COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, unique: true, defaultValue: string, collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, unique: true, defaultValue: string, collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE DEFAULT (\"stringOptional\") COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, unique: true, defaultValue: stringOptional, collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, unique: true, defaultValue: stringOptional, collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE DEFAULT ('string') COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, unique: true, defaultValue: "string", collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, unique: true, defaultValue: "string", collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE CHECK (\"string\" != '') DEFAULT (\"string\") COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, unique: true, check: string != "", defaultValue: string, collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, unique: true, check: string != "", defaultValue: string, collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE CHECK (\"string\" != '') DEFAULT (\"stringOptional\") COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, unique: true, check: string != "", defaultValue: stringOptional, collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, unique: true, check: string != "", defaultValue: stringOptional, collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE CHECK (\"stringOptional\" != '') DEFAULT (\"string\") COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, unique: true, check: stringOptional != "", defaultValue: string, collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, unique: true, check: stringOptional != "", defaultValue: string, collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE CHECK (\"stringOptional\" != '') DEFAULT (\"stringOptional\") COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, unique: true, check: stringOptional != "", defaultValue: stringOptional, collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, unique: true, check: stringOptional != "", defaultValue: stringOptional, collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE CHECK (\"string\" != '') DEFAULT ('string') COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, unique: true, check: string != "", defaultValue: "string", collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, unique: true, check: string != "", defaultValue: "string", collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE CHECK (\"stringOptional\" != '') DEFAULT ('string') COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, unique: true, check: stringOptional != "", defaultValue: "string", collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, unique: true, check: stringOptional != "", defaultValue: "string", collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL CHECK (\"string\" != '') DEFAULT (\"string\") COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, check: string != "", defaultValue: string, collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, check: string != "", defaultValue: string, collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL CHECK (\"stringOptional\" != '') DEFAULT (\"string\") COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, check: stringOptional != "", defaultValue: string, collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, check: stringOptional != "", defaultValue: string, collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL CHECK (\"string\" != '') DEFAULT (\"stringOptional\") COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, check: string != "", defaultValue: stringOptional, collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, check: string != "", defaultValue: stringOptional, collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL CHECK (\"stringOptional\" != '') DEFAULT (\"stringOptional\") COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, check: stringOptional != "", defaultValue: stringOptional, collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, check: stringOptional != "", defaultValue: stringOptional, collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL CHECK (\"string\" != '') DEFAULT ('string') COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, check: string != "", defaultValue: "string", collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, check: string != "", defaultValue: "string", collate: .rtrim) }
         )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL CHECK (\"stringOptional\" != '') DEFAULT ('string') COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, check: stringOptional != "", defaultValue: "string", collate: .Rtrim) }
+            table.create { t in t.column(stringOptional, check: stringOptional != "", defaultValue: "string", collate: .rtrim) }
         )
     }
 
@@ -676,36 +676,36 @@ class SchemaTests : XCTestCase {
     func test_addColumn_withStringExpression_compilesCollatedAlterTableExpression() {
         XCTAssertEqual(
             "ALTER TABLE \"table\" ADD COLUMN \"string\" TEXT NOT NULL DEFAULT ('string') COLLATE RTRIM",
-            table.addColumn(string, defaultValue: "string", collate: .Rtrim)
+            table.addColumn(string, defaultValue: "string", collate: .rtrim)
         )
         XCTAssertEqual(
             "ALTER TABLE \"table\" ADD COLUMN \"string\" TEXT NOT NULL CHECK (\"string\" != '') DEFAULT ('string') COLLATE RTRIM",
-            table.addColumn(string, check: string != "", defaultValue: "string", collate: .Rtrim)
+            table.addColumn(string, check: string != "", defaultValue: "string", collate: .rtrim)
         )
         XCTAssertEqual(
             "ALTER TABLE \"table\" ADD COLUMN \"string\" TEXT NOT NULL CHECK (\"stringOptional\" != '') DEFAULT ('string') COLLATE RTRIM",
-            table.addColumn(string, check: stringOptional != "", defaultValue: "string", collate: .Rtrim)
+            table.addColumn(string, check: stringOptional != "", defaultValue: "string", collate: .rtrim)
         )
 
         XCTAssertEqual(
             "ALTER TABLE \"table\" ADD COLUMN \"stringOptional\" TEXT COLLATE RTRIM",
-            table.addColumn(stringOptional, collate: .Rtrim)
+            table.addColumn(stringOptional, collate: .rtrim)
         )
         XCTAssertEqual(
             "ALTER TABLE \"table\" ADD COLUMN \"stringOptional\" TEXT CHECK (\"string\" != '') COLLATE RTRIM",
-            table.addColumn(stringOptional, check: string != "", collate: .Rtrim)
+            table.addColumn(stringOptional, check: string != "", collate: .rtrim)
         )
         XCTAssertEqual(
             "ALTER TABLE \"table\" ADD COLUMN \"stringOptional\" TEXT CHECK (\"stringOptional\" != '') COLLATE RTRIM",
-            table.addColumn(stringOptional, check: stringOptional != "", collate: .Rtrim)
+            table.addColumn(stringOptional, check: stringOptional != "", collate: .rtrim)
         )
         XCTAssertEqual(
             "ALTER TABLE \"table\" ADD COLUMN \"stringOptional\" TEXT CHECK (\"string\" != '') DEFAULT ('string') COLLATE RTRIM",
-            table.addColumn(stringOptional, check: string != "", defaultValue: "string", collate: .Rtrim)
+            table.addColumn(stringOptional, check: string != "", defaultValue: "string", collate: .rtrim)
         )
         XCTAssertEqual(
             "ALTER TABLE \"table\" ADD COLUMN \"stringOptional\" TEXT CHECK (\"stringOptional\" != '') DEFAULT ('string') COLLATE RTRIM",
-            table.addColumn(stringOptional, check: stringOptional != "", defaultValue: "string", collate: .Rtrim)
+            table.addColumn(stringOptional, check: stringOptional != "", defaultValue: "string", collate: .rtrim)
         )
     }
 
diff --git a/SQLiteTests/TestHelpers.swift b/SQLiteTests/TestHelpers.swift
index 464b9c27..7b7715b1 100644
--- a/SQLiteTests/TestHelpers.swift
+++ b/SQLiteTests/TestHelpers.swift
@@ -32,22 +32,22 @@ class SQLiteTestCase : XCTestCase {
         )
     }
 
-    func InsertUsers(names: String...) throws {
+    func InsertUsers(_ names: String...) throws {
         try InsertUsers(names)
     }
 
-    func InsertUsers(names: [String]) throws {
-        for name in names { try InsertUser(name) }
+    func InsertUsers(_ names: [String]) throws {
+        for name in names { _ = try InsertUser(name) }
     }
 
-    func InsertUser(name: String, age: Int? = nil, admin: Bool = false) throws -> Statement {
+    func InsertUser(_ name: String, age: Int? = nil, admin: Bool = false) throws -> Statement {
         return try db.run(
             "INSERT INTO \"users\" (email, age, admin) values (?, ?, ?)",
             "\(name)@example.com", age?.datatypeValue, admin.datatypeValue
         )
     }
 
-    func AssertSQL(SQL: String, _ executions: Int = 1, _ message: String? = nil, file: StaticString = #file, line: UInt = #line) {
+    func AssertSQL(_ SQL: String, _ executions: Int = 1, _ message: String? = nil, file: StaticString = #file, line: UInt = #line) {
         XCTAssertEqual(
             executions, trace[SQL] ?? 0,
             message ?? SQL,
@@ -55,8 +55,8 @@ class SQLiteTestCase : XCTestCase {
         )
     }
 
-    func AssertSQL(SQL: String, _ statement: Statement, _ message: String? = nil, file: StaticString = #file, line: UInt = #line) {
-        try! statement.run()
+    func AssertSQL(_ SQL: String, _ statement: Statement, _ message: String? = nil, file: StaticString = #file, line: UInt = #line) {
+        _ = try! statement.run()
         AssertSQL(SQL, 1, message, file: file, line: line)
         if let count = trace[SQL] { trace[SQL] = count - 1 }
     }
@@ -67,10 +67,10 @@ class SQLiteTestCase : XCTestCase {
 //        if let count = trace[SQL] { trace[SQL] = count - 1 }
 //    }
 
-    func async(expect description: String = "async", timeout: Double = 5, @noescape block: (() -> Void) -> Void) {
-        let expectation = expectationWithDescription(description)
+    func async(expect description: String = "async", timeout: Double = 5, block: (@escaping () -> Void) -> Void) {
+        let expectation = self.expectation(description: description)
         block(expectation.fulfill)
-        waitForExpectationsWithTimeout(timeout, handler: nil)
+        waitForExpectations(timeout: timeout, handler: nil)
     }
 
 }
@@ -81,8 +81,8 @@ let boolOptional = Expression<Bool?>("boolOptional")
 let data = Expression<Blob>("blob")
 let dataOptional = Expression<Blob?>("blobOptional")
 
-let date = Expression<NSDate>("date")
-let dateOptional = Expression<NSDate?>("dateOptional")
+let date = Expression<Date>("date")
+let dateOptional = Expression<Date?>("dateOptional")
 
 let double = Expression<Double>("double")
 let doubleOptional = Expression<Double?>("doubleOptional")
@@ -96,13 +96,13 @@ let int64Optional = Expression<Int64?>("int64Optional")
 let string = Expression<String>("string")
 let stringOptional = Expression<String?>("stringOptional")
 
-func AssertSQL(@autoclosure expression1: () -> String, @autoclosure _ expression2: () -> Expressible, file: StaticString = #file, line: UInt = #line) {
+func AssertSQL(_ expression1: @autoclosure () -> String, _ expression2: @autoclosure () -> Expressible, file: StaticString = #file, line: UInt = #line) {
     XCTAssertEqual(expression1(), expression2().asSQL(), file: file, line: line)
 }
 
-func AssertThrows<T>(@autoclosure expression: () throws -> T, file: StaticString = #file, line: UInt = #line) {
+func AssertThrows<T>(_ expression: @autoclosure () throws -> T, file: StaticString = #file, line: UInt = #line) {
     do {
-        try expression()
+        _ = try expression()
         XCTFail("expression expected to throw", file: file, line: line)
     } catch {
         XCTAssert(true, file: file, line: line)

From 78c7f6ae01fc06d86b24f9a595c03eb85d0bde8f Mon Sep 17 00:00:00 2001
From: Mariotaku Lee <mariotaku.lee@gmail.com>
Date: Fri, 16 Sep 2016 18:47:54 +0800
Subject: [PATCH 073/685] all tests passed

---
 SQLite.xcodeproj/project.pbxproj | 4 ++++
 SQLite/Extensions/FTS4.swift     | 2 +-
 SQLiteTests/FTS4Tests.swift      | 8 ++++----
 3 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 2f13a35f..aa951fd8 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1007,6 +1007,7 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = appletvos;
+				SWIFT_VERSION = 3.0;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
 			name = Debug;
@@ -1019,6 +1020,7 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = appletvos;
+				SWIFT_VERSION = 3.0;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
 			name = Release;
@@ -1040,6 +1042,7 @@
 				PRODUCT_NAME = SQLite;
 				SDKROOT = watchos;
 				SKIP_INSTALL = YES;
+				SWIFT_VERSION = 3.0;
 				TARGETED_DEVICE_FAMILY = 4;
 				WATCHOS_DEPLOYMENT_TARGET = 2.2;
 			};
@@ -1062,6 +1065,7 @@
 				PRODUCT_NAME = SQLite;
 				SDKROOT = watchos;
 				SKIP_INSTALL = YES;
+				SWIFT_VERSION = 3.0;
 				TARGETED_DEVICE_FAMILY = 4;
 				WATCHOS_DEPLOYMENT_TARGET = 2.2;
 			};
diff --git a/SQLite/Extensions/FTS4.swift b/SQLite/Extensions/FTS4.swift
index 52de47bf..bd8c7b2d 100644
--- a/SQLite/Extensions/FTS4.swift
+++ b/SQLite/Extensions/FTS4.swift
@@ -148,7 +148,7 @@ extension Connection {
 
             let view = string.utf8
             offset.pointee += string.substring(to: range.lowerBound).utf8.count
-            length.pointee = Int32(view.distance(from: range.lowerBound.samePosition(in: view), to: range.lowerBound.samePosition(in: view)))
+            length.pointee = Int32(view.distance(from: range.lowerBound.samePosition(in: view), to: range.upperBound.samePosition(in: view)))
             return token
         })
     }
diff --git a/SQLiteTests/FTS4Tests.swift b/SQLiteTests/FTS4Tests.swift
index 37a773a6..92f197a2 100644
--- a/SQLiteTests/FTS4Tests.swift
+++ b/SQLiteTests/FTS4Tests.swift
@@ -187,15 +187,15 @@ class FTS4IntegrationTests : SQLiteTestCase {
         let tokenizer = CFStringTokenizerCreate(nil, "" as CFString!, CFRangeMake(0, 0), UInt(kCFStringTokenizerUnitWord), locale)
         try! db.registerTokenizer(tokenizerName) { string in
             CFStringTokenizerSetString(tokenizer, string as CFString, CFRangeMake(0, CFStringGetLength(string as CFString)))
-            if CFStringTokenizerAdvanceToNextToken(tokenizer) == .none {
+            if CFStringTokenizerAdvanceToNextToken(tokenizer).isEmpty {
                 return nil
             }
             let range = CFStringTokenizerGetCurrentTokenRange(tokenizer)
-            let input = CFStringCreateWithSubstring(kCFAllocatorDefault, string as CFString, range)
-            let token = CFStringCreateMutableCopy(nil, range.length, input)
+            let input = CFStringCreateWithSubstring(kCFAllocatorDefault, string as CFString, range)!
+            let token = CFStringCreateMutableCopy(nil, range.length, input)!
             CFStringLowercase(token, locale)
             CFStringTransform(token, nil, kCFStringTransformStripDiacritics, false)
-            return ((token as String?)!, string.range(of: (input as String?)!)!)
+            return (token as String, string.range(of: input as String)!)
         }
 
         _ = try! db.run(emails.create(.FTS4([subject, body], tokenize: .Custom(tokenizerName))))

From aaa07c70e1952ce6aadccc0b79e7e0a1ce05d2ba Mon Sep 17 00:00:00 2001
From: Mariotaku Lee <mariotaku.lee@gmail.com>
Date: Sat, 17 Sep 2016 09:37:27 +0800
Subject: [PATCH 074/685] added .swift-version for pods

---
 .swift-version | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.swift-version b/.swift-version
index bb576dbd..9f55b2cc 100644
--- a/.swift-version
+++ b/.swift-version
@@ -1 +1 @@
-2.3
+3.0

From e9abf032f461bf2a6d84751d13e37998a94a2dfa Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 17 Sep 2016 17:32:30 +0100
Subject: [PATCH 075/685] Remove Xcode 7.3 tests

---
 .travis.yml | 31 ++++---------------------------
 Makefile    |  2 +-
 2 files changed, 5 insertions(+), 28 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index d855fb3c..ada13822 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,34 +3,11 @@ rvm: 2.2
 osx_image: xcode8
 matrix:
   include:
-    - env:
-        - BUILD_SCHEME="SQLite iOS"
-        - IOS_SIMULATOR="iPhone SE"
+    - env: BUILD_SCHEME="SQLite iOS"
     - env: BUILD_SCHEME="SQLite Mac"
-    - env:
-        - VALIDATOR_SUBSPEC="none"
-        - IOS_SIMULATOR="iPhone SE"
-    - env:
-        - VALIDATOR_SUBSPEC="standard"
-        - IOS_SIMULATOR="iPhone SE"
-    - env:
-        - VALIDATOR_SUBSPEC="standalone"
-        - IOS_SIMULATOR="iPhone SE"
-    - os: osx
-      osx_image: xcode7.3
-      env: BUILD_SCHEME="SQLite iOS"
-    - os: osx
-      osx_image: xcode7.3
-      env: BUILD_SCHEME="SQLite Mac"
-    - os: osx
-      osx_image: xcode7.3
-      env: VALIDATOR_SUBSPEC="none"
-    - os: osx
-      osx_image: xcode7.3
-      env: VALIDATOR_SUBSPEC="standard"
-    - os: osx
-      osx_image: xcode7.3
-      env: VALIDATOR_SUBSPEC="standalone"
+    - env: VALIDATOR_SUBSPEC="none"
+    - env: VALIDATOR_SUBSPEC="standard"
+    - env: VALIDATOR_SUBSPEC="standalone"
 before_install:
   - gem install xcpretty --no-document
 script:
diff --git a/Makefile b/Makefile
index 35edf493..2f085b6c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 BUILD_TOOL = xcodebuild
 BUILD_SCHEME = SQLite Mac
-IOS_SIMULATOR = iPhone 6
+IOS_SIMULATOR = iPhone SE
 ifeq ($(BUILD_SCHEME),SQLite iOS)
 	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -destination "platform=iOS Simulator,name=$(IOS_SIMULATOR)"
 else

From f8209be2fad7c88e41210e742a57a80338ff8a17 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 17 Sep 2016 17:37:07 +0100
Subject: [PATCH 076/685] Set swift version in podspec

---
 SQLite.swift.podspec | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 89cffff1..b7a09bc1 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -26,7 +26,7 @@ Pod::Spec.new do |s|
   s.watchos.deployment_target = "2.0"
   s.default_subspec  = 'standard'
   s.pod_target_xcconfig = {
-    'SWIFT_VERSION' => '2.3',
+    'SWIFT_VERSION' => '3.0',
   }
 
   s.subspec 'standard' do |ss|

From 33f712dc30571fd631175675a8aecf604f612eaa Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 17 Sep 2016 17:57:51 +0100
Subject: [PATCH 077/685] Set iOS simulator

---
 .travis.yml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/.travis.yml b/.travis.yml
index ada13822..d280766b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,9 @@
 language: objective-c
 rvm: 2.2
 osx_image: xcode8
+env:
+  global:
+    - IOS_SIMULATOR="iPhone SE"
 matrix:
   include:
     - env: BUILD_SCHEME="SQLite iOS"

From 183726692204ba437541ea378ad90c99644472db Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 20 Sep 2016 10:48:58 +0100
Subject: [PATCH 078/685] Swift3 enum casing

---
 Documentation/Index.md            | 34 +++++++++++++++----------------
 SQLite/Core/Connection.swift      |  8 ++++----
 SQLite/Typed/Query.swift          | 20 +++++++++---------
 SQLite/Typed/Schema.swift         | 12 +++++------
 SQLiteTests/ConnectionTests.swift |  6 +++---
 SQLiteTests/QueryTests.swift      | 10 ++++-----
 SQLiteTests/SchemaTests.swift     |  2 +-
 7 files changed, 46 insertions(+), 46 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 0579e6f3..3063d095 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -192,7 +192,7 @@ On iOS, you can create a writable database in your app’s **Documents** directo
 
 ``` swift
 let path = NSSearchPathForDirectoriesInDomains(
-    .DocumentDirectory, .UserDomainMask, true
+    .documentDirectory, .userDomainMask, true
 ).first!
 
 let db = try Connection("\(path)/db.sqlite3")
@@ -202,7 +202,7 @@ On OS X, you can use your app’s **Application Support** directory:
 
 ``` swift
 var path = NSSearchPathForDirectoriesInDomains(
-    .ApplicationSupportDirectory, .UserDomainMask, true
+    .applicationSupportDirectory, .userDomainMask, true
 ).first! + NSBundle.mainBundle().bundleIdentifier!
 
 // create parent directory iff it doesn’t exist
@@ -225,7 +225,7 @@ let db = try Connection(path, readonly: true)
 ```
 
 > _Note:_ Signed applications cannot modify their bundle resources. If you bundle a database file with your app for the purpose of bootstrapping, copy it to a writable location _before_ establishing a connection (see [Read-Write Databases](#read-write-databases), above, for typical, writable locations).
-> 
+>
 > See these two Stack Overflow questions for more information about iOS apps with SQLite databases: [1](https://stackoverflow.com/questions/34609746/what-different-between-store-database-in-different-locations-in-ios), [2](https://stackoverflow.com/questions/34614968/ios-how-to-copy-pre-seeded-database-at-the-first-running-app-with-sqlite-swift). We welcome sample code to show how to successfully copy and use a bundled "seed" database for writing in an app.
 
 #### In-Memory Databases
@@ -233,13 +233,13 @@ let db = try Connection(path, readonly: true)
 If you omit the path, SQLite.swift will provision an [in-memory database](https://www.sqlite.org/inmemorydb.html).
 
 ``` swift
-let db = try Connection() // equivalent to `Connection(.InMemory)`
+let db = try Connection() // equivalent to `Connection(.inMemory)`
 ```
 
 To create a temporary, disk-backed database, pass an empty file name.
 
 ``` swift
-let db = try Connection(.Temporary)
+let db = try Connection(.temporary)
 ```
 
 In-memory databases are automatically deleted when the database connection is closed.
@@ -367,7 +367,7 @@ The `column` function is used for a single column definition. It takes an [expre
     t.column(id, primaryKey: true)
     // "id" INTEGER PRIMARY KEY NOT NULL
 
-    t.column(id, primaryKey: .Autoincrement)
+    t.column(id, primaryKey: .autoincrement)
     // "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL
     ```
 
@@ -375,7 +375,7 @@ The `column` function is used for a single column definition. It takes an [expre
     >
     > Primary keys cannot be optional (_e.g._, `Expression<Int64?>`).
     >
-    > Only an `INTEGER PRIMARY KEY` can take `.Autoincrement`.
+    > Only an `INTEGER PRIMARY KEY` can take `.autoincrement`.
 
   - `unique` adds a `UNIQUE` constraint to the column. (See the `unique` function under [Table Constraints](#table-constraints) for uniqueness over multiple columns).
 
@@ -403,10 +403,10 @@ The `column` function is used for a single column definition. It takes an [expre
   - `collate` adds a `COLLATE` clause to `Expression<String>` (and `Expression<String?>`) column definitions with [a collating sequence](https://www.sqlite.org/datatype3.html#collation) defined in the `Collation` enumeration.
 
     ``` swift
-    t.column(email, collate: .Nocase)
+    t.column(email, collate: .nocase)
     // "email" TEXT NOT NULL COLLATE "NOCASE"
 
-    t.column(name, collate: .Rtrim)
+    t.column(name, collate: .rtrim)
     // "name" TEXT COLLATE "RTRIM"
     ```
 
@@ -454,7 +454,7 @@ Additional constraints may be provided outside the scope of a single column usin
   - `foreignKey` adds a `FOREIGN KEY` constraint to the table. Unlike [the `references` constraint, above](#column-constraints), it supports all SQLite types, both [`ON UPDATE` and `ON DELETE` actions](https://www.sqlite.org/foreignkeys.html#fk_actions), and composite (multiple column) keys.
 
     ``` swift
-    t.foreignKey(user_id, references: users, id, delete: .SetNull)
+    t.foreignKey(user_id, references: users, id, delete: .setNull)
     // FOREIGN KEY("user_id") REFERENCES "users"("id") ON DELETE SET NULL
     ```
 
@@ -471,7 +471,7 @@ We can insert rows into a table by calling a [query’s](#queries) `insert` func
 try db.run(users.insert(email <- "alice@mac.com", name <- "Alice"))
 // INSERT INTO "users" ("email", "name") VALUES ('alice@mac.com', 'Alice')
 
-try db.run(users.insert(or: .Replace, email <- "alice@mac.com", name <- "Alice B."))
+try db.run(users.insert(or: .replace, email <- "alice@mac.com", name <- "Alice B."))
 // INSERT OR REPLACE INTO "users" ("email", "name") VALUES ('alice@mac.com', 'Alice B.')
 ```
 
@@ -637,7 +637,7 @@ users.join(posts, on: user_id == users[id])
 // SELECT * FROM "users" INNER JOIN "posts" ON ("user_id" = "users"."id")
 ```
 
-The `join` function takes a [query](#queries) object (for the table being joined on), a join condition (`on`), and is prefixed with an optional join type (default: `.Inner`). Join conditions can be built using [filter operators and functions](#filter-operators-and-functions), generally require [namespacing](#column-namespacing), and sometimes require [aliasing](#table-aliasing).
+The `join` function takes a [query](#queries) object (for the table being joined on), a join condition (`on`), and is prefixed with an optional join type (default: `.inner`). Join conditions can be built using [filter operators and functions](#filter-operators-and-functions), generally require [namespacing](#column-namespacing), and sometimes require [aliasing](#table-aliasing).
 
 
 ##### Column Namespacing
@@ -996,10 +996,10 @@ The `addColumn` function shares several of the same [`column` function parameter
   - `collate` adds a `COLLATE` clause to `Expression<String>` (and `Expression<String?>`) column definitions with [a collating sequence](https://www.sqlite.org/datatype3.html#collation) defined in the `Collation` enumeration.
 
     ``` swift
-    try db.run(users.addColumn(email, collate: .Nocase))
+    try db.run(users.addColumn(email, collate: .nocase))
     // ALTER TABLE "users" ADD COLUMN "email" TEXT NOT NULL COLLATE "NOCASE"
 
-    try db.run(users.addColumn(name, collate: .Rtrim))
+    try db.run(users.addColumn(name, collate: .rtrim))
     // ALTER TABLE "users" ADD COLUMN "name" TEXT COLLATE "RTRIM"
     ```
 
@@ -1367,14 +1367,14 @@ We can create custom collating sequences by calling `createCollation` on a datab
 
 ``` swift
 try db.createCollation("NODIACRITIC") { lhs, rhs in
-    return lhs.compare(rhs, options: .DiacriticInsensitiveSearch)
+    return lhs.compare(rhs, options: .diacriticInsensitiveSearch)
 }
 ```
 
 We can reference a custom collation using the `Custom` member of the `Collation` enumeration.
 
 ``` swift
-restaurants.order(collate(.Custom("NODIACRITIC"), name))
+restaurants.order(collate(.custom("NODIACRITIC"), name))
 // SELECT * FROM "restaurants" ORDER BY "name" COLLATE "NODIACRITIC"
 ```
 
@@ -1409,7 +1409,7 @@ let config = FTS4Config()
     .column(subject)
     .column(body, [.unindexed])
     .languageId("lid")
-    .order(.Desc)
+    .order(.desc)
 
 try db.run(emails.create(.FTS4(config))
 // CREATE VIRTUAL TABLE "emails" USING fts4("subject", "body", notindexed="body", languageid="lid", order="desc")
diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index 832910ba..5acc44d2 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -274,13 +274,13 @@ public final class Connection {
     public enum TransactionMode : String {
 
         /// Defers locking the database till the first read/write executes.
-        case Deferred = "DEFERRED"
+        case deferred = "DEFERRED"
 
         /// Immediately acquires a reserved lock on the database.
-        case Immediate = "IMMEDIATE"
+        case immediate = "IMMEDIATE"
 
         /// Immediately acquires an exclusive lock on all databases.
-        case Exclusive = "EXCLUSIVE"
+        case exclusive = "EXCLUSIVE"
 
     }
 
@@ -301,7 +301,7 @@ public final class Connection {
     ///     must throw to roll the transaction back.
     ///
     /// - Throws: `Result.Error`, and rethrows.
-    public func transaction(_ mode: TransactionMode = .Deferred, block: @escaping () throws -> Void) throws {
+    public func transaction(_ mode: TransactionMode = .deferred, block: @escaping () throws -> Void) throws {
         try transaction("BEGIN \(mode.rawValue) TRANSACTION", block, "COMMIT TRANSACTION", or: "ROLLBACK TRANSACTION")
     }
 
diff --git a/SQLite/Typed/Query.swift b/SQLite/Typed/Query.swift
index d0e4572d..0e54392b 100644
--- a/SQLite/Typed/Query.swift
+++ b/SQLite/Typed/Query.swift
@@ -221,7 +221,7 @@ extension QueryType {
     ///
     /// - Returns: A query with the given `JOIN` clause applied.
     public func join(_ table: QueryType, on condition: Expression<Bool?>) -> Self {
-        return join(.Inner, table, on: condition)
+        return join(.inner, table, on: condition)
     }
 
     /// Adds a `JOIN` clause to the query.
@@ -401,7 +401,7 @@ extension QueryType {
     public func order(_ by: Expressible...) -> Self {
         return order(by)
     }
-    
+
     /// Sets an `ORDER BY` clause on the query.
     ///
     ///     let users = Table("users")
@@ -1100,28 +1100,28 @@ public struct Row {
 public enum JoinType : String {
 
     /// A `CROSS` join.
-    case Cross = "CROSS"
+    case cross = "CROSS"
 
     /// An `INNER` join.
-    case Inner = "INNER"
+    case inner = "INNER"
 
     /// A `LEFT OUTER` join.
-    case LeftOuter = "LEFT OUTER"
+    case leftOuter = "LEFT OUTER"
 
 }
 
 /// ON CONFLICT resolutions.
 public enum OnConflict: String {
 
-    case Replace = "REPLACE"
+    case replace = "REPLACE"
 
-    case Rollback = "ROLLBACK"
+    case rollback = "ROLLBACK"
 
-    case Abort = "ABORT"
+    case abort = "ABORT"
 
-    case Fail = "FAIL"
+    case fail = "FAIL"
 
-    case Ignore = "IGNORE"
+    case ignore = "IGNORE"
 
 }
 
diff --git a/SQLite/Typed/Schema.swift b/SQLite/Typed/Schema.swift
index 4c6862c0..1388170e 100644
--- a/SQLite/Typed/Schema.swift
+++ b/SQLite/Typed/Schema.swift
@@ -369,16 +369,16 @@ public final class TableBuilder {
 
     public enum Dependency: String {
 
-        case NoAction = "NO ACTION"
+        case noAction = "NO ACTION"
 
-        case Restrict = "RESTRICT"
+        case restrict = "RESTRICT"
 
-        case SetNull = "SET NULL"
+        case setNull = "SET NULL"
 
-        case SetDefault = "SET DEFAULT"
+        case setDefault = "SET DEFAULT"
+
+        case cascade = "CASCADE"
 
-        case Cascade = "CASCADE"
-        
     }
 
     public func foreignKey<T : Value>(_ column: Expression<T>, references table: QueryType, _ other: Expression<T>, update: Dependency? = nil, delete: Dependency? = nil) {
diff --git a/SQLiteTests/ConnectionTests.swift b/SQLiteTests/ConnectionTests.swift
index 0e8ebea6..c217eac7 100644
--- a/SQLiteTests/ConnectionTests.swift
+++ b/SQLiteTests/ConnectionTests.swift
@@ -95,19 +95,19 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_transaction_executesBeginDeferred() {
-        try! db.transaction(.Deferred) {}
+        try! db.transaction(.deferred) {}
 
         AssertSQL("BEGIN DEFERRED TRANSACTION")
     }
 
     func test_transaction_executesBeginImmediate() {
-        try! db.transaction(.Immediate) {}
+        try! db.transaction(.immediate) {}
 
         AssertSQL("BEGIN IMMEDIATE TRANSACTION")
     }
 
     func test_transaction_executesBeginExclusive() {
-        try! db.transaction(.Exclusive) {}
+        try! db.transaction(.exclusive) {}
 
         AssertSQL("BEGIN EXCLUSIVE TRANSACTION")
     }
diff --git a/SQLiteTests/QueryTests.swift b/SQLiteTests/QueryTests.swift
index df2ff073..ed34921e 100644
--- a/SQLiteTests/QueryTests.swift
+++ b/SQLiteTests/QueryTests.swift
@@ -20,11 +20,11 @@ class QueryTests : XCTestCase {
     func test_select_withExpression_compilesSelectClause() {
         AssertSQL("SELECT \"email\" FROM \"users\"", users.select(email))
     }
-    
+
     func test_select_withStarExpression_compilesSelectClause() {
         AssertSQL("SELECT * FROM \"users\"", users.select(*))
     }
-    
+
     func test_select_withNamespacedStarExpression_compilesSelectClause() {
         AssertSQL("SELECT \"users\".* FROM \"users\"", users.select(users[*]))
     }
@@ -59,12 +59,12 @@ class QueryTests : XCTestCase {
     func test_join_withExplicitType_compilesJoinClauseWithType() {
         AssertSQL(
             "SELECT * FROM \"users\" LEFT OUTER JOIN \"posts\" ON (\"posts\".\"user_id\" = \"users\".\"id\")",
-            users.join(.LeftOuter, posts, on: posts[userId] == users[id])
+            users.join(.leftOuter, posts, on: posts[userId] == users[id])
         )
 
         AssertSQL(
             "SELECT * FROM \"users\" CROSS JOIN \"posts\" ON (\"posts\".\"user_id\" = \"users\".\"id\")",
-            users.join(.Cross, posts, on: posts[userId] == users[id])
+            users.join(.cross, posts, on: posts[userId] == users[id])
         )
     }
 
@@ -192,7 +192,7 @@ class QueryTests : XCTestCase {
     func test_insert_withOnConflict_compilesInsertOrOnConflictExpression() {
         AssertSQL(
             "INSERT OR REPLACE INTO \"users\" (\"email\", \"age\") VALUES ('alice@example.com', 30)",
-            users.insert(or: .Replace, email <- "alice@example.com", age <- 30)
+            users.insert(or: .replace, email <- "alice@example.com", age <- 30)
         )
     }
 
diff --git a/SQLiteTests/SchemaTests.swift b/SQLiteTests/SchemaTests.swift
index 01bedda0..371459c7 100644
--- a/SQLiteTests/SchemaTests.swift
+++ b/SQLiteTests/SchemaTests.swift
@@ -568,7 +568,7 @@ class SchemaTests : XCTestCase {
 
         XCTAssertEqual(
             "CREATE TABLE \"table\" (FOREIGN KEY (\"string\") REFERENCES \"table\" (\"string\") ON UPDATE CASCADE ON DELETE SET NULL)",
-            table.create { t in t.foreignKey(string, references: table, string, update: .Cascade, delete: .SetNull) }
+            table.create { t in t.foreignKey(string, references: table, string, update: .cascade, delete: .setNull) }
         )
 
         XCTAssertEqual(

From 4ed14adaefa1ed308ff949ae5e2cff0dc2b8d4b2 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 20 Sep 2016 11:59:50 +0100
Subject: [PATCH 079/685] Nest Operation inside Connection

---
 SQLite/Core/Connection.swift      | 53 +++++++++++++++----------------
 SQLiteTests/ConnectionTests.swift |  6 ++--
 2 files changed, 29 insertions(+), 30 deletions(-)

diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index 5acc44d2..2a7ba3b0 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -54,6 +54,32 @@ public final class Connection {
         case uri(String)
     }
 
+    /// An SQL operation passed to update callbacks.
+    public enum Operation {
+
+        /// An INSERT operation.
+        case insert
+
+        /// An UPDATE operation.
+        case update
+
+        /// A DELETE operation.
+        case delete
+
+        fileprivate init(rawValue:Int32) {
+            switch rawValue {
+            case SQLITE_INSERT:
+                self = .insert
+            case SQLITE_UPDATE:
+                self = .update
+            case SQLITE_DELETE:
+                self = .delete
+            default:
+                fatalError("unhandled operation code: \(rawValue)")
+            }
+        }
+    }
+
     public var handle: OpaquePointer { return _handle! }
 
     fileprivate var _handle: OpaquePointer? = nil
@@ -638,33 +664,6 @@ extension Connection.Location : CustomStringConvertible {
 
 }
 
-/// An SQL operation passed to update callbacks.
-public enum Operation {
-
-    /// An INSERT operation.
-    case insert
-
-    /// An UPDATE operation.
-    case update
-
-    /// A DELETE operation.
-    case delete
-
-    fileprivate init(rawValue: Int32) {
-        switch rawValue {
-        case SQLITE_INSERT:
-            self = .insert
-        case SQLITE_UPDATE:
-            self = .update
-        case SQLITE_DELETE:
-            self = .delete
-        default:
-            fatalError("unhandled operation code: \(rawValue)")
-        }
-    }
-
-}
-
 public enum Result : Error {
 
     fileprivate static let successCodes: Set = [SQLITE_OK, SQLITE_ROW, SQLITE_DONE]
diff --git a/SQLiteTests/ConnectionTests.swift b/SQLiteTests/ConnectionTests.swift
index c217eac7..4db671ad 100644
--- a/SQLiteTests/ConnectionTests.swift
+++ b/SQLiteTests/ConnectionTests.swift
@@ -192,7 +192,7 @@ class ConnectionTests : SQLiteTestCase {
     func test_updateHook_setsUpdateHook_withInsert() {
         async { done in
             db.updateHook { operation, db, table, rowid in
-                XCTAssertEqual(Operation.insert, operation)
+                XCTAssertEqual(Connection.Operation.insert, operation)
                 XCTAssertEqual("main", db)
                 XCTAssertEqual("users", table)
                 XCTAssertEqual(1, rowid)
@@ -206,7 +206,7 @@ class ConnectionTests : SQLiteTestCase {
         _ = try! InsertUser("alice")
         async { done in
             db.updateHook { operation, db, table, rowid in
-                XCTAssertEqual(Operation.update, operation)
+                XCTAssertEqual(Connection.Operation.update, operation)
                 XCTAssertEqual("main", db)
                 XCTAssertEqual("users", table)
                 XCTAssertEqual(1, rowid)
@@ -220,7 +220,7 @@ class ConnectionTests : SQLiteTestCase {
         _ = try! InsertUser("alice")
         async { done in
             db.updateHook { operation, db, table, rowid in
-                XCTAssertEqual(Operation.delete, operation)
+                XCTAssertEqual(Connection.Operation.delete, operation)
                 XCTAssertEqual("main", db)
                 XCTAssertEqual("users", table)
                 XCTAssertEqual(1, rowid)

From 2c9fd0c1417bec5878226c045ae7ac86b7644bc0 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 6 Oct 2016 22:22:29 +0200
Subject: [PATCH 080/685] Flag methods executed for side-effects to silence
 warnings

---
 SQLite/Core/Connection.swift | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index 2a7ba3b0..04b515c3 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -216,7 +216,7 @@ public final class Connection {
     /// - Throws: `Result.Error` if query execution fails.
     ///
     /// - Returns: The statement.
-    public func run(_ statement: String, _ bindings: Binding?...) throws -> Statement {
+    @discardableResult public func run(_ statement: String, _ bindings: Binding?...) throws -> Statement {
         return try run(statement, bindings)
     }
 
@@ -231,7 +231,7 @@ public final class Connection {
     /// - Throws: `Result.Error` if query execution fails.
     ///
     /// - Returns: The statement.
-    public func run(_ statement: String, _ bindings: [Binding?]) throws -> Statement {
+    @discardableResult public func run(_ statement: String, _ bindings: [Binding?]) throws -> Statement {
         return try prepare(statement).run(bindings)
     }
 
@@ -246,7 +246,7 @@ public final class Connection {
     /// - Throws: `Result.Error` if query execution fails.
     ///
     /// - Returns: The statement.
-    public func run(_ statement: String, _ bindings: [String: Binding?]) throws -> Statement {
+    @discardableResult public func run(_ statement: String, _ bindings: [String: Binding?]) throws -> Statement {
         return try prepare(statement).run(bindings)
     }
 

From 8f8eec7b4c81b7547ee90bb2e51a235c9b02e222 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 7 Oct 2016 12:48:29 +0200
Subject: [PATCH 081/685] Add tests for Blob initializer

---
 SQLiteTests/BlobTests.swift | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/SQLiteTests/BlobTests.swift b/SQLiteTests/BlobTests.swift
index ba0a7c54..fbcca9bc 100644
--- a/SQLiteTests/BlobTests.swift
+++ b/SQLiteTests/BlobTests.swift
@@ -9,4 +9,15 @@ class BlobTests : XCTestCase {
         XCTAssertEqual(blob.toHex(), "000a141e28323c46505a6496faff")
     }
 
+    func test_init_array() {
+        let blob = Blob(bytes: [42, 42, 42])
+        XCTAssertEqual(blob.bytes, [42, 42, 42])
+    }
+
+    func test_init_unsafeRawPointer() {
+        let pointer = UnsafeMutablePointer<UInt8>.allocate(capacity: 3)
+        pointer.initialize(to: 42, count: 3)
+        let blob = Blob(bytes: pointer, length: 3)
+        XCTAssertEqual(blob.bytes, [42, 42, 42])
+    }
 }

From b6941cda744c6cb163180eb5c8dead1fa76d6c77 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 7 Oct 2016 15:03:53 +0200
Subject: [PATCH 082/685] Add more tests for blob handling

---
 SQLite.xcodeproj/project.pbxproj  |  8 ++++++++
 SQLite/Core/Blob.swift            |  1 -
 SQLite/Core/Statement.swift       |  9 ++++++---
 SQLite/Foundation.swift           |  6 +++---
 SQLiteTests/FoundationTests.swift | 16 ++++++++++++++++
 SQLiteTests/StatementTests.swift  | 14 +++++++++++++-
 6 files changed, 46 insertions(+), 8 deletions(-)
 create mode 100644 SQLiteTests/FoundationTests.swift

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index aa951fd8..4dddeaaf 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -51,7 +51,10 @@
 		19A17254FBA7894891F7297B /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
 		19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
 		19A1750CEE9B05267995CF3D /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
+		19A178072B371489E6A1E839 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
+		19A17E04C4C0956715C5676A /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
 		19A17EC0D68BA8C03288ADF7 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
+		19A17FB80B94E882050AA908 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
 		EE247AD71C3F04ED00AE3E12 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		EE247ADE1C3F04ED00AE3E12 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE247AD31C3F04ED00AE3E12 /* SQLite.framework */; };
 		EE247B031C3F06E900AE3E12 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
@@ -162,6 +165,7 @@
 		03A65E961C6BB3210062603F /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
 		19A1721B8984686B9963B45D /* FTS5Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5Tests.swift; sourceTree = "<group>"; };
 		19A1730E4390C775C25677D1 /* FTS5.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5.swift; sourceTree = "<group>"; };
+		19A1794CC4D7827E997E32A7 /* FoundationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationTests.swift; sourceTree = "<group>"; };
 		39548A631CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
 		39548A651CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
 		39548A671CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
@@ -415,6 +419,7 @@
 				EE247B161C3F127200AE3E12 /* TestHelpers.swift */,
 				EE247AE41C3F04ED00AE3E12 /* Info.plist */,
 				19A1721B8984686B9963B45D /* FTS5Tests.swift */,
+				19A1794CC4D7827E997E32A7 /* FoundationTests.swift */,
 			);
 			path = SQLiteTests;
 			sourceTree = "<group>";
@@ -824,6 +829,7 @@
 				03A65E8E1C6BB3030062603F /* OperatorsTests.swift in Sources */,
 				03A65E951C6BB3030062603F /* TestHelpers.swift in Sources */,
 				19A17254FBA7894891F7297B /* FTS5Tests.swift in Sources */,
+				19A17E04C4C0956715C5676A /* FoundationTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -880,6 +886,7 @@
 				EE247B2E1C3F141E00AE3E12 /* OperatorsTests.swift in Sources */,
 				EE247B251C3F137700AE3E12 /* ConnectionTests.swift in Sources */,
 				19A171E6FA242F72A308C594 /* FTS5Tests.swift in Sources */,
+				19A17FB80B94E882050AA908 /* FoundationTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -929,6 +936,7 @@
 				EE247B5E1C3F3FC700AE3E12 /* SetterTests.swift in Sources */,
 				EE247B5B1C3F3FC700AE3E12 /* QueryTests.swift in Sources */,
 				19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */,
+				19A178072B371489E6A1E839 /* FoundationTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/SQLite/Core/Blob.swift b/SQLite/Core/Blob.swift
index 45d6604a..2f5d2a14 100644
--- a/SQLite/Core/Blob.swift
+++ b/SQLite/Core/Blob.swift
@@ -31,7 +31,6 @@ public struct Blob {
     }
 
     public init(bytes: UnsafeRawPointer, length: Int) {
-        // TODO correct count
         let i8bufptr = UnsafeBufferPointer(start: bytes.assumingMemoryBound(to: UInt8.self), count: length)
         self.init(bytes: [UInt8](i8bufptr))
     }
diff --git a/SQLite/Core/Statement.swift b/SQLite/Core/Statement.swift
index 01720433..f0c05bb8 100644
--- a/SQLite/Core/Statement.swift
+++ b/SQLite/Core/Statement.swift
@@ -238,9 +238,12 @@ public struct Cursor {
     }
 
     public subscript(idx: Int) -> Blob {
-        let bytes = sqlite3_column_blob(handle, Int32(idx))
-        let length = Int(sqlite3_column_bytes(handle, Int32(idx)))
-        return Blob(bytes: bytes!, length: length)
+        if let pointer = sqlite3_column_blob(handle, Int32(idx)) {
+            let length = Int(sqlite3_column_bytes(handle, Int32(idx)))
+            return Blob(bytes: pointer, length: length)
+        } else {
+            fatalError("sqlite3_column_blob returned NULL")
+        }
     }
 
     // MARK: -
diff --git a/SQLite/Foundation.swift b/SQLite/Foundation.swift
index 5c266a05..5e102297 100644
--- a/SQLite/Foundation.swift
+++ b/SQLite/Foundation.swift
@@ -31,12 +31,12 @@ extension Data : Value {
     }
 
     public static func fromDatatypeValue(_ dataValue: Blob) -> Data {
-        return Data(bytes: UnsafePointer<UInt8>(dataValue.bytes), count: dataValue.bytes.count)
+        return Data(bytes: dataValue.bytes)
     }
 
     public var datatypeValue: Blob {
-        return withUnsafeBytes { ptr -> Blob in
-            return Blob(bytes: ptr, length: count)
+        return withUnsafeBytes { (pointer: UnsafePointer<UInt8>) -> Blob in
+            return Blob(bytes: pointer, length: count)
         }
     }
 
diff --git a/SQLiteTests/FoundationTests.swift b/SQLiteTests/FoundationTests.swift
new file mode 100644
index 00000000..0df746d9
--- /dev/null
+++ b/SQLiteTests/FoundationTests.swift
@@ -0,0 +1,16 @@
+import XCTest
+import SQLite
+
+class FoundationTests : XCTestCase {
+    func testDataFromBlob() {
+        let data = Data(bytes: [1, 2, 3])
+        let blob = data.datatypeValue
+        XCTAssertEqual([1, 2, 3], blob.bytes)
+    }
+
+    func testBlobToData() {
+        let blob = Blob(bytes: [1, 2, 3])
+        let data = Data.fromDatatypeValue(blob)
+        XCTAssertEqual(Data(bytes: [1, 2, 3]), data)
+    }
+}
diff --git a/SQLiteTests/StatementTests.swift b/SQLiteTests/StatementTests.swift
index 5965929c..fce3585c 100644
--- a/SQLiteTests/StatementTests.swift
+++ b/SQLiteTests/StatementTests.swift
@@ -1,5 +1,17 @@
 import XCTest
 import SQLite
 
-class StatementTests : XCTestCase {
+class StatementTests : SQLiteTestCase {
+    override func setUp() {
+        super.setUp()
+        CreateUsersTable()
+    }
+
+    func test_cursor_to_blob() {
+        try! InsertUsers("alice")
+        let statement = try! db.prepare("SELECT email FROM users")
+        XCTAssert(try! statement.step())
+        let blob = statement.row[0] as Blob
+        XCTAssertEqual("alice@example.com", String(bytes: blob.bytes, encoding: .utf8)!)
+    }
 }

From f7d017d858a6e0dc5b5bbc81974d3caca04b619c Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 8 Oct 2016 13:44:47 +0200
Subject: [PATCH 083/685] use @discardableResult

---
 SQLite/Core/Connection.swift      | 12 +++----
 SQLite/Core/Statement.swift       |  8 ++---
 SQLite/Extensions/FTS4.swift      | 28 +++++++--------
 SQLite/Extensions/FTS5.swift      |  6 ++--
 SQLite/Typed/Query.swift          |  6 ++--
 SQLiteTests/ConnectionTests.swift | 58 +++++++++++++++----------------
 SQLiteTests/FTS4Tests.swift       |  4 +--
 SQLiteTests/TestHelpers.swift     |  6 ++--
 8 files changed, 64 insertions(+), 64 deletions(-)

diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index 04b515c3..bd4cafb3 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -100,7 +100,7 @@ public final class Connection {
     /// - Returns: A new database connection.
     public init(_ location: Location = .inMemory, readonly: Bool = false) throws {
         let flags = readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE
-        _ = try check(sqlite3_open_v2(location.description, &_handle, flags | SQLITE_OPEN_FULLMUTEX, nil))
+        try check(sqlite3_open_v2(location.description, &_handle, flags | SQLITE_OPEN_FULLMUTEX, nil))
         queue.setSpecific(key: /*Migrator FIXME: Use a variable of type DispatchSpecificKey*/ Connection.queueKey, value: queueContext)
     }
 
@@ -356,14 +356,14 @@ public final class Connection {
 
     fileprivate func transaction(_ begin: String, _ block: @escaping () throws -> Void, _ commit: String, or rollback: String) throws {
         return try sync {
-            _ = try self.run(begin)
+            try self.run(begin)
             do {
                 try block()
             } catch {
-                _ = try self.run(rollback)
+                try self.run(rollback)
                 throw error
             }
-            _ = try self.run(commit)
+            try self.run(commit)
         }
     }
 
@@ -590,7 +590,7 @@ public final class Connection {
             let rstr = String(cString: rhs.bindMemory(to: UInt8.self, capacity: 0))
             return Int32(Int(block(lstr, rstr).rawValue))
         }
-        _ = try check(sqlite3_create_collation_v2(handle, collation, SQLITE_UTF8, unsafeBitCast(box, to: UnsafeMutableRawPointer.self), { callback, _, lhs, _, rhs in
+        try check(sqlite3_create_collation_v2(handle, collation, SQLITE_UTF8, unsafeBitCast(box, to: UnsafeMutableRawPointer.self), { callback, _, lhs, _, rhs in
             unsafeBitCast(callback, to: Collation.self)(lhs!, rhs!)
         }, nil))
         collations[collation] = box
@@ -625,7 +625,7 @@ public final class Connection {
         return success!
     }
 
-    func check(_ resultCode: Int32, statement: Statement? = nil) throws -> Int32 {
+    @discardableResult func check(_ resultCode: Int32, statement: Statement? = nil) throws -> Int32 {
         guard let error = Result(errorCode: resultCode, connection: self, statement: statement) else {
             return resultCode
         }
diff --git a/SQLite/Core/Statement.swift b/SQLite/Core/Statement.swift
index f0c05bb8..a7664993 100644
--- a/SQLite/Core/Statement.swift
+++ b/SQLite/Core/Statement.swift
@@ -37,7 +37,7 @@ public final class Statement {
 
     init(_ connection: Connection, _ SQL: String) throws {
         self.connection = connection
-        _ = try connection.check(sqlite3_prepare_v2(connection.handle, SQL, -1, &handle, nil))
+        try connection.check(sqlite3_prepare_v2(connection.handle, SQL, -1, &handle, nil))
     }
 
     deinit {
@@ -120,7 +120,7 @@ public final class Statement {
     /// - Throws: `Result.Error` if query execution fails.
     ///
     /// - Returns: The statement object (useful for chaining).
-    public func run(_ bindings: Binding?...) throws -> Statement {
+    @discardableResult public func run(_ bindings: Binding?...) throws -> Statement {
         guard bindings.isEmpty else {
             return try run(bindings)
         }
@@ -135,7 +135,7 @@ public final class Statement {
     /// - Throws: `Result.Error` if query execution fails.
     ///
     /// - Returns: The statement object (useful for chaining).
-    public func run(_ bindings: [Binding?]) throws -> Statement {
+    @discardableResult public func run(_ bindings: [Binding?]) throws -> Statement {
         return try bind(bindings).run()
     }
 
@@ -145,7 +145,7 @@ public final class Statement {
     /// - Throws: `Result.Error` if query execution fails.
     ///
     /// - Returns: The statement object (useful for chaining).
-    public func run(_ bindings: [String: Binding?]) throws -> Statement {
+    @discardableResult public func run(_ bindings: [String: Binding?]) throws -> Statement {
         return try bind(bindings).run()
     }
 
diff --git a/SQLite/Extensions/FTS4.swift b/SQLite/Extensions/FTS4.swift
index bd8c7b2d..ecaf2507 100644
--- a/SQLite/Extensions/FTS4.swift
+++ b/SQLite/Extensions/FTS4.swift
@@ -141,7 +141,7 @@ extension Tokenizer : CustomStringConvertible {
 extension Connection {
 
     public func registerTokenizer(_ submoduleName: String, next: @escaping (String) -> (String, Range<String.Index>)?) throws {
-        _ = try check(_SQLiteRegisterTokenizer(handle, Tokenizer.moduleName, submoduleName) { input, offset, length in
+        try check(_SQLiteRegisterTokenizer(handle, Tokenizer.moduleName, submoduleName) { input, offset, length in
             let string = String(cString: input)
 
             guard let (token, range) = next(string) else { return nil }
@@ -178,7 +178,7 @@ open class FTSConfig {
 
     open func columns(_ columns: [Expressible]) -> Self {
         for column in columns {
-            _ = self.column(column)
+            self.column(column)
         }
         return self
     }
@@ -217,15 +217,15 @@ open class FTSConfig {
 
     func options() -> Options {
         var options = Options()
-        _ = options.append(formatColumnDefinitions())
+        options.append(formatColumnDefinitions())
         if let tokenizer = tokenizer {
-            _ = options.append("tokenize", value: Expression<Void>(literal: tokenizer.description))
+            options.append("tokenize", value: Expression<Void>(literal: tokenizer.description))
         }
-        _ = options.appendCommaSeparated("prefix", values:prefixes.sorted().map { String($0) })
+        options.appendCommaSeparated("prefix", values:prefixes.sorted().map { String($0) })
         if isContentless {
-            _ = options.append("content", value: "")
+            options.append("content", value: "")
         } else if let externalContentSchema = externalContentSchema {
-            _ = options.append("content", value: externalContentSchema.tableName())
+            options.append("content", value: externalContentSchema.tableName())
         }
         return options
     }
@@ -238,7 +238,7 @@ open class FTSConfig {
             return self
         }
 
-        mutating func appendCommaSeparated(_ key: String, values: [String]) -> Options {
+        @discardableResult mutating func appendCommaSeparated(_ key: String, values: [String]) -> Options {
             if values.isEmpty {
                 return self
             } else {
@@ -246,7 +246,7 @@ open class FTSConfig {
             }
         }
 
-        mutating func append(_ key: String, value: CustomStringConvertible?) -> Options {
+        @discardableResult mutating func append(_ key: String, value: CustomStringConvertible?) -> Options {
             return append(key, value: value?.description)
         }
 
@@ -332,11 +332,11 @@ open class FTS4Config : FTSConfig {
         for (column, _) in (columnDefinitions.filter { $0.options.contains(.unindexed) }) {
             options.append("notindexed", value: column)
         }
-        _ = options.append("languageid", value: languageId)
-        _ = options.append("compress", value: compressFunction)
-        _ = options.append("uncompress", value: uncompressFunction)
-        _ = options.append("matchinfo", value: matchInfo)
-        _ = options.append("order", value: order)
+        options.append("languageid", value: languageId)
+        options.append("compress", value: compressFunction)
+        options.append("uncompress", value: uncompressFunction)
+        options.append("matchinfo", value: matchInfo)
+        options.append("order", value: order)
         return options
     }
 }
diff --git a/SQLite/Extensions/FTS5.swift b/SQLite/Extensions/FTS5.swift
index 9204d5b2..763927ff 100644
--- a/SQLite/Extensions/FTS5.swift
+++ b/SQLite/Extensions/FTS5.swift
@@ -77,11 +77,11 @@ open class FTS5Config : FTSConfig {
 
     override func options() -> Options {
         var options = super.options()
-        _ = options.append("content_rowid", value: contentRowId)
+        options.append("content_rowid", value: contentRowId)
         if let columnSize = columnSize {
-            _ = options.append("columnsize", value: Expression<Int>(value: columnSize))
+            options.append("columnsize", value: Expression<Int>(value: columnSize))
         }
-        _ = options.append("detail", value: detail)
+        options.append("detail", value: detail)
         return options
     }
 
diff --git a/SQLite/Typed/Query.swift b/SQLite/Typed/Query.swift
index 0e54392b..af6549de 100644
--- a/SQLite/Typed/Query.swift
+++ b/SQLite/Typed/Query.swift
@@ -971,7 +971,7 @@ extension Connection {
     public func run(_ query: Insert) throws -> Int64 {
         let expression = query.expression
         return try sync {
-            _ = try self.run(expression.template, expression.bindings)
+            try self.run(expression.template, expression.bindings)
             return self.lastInsertRowid!
         }
     }
@@ -987,7 +987,7 @@ extension Connection {
     public func run(_ query: Update) throws -> Int {
         let expression = query.expression
         return try sync {
-            _ = try self.run(expression.template, expression.bindings)
+            try self.run(expression.template, expression.bindings)
             return self.changes
         }
     }
@@ -1002,7 +1002,7 @@ extension Connection {
     public func run(_ query: Delete) throws -> Int {
         let expression = query.expression
         return try sync {
-            _ = try self.run(expression.template, expression.bindings)
+            try self.run(expression.template, expression.bindings)
             return self.changes
         }
     }
diff --git a/SQLiteTests/ConnectionTests.swift b/SQLiteTests/ConnectionTests.swift
index 4db671ad..3eb2b915 100644
--- a/SQLiteTests/ConnectionTests.swift
+++ b/SQLiteTests/ConnectionTests.swift
@@ -48,7 +48,7 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_lastInsertRowid_returnsLastIdAfterInserts() {
-        _ = try! InsertUser("alice")
+        try! InsertUser("alice")
         XCTAssertEqual(1, db.lastInsertRowid!)
     }
 
@@ -57,17 +57,17 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_changes_returnsNumberOfChanges() {
-        _ = try! InsertUser("alice")
+        try! InsertUser("alice")
         XCTAssertEqual(1, db.changes)
-        _ = try! InsertUser("betsy")
+        try! InsertUser("betsy")
         XCTAssertEqual(1, db.changes)
     }
 
     func test_totalChanges_returnsTotalNumberOfChanges() {
         XCTAssertEqual(0, db.totalChanges)
-        _ = try! InsertUser("alice")
+        try! InsertUser("alice")
         XCTAssertEqual(1, db.totalChanges)
-        _ = try! InsertUser("betsy")
+        try! InsertUser("betsy")
         XCTAssertEqual(2, db.totalChanges)
     }
 
@@ -79,10 +79,10 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_run_preparesRunsAndReturnsStatements() {
-        _ = try! db.run("SELECT * FROM users WHERE admin = 0")
-        _ = try! db.run("SELECT * FROM users WHERE admin = ?", 0)
-        _ = try! db.run("SELECT * FROM users WHERE admin = ?", [0])
-        _ = try! db.run("SELECT * FROM users WHERE admin = $admin", ["$admin": 0])
+        try! db.run("SELECT * FROM users WHERE admin = 0")
+        try! db.run("SELECT * FROM users WHERE admin = ?", 0)
+        try! db.run("SELECT * FROM users WHERE admin = ?", [0])
+        try! db.run("SELECT * FROM users WHERE admin = $admin", ["$admin": 0])
         AssertSQL("SELECT * FROM users WHERE admin = 0", 4)
     }
 
@@ -116,7 +116,7 @@ class ConnectionTests : SQLiteTestCase {
         let stmt = try! db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com")
 
         try! db.transaction {
-            _ = try stmt.run()
+            try stmt.run()
         }
 
         AssertSQL("BEGIN DEFERRED TRANSACTION")
@@ -130,8 +130,8 @@ class ConnectionTests : SQLiteTestCase {
 
         do {
             try db.transaction {
-                _ = try stmt.run()
-                _ = try stmt.run()
+                try stmt.run()
+                try stmt.run()
             }
         } catch {
         }
@@ -147,7 +147,7 @@ class ConnectionTests : SQLiteTestCase {
 
         try! db.savepoint("1") {
             try db.savepoint("2") {
-                _ = try db.run("INSERT INTO users (email) VALUES (?)", "alice@example.com")
+                try db.run("INSERT INTO users (email) VALUES (?)", "alice@example.com")
             }
         }
 
@@ -167,14 +167,14 @@ class ConnectionTests : SQLiteTestCase {
         do {
             try db.savepoint("1") {
                 try db.savepoint("2") {
-                    _ = try stmt.run()
-                    _ = try stmt.run()
-                    _ = try stmt.run()
+                    try stmt.run()
+                    try stmt.run()
+                    try stmt.run()
                 }
                 try db.savepoint("2") {
-                    _ = try stmt.run()
-                    _ = try stmt.run()
-                    _ = try stmt.run()
+                    try stmt.run()
+                    try stmt.run()
+                    try stmt.run()
                 }
             }
         } catch {
@@ -198,12 +198,12 @@ class ConnectionTests : SQLiteTestCase {
                 XCTAssertEqual(1, rowid)
                 done()
             }
-            _ = try! InsertUser("alice")
+            try! InsertUser("alice")
         }
     }
 
     func test_updateHook_setsUpdateHook_withUpdate() {
-        _ = try! InsertUser("alice")
+        try! InsertUser("alice")
         async { done in
             db.updateHook { operation, db, table, rowid in
                 XCTAssertEqual(Connection.Operation.update, operation)
@@ -212,12 +212,12 @@ class ConnectionTests : SQLiteTestCase {
                 XCTAssertEqual(1, rowid)
                 done()
             }
-            _ = try! db.run("UPDATE users SET email = 'alice@example.com'")
+            try! db.run("UPDATE users SET email = 'alice@example.com'")
         }
     }
 
     func test_updateHook_setsUpdateHook_withDelete() {
-        _ = try! InsertUser("alice")
+        try! InsertUser("alice")
         async { done in
             db.updateHook { operation, db, table, rowid in
                 XCTAssertEqual(Connection.Operation.delete, operation)
@@ -226,7 +226,7 @@ class ConnectionTests : SQLiteTestCase {
                 XCTAssertEqual(1, rowid)
                 done()
             }
-            _ = try! db.run("DELETE FROM users WHERE id = 1")
+            try! db.run("DELETE FROM users WHERE id = 1")
         }
     }
 
@@ -236,7 +236,7 @@ class ConnectionTests : SQLiteTestCase {
                 done()
             }
             try! db.transaction {
-                _ = try self.InsertUser("alice")
+                try self.InsertUser("alice")
             }
             XCTAssertEqual(1, try! db.scalar("SELECT count(*) FROM users") as? Int64)
         }
@@ -247,8 +247,8 @@ class ConnectionTests : SQLiteTestCase {
             db.rollbackHook(done)
             do {
                 try db.transaction {
-                    _ = try self.InsertUser("alice")
-                    _ = try self.InsertUser("alice") // throw
+                    try self.InsertUser("alice")
+                    try self.InsertUser("alice") // throw
                 }
             } catch {
             }
@@ -264,7 +264,7 @@ class ConnectionTests : SQLiteTestCase {
             db.rollbackHook(done)
             do {
                 try db.transaction {
-                    _ = try self.InsertUser("alice")
+                    try self.InsertUser("alice")
                 }
             } catch {
             }
@@ -308,7 +308,7 @@ class ConnectionTests : SQLiteTestCase {
         }
 
         let stmt = try! db.prepare("SELECT *, sleep(?) FROM users", 0.1)
-        _ = try! stmt.run()
+        try! stmt.run()
 
         _ = DispatchQueue.global(priority: DispatchQueue.GlobalQueuePriority.background).asyncAfter(deadline: DispatchTime.now() + Double(Int64(10 * NSEC_PER_MSEC)) / Double(NSEC_PER_SEC), execute: db.interrupt)
         AssertThrows(try stmt.run())
diff --git a/SQLiteTests/FTS4Tests.swift b/SQLiteTests/FTS4Tests.swift
index 92f197a2..0148efc3 100644
--- a/SQLiteTests/FTS4Tests.swift
+++ b/SQLiteTests/FTS4Tests.swift
@@ -198,10 +198,10 @@ class FTS4IntegrationTests : SQLiteTestCase {
             return (token as String, string.range(of: input as String)!)
         }
 
-        _ = try! db.run(emails.create(.FTS4([subject, body], tokenize: .Custom(tokenizerName))))
+        try! db.run(emails.create(.FTS4([subject, body], tokenize: .Custom(tokenizerName))))
         AssertSQL("CREATE VIRTUAL TABLE \"emails\" USING fts4(\"subject\", \"body\", tokenize=\"SQLite.swift\" \"tokenizer\")")
 
-        _ = try! db.run(emails.insert(subject <- "Aún más cáfe!"))
+        try! db.run(emails.insert(subject <- "Aún más cáfe!"))
         XCTAssertEqual(1, try! db.scalar(emails.filter(emails.match("aun")).count))
     }
 #endif
diff --git a/SQLiteTests/TestHelpers.swift b/SQLiteTests/TestHelpers.swift
index 7b7715b1..8c33bf6a 100644
--- a/SQLiteTests/TestHelpers.swift
+++ b/SQLiteTests/TestHelpers.swift
@@ -37,10 +37,10 @@ class SQLiteTestCase : XCTestCase {
     }
 
     func InsertUsers(_ names: [String]) throws {
-        for name in names { _ = try InsertUser(name) }
+        for name in names { try InsertUser(name) }
     }
 
-    func InsertUser(_ name: String, age: Int? = nil, admin: Bool = false) throws -> Statement {
+    @discardableResult func InsertUser(_ name: String, age: Int? = nil, admin: Bool = false) throws -> Statement {
         return try db.run(
             "INSERT INTO \"users\" (email, age, admin) values (?, ?, ?)",
             "\(name)@example.com", age?.datatypeValue, admin.datatypeValue
@@ -56,7 +56,7 @@ class SQLiteTestCase : XCTestCase {
     }
 
     func AssertSQL(_ SQL: String, _ statement: Statement, _ message: String? = nil, file: StaticString = #file, line: UInt = #line) {
-        _ = try! statement.run()
+        try! statement.run()
         AssertSQL(SQL, 1, message, file: file, line: line)
         if let count = trace[SQL] { trace[SQL] = count - 1 }
     }

From 6bf844a1c6c2c6bbeadaab594124fc9874026ded Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 8 Oct 2016 13:59:55 +0200
Subject: [PATCH 084/685] Fix warnings

---
 SQLite/Core/Trace.swift           |  2 ++
 SQLite/Extensions/FTS4.swift      | 10 +++++-----
 SQLite/Typed/Query.swift          |  2 +-
 SQLiteTests/ConnectionTests.swift |  2 +-
 SQLiteTests/FTS4Tests.swift       |  2 +-
 5 files changed, 10 insertions(+), 8 deletions(-)
 create mode 100644 SQLite/Core/Trace.swift

diff --git a/SQLite/Core/Trace.swift b/SQLite/Core/Trace.swift
new file mode 100644
index 00000000..350c82fa
--- /dev/null
+++ b/SQLite/Core/Trace.swift
@@ -0,0 +1,2 @@
+
+import Foundation
diff --git a/SQLite/Extensions/FTS4.swift b/SQLite/Extensions/FTS4.swift
index ecaf2507..7bbca7a5 100644
--- a/SQLite/Extensions/FTS4.swift
+++ b/SQLite/Extensions/FTS4.swift
@@ -171,12 +171,12 @@ open class FTSConfig {
     var isContentless: Bool = false
 
     /// Adds a column definition
-    open func column(_ column: Expressible, _ options: [ColumnOption] = []) -> Self {
+    @discardableResult open func column(_ column: Expressible, _ options: [ColumnOption] = []) -> Self {
         self.columnDefinitions.append((column, options))
         return self
     }
 
-    open func columns(_ columns: [Expressible]) -> Self {
+    @discardableResult open func columns(_ columns: [Expressible]) -> Self {
         for column in columns {
             self.column(column)
         }
@@ -233,7 +233,7 @@ open class FTSConfig {
     struct Options {
         var arguments = [Expressible]()
 
-        mutating func append(_ columns: [Expressible]) -> Options {
+        @discardableResult mutating func append(_ columns: [Expressible]) -> Options {
             arguments.append(contentsOf: columns)
             return self
         }
@@ -250,11 +250,11 @@ open class FTSConfig {
             return append(key, value: value?.description)
         }
 
-        mutating func append(_ key: String, value: String?) -> Options {
+        @discardableResult mutating func append(_ key: String, value: String?) -> Options {
             return append(key, value: value.map { Expression<String>($0) })
         }
 
-        mutating func append(_ key: String, value: Expressible?) -> Options {
+        @discardableResult mutating func append(_ key: String, value: Expressible?) -> Options {
             if let value = value {
                 arguments.append("=".join([Expression<Void>(literal: key), value]))
             }
diff --git a/SQLite/Typed/Query.swift b/SQLite/Typed/Query.swift
index af6549de..75f29afd 100644
--- a/SQLite/Typed/Query.swift
+++ b/SQLite/Typed/Query.swift
@@ -886,7 +886,7 @@ extension Connection {
 
         let columnNames: [String: Int] = try {
             var (columnNames, idx) = ([String: Int](), 0)
-            column: for each in query.clauses.select.columns ?? [Expression<Void>(literal: "*")] {
+            column: for each in query.clauses.select.columns {
                 var names = each.expression.template.characters.split { $0 == "." }.map(String.init)
                 let column = names.removeLast()
                 let namespace = names.joined(separator: ".")
diff --git a/SQLiteTests/ConnectionTests.swift b/SQLiteTests/ConnectionTests.swift
index 3eb2b915..1d18bdca 100644
--- a/SQLiteTests/ConnectionTests.swift
+++ b/SQLiteTests/ConnectionTests.swift
@@ -310,7 +310,7 @@ class ConnectionTests : SQLiteTestCase {
         let stmt = try! db.prepare("SELECT *, sleep(?) FROM users", 0.1)
         try! stmt.run()
 
-        _ = DispatchQueue.global(priority: DispatchQueue.GlobalQueuePriority.background).asyncAfter(deadline: DispatchTime.now() + Double(Int64(10 * NSEC_PER_MSEC)) / Double(NSEC_PER_SEC), execute: db.interrupt)
+        _ = DispatchQueue.global(qos: .background).asyncAfter(deadline: DispatchTime.now() + Double(Int64(10 * NSEC_PER_MSEC)) / Double(NSEC_PER_SEC), execute: db.interrupt)
         AssertThrows(try stmt.run())
     }
 
diff --git a/SQLiteTests/FTS4Tests.swift b/SQLiteTests/FTS4Tests.swift
index 0148efc3..b2ccc86c 100644
--- a/SQLiteTests/FTS4Tests.swift
+++ b/SQLiteTests/FTS4Tests.swift
@@ -201,7 +201,7 @@ class FTS4IntegrationTests : SQLiteTestCase {
         try! db.run(emails.create(.FTS4([subject, body], tokenize: .Custom(tokenizerName))))
         AssertSQL("CREATE VIRTUAL TABLE \"emails\" USING fts4(\"subject\", \"body\", tokenize=\"SQLite.swift\" \"tokenizer\")")
 
-        try! db.run(emails.insert(subject <- "Aún más cáfe!"))
+        try! _ = db.run(emails.insert(subject <- "Aún más cáfe!"))
         XCTAssertEqual(1, try! db.scalar(emails.filter(emails.match("aun")).count))
     }
 #endif

From 15490620c798e7715b43acec889af80230deedd6 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 8 Oct 2016 14:01:06 +0200
Subject: [PATCH 085/685] Accidental commit

---
 SQLite/Core/Trace.swift | 2 --
 1 file changed, 2 deletions(-)
 delete mode 100644 SQLite/Core/Trace.swift

diff --git a/SQLite/Core/Trace.swift b/SQLite/Core/Trace.swift
deleted file mode 100644
index 350c82fa..00000000
--- a/SQLite/Core/Trace.swift
+++ /dev/null
@@ -1,2 +0,0 @@
-
-import Foundation

From 5bc521eb8abd7f125a0fab8338f61064e19811d7 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 8 Oct 2016 14:39:51 +0200
Subject: [PATCH 086/685] Only available on OS X 10.10 or newer

---
 SQLiteTests/ConnectionTests.swift | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/SQLiteTests/ConnectionTests.swift b/SQLiteTests/ConnectionTests.swift
index 1d18bdca..33fa113d 100644
--- a/SQLiteTests/ConnectionTests.swift
+++ b/SQLiteTests/ConnectionTests.swift
@@ -310,7 +310,8 @@ class ConnectionTests : SQLiteTestCase {
         let stmt = try! db.prepare("SELECT *, sleep(?) FROM users", 0.1)
         try! stmt.run()
 
-        _ = DispatchQueue.global(qos: .background).asyncAfter(deadline: DispatchTime.now() + Double(Int64(10 * NSEC_PER_MSEC)) / Double(NSEC_PER_SEC), execute: db.interrupt)
+        let deadline = DispatchTime.now() + Double(Int64(10 * NSEC_PER_MSEC)) / Double(NSEC_PER_SEC)
+        _ = DispatchQueue.global(priority: .background).asyncAfter(deadline: deadline, execute: db.interrupt)
         AssertThrows(try stmt.run())
     }
 

From f11f6b8985bc5da530022a047f51b6d5585a72a9 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 9 Oct 2016 08:52:59 +0200
Subject: [PATCH 087/685] cleanup

---
 SQLite/Core/Connection.swift | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index bd4cafb3..ad97466b 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -584,15 +584,20 @@ public final class Connection {
     ///   - block: A collation function that takes two strings and returns the
     ///     comparison result.
     public func createCollation(_ collation: String, _ block: @escaping (_ lhs: String, _ rhs: String) -> ComparisonResult) throws {
-        // TODO correct capacity
-        let box: Collation = { lhs, rhs in
-            let lstr = String(cString: lhs.bindMemory(to: UInt8.self, capacity: 0))
-            let rstr = String(cString: rhs.bindMemory(to: UInt8.self, capacity: 0))
-            return Int32(Int(block(lstr, rstr).rawValue))
+        let box: Collation = { (lhs:UnsafeRawPointer, rhs:UnsafeRawPointer) in
+            let lstr = String(cString: lhs.assumingMemoryBound(to: UInt8.self))
+            let rstr = String(cString: rhs.assumingMemoryBound(to: UInt8.self))
+            return Int32(block(lstr, rstr).rawValue)
         }
-        try check(sqlite3_create_collation_v2(handle, collation, SQLITE_UTF8, unsafeBitCast(box, to: UnsafeMutableRawPointer.self), { callback, _, lhs, _, rhs in
-            unsafeBitCast(callback, to: Collation.self)(lhs!, rhs!)
-        }, nil))
+        try check(sqlite3_create_collation_v2(handle, collation, SQLITE_UTF8,
+            unsafeBitCast(box, to: UnsafeMutableRawPointer.self),
+            { (callback:UnsafeMutableRawPointer?, _, lhs:UnsafeRawPointer?, _, rhs:UnsafeRawPointer?) in /* xCompare */
+            if let lhs = lhs, let rhs = rhs {
+                return unsafeBitCast(callback, to: Collation.self)(lhs, rhs)
+            } else {
+                fatalError("sqlite3_create_collation_v2 callback called with NULL pointer")
+            }
+        }, nil /* xDestroy */))
         collations[collation] = box
     }
     fileprivate typealias Collation = @convention(block) (UnsafeRawPointer, UnsafeRawPointer) -> Int32

From 6152ee3c17abe952ebea291f8d04557086b2ab07 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 9 Oct 2016 16:20:19 +0200
Subject: [PATCH 088/685] Documentation updates

---
 Documentation/Index.md | 42 +++++++++++++++++++++---------------------
 README.md              |  4 ++--
 2 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 3063d095..8b136246 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -65,7 +65,7 @@
 
 ## Installation
 
-> _Note:_ SQLite.swift requires Swift 2 (and [Xcode 7](https://developer.apple.com/xcode/downloads/)) or greater.
+> _Note:_ SQLite.swift requires Swift 3 (and [Xcode 8](https://developer.apple.com/xcode/downloads/)) or greater.
 
 
 ### Carthage
@@ -203,10 +203,10 @@ On OS X, you can use your app’s **Application Support** directory:
 ``` swift
 var path = NSSearchPathForDirectoriesInDomains(
     .applicationSupportDirectory, .userDomainMask, true
-).first! + NSBundle.mainBundle().bundleIdentifier!
+).first! + Bundle.main.bundleIdentifier!
 
 // create parent directory iff it doesn’t exist
-try NSFileManager.defaultManager().createDirectoryAtPath(
+try FileManager.default.createDirectoryAtPath(
     path, withIntermediateDirectories: true, attributes: nil
 )
 
@@ -219,7 +219,7 @@ let db = try Connection("\(path)/db.sqlite3")
 If you bundle a database with your app (_i.e._, you’ve copied a database file into your Xcode project and added it to your application target), you can establish a _read-only_ connection to it.
 
 ``` swift
-let path = NSBundle.mainBundle().pathForResource("db", ofType: "sqlite3")!
+let path = Bundle.main.pathForResource("db", ofType: "sqlite3")!
 
 let db = try Connection(path, readonly: true)
 ```
@@ -1114,16 +1114,16 @@ Once extended, the type can be used [_almost_](#custom-type-caveats) wherever ty
 
 ### Date-Time Values
 
-In SQLite, `DATETIME` columns can be treated as strings or numbers, so we can transparently bridge `NSDate` objects through Swift’s `String` or `Int` types.
+In SQLite, `DATETIME` columns can be treated as strings or numbers, so we can transparently bridge `Date` objects through Swift’s `String` or `Int` types.
 
-To serialize `NSDate` objects as `TEXT` values (in ISO 8601), we’ll use `String`.
+To serialize `Date` objects as `TEXT` values (in ISO 8601), we’ll use `String`.
 
 ``` swift
-extension NSDate: Value {
+extension Date: Value {
     class var declaredDatatype: String {
         return String.declaredDatatype
     }
-    class func fromDatatypeValue(stringValue: String) -> NSDate {
+    class func fromDatatypeValue(stringValue: String) -> Date {
         return SQLDateFormatter.dateFromString(stringValue)!
     }
     var datatypeValue: String {
@@ -1131,11 +1131,11 @@ extension NSDate: Value {
     }
 }
 
-let SQLDateFormatter: NSDateFormatter = {
-    let formatter = NSDateFormatter()
+let SQLDateFormatter: DateFormatter = {
+    let formatter = DateFormatter()
     formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"
-    formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
-    formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0)
+    formatter.locale = Locale(localeIdentifier: "en_US_POSIX")
+    formatter.timeZone = TimeZone(forSecondsFromGMT: 0)
     return formatter
 }()
 ```
@@ -1143,12 +1143,12 @@ let SQLDateFormatter: NSDateFormatter = {
 We can also treat them as `INTEGER` values using `Int`.
 
 ``` swift
-extension NSDate: Value {
+extension Date: Value {
     class var declaredDatatype: String {
         return Int.declaredDatatype
     }
     class func fromDatatypeValue(intValue: Int) -> Self {
-        return self(timeIntervalSince1970: NSTimeInterval(intValue))
+        return self(timeIntervalSince1970: TimeInterval(intValue))
     }
     var datatypeValue: Int {
         return Int(timeIntervalSince1970)
@@ -1161,9 +1161,9 @@ extension NSDate: Value {
 Once defined, we can use these types directly in SQLite statements.
 
 ``` swift
-let published_at = Expression<NSDate>("published_at")
+let published_at = Expression<Date>("published_at")
 
-let published = posts.filter(published_at <= NSDate())
+let published = posts.filter(published_at <= Date())
 // extension where Datatype == String:
 //     SELECT * FROM "posts" WHERE "published_at" <= '2014-11-18 12:45:30'
 // extension where Datatype == Int:
@@ -1175,10 +1175,10 @@ let published = posts.filter(published_at <= NSDate())
 
 Any object that can be encoded and decoded can be stored as a blob of data in SQL.
 
-We can create an `NSData` bridge rather trivially.
+We can create an `Data` bridge rather trivially.
 
 ``` swift
-extension NSData: Value {
+extension Data: Value {
     class var declaredDatatype: String {
         return Blob.declaredDatatype
     }
@@ -1191,16 +1191,16 @@ extension NSData: Value {
 }
 ```
 
-We can bridge any type that can be initialized from and encoded to `NSData`.
+We can bridge any type that can be initialized from and encoded to `Data`.
 
 ``` swift
-// assumes NSData conformance, above
+// assumes Data conformance, above
 extension UIImage: Value {
     public class var declaredDatatype: String {
         return Blob.declaredDatatype
     }
     public class func fromDatatypeValue(blobValue: Blob) -> UIImage {
-        return UIImage(data: NSData.fromDatatypeValue(blobValue))!
+        return UIImage(data: Data.fromDatatypeValue(blobValue))!
     }
     public var datatypeValue: Blob {
         return UIImagePNGRepresentation(self)!.datatypeValue
diff --git a/README.md b/README.md
index 53d654fb..bdd652f2 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # SQLite.swift 
 
-[![Build Status][Badge]][Travis] [![CocoaPods Version](https://cocoapod-badges.herokuapp.com/v/SQLite.swift/badge.png)](http://cocoadocs.org/docsets/SQLite.swift) [![Platform](https://cocoapod-badges.herokuapp.com/p/SQLite.swift/badge.png)](http://cocoadocs.org/docsets/SQLite.swift) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![Join the chat at https://gitter.im/stephencelis/SQLite.swift](https://badges.gitter.im/stephencelis/SQLite.swift.svg)](https://gitter.im/stephencelis/SQLite.swift)
+[![Build Status][Badge]][Travis] [![CocoaPods Version](https://cocoapod-badges.herokuapp.com/v/SQLite.swift/badge.png)](http://cocoadocs.org/docsets/SQLite.swift) [![Swift](https://img.shields.io/badge/swift-3-orange.svg?style=flat)](https://developer.apple.com/swift/) [![Platform](https://cocoapod-badges.herokuapp.com/p/SQLite.swift/badge.png)](http://cocoadocs.org/docsets/SQLite.swift) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![Join the chat at https://gitter.im/stephencelis/SQLite.swift](https://badges.gitter.im/stephencelis/SQLite.swift.svg)](https://gitter.im/stephencelis/SQLite.swift)
 
 A type-safe, [Swift][]-language layer over [SQLite3][].
 
@@ -109,7 +109,7 @@ For a more comprehensive example, see [this article](http://masteringswift.blogs
 
 ## Installation
 
-> _Note:_ SQLite.swift requires Swift 2 (and [Xcode][] 7) or greater.
+> _Note:_ SQLite.swift requires Swift 3 (and [Xcode][] 8) or greater.
 >
 > The following instructions apply to targets that support embedded
 > Swift frameworks. To use SQLite.swift in iOS 7 or an OS X command line

From bbab40147c17ab1c68f5a57d68b564d97c8a4f1a Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 9 Oct 2016 16:24:47 +0200
Subject: [PATCH 089/685] Remove FIXME

---
 SQLite/Core/Connection.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index ad97466b..f95246fd 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -101,7 +101,7 @@ public final class Connection {
     public init(_ location: Location = .inMemory, readonly: Bool = false) throws {
         let flags = readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE
         try check(sqlite3_open_v2(location.description, &_handle, flags | SQLITE_OPEN_FULLMUTEX, nil))
-        queue.setSpecific(key: /*Migrator FIXME: Use a variable of type DispatchSpecificKey*/ Connection.queueKey, value: queueContext)
+        queue.setSpecific(key: Connection.queueKey, value: queueContext)
     }
 
     /// Initializes a new connection to a database.

From 96238f558d776354ceeafe52d04bc17df280bb34 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 9 Oct 2016 16:36:41 +0200
Subject: [PATCH 090/685] sqlite3_trace

---
 SQLite/Core/Connection.swift | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index f95246fd..d836f1d4 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -419,9 +419,13 @@ public final class Connection {
         }
 
         let box: Trace = { callback(String(cString: $0)) }
-        sqlite3_trace(handle, { callback, SQL in
-            unsafeBitCast(callback, to: Trace.self)(SQL!)
-        }, unsafeBitCast(box, to: UnsafeMutableRawPointer.self))
+        sqlite3_trace(handle, {
+            (callback: UnsafeMutableRawPointer?, SQL: UnsafePointer<Int8>?) in
+                 guard let callback = callback, let SQL = SQL else { return }
+                 unsafeBitCast(callback, to: Trace.self)(SQL)
+            },
+            unsafeBitCast(box, to: UnsafeMutableRawPointer.self)
+        )
         trace = box
     }
     fileprivate typealias Trace = @convention(block) (UnsafePointer<Int8>) -> Void
@@ -584,14 +588,14 @@ public final class Connection {
     ///   - block: A collation function that takes two strings and returns the
     ///     comparison result.
     public func createCollation(_ collation: String, _ block: @escaping (_ lhs: String, _ rhs: String) -> ComparisonResult) throws {
-        let box: Collation = { (lhs:UnsafeRawPointer, rhs:UnsafeRawPointer) in
+        let box: Collation = { (lhs: UnsafeRawPointer, rhs: UnsafeRawPointer) in
             let lstr = String(cString: lhs.assumingMemoryBound(to: UInt8.self))
             let rstr = String(cString: rhs.assumingMemoryBound(to: UInt8.self))
             return Int32(block(lstr, rstr).rawValue)
         }
         try check(sqlite3_create_collation_v2(handle, collation, SQLITE_UTF8,
             unsafeBitCast(box, to: UnsafeMutableRawPointer.self),
-            { (callback:UnsafeMutableRawPointer?, _, lhs:UnsafeRawPointer?, _, rhs:UnsafeRawPointer?) in /* xCompare */
+            { (callback: UnsafeMutableRawPointer?, _, lhs: UnsafeRawPointer?, _, rhs: UnsafeRawPointer?) in /* xCompare */
             if let lhs = lhs, let rhs = rhs {
                 return unsafeBitCast(callback, to: Collation.self)(lhs, rhs)
             } else {

From b392eaf6620a662e477597518e240760f48a04cd Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 9 Oct 2016 16:42:54 +0200
Subject: [PATCH 091/685] Remove unneeded typealias

---
 SQLite/Core/Connection.swift | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index d836f1d4..6aa27dc6 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -576,9 +576,6 @@ public final class Connection {
     fileprivate typealias Function = @convention(block) (OpaquePointer?, Int32, UnsafeMutablePointer<OpaquePointer?>?) -> Void
     fileprivate var functions = [String: [Int: Function]]()
 
-    /// The return type of a collation comparison function.
-    public typealias ComparisonResult = Foundation.ComparisonResult
-
     /// Defines a new collating sequence.
     ///
     /// - Parameters:

From 336faa1726887a90745e2949241394e41dd59be7 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 8 Oct 2016 11:01:54 +0200
Subject: [PATCH 092/685] Use sqlite3_trace_v2 where available

---
 SQLite/Core/Connection.swift      | 60 ++++++++++++++++++++++++++-----
 SQLiteTests/ConnectionTests.swift |  6 ++++
 2 files changed, 58 insertions(+), 8 deletions(-)

diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index 6aa27dc6..ff284ada 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -412,23 +412,67 @@ public final class Connection {
     ///
     ///       db.trace { SQL in print(SQL) }
     public func trace(_ callback: ((String) -> Void)?) {
+        if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) {
+            trace_v2(callback)
+        } else {
+            trace_v1(callback)
+        }
+    }
+
+    fileprivate func trace_v1(_ callback: ((String) -> Void)?) {
         guard let callback = callback else {
-            sqlite3_trace(handle, nil, nil)
+            sqlite3_trace(handle, nil /* xCallback */, nil /* pCtx */)
             trace = nil
             return
         }
-
-        let box: Trace = { callback(String(cString: $0)) }
-        sqlite3_trace(handle, {
-            (callback: UnsafeMutableRawPointer?, SQL: UnsafePointer<Int8>?) in
-                 guard let callback = callback, let SQL = SQL else { return }
-                 unsafeBitCast(callback, to: Trace.self)(SQL)
+        let box: Trace = { (pointer: UnsafeRawPointer) in
+            callback(String(cString: pointer.assumingMemoryBound(to: UInt8.self)))
+        }
+        sqlite3_trace(handle,
+            {
+                (C: UnsafeMutableRawPointer?, SQL: UnsafePointer<Int8>?) in
+                    if let C = C, let SQL = SQL {
+                        unsafeBitCast(C, to: Trace.self)(SQL)
+                    }
             },
             unsafeBitCast(box, to: UnsafeMutableRawPointer.self)
         )
         trace = box
     }
-    fileprivate typealias Trace = @convention(block) (UnsafePointer<Int8>) -> Void
+
+    @available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *)
+    fileprivate func trace_v2(_ callback: ((String) -> Void)?) {
+        guard let callback = callback else {
+            // If the X callback is NULL or if the M mask is zero, then tracing is disabled.
+            sqlite3_trace_v2(handle, 0 /* mask */, nil /* xCallback */, nil /* pCtx */)
+            trace = nil
+            return
+        }
+
+        let box: Trace = { (pointer: UnsafeRawPointer) in
+            callback(String(cString: pointer.assumingMemoryBound(to: UInt8.self)))
+        }
+        sqlite3_trace_v2(handle,
+            UInt32(SQLITE_TRACE_STMT) /* mask */,
+            {
+                // A trace callback is invoked with four arguments: callback(T,C,P,X).
+                // The T argument is one of the SQLITE_TRACE constants to indicate why the
+                // callback was invoked. The C argument is a copy of the context pointer.
+                // The P and X arguments are pointers whose meanings depend on T.
+                (T: UInt32, C: UnsafeMutableRawPointer?, P: UnsafeMutableRawPointer?, X: UnsafeMutableRawPointer?) in
+                    if let P = P,
+                       let expandedSQL = sqlite3_expanded_sql(OpaquePointer(P)) {
+                        unsafeBitCast(C, to: Trace.self)(expandedSQL)
+                        sqlite3_free(expandedSQL)
+                    }
+                    return Int32(0) // currently ignored
+            },
+            unsafeBitCast(box, to: UnsafeMutableRawPointer.self) /* pCtx */
+        )
+        trace = box
+    }
+
+    fileprivate typealias Trace = @convention(block) (UnsafeRawPointer) -> Void
     fileprivate var trace: Trace?
 
     /// Registers a callback to be invoked whenever a row is inserted, updated,
diff --git a/SQLiteTests/ConnectionTests.swift b/SQLiteTests/ConnectionTests.swift
index 33fa113d..99b9d8a1 100644
--- a/SQLiteTests/ConnectionTests.swift
+++ b/SQLiteTests/ConnectionTests.swift
@@ -94,6 +94,12 @@ class ConnectionTests : SQLiteTestCase {
         AssertSQL("SELECT count(*) FROM users WHERE admin = 0", 4)
     }
 
+    func test_execute_comment() {
+        try! db.run("-- this is a comment\nSELECT 1")
+        AssertSQL("-- this is a comment", 0)
+        AssertSQL("SELECT 1", 0)
+    }
+
     func test_transaction_executesBeginDeferred() {
         try! db.transaction(.deferred) {}
 

From 8ba973e2fed5e008b7129596107a215578090c54 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 10 Oct 2016 15:13:41 +0200
Subject: [PATCH 093/685] Remove outdated sample code (#516)

---
 Documentation/Index.md | 19 -------------------
 1 file changed, 19 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 8b136246..91f631ef 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1173,28 +1173,9 @@ let published = posts.filter(published_at <= Date())
 
 ### Binary Data
 
-Any object that can be encoded and decoded can be stored as a blob of data in SQL.
-
-We can create an `Data` bridge rather trivially.
-
-``` swift
-extension Data: Value {
-    class var declaredDatatype: String {
-        return Blob.declaredDatatype
-    }
-    class func fromDatatypeValue(blobValue: Blob) -> Self {
-        return self(bytes: blobValue.bytes, length: blobValue.length)
-    }
-    var datatypeValue: Blob {
-        return Blob(bytes: bytes, length: length)
-    }
-}
-```
-
 We can bridge any type that can be initialized from and encoded to `Data`.
 
 ``` swift
-// assumes Data conformance, above
 extension UIImage: Value {
     public class var declaredDatatype: String {
         return Blob.declaredDatatype

From 681e21926f3b8bb813c91319d63e04cab4eb3f76 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 10 Oct 2016 19:33:51 +0200
Subject: [PATCH 094/685] Update bundler

---
 .travis.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.travis.yml b/.travis.yml
index d280766b..925ceee3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,6 +12,7 @@ matrix:
     - env: VALIDATOR_SUBSPEC="standard"
     - env: VALIDATOR_SUBSPEC="standalone"
 before_install:
+  - gem update bundler
   - gem install xcpretty --no-document
 script:
   - ./run-tests.sh

From db8f39b0a1cc845f0158f70a27c6e29e5d8d9e28 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 11 Oct 2016 15:08:03 +0200
Subject: [PATCH 095/685] Only import module when building with CocoaPods

---
 SQLite/Core/Connection.swift | 2 +-
 SQLite/Core/Statement.swift  | 2 +-
 SQLite/Helpers.swift         | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index 6aa27dc6..22f09c27 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -26,7 +26,7 @@ import Foundation.NSUUID
 import Dispatch
 #if SQLITE_SWIFT_STANDALONE
 import sqlite3
-#else
+#elseif COCOAPODS
 import CSQLite
 #endif
 
diff --git a/SQLite/Core/Statement.swift b/SQLite/Core/Statement.swift
index a7664993..64b9017f 100644
--- a/SQLite/Core/Statement.swift
+++ b/SQLite/Core/Statement.swift
@@ -24,7 +24,7 @@
 
 #if SQLITE_SWIFT_STANDALONE
 import sqlite3
-#else
+#elseif COCOAPODS
 import CSQLite
 #endif
 
diff --git a/SQLite/Helpers.swift b/SQLite/Helpers.swift
index e9a17ce6..febdc949 100644
--- a/SQLite/Helpers.swift
+++ b/SQLite/Helpers.swift
@@ -24,7 +24,7 @@
 
 #if SQLITE_SWIFT_STANDALONE
 import sqlite3
-#else
+#elseif COCOAPODS
 import CSQLite
 #endif
 

From 6b4cb81e78852c203397bf9132f75d78bab92b1c Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 11 Oct 2016 15:51:13 +0200
Subject: [PATCH 096/685] Mention swift-2.3 branch in documentation

---
 README.md | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index bdd652f2..87d283d6 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# SQLite.swift 
+# SQLite.swift
 
 [![Build Status][Badge]][Travis] [![CocoaPods Version](https://cocoapod-badges.herokuapp.com/v/SQLite.swift/badge.png)](http://cocoadocs.org/docsets/SQLite.swift) [![Swift](https://img.shields.io/badge/swift-3-orange.svg?style=flat)](https://developer.apple.com/swift/) [![Platform](https://cocoapod-badges.herokuapp.com/p/SQLite.swift/badge.png)](http://cocoadocs.org/docsets/SQLite.swift) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![Join the chat at https://gitter.im/stephencelis/SQLite.swift](https://badges.gitter.im/stephencelis/SQLite.swift.svg)](https://gitter.im/stephencelis/SQLite.swift)
 
@@ -109,7 +109,9 @@ For a more comprehensive example, see [this article](http://masteringswift.blogs
 
 ## Installation
 
-> _Note:_ SQLite.swift requires Swift 3 (and [Xcode][] 8) or greater.
+> _Note:_ SQLite.swift requires Swift 3 (and [Xcode][] 8) or greater. If you absolutely
+> need compatibility with Swift 2.3 you can use the [swift-2.3][] branch or older
+> released versions. New development will happen exclusively on the master/Swift 3 branch.
 >
 > The following instructions apply to targets that support embedded
 > Swift frameworks. To use SQLite.swift in iOS 7 or an OS X command line
@@ -199,7 +201,7 @@ To install SQLite.swift as an Xcode sub-project:
  - Found a **bug** or have a **feature request**? [Open an issue][].
  - Want to **contribute**? [Submit a pull request][].
 
-[See the planning document]: /Documentation/Planning.md 
+[See the planning document]: /Documentation/Planning.md
 [Read the contributing guidelines]: ./CONTRIBUTING.md#contributing
 [Ask on Stack Overflow]: http://stackoverflow.com/questions/tagged/sqlite.swift
 [Open an issue]: https://github.com/stephencelis/SQLite.swift/issues/new
@@ -237,3 +239,4 @@ Looking for something else? Try another Swift wrapper (or [FMDB][]):
  - [SwiftSQLite](https://github.com/chrismsimpson/SwiftSQLite)
 
 [FMDB]: https://github.com/ccgus/fmdb
+[swift-2.3]: https://github.com/stephencelis/SQLite.swift/tree/swift-2.3

From 3dacf3b00d9e5ed41cd1dd13a0279b62ed109128 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 15 Oct 2016 12:12:58 +0200
Subject: [PATCH 097/685] Prepare 0.11.0

---
 Documentation/Index.md | 8 ++++----
 README.md              | 4 ++--
 SQLite.swift.podspec   | 2 +-
 SQLite/Info.plist      | 2 +-
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 91f631ef..3ecbbf77 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -78,7 +78,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```
-    github "stephencelis/SQLite.swift" ~> 0.10.1
+    github "stephencelis/SQLite.swift" ~> 0.11.0
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -106,7 +106,7 @@ install SQLite.swift with Carthage:
     ``` ruby
     use_frameworks!
 
-    pod 'SQLite.swift', '~> 0.10.1'
+    pod 'SQLite.swift', '~> 0.11.0'
     ```
 
  3. Run `pod install`.
@@ -116,13 +116,13 @@ install SQLite.swift with Carthage:
  If you want to use a more recent version of SQLite than what is provided with the OS you can require the `standalone` subspec:
 
 ``` ruby
-    pod 'SQLite.swift/standalone', '~> 0.10.1'
+    pod 'SQLite.swift/standalone', '~> 0.11.0'
 ```
 
 By default this will use the most recent version of SQLite without any extras. If you want you can further customize this by adding another dependency to sqlite3 or one of its subspecs:
 
 ``` ruby
-    pod 'SQLite.swift/standalone', '~> 0.10.1'
+    pod 'SQLite.swift/standalone', '~> 0.11.0'
     pod 'sqlite3/fts5', '= 3.11.1'  # SQLite 3.11.1 with FTS5 enabled
 ```
 
diff --git a/README.md b/README.md
index 87d283d6..6e9857bd 100644
--- a/README.md
+++ b/README.md
@@ -129,7 +129,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```
-    github "stephencelis/SQLite.swift" ~> 0.10.1
+    github "stephencelis/SQLite.swift" ~> 0.11.0
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -159,7 +159,7 @@ SQLite.swift with CocoaPods:
     ``` ruby
     use_frameworks!
 
-    pod 'SQLite.swift', '~> 0.10.1'
+    pod 'SQLite.swift', '~> 0.11.0'
     ```
 
  3. Run `pod install`.
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index b7a09bc1..a6efaf2a 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -5,7 +5,7 @@
 
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.10.1"
+  s.version          = "0.11.0"
   s.summary          = "A type-safe, Swift-language layer over SQLite3 for iOS and OS X."
 
   s.description      = <<-DESC
diff --git a/SQLite/Info.plist b/SQLite/Info.plist
index d93473a7..03d53553 100644
--- a/SQLite/Info.plist
+++ b/SQLite/Info.plist
@@ -15,7 +15,7 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>0.10.1</string>
+	<string>0.11.0</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>

From f160b86be47735b69262a00d713b796a29cf2f89 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 15 Oct 2016 12:25:47 +0200
Subject: [PATCH 098/685] Docs

---
 Documentation/Index.md | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 3ecbbf77..ac8bfa3e 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -93,15 +93,17 @@ install SQLite.swift with Carthage:
 
 [CocoaPods][] is a dependency manager for Cocoa projects. To install SQLite.swift with CocoaPods:
 
- 1. Make sure the latest CocoaPods beta is [installed][CocoaPods Installation]. (SQLite.swift requires version 1.0.0.beta.6 or greater.)
+ 1. Verify that your copy of Xcode is installed in the default location (`/Application/Xcode.app`).
+
+ 2. Make sure CocoaPods is [installed][CocoaPods Installation] (SQLite.swift requires version 1.0.0 or greater).
 
     ``` sh
     # Using the default Ruby install will require you to use sudo when
     # installing and updating gems.
-    sudo gem install --pre cocoapods
+    sudo gem install cocoapods
     ```
 
- 2. Update your Podfile to include the following:
+ 3. Update your Podfile to include the following:
 
     ``` ruby
     use_frameworks!
@@ -109,7 +111,8 @@ install SQLite.swift with Carthage:
     pod 'SQLite.swift', '~> 0.11.0'
     ```
 
- 3. Run `pod install`.
+ 4. Run `pod install`.
+
 
  #### Requiring a specific version of SQLite
 

From 89102d79a39e68dee15b5e79554baecd0f823396 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 15 Oct 2016 12:30:07 +0200
Subject: [PATCH 099/685] Update SQLite version

---
 Documentation/Index.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index ac8bfa3e..3940541b 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -126,7 +126,7 @@ By default this will use the most recent version of SQLite without any extras. I
 
 ``` ruby
     pod 'SQLite.swift/standalone', '~> 0.11.0'
-    pod 'sqlite3/fts5', '= 3.11.1'  # SQLite 3.11.1 with FTS5 enabled
+    pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
 ```
 
 See the [sqlite3 podspec][sqlite3pod] for more details.

From d3d2e4e72b15624d0e0ca1e3814d5e4279daa335 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 15 Oct 2016 12:31:38 +0200
Subject: [PATCH 100/685] Fix screenshot path

---
 Documentation/Index.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 3940541b..6107969a 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -142,7 +142,7 @@ To install SQLite.swift as an Xcode sub-project:
 
  1. Drag the **SQLite.xcodeproj** file into your own project. ([Submodule](http://git-scm.com/book/en/Git-Tools-Submodules), clone, or [download](https://github.com/stephencelis/SQLite.swift/archive/master.zip) the project first.)
 
-    ![Installation Screen Shot](Documentation/Resources/installation@2x.png)
+    ![Installation Screen Shot](Resources/installation@2x.png)
 
  2. In your target’s **General** tab, click the **+** button under **Linked Frameworks and Libraries**.
 

From 0a89b1b7dcdcd5a22830a966a025b6c9c451852f Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 15 Oct 2016 12:45:34 +0200
Subject: [PATCH 101/685] Spec lints OK now

---
 SQLite.swift.podspec | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index a6efaf2a..9c3a35e0 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,8 +1,3 @@
-#
-# `pod lib lint SQLite.swift.podspec' fails - see
-#    https://github.com/CocoaPods/CocoaPods/issues/4607
-#
-
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
   s.version          = "0.11.0"

From 18aad56f33410ae295eb45459b0d84bc1b4d76ce Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 15 Oct 2016 13:07:35 +0200
Subject: [PATCH 102/685] Add watchOS scheme

---
 CocoaPodsTests/test_running_validator.rb      |  7 +-
 SQLite.xcodeproj/project.pbxproj              |  4 +
 .../xcschemes/SQLite watchOS.xcscheme         | 80 +++++++++++++++++++
 3 files changed, 90 insertions(+), 1 deletion(-)
 create mode 100644 SQLite.xcodeproj/xcshareddata/xcschemes/SQLite watchOS.xcscheme

diff --git a/CocoaPodsTests/test_running_validator.rb b/CocoaPodsTests/test_running_validator.rb
index 1eefa4b8..1a06e48a 100644
--- a/CocoaPodsTests/test_running_validator.rb
+++ b/CocoaPodsTests/test_running_validator.rb
@@ -9,11 +9,13 @@ class TestRunningValidator < Pod::Validator
   attr_accessor :test_files
   attr_accessor :ios_simulator
   attr_accessor :tvos_simulator
+  attr_accessor :watchos_simulator
 
   def initialize(spec_or_path, source_urls)
     super(spec_or_path, source_urls)
     self.ios_simulator = :oldest
     self.tvos_simulator = :oldest
+    self.watchos_simulator = :oldest
   end
 
   def create_app_project
@@ -91,8 +93,11 @@ def run_tests
     when :tvos
       command += %w(CODE_SIGN_IDENTITY=- -sdk appletvsimulator)
       command += Fourflusher::SimControl.new.destination(tvos_simulator, 'tvOS', deployment_target)
+    when :watchos
+      command += %w(CODE_SIGN_IDENTITY=- -sdk watchsimulator)
+      command += Fourflusher::SimControl.new.destination(watchos_simulator, 'watchOS', deployment_target)
     else
-      return # skip watchos
+      return
     end
 
     output, status = _xcodebuild(command)
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 4dddeaaf..690a1bea 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1043,6 +1043,8 @@
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
+				"FRAMEWORK_SEARCH_PATHS[sdk=watchos*]" = "$(SRCROOT)/CocoaPods/watchos";
+				"FRAMEWORK_SEARCH_PATHS[sdk=watchsimulator*]" = "$(SRCROOT)/CocoaPods/watchsimulator";
 				INFOPLIST_FILE = SQLite/Info.plist;
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@@ -1066,6 +1068,8 @@
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
+				"FRAMEWORK_SEARCH_PATHS[sdk=watchos*]" = "$(SRCROOT)/CocoaPods/watchos";
+				"FRAMEWORK_SEARCH_PATHS[sdk=watchsimulator*]" = "$(SRCROOT)/CocoaPods/watchsimulator";
 				INFOPLIST_FILE = SQLite/Info.plist;
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite watchOS.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite watchOS.xcscheme
new file mode 100644
index 00000000..d2088e81
--- /dev/null
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite watchOS.xcscheme	
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0800"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "A121AC441CA35C79005A31D1"
+               BuildableName = "SQLite.framework"
+               BlueprintName = "SQLite watchOS"
+               ReferencedContainer = "container:SQLite.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "A121AC441CA35C79005A31D1"
+            BuildableName = "SQLite.framework"
+            BlueprintName = "SQLite watchOS"
+            ReferencedContainer = "container:SQLite.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "A121AC441CA35C79005A31D1"
+            BuildableName = "SQLite.framework"
+            BlueprintName = "SQLite watchOS"
+            ReferencedContainer = "container:SQLite.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

From 15887ae7730e76b76c94757498f3a2c6ea408cd8 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 15 Oct 2016 13:11:06 +0200
Subject: [PATCH 103/685] Swift incude paths

---
 SQLite.xcodeproj/project.pbxproj | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 690a1bea..f0b18841 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1043,8 +1043,8 @@
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
-				"FRAMEWORK_SEARCH_PATHS[sdk=watchos*]" = "$(SRCROOT)/CocoaPods/watchos";
-				"FRAMEWORK_SEARCH_PATHS[sdk=watchsimulator*]" = "$(SRCROOT)/CocoaPods/watchsimulator";
+				"SWIFT_INCLUDE_PATHS[sdk=watchos*]" = "$(SRCROOT)/CocoaPods/watchos";
+				"SWIFT_INCLUDE_PATHS[sdk=watchsimulator*]" = "$(SRCROOT)/CocoaPods/watchsimulator";
 				INFOPLIST_FILE = SQLite/Info.plist;
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@@ -1068,8 +1068,8 @@
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
-				"FRAMEWORK_SEARCH_PATHS[sdk=watchos*]" = "$(SRCROOT)/CocoaPods/watchos";
-				"FRAMEWORK_SEARCH_PATHS[sdk=watchsimulator*]" = "$(SRCROOT)/CocoaPods/watchsimulator";
+				"SWIFT_INCLUDE_PATHS[sdk=watchos*]" = "$(SRCROOT)/CocoaPods/watchos";
+				"SWIFT_INCLUDE_PATHS[sdk=watchsimulator*]" = "$(SRCROOT)/CocoaPods/watchsimulator";
 				INFOPLIST_FILE = SQLite/Info.plist;
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";

From dd2568fa23377bd281c270937977a5efc5b82919 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 15 Oct 2016 13:15:44 +0200
Subject: [PATCH 104/685] Add files to watchOS target

---
 SQLite.xcodeproj/project.pbxproj | 66 ++++++++++++++++++++++++++++++--
 1 file changed, 62 insertions(+), 4 deletions(-)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index f0b18841..7b33eac6 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -55,6 +55,30 @@
 		19A17E04C4C0956715C5676A /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
 		19A17EC0D68BA8C03288ADF7 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
 		19A17FB80B94E882050AA908 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
+		3D67B3E61DB2469200A4F4C6 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */; };
+		3D67B3E71DB246BA00A4F4C6 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
+		3D67B3E81DB246BA00A4F4C6 /* Connection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEF1C3F06E900AE3E12 /* Connection.swift */; };
+		3D67B3E91DB246D100A4F4C6 /* Statement.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF21C3F06E900AE3E12 /* Statement.swift */; };
+		3D67B3EA1DB246D100A4F4C6 /* Value.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF31C3F06E900AE3E12 /* Value.swift */; };
+		3D67B3EB1DB246D100A4F4C6 /* FTS4.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF51C3F06E900AE3E12 /* FTS4.swift */; };
+		3D67B3EC1DB246D100A4F4C6 /* RTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF61C3F06E900AE3E12 /* RTree.swift */; };
+		3D67B3ED1DB246D100A4F4C6 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
+		3D67B3EE1DB246D100A4F4C6 /* AggregateFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFA1C3F06E900AE3E12 /* AggregateFunctions.swift */; };
+		3D67B3EF1DB246D100A4F4C6 /* Collation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFB1C3F06E900AE3E12 /* Collation.swift */; };
+		3D67B3F01DB246D100A4F4C6 /* CoreFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFC1C3F06E900AE3E12 /* CoreFunctions.swift */; };
+		3D67B3F11DB246D100A4F4C6 /* CustomFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFD1C3F06E900AE3E12 /* CustomFunctions.swift */; };
+		3D67B3F21DB246D100A4F4C6 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFE1C3F06E900AE3E12 /* Expression.swift */; };
+		3D67B3F31DB246D100A4F4C6 /* Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFF1C3F06E900AE3E12 /* Operators.swift */; };
+		3D67B3F41DB246D100A4F4C6 /* Query.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B001C3F06E900AE3E12 /* Query.swift */; };
+		3D67B3F51DB246D100A4F4C6 /* Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B011C3F06E900AE3E12 /* Schema.swift */; };
+		3D67B3F61DB246D100A4F4C6 /* Setter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B021C3F06E900AE3E12 /* Setter.swift */; };
+		3D67B3F71DB246D700A4F4C6 /* Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF71C3F06E900AE3E12 /* Foundation.swift */; };
+		3D67B3F81DB246D700A4F4C6 /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF81C3F06E900AE3E12 /* Helpers.swift */; };
+		3D67B3F91DB246E700A4F4C6 /* SQLite-Bridging.m in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */; };
+		3D67B3FA1DB2470600A4F4C6 /* usr/include/sqlite3.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808B1C46E34A0038162A /* usr/include/sqlite3.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3D67B3FB1DB2470600A4F4C6 /* SQLite-Bridging.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808D1C46E5230038162A /* SQLite-Bridging.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3D67B3FC1DB2471B00A4F4C6 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3D67B3FD1DB2472D00A4F4C6 /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */; };
 		EE247AD71C3F04ED00AE3E12 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		EE247ADE1C3F04ED00AE3E12 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE247AD31C3F04ED00AE3E12 /* SQLite.framework */; };
 		EE247B031C3F06E900AE3E12 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
@@ -173,6 +197,7 @@
 		39548A6B1CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
 		39548A6D1CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
 		39548A6F1CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
+		3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.0.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
 		A121AC451CA35C79005A31D1 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AD31C3F04ED00AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AD61C3F04ED00AE3E12 /* SQLite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLite.h; sourceTree = "<group>"; };
@@ -250,6 +275,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				3D67B3E61DB2469200A4F4C6 /* libsqlite3.tbd in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -358,6 +384,14 @@
 			path = watchsimulator;
 			sourceTree = "<group>";
 		};
+		3D67B3E41DB2469200A4F4C6 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
 		EE247AC91C3F04ED00AE3E12 = {
 			isa = PBXGroup;
 			children = (
@@ -365,6 +399,7 @@
 				EE247AE11C3F04ED00AE3E12 /* SQLiteTests */,
 				EE247B8A1C3F81D000AE3E12 /* Metadata */,
 				EE247AD41C3F04ED00AE3E12 /* Products */,
+				3D67B3E41DB2469200A4F4C6 /* Frameworks */,
 			);
 			indentWidth = 4;
 			sourceTree = "<group>";
@@ -517,6 +552,10 @@
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				3D67B3FA1DB2470600A4F4C6 /* usr/include/sqlite3.h in Headers */,
+				3D67B3FB1DB2470600A4F4C6 /* SQLite-Bridging.h in Headers */,
+				3D67B3FC1DB2471B00A4F4C6 /* SQLite.h in Headers */,
+				3D67B3FD1DB2472D00A4F4C6 /* fts3_tokenizer.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -837,6 +876,25 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				3D67B3F91DB246E700A4F4C6 /* SQLite-Bridging.m in Sources */,
+				3D67B3F71DB246D700A4F4C6 /* Foundation.swift in Sources */,
+				3D67B3F81DB246D700A4F4C6 /* Helpers.swift in Sources */,
+				3D67B3E91DB246D100A4F4C6 /* Statement.swift in Sources */,
+				3D67B3EA1DB246D100A4F4C6 /* Value.swift in Sources */,
+				3D67B3EB1DB246D100A4F4C6 /* FTS4.swift in Sources */,
+				3D67B3EC1DB246D100A4F4C6 /* RTree.swift in Sources */,
+				3D67B3ED1DB246D100A4F4C6 /* FTS5.swift in Sources */,
+				3D67B3EE1DB246D100A4F4C6 /* AggregateFunctions.swift in Sources */,
+				3D67B3EF1DB246D100A4F4C6 /* Collation.swift in Sources */,
+				3D67B3F01DB246D100A4F4C6 /* CoreFunctions.swift in Sources */,
+				3D67B3F11DB246D100A4F4C6 /* CustomFunctions.swift in Sources */,
+				3D67B3F21DB246D100A4F4C6 /* Expression.swift in Sources */,
+				3D67B3F31DB246D100A4F4C6 /* Operators.swift in Sources */,
+				3D67B3F41DB246D100A4F4C6 /* Query.swift in Sources */,
+				3D67B3F51DB246D100A4F4C6 /* Schema.swift in Sources */,
+				3D67B3F61DB246D100A4F4C6 /* Setter.swift in Sources */,
+				3D67B3E71DB246BA00A4F4C6 /* Blob.swift in Sources */,
+				3D67B3E81DB246BA00A4F4C6 /* Connection.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1043,8 +1101,6 @@
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
-				"SWIFT_INCLUDE_PATHS[sdk=watchos*]" = "$(SRCROOT)/CocoaPods/watchos";
-				"SWIFT_INCLUDE_PATHS[sdk=watchsimulator*]" = "$(SRCROOT)/CocoaPods/watchsimulator";
 				INFOPLIST_FILE = SQLite/Info.plist;
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@@ -1052,6 +1108,8 @@
 				PRODUCT_NAME = SQLite;
 				SDKROOT = watchos;
 				SKIP_INSTALL = YES;
+				"SWIFT_INCLUDE_PATHS[sdk=watchos*]" = "$(SRCROOT)/CocoaPods/watchos";
+				"SWIFT_INCLUDE_PATHS[sdk=watchsimulator*]" = "$(SRCROOT)/CocoaPods/watchsimulator";
 				SWIFT_VERSION = 3.0;
 				TARGETED_DEVICE_FAMILY = 4;
 				WATCHOS_DEPLOYMENT_TARGET = 2.2;
@@ -1068,8 +1126,6 @@
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
-				"SWIFT_INCLUDE_PATHS[sdk=watchos*]" = "$(SRCROOT)/CocoaPods/watchos";
-				"SWIFT_INCLUDE_PATHS[sdk=watchsimulator*]" = "$(SRCROOT)/CocoaPods/watchsimulator";
 				INFOPLIST_FILE = SQLite/Info.plist;
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@@ -1077,6 +1133,8 @@
 				PRODUCT_NAME = SQLite;
 				SDKROOT = watchos;
 				SKIP_INSTALL = YES;
+				"SWIFT_INCLUDE_PATHS[sdk=watchos*]" = "$(SRCROOT)/CocoaPods/watchos";
+				"SWIFT_INCLUDE_PATHS[sdk=watchsimulator*]" = "$(SRCROOT)/CocoaPods/watchsimulator";
 				SWIFT_VERSION = 3.0;
 				TARGETED_DEVICE_FAMILY = 4;
 				WATCHOS_DEPLOYMENT_TARGET = 2.2;

From 9bed4fcb6db633a40996037f0ca8cfab325c5f42 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 15 Oct 2016 13:28:29 +0200
Subject: [PATCH 105/685] Update bundle

---
 CocoaPodsTests/Gemfile      |  2 +-
 CocoaPodsTests/Gemfile.lock | 30 +++++++++++++++---------------
 2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/CocoaPodsTests/Gemfile b/CocoaPodsTests/Gemfile
index 287dcbfc..29e72332 100644
--- a/CocoaPodsTests/Gemfile
+++ b/CocoaPodsTests/Gemfile
@@ -1,4 +1,4 @@
 source 'https://rubygems.org'
 
-gem 'cocoapods', '~> 1.1.0.rc.2'
+gem 'cocoapods', '~> 1.1.0.rc.3'
 gem 'minitest'
diff --git a/CocoaPodsTests/Gemfile.lock b/CocoaPodsTests/Gemfile.lock
index 93a54bb9..f8cc1118 100644
--- a/CocoaPodsTests/Gemfile.lock
+++ b/CocoaPodsTests/Gemfile.lock
@@ -7,26 +7,26 @@ GEM
       minitest (~> 5.1)
       thread_safe (~> 0.3, >= 0.3.4)
       tzinfo (~> 1.1)
-    claide (1.0.0)
-    cocoapods (1.1.0.rc.2)
+    claide (1.0.1)
+    cocoapods (1.1.0.rc.3)
       activesupport (>= 4.0.2, < 5)
-      claide (>= 1.0.0, < 2.0)
-      cocoapods-core (= 1.1.0.rc.2)
+      claide (>= 1.0.1, < 2.0)
+      cocoapods-core (= 1.1.0.rc.3)
       cocoapods-deintegrate (>= 1.0.1, < 2.0)
       cocoapods-downloader (>= 1.1.1, < 2.0)
       cocoapods-plugins (>= 1.0.0, < 2.0)
       cocoapods-search (>= 1.0.0, < 2.0)
       cocoapods-stats (>= 1.0.0, < 2.0)
-      cocoapods-trunk (>= 1.0.0, < 2.0)
+      cocoapods-trunk (= 1.1.0.beta.1)
       cocoapods-try (>= 1.1.0, < 2.0)
       colored (~> 1.2)
       escape (~> 0.0.4)
-      fourflusher (~> 1.0.1)
+      fourflusher (~> 2.0)
       gh_inspector (~> 1.0)
       molinillo (~> 0.5.1)
       nap (~> 1.0)
-      xcodeproj (>= 1.3.1, < 2.0)
-    cocoapods-core (1.1.0.rc.2)
+      xcodeproj (>= 1.3.2, < 2.0)
+    cocoapods-core (1.1.0.rc.3)
       activesupport (>= 4.0.2, < 5)
       fuzzy_match (~> 2.0.4)
       nap (~> 1.0)
@@ -36,35 +36,35 @@ GEM
       nap
     cocoapods-search (1.0.0)
     cocoapods-stats (1.0.0)
-    cocoapods-trunk (1.0.0)
+    cocoapods-trunk (1.1.0.beta.1)
       nap (>= 0.8, < 2.0)
       netrc (= 0.7.8)
     cocoapods-try (1.1.0)
     colored (1.2)
     escape (0.0.4)
-    fourflusher (1.0.1)
+    fourflusher (2.0.0)
     fuzzy_match (2.0.4)
     gh_inspector (1.0.2)
     i18n (0.7.0)
     json (1.8.3)
-    minitest (5.9.0)
+    minitest (5.9.1)
     molinillo (0.5.1)
     nap (1.1.0)
     netrc (0.7.8)
     thread_safe (0.3.5)
     tzinfo (1.2.2)
       thread_safe (~> 0.1)
-    xcodeproj (1.3.1)
+    xcodeproj (1.3.2)
       activesupport (>= 3)
-      claide (>= 1.0.0, < 2.0)
+      claide (>= 1.0.1, < 2.0)
       colored (~> 1.2)
 
 PLATFORMS
   ruby
 
 DEPENDENCIES
-  cocoapods (~> 1.1.0.rc.2)
+  cocoapods (~> 1.1.0.rc.3)
   minitest
 
 BUNDLED WITH
-   1.10.6
+   1.13.1

From e68f8da46e3025e8e281fb3eb1061073e75bcc9f Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 15 Oct 2016 13:55:08 +0200
Subject: [PATCH 106/685] Don't print logs after failure

---
 .travis.yml | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 925ceee3..d28be8de 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -16,6 +16,3 @@ before_install:
   - gem install xcpretty --no-document
 script:
   - ./run-tests.sh
-after_failure:
-  - find $HOME/Library/Developer/Xcode/DerivedData/ -name '*.log' -print0 | xargs -0 cat
-  - cat /var/log/system.log

From 7d63509c5007550ea71b03cf1117bce0fba3bfbf Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 15 Oct 2016 14:07:31 +0200
Subject: [PATCH 107/685] skip watchOS

---
 CocoaPodsTests/test_running_validator.rb | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/CocoaPodsTests/test_running_validator.rb b/CocoaPodsTests/test_running_validator.rb
index 1a06e48a..949e8489 100644
--- a/CocoaPodsTests/test_running_validator.rb
+++ b/CocoaPodsTests/test_running_validator.rb
@@ -94,8 +94,8 @@ def run_tests
       command += %w(CODE_SIGN_IDENTITY=- -sdk appletvsimulator)
       command += Fourflusher::SimControl.new.destination(tvos_simulator, 'tvOS', deployment_target)
     when :watchos
-      command += %w(CODE_SIGN_IDENTITY=- -sdk watchsimulator)
-      command += Fourflusher::SimControl.new.destination(watchos_simulator, 'watchOS', deployment_target)
+      # there's no XCTest on watchOS (https://openradar.appspot.com/21760513)
+      return
     else
       return
     end

From 517c2b624d6bed5e0d653974d0cb45bca33c821f Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 20 Oct 2016 08:26:26 +0200
Subject: [PATCH 108/685] Connection#pluck can throw

---
 SQLite.playground/Contents.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/SQLite.playground/Contents.swift b/SQLite.playground/Contents.swift
index 2015531a..11e13139 100644
--- a/SQLite.playground/Contents.swift
+++ b/SQLite.playground/Contents.swift
@@ -35,7 +35,7 @@ try! db.run(emails.insert(
     body <- "This is a hello world message."
 ))
 
-let row = db.pluck(emails.match("hello"))
+let row = try! db.pluck(emails.match("hello"))
 
 let query = try! db.prepare(emails.match("hello"))
 for row in query {

From 61bb2dd588751b97195aba4e40b1d3cb0e4dc13f Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 20 Oct 2016 10:43:44 +0200
Subject: [PATCH 109/685] Fix for ~= operator used with Double ranges

---
 SQLite/Typed/Operators.swift     | 4 ++--
 SQLiteTests/OperatorsTests.swift | 7 ++++++-
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/SQLite/Typed/Operators.swift b/SQLite/Typed/Operators.swift
index 616015dc..fdd293be 100644
--- a/SQLite/Typed/Operators.swift
+++ b/SQLite/Typed/Operators.swift
@@ -474,10 +474,10 @@ public func <=<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> wher
     return infix(lhs, rhs)
 }
 
-public func ~=<V : Value>(lhs: CountableClosedRange<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Binding & Comparable {
+public func ~=<V : Value>(lhs: ClosedRange<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Binding & Comparable {
     return Expression("\(rhs.template) BETWEEN ? AND ?", rhs.bindings + [lhs.lowerBound as? Binding, lhs.upperBound as? Binding])
 }
-public func ~=<V : Value>(lhs: CountableClosedRange<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Binding & Comparable {
+public func ~=<V : Value>(lhs: ClosedRange<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Binding & Comparable {
     return Expression("\(rhs.template) BETWEEN ? AND ?", rhs.bindings + [lhs.lowerBound as? Binding, lhs.upperBound as? Binding])
 }
 
diff --git a/SQLiteTests/OperatorsTests.swift b/SQLiteTests/OperatorsTests.swift
index 819cf292..d2ce17ef 100644
--- a/SQLiteTests/OperatorsTests.swift
+++ b/SQLiteTests/OperatorsTests.swift
@@ -245,11 +245,16 @@ class OperatorsTests : XCTestCase {
         AssertSQL("(1 <= \"boolOptional\")", true <= boolOptional)
     }
 
-    func test_patternMatchingOperator_withComparableInterval_buildsBetweenBooleanExpression() {
+    func test_patternMatchingOperator_withComparableCountableClosedRange_buildsBetweenBooleanExpression() {
         AssertSQL("\"int\" BETWEEN 0 AND 5", 0...5 ~= int)
         AssertSQL("\"intOptional\" BETWEEN 0 AND 5", 0...5 ~= intOptional)
     }
 
+    func test_patternMatchingOperator_withComparableClosedRange_buildsBetweenBooleanExpression() {
+        AssertSQL("\"double\" BETWEEN 1.2 AND 4.5", 1.2...4.5 ~= double)
+        AssertSQL("\"doubleOptional\" BETWEEN 1.2 AND 4.5", 1.2...4.5 ~= doubleOptional)
+    }
+
     func test_doubleAndOperator_withBooleanExpressions_buildsCompoundExpression() {
         AssertSQL("(\"bool\" AND \"bool\")", bool && bool)
         AssertSQL("(\"bool\" AND \"boolOptional\")", bool && boolOptional)

From 14c0a48d075906efdc3366ad7a42cdf4ba741169 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 20 Oct 2016 10:48:27 +0200
Subject: [PATCH 110/685] Tag as discardable

---
 SQLite/Typed/Query.swift | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/SQLite/Typed/Query.swift b/SQLite/Typed/Query.swift
index 75f29afd..375c1d0a 100644
--- a/SQLite/Typed/Query.swift
+++ b/SQLite/Typed/Query.swift
@@ -968,7 +968,7 @@ extension Connection {
     /// - Parameter query: An insert query.
     ///
     /// - Returns: The insert’s rowid.
-    public func run(_ query: Insert) throws -> Int64 {
+    @discardableResult public func run(_ query: Insert) throws -> Int64 {
         let expression = query.expression
         return try sync {
             try self.run(expression.template, expression.bindings)
@@ -984,7 +984,7 @@ extension Connection {
     /// - Parameter query: An update query.
     ///
     /// - Returns: The number of updated rows.
-    public func run(_ query: Update) throws -> Int {
+    @discardableResult public func run(_ query: Update) throws -> Int {
         let expression = query.expression
         return try sync {
             try self.run(expression.template, expression.bindings)
@@ -999,7 +999,7 @@ extension Connection {
     /// - Parameter query: A delete query.
     ///
     /// - Returns: The number of deleted rows.
-    public func run(_ query: Delete) throws -> Int {
+    @discardableResult public func run(_ query: Delete) throws -> Int {
         let expression = query.expression
         return try sync {
             try self.run(expression.template, expression.bindings)

From 26ef2597ad40bd42f8a40616c34d857d3f69b40e Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 20 Oct 2016 10:58:35 +0200
Subject: [PATCH 111/685] Test String ranges

---
 SQLiteTests/OperatorsTests.swift | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/SQLiteTests/OperatorsTests.swift b/SQLiteTests/OperatorsTests.swift
index d2ce17ef..f0e585cd 100644
--- a/SQLiteTests/OperatorsTests.swift
+++ b/SQLiteTests/OperatorsTests.swift
@@ -255,6 +255,11 @@ class OperatorsTests : XCTestCase {
         AssertSQL("\"doubleOptional\" BETWEEN 1.2 AND 4.5", 1.2...4.5 ~= doubleOptional)
     }
 
+    func test_patternMatchingOperator_withomparableClosedRangeString_buildsBetweenBooleanExpression() {
+        AssertSQL("\"string\" BETWEEN 'a' AND 'b'", "a"..."b" ~= string)
+        AssertSQL("\"stringOptional\" BETWEEN 'a' AND 'b'", "a"..."b" ~= stringOptional)
+    }
+
     func test_doubleAndOperator_withBooleanExpressions_buildsCompoundExpression() {
         AssertSQL("(\"bool\" AND \"bool\")", bool && bool)
         AssertSQL("(\"bool\" AND \"boolOptional\")", bool && boolOptional)

From d95a518178570c805bb18b971d264b8a48edbcf5 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 21 Oct 2016 08:56:21 +0200
Subject: [PATCH 112/685] Bump version

---
 Documentation/Index.md | 8 ++++----
 README.md              | 4 ++--
 SQLite.swift.podspec   | 2 +-
 SQLite/Info.plist      | 2 +-
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 6107969a..50d7d840 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -78,7 +78,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```
-    github "stephencelis/SQLite.swift" ~> 0.11.0
+    github "stephencelis/SQLite.swift" ~> 0.11.1
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -108,7 +108,7 @@ install SQLite.swift with Carthage:
     ``` ruby
     use_frameworks!
 
-    pod 'SQLite.swift', '~> 0.11.0'
+    pod 'SQLite.swift', '~> 0.11.1'
     ```
 
  4. Run `pod install`.
@@ -119,13 +119,13 @@ install SQLite.swift with Carthage:
  If you want to use a more recent version of SQLite than what is provided with the OS you can require the `standalone` subspec:
 
 ``` ruby
-    pod 'SQLite.swift/standalone', '~> 0.11.0'
+    pod 'SQLite.swift/standalone', '~> 0.11.1'
 ```
 
 By default this will use the most recent version of SQLite without any extras. If you want you can further customize this by adding another dependency to sqlite3 or one of its subspecs:
 
 ``` ruby
-    pod 'SQLite.swift/standalone', '~> 0.11.0'
+    pod 'SQLite.swift/standalone', '~> 0.11.1'
     pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
 ```
 
diff --git a/README.md b/README.md
index 6e9857bd..85767b38 100644
--- a/README.md
+++ b/README.md
@@ -129,7 +129,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```
-    github "stephencelis/SQLite.swift" ~> 0.11.0
+    github "stephencelis/SQLite.swift" ~> 0.11.1
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -159,7 +159,7 @@ SQLite.swift with CocoaPods:
     ``` ruby
     use_frameworks!
 
-    pod 'SQLite.swift', '~> 0.11.0'
+    pod 'SQLite.swift', '~> 0.11.1'
     ```
 
  3. Run `pod install`.
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 9c3a35e0..ac7ed8bb 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.11.0"
+  s.version          = "0.11.1"
   s.summary          = "A type-safe, Swift-language layer over SQLite3 for iOS and OS X."
 
   s.description      = <<-DESC
diff --git a/SQLite/Info.plist b/SQLite/Info.plist
index 03d53553..21f24d9d 100644
--- a/SQLite/Info.plist
+++ b/SQLite/Info.plist
@@ -15,7 +15,7 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>0.11.0</string>
+	<string>0.11.1</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>

From f58ebbf2850693d262af7df4521716bd53c74d12 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 8 Nov 2016 12:45:29 +0000
Subject: [PATCH 113/685] Update CocoaPods doc

---
 Documentation/Index.md | 2 +-
 README.md              | 9 +++++----
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 50d7d840..367236ae 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -100,7 +100,7 @@ install SQLite.swift with Carthage:
     ``` sh
     # Using the default Ruby install will require you to use sudo when
     # installing and updating gems.
-    sudo gem install cocoapods
+    [sudo] gem install cocoapods
     ```
 
  3. Update your Podfile to include the following:
diff --git a/README.md b/README.md
index 85767b38..e3c766a1 100644
--- a/README.md
+++ b/README.md
@@ -145,8 +145,9 @@ install SQLite.swift with Carthage:
 [CocoaPods][] is a dependency manager for Cocoa projects. To install
 SQLite.swift with CocoaPods:
 
- 1. Make sure the latest CocoaPods beta is [installed][CocoaPods
-    Installation]. (SQLite.swift requires version 1.0.0.beta.6 or greater.)
+ 1. Verify that your copy of Xcode is installed in the default location (`/Application/Xcode.app`).
+
+ 2. Make sure the latest CocoaPods beta is [installed][CocoaPods Installation]. (SQLite.swift requires version 1.0.0 or greater.)
 
     ``` sh
     # Using the default Ruby install will require you to use sudo when
@@ -154,7 +155,7 @@ SQLite.swift with CocoaPods:
     [sudo] gem install cocoapods
     ```
 
- 2. Update your Podfile to include the following:
+ 3. Update your Podfile to include the following:
 
     ``` ruby
     use_frameworks!
@@ -162,7 +163,7 @@ SQLite.swift with CocoaPods:
     pod 'SQLite.swift', '~> 0.11.1'
     ```
 
- 3. Run `pod install`.
+ 4. Run `pod install`.
 
 [CocoaPods]: https://cocoapods.org
 [CocoaPods Installation]: https://guides.cocoapods.org/using/getting-started.html#getting-started

From 2d059b0f4a8759d224e0b78f34b26cfd4f6c5f6d Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 8 Nov 2016 13:06:04 +0000
Subject: [PATCH 114/685] Docs: restore migration information

---
 Documentation/Index.md | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 367236ae..77f9d8e6 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1079,11 +1079,22 @@ try db.run(users.drop(ifExists: true))
 ```
 
 
-<!-- ### Migrations and Schema Versioning
+### Migrations and Schema Versioning
 
-SQLite.swift provides a convenience property on `Database` to query and set the [`PRAGMA user_version`](https://sqlite.org/pragma.html#pragma_schema_version). This is a great way to manage your schema’s version over migrations.
+You can add a convenience property on `Connection` to query and set the [`PRAGMA user_version`](https://sqlite.org/pragma.html#pragma_schema_version).
+
+This is a great way to manage your schema’s version over migrations.
 
 ``` swift
+public var userVersion: Int32 {
+      get { return Int32(try! scalar("PRAGMA user_version") as! Int64)}
+      set { try! run("PRAGMA user_version = \(newValue)") }
+}
+```
+
+Then you can conditionally run your migrations along the lines of:
+
+```swift
 if db.userVersion == 0 {
     // handle first migration
     db.userVersion = 1
@@ -1092,7 +1103,7 @@ if db.userVersion == 1 {
     // handle second migration
     db.userVersion = 2
 }
-``` -->
+```
 
 
 ## Custom Types

From bf6a722fc35aef5661edfa165ae43cefbfecd160 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 8 Nov 2016 13:09:05 +0000
Subject: [PATCH 115/685] Add missing boilerplate

---
 Documentation/Index.md | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 77f9d8e6..7fabe836 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1086,9 +1086,11 @@ You can add a convenience property on `Connection` to query and set the [`PRAGMA
 This is a great way to manage your schema’s version over migrations.
 
 ``` swift
-public var userVersion: Int32 {
-      get { return Int32(try! scalar("PRAGMA user_version") as! Int64)}
-      set { try! run("PRAGMA user_version = \(newValue)") }
+extension Connection {
+    public var userVersion: Int32 {
+        get { return Int32(try! scalar("PRAGMA user_version") as! Int64)}
+        set { try! run("PRAGMA user_version = \(newValue)") }
+    }
 }
 ```
 

From d784548f25a2989cda873f158aec63f2d9f9eedd Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 8 Nov 2016 13:10:29 +0000
Subject: [PATCH 116/685] Fix link target

---
 Documentation/Index.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 7fabe836..a8aa0747 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1081,7 +1081,7 @@ try db.run(users.drop(ifExists: true))
 
 ### Migrations and Schema Versioning
 
-You can add a convenience property on `Connection` to query and set the [`PRAGMA user_version`](https://sqlite.org/pragma.html#pragma_schema_version).
+You can add a convenience property on `Connection` to query and set the [`PRAGMA user_version`](https://sqlite.org/pragma.html#pragma_user_version).
 
 This is a great way to manage your schema’s version over migrations.
 

From 8b960d443b9475f5c7866e22a5eb0183bcd9618a Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 10 Nov 2016 15:17:19 +0000
Subject: [PATCH 117/685] Tell users to perform a repo update when installing
 pods

#540
---
 Documentation/Index.md | 2 +-
 README.md              | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index a8aa0747..e5eda36a 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -111,7 +111,7 @@ install SQLite.swift with Carthage:
     pod 'SQLite.swift', '~> 0.11.1'
     ```
 
- 4. Run `pod install`.
+ 4. Run `pod install --repo-update`.
 
 
  #### Requiring a specific version of SQLite
diff --git a/README.md b/README.md
index e3c766a1..14c0f6f6 100644
--- a/README.md
+++ b/README.md
@@ -163,7 +163,7 @@ SQLite.swift with CocoaPods:
     pod 'SQLite.swift', '~> 0.11.1'
     ```
 
- 4. Run `pod install`.
+ 4. Run `pod install --repo-update`.
 
 [CocoaPods]: https://cocoapods.org
 [CocoaPods Installation]: https://guides.cocoapods.org/using/getting-started.html#getting-started

From c2f3fc8b0f2ed5ea413e692952f44b13efe237db Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 12 Nov 2016 16:11:27 +0000
Subject: [PATCH 118/685] Link to SQLiteMigrationManager.swift now that it is
 Swift3 compatible

---
 Documentation/Index.md | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index e5eda36a..3678368b 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1107,6 +1107,8 @@ if db.userVersion == 1 {
 }
 ```
 
+For more complex migration requirements check out the schema management system
+[SQLiteMigrationManager.swift][].
 
 ## Custom Types
 
@@ -1526,3 +1528,4 @@ We can log SQL using the database’s `trace` function.
 
 
 [ROWID]: https://sqlite.org/lang_createtable.html#rowid
+[SQLiteMigrationManager.swift]: https://github.com/garriguv/SQLiteMigrationManager.swift

From 6e30a3d40cdecf94124c43729c7566dd03f0d8d8 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 12 Nov 2016 19:40:24 +0000
Subject: [PATCH 119/685] Add config file for CocoaDocs

---
 .cocoadocs.yml | 2 ++
 1 file changed, 2 insertions(+)
 create mode 100644 .cocoadocs.yml

diff --git a/.cocoadocs.yml b/.cocoadocs.yml
new file mode 100644
index 00000000..27840032
--- /dev/null
+++ b/.cocoadocs.yml
@@ -0,0 +1,2 @@
+additional_guides:
+  - Documentation/Index.md

From 6b784093b8661cd81b2f4a075a8e5880cca2da47 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 15 Nov 2016 08:04:45 +0000
Subject: [PATCH 120/685] Mention FTS5 query differences in docs

Closes #544
---
 Documentation/Index.md | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 3678368b..190c1d2d 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1444,6 +1444,13 @@ let config = FTS5Config()
 
 try db.run(emails.create(.FTS5(config))
 // CREATE VIRTUAL TABLE "emails" USING fts5("subject", "body" UNINDEXED)
+
+// Note that FTS5 uses a different syntax to select columns, so we need to rewrite
+// the last FTS4 query above as:
+let replies = emails.filter(emails.match("subject:\"Re:\"*))
+// SELECT * FROM "emails" WHERE "emails" MATCH 'subject:"Re:"*'
+
+// https://www.sqlite.org/fts5.html#_changes_to_select_statements_
 ```
 
 ## Executing Arbitrary SQL

From 75394dab16991f64672dbf8a11fbb8e80c17a2e7 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 15 Nov 2016 11:27:09 +0000
Subject: [PATCH 121/685] Make lastInsertRowid consistent with other SQLite
 wrappers

closes #532
---
 SQLite/Core/Connection.swift      |  5 ++---
 SQLite/Typed/Query.swift          |  2 +-
 SQLiteTests/ConnectionTests.swift | 22 +++++++++++++++++-----
 3 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index 5d6ebcdc..e96a84b5 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -132,9 +132,8 @@ public final class Connection {
     public var readonly: Bool { return sqlite3_db_readonly(handle, nil) == 1 }
 
     /// The last rowid inserted into the database via this connection.
-    public var lastInsertRowid: Int64? {
-        let rowid = sqlite3_last_insert_rowid(handle)
-        return rowid != 0 ? rowid : nil
+    public var lastInsertRowid: Int64 {
+        return sqlite3_last_insert_rowid(handle)
     }
 
     /// The last number of changes (inserts, updates, or deletes) made to the
diff --git a/SQLite/Typed/Query.swift b/SQLite/Typed/Query.swift
index 375c1d0a..288768c1 100644
--- a/SQLite/Typed/Query.swift
+++ b/SQLite/Typed/Query.swift
@@ -972,7 +972,7 @@ extension Connection {
         let expression = query.expression
         return try sync {
             try self.run(expression.template, expression.bindings)
-            return self.lastInsertRowid!
+            return self.lastInsertRowid
         }
     }
 
diff --git a/SQLiteTests/ConnectionTests.swift b/SQLiteTests/ConnectionTests.swift
index 99b9d8a1..ab0e957c 100644
--- a/SQLiteTests/ConnectionTests.swift
+++ b/SQLiteTests/ConnectionTests.swift
@@ -43,17 +43,29 @@ class ConnectionTests : SQLiteTestCase {
         XCTAssertTrue(db.readonly)
     }
 
-    func test_lastInsertRowid_returnsNilOnNewConnections() {
-        XCTAssert(db.lastInsertRowid == nil)
+    func test_changes_returnsZeroOnNewConnections() {
+        XCTAssertEqual(0, db.changes)
     }
 
     func test_lastInsertRowid_returnsLastIdAfterInserts() {
         try! InsertUser("alice")
-        XCTAssertEqual(1, db.lastInsertRowid!)
+        XCTAssertEqual(1, db.lastInsertRowid)
     }
 
-    func test_changes_returnsZeroOnNewConnections() {
-        XCTAssertEqual(0, db.changes)
+    func test_lastInsertRowid_doesNotResetAfterError() {
+        XCTAssert(db.lastInsertRowid == 0)
+        try! InsertUser("alice")
+        XCTAssertEqual(1, db.lastInsertRowid)
+        XCTAssertThrowsError(
+            try db.run("INSERT INTO \"users\" (email, age, admin) values ('invalid@example.com', 12, 'invalid')")
+        ) { error in
+            if case SQLite.Result.error(_, let code, _) = error {
+                XCTAssertEqual(SQLITE_CONSTRAINT, code)
+            } else {
+                XCTFail("expected error")
+            }
+        }
+        XCTAssertEqual(1, db.lastInsertRowid)
     }
 
     func test_changes_returnsNumberOfChanges() {

From c7480062ee75bea70ba3f4be157c4ffa0bb293ee Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 15 Nov 2016 11:28:22 +0000
Subject: [PATCH 122/685] Add changelog

---
 CHANGELOG.md | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
 create mode 100644 CHANGELOG.md

diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 00000000..ca8da53e
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,15 @@
+0.11.1 (unreleased, [diff][diff-0.11.1])
+========================================
+
+* Made lastInsertRowid consistent with other SQLite wrappers (#532)
+* Fix for ~= operator used with Double ranges
+* Various documentation updates
+
+0.11.0 (19-10-2016)
+===================
+
+* Swift3 migration ([diff][diff-0.11.0])
+
+
+[diff-0.11.1]: https://github.com/stephencelis/SQLite.swift/compare/0.11.1...0.11.0
+[diff-0.11.0]: https://github.com/stephencelis/SQLite.swift/compare/0.10.1...0.11.0

From fbea9bf6593100b10f4473a9c241b841b5b84b36 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 15 Nov 2016 13:03:05 +0000
Subject: [PATCH 123/685] Retry failed builds

---
 .travis.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index d28be8de..192c9979 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,4 +15,4 @@ before_install:
   - gem update bundler
   - gem install xcpretty --no-document
 script:
-  - ./run-tests.sh
+  - travis_retry ./run-tests.sh

From 095026d1b1ec8f249a51a624ff44e200251d2407 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 15 Nov 2016 13:13:00 +0000
Subject: [PATCH 124/685] Add missing imports

---
 SQLiteTests/ConnectionTests.swift | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/SQLiteTests/ConnectionTests.swift b/SQLiteTests/ConnectionTests.swift
index ab0e957c..20d4215a 100644
--- a/SQLiteTests/ConnectionTests.swift
+++ b/SQLiteTests/ConnectionTests.swift
@@ -1,5 +1,10 @@
 import XCTest
 import SQLite
+#if SQLITE_SWIFT_STANDALONE
+import sqlite3
+#elseif COCOAPODS
+import CSQLite
+#endif
 
 class ConnectionTests : SQLiteTestCase {
 

From e177a1d6f3bb85161e326c20423a0ca014b56b4a Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 15 Nov 2016 14:26:10 +0000
Subject: [PATCH 125/685] Switch to released CocoaPods version

---
 CocoaPodsTests/Gemfile      |  2 +-
 CocoaPodsTests/Gemfile.lock | 32 ++++++++++++++++++--------------
 2 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/CocoaPodsTests/Gemfile b/CocoaPodsTests/Gemfile
index 29e72332..94018f18 100644
--- a/CocoaPodsTests/Gemfile
+++ b/CocoaPodsTests/Gemfile
@@ -1,4 +1,4 @@
 source 'https://rubygems.org'
 
-gem 'cocoapods', '~> 1.1.0.rc.3'
+gem 'cocoapods', '~> 1.1.0'
 gem 'minitest'
diff --git a/CocoaPodsTests/Gemfile.lock b/CocoaPodsTests/Gemfile.lock
index f8cc1118..e8879f13 100644
--- a/CocoaPodsTests/Gemfile.lock
+++ b/CocoaPodsTests/Gemfile.lock
@@ -1,6 +1,7 @@
 GEM
   remote: https://rubygems.org/
   specs:
+    CFPropertyList (2.3.3)
     activesupport (4.2.7.1)
       i18n (~> 0.7)
       json (~> 1.7, >= 1.7.7)
@@ -8,63 +9,66 @@ GEM
       thread_safe (~> 0.3, >= 0.3.4)
       tzinfo (~> 1.1)
     claide (1.0.1)
-    cocoapods (1.1.0.rc.3)
+    cocoapods (1.1.1)
       activesupport (>= 4.0.2, < 5)
       claide (>= 1.0.1, < 2.0)
-      cocoapods-core (= 1.1.0.rc.3)
+      cocoapods-core (= 1.1.1)
       cocoapods-deintegrate (>= 1.0.1, < 2.0)
-      cocoapods-downloader (>= 1.1.1, < 2.0)
+      cocoapods-downloader (>= 1.1.2, < 2.0)
       cocoapods-plugins (>= 1.0.0, < 2.0)
       cocoapods-search (>= 1.0.0, < 2.0)
       cocoapods-stats (>= 1.0.0, < 2.0)
-      cocoapods-trunk (= 1.1.0.beta.1)
+      cocoapods-trunk (>= 1.1.1, < 2.0)
       cocoapods-try (>= 1.1.0, < 2.0)
       colored (~> 1.2)
       escape (~> 0.0.4)
-      fourflusher (~> 2.0)
+      fourflusher (~> 2.0.1)
       gh_inspector (~> 1.0)
       molinillo (~> 0.5.1)
       nap (~> 1.0)
-      xcodeproj (>= 1.3.2, < 2.0)
-    cocoapods-core (1.1.0.rc.3)
+      xcodeproj (>= 1.3.3, < 2.0)
+    cocoapods-core (1.1.1)
       activesupport (>= 4.0.2, < 5)
       fuzzy_match (~> 2.0.4)
       nap (~> 1.0)
     cocoapods-deintegrate (1.0.1)
-    cocoapods-downloader (1.1.1)
+    cocoapods-downloader (1.1.2)
     cocoapods-plugins (1.0.0)
       nap
     cocoapods-search (1.0.0)
     cocoapods-stats (1.0.0)
-    cocoapods-trunk (1.1.0.beta.1)
+    cocoapods-trunk (1.1.1)
       nap (>= 0.8, < 2.0)
       netrc (= 0.7.8)
     cocoapods-try (1.1.0)
     colored (1.2)
     escape (0.0.4)
-    fourflusher (2.0.0)
+    fourflusher (2.0.1)
     fuzzy_match (2.0.4)
     gh_inspector (1.0.2)
     i18n (0.7.0)
     json (1.8.3)
     minitest (5.9.1)
-    molinillo (0.5.1)
+    molinillo (0.5.4)
+    nanaimo (0.2.2)
     nap (1.1.0)
     netrc (0.7.8)
     thread_safe (0.3.5)
     tzinfo (1.2.2)
       thread_safe (~> 0.1)
-    xcodeproj (1.3.2)
+    xcodeproj (1.4.1)
+      CFPropertyList (~> 2.3.3)
       activesupport (>= 3)
       claide (>= 1.0.1, < 2.0)
       colored (~> 1.2)
+      nanaimo (~> 0.2.0)
 
 PLATFORMS
   ruby
 
 DEPENDENCIES
-  cocoapods (~> 1.1.0.rc.3)
+  cocoapods (~> 1.1.0)
   minitest
 
 BUNDLED WITH
-   1.13.1
+   1.13.3

From bb3b7059a324651e89357da0e6edeaa2c5d06d36 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 16 Nov 2016 15:09:42 +0000
Subject: [PATCH 126/685] public check method, needed for #389

---
 SQLite/Core/Connection.swift      | 2 +-
 SQLiteTests/ConnectionTests.swift | 7 +++++++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index e96a84b5..6b447305 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -674,7 +674,7 @@ public final class Connection {
         return success!
     }
 
-    @discardableResult func check(_ resultCode: Int32, statement: Statement? = nil) throws -> Int32 {
+    @discardableResult public func check(_ resultCode: Int32, statement: Statement? = nil) throws -> Int32 {
         guard let error = Result(errorCode: resultCode, connection: self, statement: statement) else {
             return resultCode
         }
diff --git a/SQLiteTests/ConnectionTests.swift b/SQLiteTests/ConnectionTests.swift
index 20d4215a..6455d30a 100644
--- a/SQLiteTests/ConnectionTests.swift
+++ b/SQLiteTests/ConnectionTests.swift
@@ -338,4 +338,11 @@ class ConnectionTests : SQLiteTestCase {
         AssertThrows(try stmt.run())
     }
 
+    func test_check_with_successCode_returnsCode() {
+        try! XCTAssertEqual(SQLITE_OK, db.check(SQLITE_OK))
+    }
+
+    func test_check_with_errorCode_throws() {
+        XCTAssertThrowsError(try db.check(SQLITE_CONSTRAINT))
+    }
 }

From 6b8661afdf4128379f6382ee55e8eea2b444e5ea Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 16 Nov 2016 15:11:09 +0000
Subject: [PATCH 127/685] Try out xcode 8.1

---
 .travis.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index 192c9979..b27d7061 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,6 @@
 language: objective-c
 rvm: 2.2
-osx_image: xcode8
+osx_image: xcode8.1
 env:
   global:
     - IOS_SIMULATOR="iPhone SE"

From 433d2479939ba583e3d15939c081126cbd027c0b Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 20 Nov 2016 09:43:21 +0000
Subject: [PATCH 128/685] Xcode 8.2

---
 .travis.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index b27d7061..9138ddb7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,6 @@
 language: objective-c
 rvm: 2.2
-osx_image: xcode8.1
+osx_image: xcode8.2
 env:
   global:
     - IOS_SIMULATOR="iPhone SE"

From fbf994a331c3f5a2fc1729be5e35605c1943c31b Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 20 Nov 2016 09:51:04 +0000
Subject: [PATCH 129/685] Specify destination

---
 Makefile | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile
index 2f085b6c..bb459c2c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 BUILD_TOOL = xcodebuild
 BUILD_SCHEME = SQLite Mac
-IOS_SIMULATOR = iPhone SE
+IOS_SIMULATOR = iPhone 6s
 ifeq ($(BUILD_SCHEME),SQLite iOS)
-	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -destination "platform=iOS Simulator,name=$(IOS_SIMULATOR)"
+	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -destination "platform=iOS Simulator,name=$(IOS_SIMULATOR),OS=9.3"
 else
 	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)"
 endif

From 6e53f365d7d3d871f95b1705e8af8e0fb9e4e293 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 20 Nov 2016 10:56:08 +0000
Subject: [PATCH 130/685] Use 6s

---
 .travis.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index 9138ddb7..9e06164f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,7 +3,7 @@ rvm: 2.2
 osx_image: xcode8.2
 env:
   global:
-    - IOS_SIMULATOR="iPhone SE"
+    - IOS_SIMULATOR="iPhone 6s"
 matrix:
   include:
     - env: BUILD_SCHEME="SQLite iOS"

From cbf5e0e92103180e539f4e883b3f32ff28ecf0d1 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 20 Nov 2016 11:01:06 +0000
Subject: [PATCH 131/685] Remove travis_retry workaround

---
 .travis.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index 9e06164f..833c67d5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,4 +15,4 @@ before_install:
   - gem update bundler
   - gem install xcpretty --no-document
 script:
-  - travis_retry ./run-tests.sh
+  - ./run-tests.sh

From f23969f589e84d7f542dbe83db7a7bd391f363dd Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 20 Nov 2016 11:14:04 +0000
Subject: [PATCH 132/685] Specify iOS version

---
 .travis.yml | 1 +
 Makefile    | 3 ++-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index 833c67d5..818639c4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,6 +4,7 @@ osx_image: xcode8.2
 env:
   global:
     - IOS_SIMULATOR="iPhone 6s"
+    - IOS_VERSION="9.3"
 matrix:
   include:
     - env: BUILD_SCHEME="SQLite iOS"
diff --git a/Makefile b/Makefile
index bb459c2c..537fb1ff 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,9 @@
 BUILD_TOOL = xcodebuild
 BUILD_SCHEME = SQLite Mac
 IOS_SIMULATOR = iPhone 6s
+IOS_VERSION = 9.3
 ifeq ($(BUILD_SCHEME),SQLite iOS)
-	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -destination "platform=iOS Simulator,name=$(IOS_SIMULATOR),OS=9.3"
+	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -destination "platform=iOS Simulator,name=$(IOS_SIMULATOR),OS=$(IOS_VERSION)"
 else
 	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)"
 endif

From 2e6e3c93b926f8e31d1a52f84c3790826302c1eb Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 20 Nov 2016 12:49:21 +0000
Subject: [PATCH 133/685] Remove env

---
 .travis.yml | 1 -
 1 file changed, 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index 818639c4..833c67d5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,7 +4,6 @@ osx_image: xcode8.2
 env:
   global:
     - IOS_SIMULATOR="iPhone 6s"
-    - IOS_VERSION="9.3"
 matrix:
   include:
     - env: BUILD_SCHEME="SQLite iOS"

From 3472f4e47988223047c6ae0768c6c0ce6c584480 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 4 Dec 2016 20:52:47 +0000
Subject: [PATCH 134/685] Split testing into separate commands

---
 CocoaPodsTests/test_running_validator.rb | 2 +-
 Makefile                                 | 5 +++--
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/CocoaPodsTests/test_running_validator.rb b/CocoaPodsTests/test_running_validator.rb
index 949e8489..410f9465 100644
--- a/CocoaPodsTests/test_running_validator.rb
+++ b/CocoaPodsTests/test_running_validator.rb
@@ -79,7 +79,7 @@ def add_test_target(pod_file)
 
   def run_tests
     command = [
-      'clean', 'test',
+      'clean', 'build', 'build-for-testing', 'test-without-building',
       '-workspace', File.join(validation_dir, "#{APP_TARGET}.xcworkspace"),
       '-scheme', TEST_TARGET,
       '-configuration', 'Debug'
diff --git a/Makefile b/Makefile
index 537fb1ff..d4f51d53 100644
--- a/Makefile
+++ b/Makefile
@@ -11,6 +11,7 @@ endif
 XCPRETTY := $(shell command -v xcpretty)
 SWIFTCOV := $(shell command -v swiftcov)
 GCOVR := $(shell command -v gcovr)
+TEST_ACTIONS := clean build build-for-testing test-without-building
 
 default: test
 
@@ -19,9 +20,9 @@ build:
 
 test:
 ifdef XCPRETTY
-	@set -o pipefail && $(BUILD_TOOL) $(BUILD_ARGUMENTS) test | $(XCPRETTY) -c
+	@set -o pipefail && $(BUILD_TOOL) $(BUILD_ARGUMENTS) $(TEST_ACTIONS) | $(XCPRETTY) -c
 else
-	$(BUILD_TOOL) $(BUILD_ARGUMENTS) test
+	$(BUILD_TOOL) $(BUILD_ARGUMENTS) $(TEST_ACTIONS)
 endif
 
 coverage:

From 0613cf53f68aea306463d3c4322ba15e5230e320 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 5 Dec 2016 00:30:55 +0000
Subject: [PATCH 135/685] Update changelog

---
 CHANGELOG.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ca8da53e..6cfd1fe6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,11 +1,11 @@
-0.11.1 (unreleased, [diff][diff-0.11.1])
+0.11.1 (05-12-2016), [diff][diff-0.11.1])
 ========================================
 
 * Made lastInsertRowid consistent with other SQLite wrappers (#532)
 * Fix for ~= operator used with Double ranges
 * Various documentation updates
 
-0.11.0 (19-10-2016)
+0.11.0 (10-19-2016)
 ===================
 
 * Swift3 migration ([diff][diff-0.11.0])

From e2eb4fd6556d852045af96abc35c3c85175418ad Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 5 Dec 2016 14:03:58 +0000
Subject: [PATCH 136/685] Integrate SQLCipher

---
 CHANGELOG.md                      |  1 +
 Documentation/Index.md            | 22 ++++++++-
 README.md                         |  3 +-
 SQLite.swift.podspec              | 11 +++++
 SQLite.xcodeproj/project.pbxproj  | 18 +++++++
 SQLite/Core/Cipher.swift          | 29 +++++++++++
 SQLite/Core/Connection.swift      | 81 ++++++++++++++++++-------------
 SQLite/Core/Statement.swift       |  2 +
 SQLite/Helpers.swift              |  2 +
 SQLiteTests/CipherTests.swift     | 74 ++++++++++++++++++++++++++++
 SQLiteTests/ConnectionTests.swift |  2 +
 SQLiteTests/FTS4Tests.swift       |  2 +-
 12 files changed, 209 insertions(+), 38 deletions(-)
 create mode 100644 SQLite/Core/Cipher.swift
 create mode 100644 SQLiteTests/CipherTests.swift

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6cfd1fe6..34cd0bc4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
 0.11.1 (05-12-2016), [diff][diff-0.11.1])
 ========================================
 
+* Integrate SQLCipher via CocoaPods (#546)
 * Made lastInsertRowid consistent with other SQLite wrappers (#532)
 * Fix for ~= operator used with Double ranges
 * Various documentation updates
diff --git a/Documentation/Index.md b/Documentation/Index.md
index 190c1d2d..82e9f43f 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -131,10 +131,30 @@ By default this will use the most recent version of SQLite without any extras. I
 
 See the [sqlite3 podspec][sqlite3pod] for more details.
 
+#### Using SQLite.swift with SQLCipher
+
+If you want to use [SQLCipher][] with SQLite.swift you can require the `sqlcipher`
+subspec in your Podfile:
+
+``` ruby
+    pod 'SQLite.swift/sqlcipher', '~> 0.11.1'
+```
+
+This will automatically add a dependency to the SQLCipher pod as well as extend
+`Connection` with methods to change the database key:
+
+``` swift
+import SQLite
+
+let db = try Connection("path/to/db.sqlite3")
+try db.key("secret")
+try db.rekey("another secret")
+```
+
 [CocoaPods]: https://cocoapods.org
 [CocoaPods Installation]: https://guides.cocoapods.org/using/getting-started.html#getting-started
 [sqlite3pod]: https://github.com/clemensg/sqlite3pod
-
+[SQLCipher]: https://www.zetetic.net/sqlcipher/
 
 ### Manual
 
diff --git a/README.md b/README.md
index 14c0f6f6..a9b44abe 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@ syntax _and_ intent.
  - [Full-text search][] support
  - [Well-documented][See Documentation]
  - Extensively tested
- - Companion project has [SQLCipher support](https://github.com/stephencelis/SQLiteCipher.swift)
+ - SQLCipher support via CocoaPods
  - Active support at [StackOverflow](http://stackoverflow.com/questions/tagged/sqlite.swift), and [Gitter Chat Room](https://gitter.im/stephencelis/SQLite.swift) (_experimental_)
 
 [Full-text search]: Documentation/Index.md#full-text-search
@@ -224,7 +224,6 @@ file](./LICENSE.txt) for more information.
 
 These projects enhance or use SQLite.swift:
 
- - [SQLiteCipher.swift](https://github.com/stephencelis/SQLiteCipher.swift)
  - [SQLiteMigrationManager.swift](https://github.com/garriguv/SQLiteMigrationManager.swift) (inspired by [FMDBMigrationManager](https://github.com/layerhq/FMDBMigrationManager))
 
 
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index ac7ed8bb..fb17adda 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -52,4 +52,15 @@ Pod::Spec.new do |s|
 
     ss.dependency 'sqlite3'
   end
+
+  s.subspec 'sqlcipher' do |ss|
+    ss.source_files = 'SQLite/**/*.{c,h,m,swift}'
+    ss.private_header_files = 'SQLite/Core/fts3_tokenizer.h'
+    ss.xcconfig = {
+      'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_SWIFT_SQLCIPHER',
+      'GCC_PREPROCESSOR_DEFINITIONS' => 'SQLITE_HAS_CODEC=1',
+      'OTHER_CFLAGS' => '-DSQLITE_HAS_CODEC'
+    }
+    ss.dependency 'SQLCipher'
+  end
 end
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 7b33eac6..69cd87fb 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -51,8 +51,15 @@
 		19A17254FBA7894891F7297B /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
 		19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
 		19A1750CEE9B05267995CF3D /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
+		19A177CC33F2E6A24AF90B02 /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
 		19A178072B371489E6A1E839 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
+		19A179A0C45377CB09BB358C /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
+		19A179C2C078DDD29E052DA9 /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171CACA25EB58FE045146 /* Cipher.swift */; };
+		19A17BF0509EA4A026530E23 /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171CACA25EB58FE045146 /* Cipher.swift */; };
+		19A17C4B951CB054EE48AB1C /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
 		19A17E04C4C0956715C5676A /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
+		19A17E24574F51C37C04C758 /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171CACA25EB58FE045146 /* Cipher.swift */; };
+		19A17E7E3DA4966FA2921857 /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171CACA25EB58FE045146 /* Cipher.swift */; };
 		19A17EC0D68BA8C03288ADF7 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
 		19A17FB80B94E882050AA908 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
 		3D67B3E61DB2469200A4F4C6 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */; };
@@ -187,8 +194,10 @@
 		03A65E5A1C6BB0F50062603F /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		03A65E631C6BB0F60062603F /* SQLiteTests tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SQLiteTests tvOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
 		03A65E961C6BB3210062603F /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
+		19A171CACA25EB58FE045146 /* Cipher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cipher.swift; sourceTree = "<group>"; };
 		19A1721B8984686B9963B45D /* FTS5Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5Tests.swift; sourceTree = "<group>"; };
 		19A1730E4390C775C25677D1 /* FTS5.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5.swift; sourceTree = "<group>"; };
+		19A17399EA9E61235D5D77BF /* CipherTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CipherTests.swift; sourceTree = "<group>"; };
 		19A1794CC4D7827E997E32A7 /* FoundationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationTests.swift; sourceTree = "<group>"; };
 		39548A631CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
 		39548A651CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
@@ -455,6 +464,7 @@
 				EE247AE41C3F04ED00AE3E12 /* Info.plist */,
 				19A1721B8984686B9963B45D /* FTS5Tests.swift */,
 				19A1794CC4D7827E997E32A7 /* FoundationTests.swift */,
+				19A17399EA9E61235D5D77BF /* CipherTests.swift */,
 			);
 			path = SQLiteTests;
 			sourceTree = "<group>";
@@ -469,6 +479,7 @@
 				EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */,
 				EE247AF21C3F06E900AE3E12 /* Statement.swift */,
 				EE247AF31C3F06E900AE3E12 /* Value.swift */,
+				19A171CACA25EB58FE045146 /* Cipher.swift */,
 			);
 			path = Core;
 			sourceTree = "<group>";
@@ -845,6 +856,7 @@
 				03A65E771C6BB2E60062603F /* Connection.swift in Sources */,
 				03A65E7E1C6BB2FB0062603F /* AggregateFunctions.swift in Sources */,
 				19A17EC0D68BA8C03288ADF7 /* FTS5.swift in Sources */,
+				19A179C2C078DDD29E052DA9 /* Cipher.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -869,6 +881,7 @@
 				03A65E951C6BB3030062603F /* TestHelpers.swift in Sources */,
 				19A17254FBA7894891F7297B /* FTS5Tests.swift in Sources */,
 				19A17E04C4C0956715C5676A /* FoundationTests.swift in Sources */,
+				19A179A0C45377CB09BB358C /* CipherTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -895,6 +908,7 @@
 				3D67B3F61DB246D100A4F4C6 /* Setter.swift in Sources */,
 				3D67B3E71DB246BA00A4F4C6 /* Blob.swift in Sources */,
 				3D67B3E81DB246BA00A4F4C6 /* Connection.swift in Sources */,
+				19A17E7E3DA4966FA2921857 /* Cipher.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -921,6 +935,7 @@
 				EE247B071C3F06E900AE3E12 /* Statement.swift in Sources */,
 				EE247B0D1C3F06E900AE3E12 /* AggregateFunctions.swift in Sources */,
 				19A1717B10CC941ACB5533D6 /* FTS5.swift in Sources */,
+				19A17E24574F51C37C04C758 /* Cipher.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -945,6 +960,7 @@
 				EE247B251C3F137700AE3E12 /* ConnectionTests.swift in Sources */,
 				19A171E6FA242F72A308C594 /* FTS5Tests.swift in Sources */,
 				19A17FB80B94E882050AA908 /* FoundationTests.swift in Sources */,
+				19A177CC33F2E6A24AF90B02 /* CipherTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -971,6 +987,7 @@
 				EE247B661C3F3FEC00AE3E12 /* Connection.swift in Sources */,
 				EE247B6D1C3F3FEC00AE3E12 /* AggregateFunctions.swift in Sources */,
 				19A1750CEE9B05267995CF3D /* FTS5.swift in Sources */,
+				19A17BF0509EA4A026530E23 /* Cipher.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -995,6 +1012,7 @@
 				EE247B5B1C3F3FC700AE3E12 /* QueryTests.swift in Sources */,
 				19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */,
 				19A178072B371489E6A1E839 /* FoundationTests.swift in Sources */,
+				19A17C4B951CB054EE48AB1C /* CipherTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/SQLite/Core/Cipher.swift b/SQLite/Core/Cipher.swift
new file mode 100644
index 00000000..3533854e
--- /dev/null
+++ b/SQLite/Core/Cipher.swift
@@ -0,0 +1,29 @@
+#if SQLITE_SWIFT_SQLCIPHER
+import SQLCipher
+
+extension Connection {
+    public func key(_ key: String) throws {
+        try check(sqlite3_key(handle, key, Int32(key.utf8.count)))
+        try execute(
+            "CREATE TABLE \"__SQLCipher.swift__\" (\"cipher key check\");\n" +
+            "DROP TABLE \"__SQLCipher.swift__\";"
+        )
+    }
+
+    public func rekey(_ key: String) throws {
+        try check(sqlite3_rekey(handle, key, Int32(key.utf8.count)))
+    }
+
+    public func key(_ key: Blob) throws {
+        try check(sqlite3_key(handle, key.bytes, Int32(key.bytes.count)))
+        try execute(
+            "CREATE TABLE \"__SQLCipher.swift__\" (\"cipher key check\");\n" +
+            "DROP TABLE \"__SQLCipher.swift__\";"
+        )
+    }
+
+    public func rekey(_ key: Blob) throws {
+        try check(sqlite3_rekey(handle, key.bytes, Int32(key.bytes.count)))
+    }
+}
+#endif
diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index 6b447305..42cfc2a5 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -26,6 +26,8 @@ import Foundation.NSUUID
 import Dispatch
 #if SQLITE_SWIFT_STANDALONE
 import sqlite3
+#elseif SQLITE_SWIFT_SQLCIPHER
+import SQLCipher
 #elseif COCOAPODS
 import CSQLite
 #endif
@@ -411,11 +413,15 @@ public final class Connection {
     ///
     ///       db.trace { SQL in print(SQL) }
     public func trace(_ callback: ((String) -> Void)?) {
-        if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) {
-            trace_v2(callback)
-        } else {
+        #if SQLITE_SWIFT_SQLCIPHER
             trace_v1(callback)
-        }
+        #else
+            if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) {
+                trace_v2(callback)
+            } else {
+                trace_v1(callback)
+            }
+        #endif
     }
 
     fileprivate func trace_v1(_ callback: ((String) -> Void)?) {
@@ -439,37 +445,8 @@ public final class Connection {
         trace = box
     }
 
-    @available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *)
-    fileprivate func trace_v2(_ callback: ((String) -> Void)?) {
-        guard let callback = callback else {
-            // If the X callback is NULL or if the M mask is zero, then tracing is disabled.
-            sqlite3_trace_v2(handle, 0 /* mask */, nil /* xCallback */, nil /* pCtx */)
-            trace = nil
-            return
-        }
 
-        let box: Trace = { (pointer: UnsafeRawPointer) in
-            callback(String(cString: pointer.assumingMemoryBound(to: UInt8.self)))
-        }
-        sqlite3_trace_v2(handle,
-            UInt32(SQLITE_TRACE_STMT) /* mask */,
-            {
-                // A trace callback is invoked with four arguments: callback(T,C,P,X).
-                // The T argument is one of the SQLITE_TRACE constants to indicate why the
-                // callback was invoked. The C argument is a copy of the context pointer.
-                // The P and X arguments are pointers whose meanings depend on T.
-                (T: UInt32, C: UnsafeMutableRawPointer?, P: UnsafeMutableRawPointer?, X: UnsafeMutableRawPointer?) in
-                    if let P = P,
-                       let expandedSQL = sqlite3_expanded_sql(OpaquePointer(P)) {
-                        unsafeBitCast(C, to: Trace.self)(expandedSQL)
-                        sqlite3_free(expandedSQL)
-                    }
-                    return Int32(0) // currently ignored
-            },
-            unsafeBitCast(box, to: UnsafeMutableRawPointer.self) /* pCtx */
-        )
-        trace = box
-    }
+
 
     fileprivate typealias Trace = @convention(block) (UnsafeRawPointer) -> Void
     fileprivate var trace: Trace?
@@ -740,3 +717,39 @@ extension Result : CustomStringConvertible {
     }
 
 }
+
+#if !SQLITE_SWIFT_SQLCIPHER
+@available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *)
+extension Connection {
+    fileprivate func trace_v2(_ callback: ((String) -> Void)?) {
+        guard let callback = callback else {
+            // If the X callback is NULL or if the M mask is zero, then tracing is disabled.
+            sqlite3_trace_v2(handle, 0 /* mask */, nil /* xCallback */, nil /* pCtx */)
+            trace = nil
+            return
+        }
+
+        let box: Trace = { (pointer: UnsafeRawPointer) in
+            callback(String(cString: pointer.assumingMemoryBound(to: UInt8.self)))
+        }
+        sqlite3_trace_v2(handle,
+            UInt32(SQLITE_TRACE_STMT) /* mask */,
+            {
+                // A trace callback is invoked with four arguments: callback(T,C,P,X).
+                // The T argument is one of the SQLITE_TRACE constants to indicate why the
+                // callback was invoked. The C argument is a copy of the context pointer.
+                // The P and X arguments are pointers whose meanings depend on T.
+                (T: UInt32, C: UnsafeMutableRawPointer?, P: UnsafeMutableRawPointer?, X: UnsafeMutableRawPointer?) in
+                    if let P = P,
+                       let expandedSQL = sqlite3_expanded_sql(OpaquePointer(P)) {
+                        unsafeBitCast(C, to: Trace.self)(expandedSQL)
+                        sqlite3_free(expandedSQL)
+                    }
+                    return Int32(0) // currently ignored
+            },
+            unsafeBitCast(box, to: UnsafeMutableRawPointer.self) /* pCtx */
+        )
+        trace = box
+    }
+}
+#endif
diff --git a/SQLite/Core/Statement.swift b/SQLite/Core/Statement.swift
index 64b9017f..1dc3e93d 100644
--- a/SQLite/Core/Statement.swift
+++ b/SQLite/Core/Statement.swift
@@ -24,6 +24,8 @@
 
 #if SQLITE_SWIFT_STANDALONE
 import sqlite3
+#elseif SQLITE_SWIFT_SQLCIPHER
+import SQLCipher
 #elseif COCOAPODS
 import CSQLite
 #endif
diff --git a/SQLite/Helpers.swift b/SQLite/Helpers.swift
index febdc949..08c9a144 100644
--- a/SQLite/Helpers.swift
+++ b/SQLite/Helpers.swift
@@ -24,6 +24,8 @@
 
 #if SQLITE_SWIFT_STANDALONE
 import sqlite3
+#elseif SQLITE_SWIFT_SQLCIPHER
+import SQLCipher
 #elseif COCOAPODS
 import CSQLite
 #endif
diff --git a/SQLiteTests/CipherTests.swift b/SQLiteTests/CipherTests.swift
new file mode 100644
index 00000000..89b67f76
--- /dev/null
+++ b/SQLiteTests/CipherTests.swift
@@ -0,0 +1,74 @@
+#if SQLITE_SWIFT_SQLCIPHER
+import XCTest
+import SQLite
+import SQLCipher
+
+class CipherTests: XCTestCase {
+
+    let db = try! Connection()
+    let db2 = try! Connection()
+
+    override func setUp() {
+        // db
+        try! db.key("hello")
+
+        try! db.run("CREATE TABLE foo (bar TEXT)")
+        try! db.run("INSERT INTO foo (bar) VALUES ('world')")
+
+        // db2
+        let keyData = NSMutableData(length: 64)!
+        let _ = SecRandomCopyBytes(kSecRandomDefault, 64,
+                                   keyData.mutableBytes.assumingMemoryBound(to: UInt8.self))
+        try! db2.key(Blob(bytes: keyData.bytes, length: keyData.length))
+
+        try! db2.run("CREATE TABLE foo (bar TEXT)")
+        try! db2.run("INSERT INTO foo (bar) VALUES ('world')")
+
+        super.setUp()
+    }
+
+    func test_key() {
+        XCTAssertEqual(1, try! db.scalar("SELECT count(*) FROM foo") as? Int64)
+    }
+
+    func test_rekey() {
+        try! db.rekey("goodbye")
+        XCTAssertEqual(1, try! db.scalar("SELECT count(*) FROM foo") as? Int64)
+    }
+
+    func test_data_key() {
+        XCTAssertEqual(1, try! db2.scalar("SELECT count(*) FROM foo") as? Int64)
+    }
+
+    func test_data_rekey() {
+        let keyData = NSMutableData(length: 64)!
+        let _  = SecRandomCopyBytes(kSecRandomDefault, 64,
+                           keyData.mutableBytes.assumingMemoryBound(to: UInt8.self))
+
+        try! db2.rekey(Blob(bytes: keyData.bytes, length: keyData.length))
+        XCTAssertEqual(1, try! db2.scalar("SELECT count(*) FROM foo") as? Int64)
+    }
+
+    func test_keyFailure() {
+        let path = "\(NSTemporaryDirectory())/db.sqlite3"
+        _ = try? FileManager.default.removeItem(atPath: path)
+
+        let connA = try! Connection(path)
+        defer { try! FileManager.default.removeItem(atPath: path) }
+
+        try! connA.key("hello")
+
+        let connB = try! Connection(path)
+
+        var rc: Int32?
+        do {
+            try connB.key("world")
+        } catch Result.error(_, let code, _) {
+            rc = code
+        } catch {
+            XCTFail()
+        }
+        XCTAssertEqual(SQLITE_NOTADB, rc)
+    }
+}
+#endif
diff --git a/SQLiteTests/ConnectionTests.swift b/SQLiteTests/ConnectionTests.swift
index 6455d30a..e5e690f7 100644
--- a/SQLiteTests/ConnectionTests.swift
+++ b/SQLiteTests/ConnectionTests.swift
@@ -2,6 +2,8 @@ import XCTest
 import SQLite
 #if SQLITE_SWIFT_STANDALONE
 import sqlite3
+#elseif SQLITE_SWIFT_SQLCIPHER
+import SQLCipher
 #elseif COCOAPODS
 import CSQLite
 #endif
diff --git a/SQLiteTests/FTS4Tests.swift b/SQLiteTests/FTS4Tests.swift
index b2ccc86c..4373bf8b 100644
--- a/SQLiteTests/FTS4Tests.swift
+++ b/SQLiteTests/FTS4Tests.swift
@@ -176,7 +176,7 @@ class FTS4ConfigTests : XCTestCase {
 }
 
 class FTS4IntegrationTests : SQLiteTestCase {
-#if !SQLITE_SWIFT_STANDALONE
+#if !SQLITE_SWIFT_STANDALONE && !SQLITE_SWIFT_SQLCIPHER
     func test_registerTokenizer_registersTokenizer() {
         let emails = VirtualTable("emails")
         let subject = Expression<String?>("subject")

From 3d85793876d65198b17749db784ac4081030cba3 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 5 Dec 2016 14:55:15 +0000
Subject: [PATCH 137/685] Add sqlcipher subspec

---
 .travis.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.travis.yml b/.travis.yml
index 833c67d5..3de39c11 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,6 +11,7 @@ matrix:
     - env: VALIDATOR_SUBSPEC="none"
     - env: VALIDATOR_SUBSPEC="standard"
     - env: VALIDATOR_SUBSPEC="standalone"
+    - env: VALIDATOR_SUBSPEC="sqlcipher"
 before_install:
   - gem update bundler
   - gem install xcpretty --no-document

From 20a10a3492e688df7b246ae99beecce83a664b35 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 5 Dec 2016 19:19:39 +0000
Subject: [PATCH 138/685] WS

---
 Documentation/Index.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 82e9f43f..49acfc55 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -114,7 +114,7 @@ install SQLite.swift with Carthage:
  4. Run `pod install --repo-update`.
 
 
- #### Requiring a specific version of SQLite
+#### Requiring a specific version of SQLite
 
  If you want to use a more recent version of SQLite than what is provided with the OS you can require the `standalone` subspec:
 

From ffd079317fea9b703322ce8a35831974bf60ae7a Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 5 Dec 2016 19:27:56 +0000
Subject: [PATCH 139/685] Revert "public check method, needed for #389"

This reverts commit bb3b7059a324651e89357da0e6edeaa2c5d06d36.
---
 SQLite/Core/Connection.swift      | 2 +-
 SQLiteTests/ConnectionTests.swift | 7 -------
 2 files changed, 1 insertion(+), 8 deletions(-)

diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index 42cfc2a5..cad25996 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -651,7 +651,7 @@ public final class Connection {
         return success!
     }
 
-    @discardableResult public func check(_ resultCode: Int32, statement: Statement? = nil) throws -> Int32 {
+    @discardableResult func check(_ resultCode: Int32, statement: Statement? = nil) throws -> Int32 {
         guard let error = Result(errorCode: resultCode, connection: self, statement: statement) else {
             return resultCode
         }
diff --git a/SQLiteTests/ConnectionTests.swift b/SQLiteTests/ConnectionTests.swift
index e5e690f7..3b255fd0 100644
--- a/SQLiteTests/ConnectionTests.swift
+++ b/SQLiteTests/ConnectionTests.swift
@@ -340,11 +340,4 @@ class ConnectionTests : SQLiteTestCase {
         AssertThrows(try stmt.run())
     }
 
-    func test_check_with_successCode_returnsCode() {
-        try! XCTAssertEqual(SQLITE_OK, db.check(SQLITE_OK))
-    }
-
-    func test_check_with_errorCode_throws() {
-        XCTAssertThrowsError(try db.check(SQLITE_CONSTRAINT))
-    }
 }

From c86db3d67337cd9bb3bb5be2c6b29f06e28826ae Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 5 Dec 2016 20:15:39 +0000
Subject: [PATCH 140/685] Naming; paths

---
 .travis.yml                              |  2 +-
 Documentation/Index.md                   |  4 ++--
 SQLite.swift.podspec                     | 12 ++++++++----
 SQLite.xcodeproj/project.pbxproj         | 20 ++++++++++----------
 SQLite/{Core => Extensions}/Cipher.swift |  0
 5 files changed, 21 insertions(+), 17 deletions(-)
 rename SQLite/{Core => Extensions}/Cipher.swift (100%)

diff --git a/.travis.yml b/.travis.yml
index 3de39c11..98975aba 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,7 +11,7 @@ matrix:
     - env: VALIDATOR_SUBSPEC="none"
     - env: VALIDATOR_SUBSPEC="standard"
     - env: VALIDATOR_SUBSPEC="standalone"
-    - env: VALIDATOR_SUBSPEC="sqlcipher"
+    - env: VALIDATOR_SUBSPEC="SQLCipher"
 before_install:
   - gem update bundler
   - gem install xcpretty --no-document
diff --git a/Documentation/Index.md b/Documentation/Index.md
index 49acfc55..ae3a8a0b 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -133,11 +133,11 @@ See the [sqlite3 podspec][sqlite3pod] for more details.
 
 #### Using SQLite.swift with SQLCipher
 
-If you want to use [SQLCipher][] with SQLite.swift you can require the `sqlcipher`
+If you want to use [SQLCipher][] with SQLite.swift you can require the `SQLCipher`
 subspec in your Podfile:
 
 ``` ruby
-    pod 'SQLite.swift/sqlcipher', '~> 0.11.1'
+    pod 'SQLite.swift/SQLCipher', '~> 0.11.1'
 ```
 
 This will automatically add a dependency to the SQLCipher pod as well as extend
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index fb17adda..9df09b47 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -26,6 +26,7 @@ Pod::Spec.new do |s|
 
   s.subspec 'standard' do |ss|
     ss.source_files = 'SQLite/**/*.{c,h,m,swift}'
+    ss.exclude_files = 'SQLite/Extensions/Cipher.swift'
     ss.private_header_files = 'SQLite/Core/fts3_tokenizer.h'
 
     ss.library = 'sqlite3'
@@ -47,20 +48,23 @@ Pod::Spec.new do |s|
 
   s.subspec 'standalone' do |ss|
     ss.source_files = 'SQLite/**/*.{c,h,m,swift}'
+    ss.exclude_files = 'SQLite/Extensions/Cipher.swift'
     ss.private_header_files = 'SQLite/Core/fts3_tokenizer.h'
-    ss.xcconfig = { 'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_SWIFT_STANDALONE' }
+    ss.xcconfig = {
+      'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_SWIFT_STANDALONE'
+    }
 
     ss.dependency 'sqlite3'
   end
 
-  s.subspec 'sqlcipher' do |ss|
+  s.subspec 'SQLCipher' do |ss|
     ss.source_files = 'SQLite/**/*.{c,h,m,swift}'
     ss.private_header_files = 'SQLite/Core/fts3_tokenizer.h'
     ss.xcconfig = {
       'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_SWIFT_SQLCIPHER',
-      'GCC_PREPROCESSOR_DEFINITIONS' => 'SQLITE_HAS_CODEC=1',
-      'OTHER_CFLAGS' => '-DSQLITE_HAS_CODEC'
+      'GCC_PREPROCESSOR_DEFINITIONS' => 'SQLITE_HAS_CODEC=1'
     }
+
     ss.dependency 'SQLCipher'
   end
 end
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 69cd87fb..531d5713 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -48,18 +48,18 @@
 		03A65E971C6BB3210062603F /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 03A65E961C6BB3210062603F /* libsqlite3.tbd */; };
 		19A1717B10CC941ACB5533D6 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
 		19A171E6FA242F72A308C594 /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
+		19A171F12AB8B07F2FD7201A /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
 		19A17254FBA7894891F7297B /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
 		19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
 		19A1750CEE9B05267995CF3D /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
 		19A177CC33F2E6A24AF90B02 /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
 		19A178072B371489E6A1E839 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
+		19A17835FD5886FDC5A3228F /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
 		19A179A0C45377CB09BB358C /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
-		19A179C2C078DDD29E052DA9 /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171CACA25EB58FE045146 /* Cipher.swift */; };
-		19A17BF0509EA4A026530E23 /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171CACA25EB58FE045146 /* Cipher.swift */; };
+		19A179CCF9671E345E5A9811 /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
+		19A179E76EA6207669B60C1B /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
 		19A17C4B951CB054EE48AB1C /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
 		19A17E04C4C0956715C5676A /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
-		19A17E24574F51C37C04C758 /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171CACA25EB58FE045146 /* Cipher.swift */; };
-		19A17E7E3DA4966FA2921857 /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171CACA25EB58FE045146 /* Cipher.swift */; };
 		19A17EC0D68BA8C03288ADF7 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
 		19A17FB80B94E882050AA908 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
 		3D67B3E61DB2469200A4F4C6 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */; };
@@ -194,10 +194,10 @@
 		03A65E5A1C6BB0F50062603F /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		03A65E631C6BB0F60062603F /* SQLiteTests tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SQLiteTests tvOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
 		03A65E961C6BB3210062603F /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
-		19A171CACA25EB58FE045146 /* Cipher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cipher.swift; sourceTree = "<group>"; };
 		19A1721B8984686B9963B45D /* FTS5Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5Tests.swift; sourceTree = "<group>"; };
 		19A1730E4390C775C25677D1 /* FTS5.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5.swift; sourceTree = "<group>"; };
 		19A17399EA9E61235D5D77BF /* CipherTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CipherTests.swift; sourceTree = "<group>"; };
+		19A178A39ACA9667A62663CC /* Cipher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cipher.swift; sourceTree = "<group>"; };
 		19A1794CC4D7827E997E32A7 /* FoundationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationTests.swift; sourceTree = "<group>"; };
 		39548A631CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
 		39548A651CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
@@ -479,7 +479,6 @@
 				EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */,
 				EE247AF21C3F06E900AE3E12 /* Statement.swift */,
 				EE247AF31C3F06E900AE3E12 /* Value.swift */,
-				19A171CACA25EB58FE045146 /* Cipher.swift */,
 			);
 			path = Core;
 			sourceTree = "<group>";
@@ -490,6 +489,7 @@
 				EE247AF51C3F06E900AE3E12 /* FTS4.swift */,
 				EE247AF61C3F06E900AE3E12 /* RTree.swift */,
 				19A1730E4390C775C25677D1 /* FTS5.swift */,
+				19A178A39ACA9667A62663CC /* Cipher.swift */,
 			);
 			path = Extensions;
 			sourceTree = "<group>";
@@ -856,7 +856,7 @@
 				03A65E771C6BB2E60062603F /* Connection.swift in Sources */,
 				03A65E7E1C6BB2FB0062603F /* AggregateFunctions.swift in Sources */,
 				19A17EC0D68BA8C03288ADF7 /* FTS5.swift in Sources */,
-				19A179C2C078DDD29E052DA9 /* Cipher.swift in Sources */,
+				19A179E76EA6207669B60C1B /* Cipher.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -908,7 +908,7 @@
 				3D67B3F61DB246D100A4F4C6 /* Setter.swift in Sources */,
 				3D67B3E71DB246BA00A4F4C6 /* Blob.swift in Sources */,
 				3D67B3E81DB246BA00A4F4C6 /* Connection.swift in Sources */,
-				19A17E7E3DA4966FA2921857 /* Cipher.swift in Sources */,
+				19A179CCF9671E345E5A9811 /* Cipher.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -935,7 +935,7 @@
 				EE247B071C3F06E900AE3E12 /* Statement.swift in Sources */,
 				EE247B0D1C3F06E900AE3E12 /* AggregateFunctions.swift in Sources */,
 				19A1717B10CC941ACB5533D6 /* FTS5.swift in Sources */,
-				19A17E24574F51C37C04C758 /* Cipher.swift in Sources */,
+				19A171F12AB8B07F2FD7201A /* Cipher.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -987,7 +987,7 @@
 				EE247B661C3F3FEC00AE3E12 /* Connection.swift in Sources */,
 				EE247B6D1C3F3FEC00AE3E12 /* AggregateFunctions.swift in Sources */,
 				19A1750CEE9B05267995CF3D /* FTS5.swift in Sources */,
-				19A17BF0509EA4A026530E23 /* Cipher.swift in Sources */,
+				19A17835FD5886FDC5A3228F /* Cipher.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/SQLite/Core/Cipher.swift b/SQLite/Extensions/Cipher.swift
similarity index 100%
rename from SQLite/Core/Cipher.swift
rename to SQLite/Extensions/Cipher.swift

From 47dfa59d96e130d5444ce99c537002e3159175f6 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 5 Dec 2016 20:48:37 +0000
Subject: [PATCH 141/685] Remove some duplication in key/rekey

---
 SQLite/Extensions/Cipher.swift | 25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/SQLite/Extensions/Cipher.swift b/SQLite/Extensions/Cipher.swift
index 3533854e..e0b53390 100644
--- a/SQLite/Extensions/Cipher.swift
+++ b/SQLite/Extensions/Cipher.swift
@@ -3,27 +3,32 @@ import SQLCipher
 
 extension Connection {
     public func key(_ key: String) throws {
-        try check(sqlite3_key(handle, key, Int32(key.utf8.count)))
-        try execute(
-            "CREATE TABLE \"__SQLCipher.swift__\" (\"cipher key check\");\n" +
-            "DROP TABLE \"__SQLCipher.swift__\";"
-        )
+        try _key(keyPointer: key, keySize: key.utf8.count)
+    }
+
+    public func key(_ key: Blob) throws {
+        try _key(keyPointer: key.bytes, keySize: key.bytes.count)
     }
 
     public func rekey(_ key: String) throws {
-        try check(sqlite3_rekey(handle, key, Int32(key.utf8.count)))
+        try _rekey(keyPointer: key, keySize: key.utf8.count)
     }
 
-    public func key(_ key: Blob) throws {
-        try check(sqlite3_key(handle, key.bytes, Int32(key.bytes.count)))
+    public func rekey(_ key: Blob) throws {
+        try _rekey(keyPointer: key.bytes, keySize: key.bytes.count)
+    }
+
+    // MARK: - private
+    private func _key(keyPointer: UnsafePointer<UInt8>, keySize: Int) throws {
+        try check(sqlite3_key(handle, keyPointer, Int32(keySize)))
         try execute(
             "CREATE TABLE \"__SQLCipher.swift__\" (\"cipher key check\");\n" +
             "DROP TABLE \"__SQLCipher.swift__\";"
         )
     }
 
-    public func rekey(_ key: Blob) throws {
-        try check(sqlite3_rekey(handle, key.bytes, Int32(key.bytes.count)))
+    private func _rekey(keyPointer: UnsafePointer<UInt8>, keySize: Int) throws {
+        try check(sqlite3_rekey(handle, keyPointer, Int32(keySize)))
     }
 }
 #endif

From 9c37e8730720ff0dbdf720eea999dec8d3158367 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 6 Dec 2016 06:43:19 +0000
Subject: [PATCH 142/685] =?UTF-8?q?Don=E2=80=99t=20overwrite=20settings?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 SQLite.swift.podspec | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 9df09b47..589d73c0 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -62,7 +62,7 @@ Pod::Spec.new do |s|
     ss.private_header_files = 'SQLite/Core/fts3_tokenizer.h'
     ss.xcconfig = {
       'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_SWIFT_SQLCIPHER',
-      'GCC_PREPROCESSOR_DEFINITIONS' => 'SQLITE_HAS_CODEC=1'
+      'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SQLITE_HAS_CODEC=1'
     }
 
     ss.dependency 'SQLCipher'

From 1a76ab1cbbe7d6b9120535b28d380adb4ea9898b Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 6 Dec 2016 06:58:45 +0000
Subject: [PATCH 143/685] Explicitly set required versions

---
 SQLite.swift.podspec | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 589d73c0..ad423298 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -54,7 +54,7 @@ Pod::Spec.new do |s|
       'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_SWIFT_STANDALONE'
     }
 
-    ss.dependency 'sqlite3'
+    ss.dependency 'sqlite3', '>= 3.14.0'
   end
 
   s.subspec 'SQLCipher' do |ss|
@@ -65,6 +65,6 @@ Pod::Spec.new do |s|
       'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SQLITE_HAS_CODEC=1'
     }
 
-    ss.dependency 'SQLCipher'
+    ss.dependency 'SQLCipher', '>= 3.4.0'
   end
 end

From a5184bed7c694ce6b9835a6593b9568a902de575 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 6 Dec 2016 07:04:16 +0000
Subject: [PATCH 144/685] Update release date

---
 CHANGELOG.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 34cd0bc4..cdf98550 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,4 @@
-0.11.1 (05-12-2016), [diff][diff-0.11.1])
+0.11.1 (06-12-2016), [diff][diff-0.11.1])
 ========================================
 
 * Integrate SQLCipher via CocoaPods (#546)

From f8be0b2f512015c0ce8b84f24e12dfd1987a7532 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 6 Dec 2016 07:09:10 +0000
Subject: [PATCH 145/685] Update planning

---
 Documentation/Planning.md | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/Documentation/Planning.md b/Documentation/Planning.md
index 12555703..a0c6d049 100644
--- a/Documentation/Planning.md
+++ b/Documentation/Planning.md
@@ -1,24 +1,19 @@
 # SQLite.swift Planning
 
-This document captures both near term steps (aka Roadmap) and feature requests. 
+This document captures both near term steps (aka Roadmap) and feature requests.
 The goal is to add some visibility and guidance for future additions and Pull Requests, as well as to keep the Issues list clear of enhancement requests so that bugs are more visible.
 
 ## Roadmap
 
 _Lists agreed upon next steps in approximate priority order._
 
- * ~~publish to the CocoaPods directory at https://cocoapods.org/, per [#257](https://github.com/stephencelis/SQLite.swift/issues/257)~~ _jan 7, 2016_)
- * add SQLCipher back into the product as a separate repo, per [#311](https://github.com/stephencelis/SQLite.swift/issues/311), _in progress jan 6, 2016_
-
-
 ## Feature Requests
 
 _A gathering point for ideas for new features. In general, the corresponding issue will be closed once it is added here, with the assumption that it will be referred to when it comes time to add the corresponding feature._
 
 ### Packaging
 
- * add TV OS support, per [#272](https://github.com/stephencelis/SQLite.swift/issues/272) - currently pending SQLiteCipher merge and/or adding ability for user to pick their preferred [SQLCipher](https://github.com/sqlcipher/sqlcipher) branch
- * linux support via Swift Package Manager, per [#315](https://github.com/stephencelis/SQLite.swift/issues/315)
+ * linux support via Swift Package Manager, per [#315](https://github.com/stephencelis/SQLite.swift/issues/315), _in progress_: [#548](https://github.com/stephencelis/SQLite.swift/pull/548)
 
 ### Features
 

From 2ecb8d9b41cd8a1b26a68b9f0570f8c2d491b7bd Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 6 Dec 2016 07:09:51 +0000
Subject: [PATCH 146/685] Update CHANGELOG

---
 CHANGELOG.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index cdf98550..27036a7f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,5 +12,5 @@
 * Swift3 migration ([diff][diff-0.11.0])
 
 
-[diff-0.11.1]: https://github.com/stephencelis/SQLite.swift/compare/0.11.1...0.11.0
+[diff-0.11.1]: https://github.com/stephencelis/SQLite.swift/compare/0.11.0...0.11.1
 [diff-0.11.0]: https://github.com/stephencelis/SQLite.swift/compare/0.10.1...0.11.0

From f8bdf2aef5ba0b624c23f0b4f9023c728df04f6d Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 6 Dec 2016 07:21:32 +0000
Subject: [PATCH 147/685] Link to issues/PRs in changelog

---
 CHANGELOG.md | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 27036a7f..394f651f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,8 +1,9 @@
-0.11.1 (06-12-2016), [diff][diff-0.11.1])
+
+0.11.1 (06-12-2016), [diff][diff-0.11.1]
 ========================================
 
-* Integrate SQLCipher via CocoaPods (#546)
-* Made lastInsertRowid consistent with other SQLite wrappers (#532)
+* Integrate SQLCipher via CocoaPods ([#546][], [#553][])
+* Made lastInsertRowid consistent with other SQLite wrappers ([#532][])
 * Fix for ~= operator used with Double ranges
 * Various documentation updates
 
@@ -14,3 +15,7 @@
 
 [diff-0.11.1]: https://github.com/stephencelis/SQLite.swift/compare/0.11.0...0.11.1
 [diff-0.11.0]: https://github.com/stephencelis/SQLite.swift/compare/0.10.1...0.11.0
+
+[#532]: https://github.com/stephencelis/SQLite.swift/issues/532
+[#546]: https://github.com/stephencelis/SQLite.swift/issues/546
+[#553]: https://github.com/stephencelis/SQLite.swift/pull/553

From 59fd5e7f3c0fa23af1080bef2c6d15476ba78d9e Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 7 Dec 2016 20:04:08 +0000
Subject: [PATCH 148/685] Update instructions for manual install

Closes #536
---
 Documentation/Index.md | 7 +++++++
 README.md              | 9 +++++++++
 2 files changed, 16 insertions(+)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index ae3a8a0b..c70ba2b9 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -172,6 +172,13 @@ To install SQLite.swift as an Xcode sub-project:
 
 You should now be able to `import SQLite` from any of your target’s source files and begin using SQLite.swift.
 
+Some additional steps are required to install the application on an actual device:
+
+ 5. In the **General** tab, click the **+** button under **Embedded Binaries**.
+
+ 6. Select the appropriate **SQLite.framework** for your platform.
+
+ 7. **Add**.
 
 ### Frameworkless Targets
 
diff --git a/README.md b/README.md
index a9b44abe..4d28f3b5 100644
--- a/README.md
+++ b/README.md
@@ -185,6 +185,15 @@ To install SQLite.swift as an Xcode sub-project:
 
  4. **Add**.
 
+Some additional steps are required to install the application on an actual device:
+
+ 5. In the **General** tab, click the **+** button under **Embedded Binaries**.
+
+ 6. Select the appropriate **SQLite.framework** for your platform.
+
+ 7. **Add**.
+
+
 [Frameworkless Targets]: Documentation/Index.md#frameworkless-targets
 [Xcode]: https://developer.apple.com/xcode/downloads/
 [Submodule]: http://git-scm.com/book/en/Git-Tools-Submodules

From f32a43c316df8008aacb5fdc53e99924532064f5 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 7 Dec 2016 21:18:38 +0000
Subject: [PATCH 149/685] Updated for CocoaPods 1.x

---
 Documentation/Index.md | 4 +++-
 README.md              | 4 +++-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index c70ba2b9..9f52724f 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -108,7 +108,9 @@ install SQLite.swift with Carthage:
     ``` ruby
     use_frameworks!
 
-    pod 'SQLite.swift', '~> 0.11.1'
+    target 'YourAppTargetName' do
+        pod 'SQLite.swift', '~> 0.11.1'
+    end
     ```
 
  4. Run `pod install --repo-update`.
diff --git a/README.md b/README.md
index 4d28f3b5..f75aaa31 100644
--- a/README.md
+++ b/README.md
@@ -160,7 +160,9 @@ SQLite.swift with CocoaPods:
     ``` ruby
     use_frameworks!
 
-    pod 'SQLite.swift', '~> 0.11.1'
+    target 'YourAppTargetName' do
+        pod 'SQLite.swift', '~> 0.11.1'
+    end
     ```
 
  4. Run `pod install --repo-update`.

From edf1112b98295f5dfd10f9c422554b47875d9c45 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 8 Dec 2016 02:14:04 +0000
Subject: [PATCH 150/685] Use sqlcipher v2 methods, refactor, add docs

---
 SQLite/Extensions/Cipher.swift | 57 +++++++++++++++++++++++++---------
 SQLiteTests/CipherTests.swift  | 21 +++++++------
 2 files changed, 55 insertions(+), 23 deletions(-)

diff --git a/SQLite/Extensions/Cipher.swift b/SQLite/Extensions/Cipher.swift
index e0b53390..5b7074bb 100644
--- a/SQLite/Extensions/Cipher.swift
+++ b/SQLite/Extensions/Cipher.swift
@@ -1,34 +1,63 @@
 #if SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
 
+
+/// Extension methods for [SQLCipher](https://www.zetetic.net/sqlcipher/).
 extension Connection {
-    public func key(_ key: String) throws {
-        try _key(keyPointer: key, keySize: key.utf8.count)
+
+    /// Specify the key for an encrypted database.  This routine should be
+    /// called right after sqlite3_open().
+    ///
+    /// @param key The key to use.The key itself can be a passphrase, which is converted to a key
+    ///            using [PBKDF2](https://en.wikipedia.org/wiki/PBKDF2) key derivation. The result
+    ///            is used as the encryption key for the database.
+    ///
+    ///            Alternatively, it is possible to specify an exact byte sequence using a blob literal.
+    ///            With this method, it is the calling application's responsibility to ensure that the data
+    ///            provided is a 64 character hex string, which will be converted directly to 32 bytes (256 bits)
+    ///            of key data.
+    ///            e.g. x'2DD29CA851E7B56E4697B0E1F08507293D761A05CE4D1B628663F411A8086D99'
+    /// @param db name of the database, defaults to 'main'
+    public func key(_ key: String, db: String = "main") throws {
+        try _key_v2(db: db, keyPointer: key, keySize: key.utf8.count)
     }
 
-    public func key(_ key: Blob) throws {
-        try _key(keyPointer: key.bytes, keySize: key.bytes.count)
+    public func key(_ key: Blob, db: String = "main") throws {
+        try _key_v2(db: db, keyPointer: key.bytes, keySize: key.bytes.count)
     }
 
-    public func rekey(_ key: String) throws {
-        try _rekey(keyPointer: key, keySize: key.utf8.count)
+
+    /// Change the key on an open database.  If the current database is not encrypted, this routine
+    /// will encrypt it.
+    /// To change the key on an existing encrypted database, it must first be unlocked with the
+    /// current encryption key. Once the database is readable and writeable, rekey can be used
+    /// to re-encrypt every page in the database with a new key.
+    public func rekey(_ key: String, db: String = "main") throws {
+        try _rekey_v2(db: db, keyPointer: key, keySize: key.utf8.count)
     }
 
-    public func rekey(_ key: Blob) throws {
-        try _rekey(keyPointer: key.bytes, keySize: key.bytes.count)
+    public func rekey(_ key: Blob, db: String = "main") throws {
+        try _rekey_v2(db: db, keyPointer: key.bytes, keySize: key.bytes.count)
     }
 
     // MARK: - private
-    private func _key(keyPointer: UnsafePointer<UInt8>, keySize: Int) throws {
-        try check(sqlite3_key(handle, keyPointer, Int32(keySize)))
+    private func _key_v2(db: String, keyPointer: UnsafePointer<UInt8>, keySize: Int) throws {
+        try check(sqlite3_key_v2(handle, db, keyPointer, Int32(keySize)))
+        try cipher_key_check()
+    }
+
+    private func _rekey_v2(db: String, keyPointer: UnsafePointer<UInt8>, keySize: Int) throws {
+        try check(sqlite3_rekey_v2(handle, db, keyPointer, Int32(keySize)))
+    }
+
+    // When opening an existing database, sqlite3_key_v2 will not immediately throw an error if
+    // the key provided is incorrect. To test that the database can be successfully opened with the
+    // provided key, it is necessary to perform some operation on the database (i.e. read from it).
+    private func cipher_key_check() throws {
         try execute(
             "CREATE TABLE \"__SQLCipher.swift__\" (\"cipher key check\");\n" +
             "DROP TABLE \"__SQLCipher.swift__\";"
         )
     }
-
-    private func _rekey(keyPointer: UnsafePointer<UInt8>, keySize: Int) throws {
-        try check(sqlite3_rekey(handle, keyPointer, Int32(keySize)))
-    }
 }
 #endif
diff --git a/SQLiteTests/CipherTests.swift b/SQLiteTests/CipherTests.swift
index 89b67f76..e7eb099a 100644
--- a/SQLiteTests/CipherTests.swift
+++ b/SQLiteTests/CipherTests.swift
@@ -16,10 +16,8 @@ class CipherTests: XCTestCase {
         try! db.run("INSERT INTO foo (bar) VALUES ('world')")
 
         // db2
-        let keyData = NSMutableData(length: 64)!
-        let _ = SecRandomCopyBytes(kSecRandomDefault, 64,
-                                   keyData.mutableBytes.assumingMemoryBound(to: UInt8.self))
-        try! db2.key(Blob(bytes: keyData.bytes, length: keyData.length))
+        let key = keyData()
+        try! db2.key(Blob(bytes: key.bytes, length: key.length))
 
         try! db2.run("CREATE TABLE foo (bar TEXT)")
         try! db2.run("INSERT INTO foo (bar) VALUES ('world')")
@@ -41,11 +39,8 @@ class CipherTests: XCTestCase {
     }
 
     func test_data_rekey() {
-        let keyData = NSMutableData(length: 64)!
-        let _  = SecRandomCopyBytes(kSecRandomDefault, 64,
-                           keyData.mutableBytes.assumingMemoryBound(to: UInt8.self))
-
-        try! db2.rekey(Blob(bytes: keyData.bytes, length: keyData.length))
+        let key = keyData()
+        try! db2.rekey(Blob(bytes: key.bytes, length: key.length))
         XCTAssertEqual(1, try! db2.scalar("SELECT count(*) FROM foo") as? Int64)
     }
 
@@ -70,5 +65,13 @@ class CipherTests: XCTestCase {
         }
         XCTAssertEqual(SQLITE_NOTADB, rc)
     }
+
+    private func keyData(length: Int = 64) -> NSMutableData {
+        let keyData = NSMutableData(length: length)!
+        let result  = SecRandomCopyBytes(kSecRandomDefault, length,
+                                         keyData.mutableBytes.assumingMemoryBound(to: UInt8.self))
+        XCTAssertEqual(0, result)
+        return keyData
+    }
 }
 #endif

From 4747d9e2891135e03e8d305446976e830649f378 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 8 Dec 2016 09:25:26 +0000
Subject: [PATCH 151/685] Test naming

---
 SQLite/Extensions/Cipher.swift |  1 +
 SQLiteTests/CipherTests.swift  | 23 ++++++++++++-----------
 2 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/SQLite/Extensions/Cipher.swift b/SQLite/Extensions/Cipher.swift
index 5b7074bb..9be3fa91 100644
--- a/SQLite/Extensions/Cipher.swift
+++ b/SQLite/Extensions/Cipher.swift
@@ -3,6 +3,7 @@ import SQLCipher
 
 
 /// Extension methods for [SQLCipher](https://www.zetetic.net/sqlcipher/).
+/// @see [sqlcipher api](https://www.zetetic.net/sqlcipher/sqlcipher-api/)
 extension Connection {
 
     /// Specify the key for an encrypted database.  This routine should be
diff --git a/SQLiteTests/CipherTests.swift b/SQLiteTests/CipherTests.swift
index e7eb099a..6989e112 100644
--- a/SQLiteTests/CipherTests.swift
+++ b/SQLiteTests/CipherTests.swift
@@ -5,19 +5,20 @@ import SQLCipher
 
 class CipherTests: XCTestCase {
 
-    let db = try! Connection()
+    let db1 = try! Connection()
     let db2 = try! Connection()
 
     override func setUp() {
         // db
-        try! db.key("hello")
 
-        try! db.run("CREATE TABLE foo (bar TEXT)")
-        try! db.run("INSERT INTO foo (bar) VALUES ('world')")
+        try! db1.key("hello")
+
+        try! db1.run("CREATE TABLE foo (bar TEXT)")
+        try! db1.run("INSERT INTO foo (bar) VALUES ('world')")
 
         // db2
-        let key = keyData()
-        try! db2.key(Blob(bytes: key.bytes, length: key.length))
+        let key2 = keyData()
+        try! db2.key(Blob(bytes: key2.bytes, length: key2.length))
 
         try! db2.run("CREATE TABLE foo (bar TEXT)")
         try! db2.run("INSERT INTO foo (bar) VALUES ('world')")
@@ -26,12 +27,12 @@ class CipherTests: XCTestCase {
     }
 
     func test_key() {
-        XCTAssertEqual(1, try! db.scalar("SELECT count(*) FROM foo") as? Int64)
+        XCTAssertEqual(1, try! db1.scalar("SELECT count(*) FROM foo") as? Int64)
     }
 
     func test_rekey() {
-        try! db.rekey("goodbye")
-        XCTAssertEqual(1, try! db.scalar("SELECT count(*) FROM foo") as? Int64)
+        try! db1.rekey("goodbye")
+        XCTAssertEqual(1, try! db1.scalar("SELECT count(*) FROM foo") as? Int64)
     }
 
     func test_data_key() {
@@ -39,8 +40,8 @@ class CipherTests: XCTestCase {
     }
 
     func test_data_rekey() {
-        let key = keyData()
-        try! db2.rekey(Blob(bytes: key.bytes, length: key.length))
+        let newKey = keyData()
+        try! db2.rekey(Blob(bytes: newKey.bytes, length: newKey.length))
         XCTAssertEqual(1, try! db2.scalar("SELECT count(*) FROM foo") as? Int64)
     }
 

From 53dda835477415709d37997442d60773a433ffda Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 8 Dec 2016 10:02:13 +0000
Subject: [PATCH 152/685] Add test to read pre-encrypted file

---
 SQLite.xcodeproj/project.pbxproj      |  16 ++++++++++++++++
 SQLiteTests/CipherTests.swift         |  16 ++++++++++++++++
 SQLiteTests/Fixtures.swift            |   8 ++++++++
 SQLiteTests/fixtures/encrypted.sqlite | Bin 0 -> 2048 bytes
 4 files changed, 40 insertions(+)
 create mode 100644 SQLiteTests/Fixtures.swift
 create mode 100644 SQLiteTests/fixtures/encrypted.sqlite

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 531d5713..0a242fbc 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -46,12 +46,15 @@
 		03A65E941C6BB3030062603F /* ValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B331C3F142E00AE3E12 /* ValueTests.swift */; };
 		03A65E951C6BB3030062603F /* TestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B161C3F127200AE3E12 /* TestHelpers.swift */; };
 		03A65E971C6BB3210062603F /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 03A65E961C6BB3210062603F /* libsqlite3.tbd */; };
+		19A1709C3E7A406E62293B2A /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; };
 		19A1717B10CC941ACB5533D6 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
 		19A171E6FA242F72A308C594 /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
 		19A171F12AB8B07F2FD7201A /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
 		19A17254FBA7894891F7297B /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
+		19A17408007B182F884E3A53 /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; };
 		19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
 		19A1750CEE9B05267995CF3D /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
+		19A175DFF47B84757E547C62 /* fixtures in Resources */ = {isa = PBXBuildFile; fileRef = 19A17E2695737FAB5D6086E3 /* fixtures */; };
 		19A177CC33F2E6A24AF90B02 /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
 		19A178072B371489E6A1E839 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
 		19A17835FD5886FDC5A3228F /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
@@ -61,7 +64,10 @@
 		19A17C4B951CB054EE48AB1C /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
 		19A17E04C4C0956715C5676A /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
 		19A17EC0D68BA8C03288ADF7 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
+		19A17F3E1F7ACA33BD43E138 /* fixtures in Resources */ = {isa = PBXBuildFile; fileRef = 19A17E2695737FAB5D6086E3 /* fixtures */; };
+		19A17F60B685636D1F83C2DD /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; };
 		19A17FB80B94E882050AA908 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
+		19A17FDA323BAFDEC627E76F /* fixtures in Resources */ = {isa = PBXBuildFile; fileRef = 19A17E2695737FAB5D6086E3 /* fixtures */; };
 		3D67B3E61DB2469200A4F4C6 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */; };
 		3D67B3E71DB246BA00A4F4C6 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
 		3D67B3E81DB246BA00A4F4C6 /* Connection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEF1C3F06E900AE3E12 /* Connection.swift */; };
@@ -199,6 +205,8 @@
 		19A17399EA9E61235D5D77BF /* CipherTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CipherTests.swift; sourceTree = "<group>"; };
 		19A178A39ACA9667A62663CC /* Cipher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cipher.swift; sourceTree = "<group>"; };
 		19A1794CC4D7827E997E32A7 /* FoundationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationTests.swift; sourceTree = "<group>"; };
+		19A17B93B48B5560E6E51791 /* Fixtures.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Fixtures.swift; sourceTree = "<group>"; };
+		19A17E2695737FAB5D6086E3 /* fixtures */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = folder; path = fixtures; sourceTree = "<group>"; };
 		39548A631CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
 		39548A651CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
 		39548A671CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
@@ -465,6 +473,8 @@
 				19A1721B8984686B9963B45D /* FTS5Tests.swift */,
 				19A1794CC4D7827E997E32A7 /* FoundationTests.swift */,
 				19A17399EA9E61235D5D77BF /* CipherTests.swift */,
+				19A17E2695737FAB5D6086E3 /* fixtures */,
+				19A17B93B48B5560E6E51791 /* Fixtures.swift */,
 			);
 			path = SQLiteTests;
 			sourceTree = "<group>";
@@ -792,6 +802,7 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				19A17F3E1F7ACA33BD43E138 /* fixtures in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -813,6 +824,7 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				19A17FDA323BAFDEC627E76F /* fixtures in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -827,6 +839,7 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				19A175DFF47B84757E547C62 /* fixtures in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -882,6 +895,7 @@
 				19A17254FBA7894891F7297B /* FTS5Tests.swift in Sources */,
 				19A17E04C4C0956715C5676A /* FoundationTests.swift in Sources */,
 				19A179A0C45377CB09BB358C /* CipherTests.swift in Sources */,
+				19A17F60B685636D1F83C2DD /* Fixtures.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -961,6 +975,7 @@
 				19A171E6FA242F72A308C594 /* FTS5Tests.swift in Sources */,
 				19A17FB80B94E882050AA908 /* FoundationTests.swift in Sources */,
 				19A177CC33F2E6A24AF90B02 /* CipherTests.swift in Sources */,
+				19A17408007B182F884E3A53 /* Fixtures.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1013,6 +1028,7 @@
 				19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */,
 				19A178072B371489E6A1E839 /* FoundationTests.swift in Sources */,
 				19A17C4B951CB054EE48AB1C /* CipherTests.swift in Sources */,
+				19A1709C3E7A406E62293B2A /* Fixtures.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/SQLiteTests/CipherTests.swift b/SQLiteTests/CipherTests.swift
index 6989e112..b3ff2d33 100644
--- a/SQLiteTests/CipherTests.swift
+++ b/SQLiteTests/CipherTests.swift
@@ -30,6 +30,11 @@ class CipherTests: XCTestCase {
         XCTAssertEqual(1, try! db1.scalar("SELECT count(*) FROM foo") as? Int64)
     }
 
+    func test_key_blob_literal() {
+        let db = try! Connection()
+        try! db.key("x'2DD29CA851E7B56E4697B0E1F08507293D761A05CE4D1B628663F411A8086D99'")
+    }
+
     func test_rekey() {
         try! db1.rekey("goodbye")
         XCTAssertEqual(1, try! db1.scalar("SELECT count(*) FROM foo") as? Int64)
@@ -67,6 +72,17 @@ class CipherTests: XCTestCase {
         XCTAssertEqual(SQLITE_NOTADB, rc)
     }
 
+    func test_open_db_encrypted_with_sqlcipher() {
+        // $ sqlcipher SQLiteTests/fixtures/encrypted.sqlite
+        // sqlite> pragma key = 'sqlcipher-test';
+        // sqlite> CREATE TABLE foo (bar TEXT);
+        // sqlite> INSERT INTO foo (bar) VALUES ('world');
+        let encryptedFile = fixture("encrypted", withExtension: "sqlite")
+        let conn = try! Connection(encryptedFile)
+        try! conn.key("sqlcipher-test")
+        XCTAssertEqual(1, try! conn.scalar("SELECT count(*) FROM foo") as? Int64)
+    }
+
     private func keyData(length: Int = 64) -> NSMutableData {
         let keyData = NSMutableData(length: length)!
         let result  = SecRandomCopyBytes(kSecRandomDefault, length,
diff --git a/SQLiteTests/Fixtures.swift b/SQLiteTests/Fixtures.swift
new file mode 100644
index 00000000..13f83f77
--- /dev/null
+++ b/SQLiteTests/Fixtures.swift
@@ -0,0 +1,8 @@
+import Foundation
+
+func fixture(_ name: String, withExtension: String?) -> String {
+    let testBundle = Bundle(for: SQLiteTestCase.self)
+    return testBundle.url(
+        forResource: URL(string: "fixtures")?.appendingPathComponent(name).path,
+        withExtension: withExtension)!.path
+}
diff --git a/SQLiteTests/fixtures/encrypted.sqlite b/SQLiteTests/fixtures/encrypted.sqlite
new file mode 100644
index 0000000000000000000000000000000000000000..4b3c4d0ec06c7224bbe23ca0e8bf3c5538a66ae9
GIT binary patch

From 555a62054f3c0bfc73040da3852b581c4d6619cb Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 8 Dec 2016 11:02:49 +0000
Subject: [PATCH 153/685] Add resources to test target

---
 CocoaPodsTests/integration_test.rb       | 1 +
 CocoaPodsTests/test_running_validator.rb | 4 ++++
 2 files changed, 5 insertions(+)

diff --git a/CocoaPodsTests/integration_test.rb b/CocoaPodsTests/integration_test.rb
index c62e066e..7f3e8132 100755
--- a/CocoaPodsTests/integration_test.rb
+++ b/CocoaPodsTests/integration_test.rb
@@ -14,6 +14,7 @@ def test_validate_project
   def validator
     @validator ||= TestRunningValidator.new(podspec, []).tap do |validator|
         validator.test_files = Dir["#{project_test_dir}/*.swift"]
+        validator.test_resources = Dir["#{project_test_dir}/fixtures"]
         validator.config.verbose = true
         validator.no_clean = true
         validator.use_frameworks = true
diff --git a/CocoaPodsTests/test_running_validator.rb b/CocoaPodsTests/test_running_validator.rb
index 410f9465..fcfd3c28 100644
--- a/CocoaPodsTests/test_running_validator.rb
+++ b/CocoaPodsTests/test_running_validator.rb
@@ -7,12 +7,15 @@ class TestRunningValidator < Pod::Validator
   TEST_TARGET = 'Tests'
 
   attr_accessor :test_files
+  attr_accessor :test_resources
   attr_accessor :ios_simulator
   attr_accessor :tvos_simulator
   attr_accessor :watchos_simulator
 
   def initialize(spec_or_path, source_urls)
     super(spec_or_path, source_urls)
+    self.test_files = []
+    self.test_resources = []
     self.ios_simulator = :oldest
     self.tvos_simulator = :oldest
     self.watchos_simulator = :oldest
@@ -30,6 +33,7 @@ def add_app_project_import
     project = Xcodeproj::Project.open(validation_dir + 'App.xcodeproj')
     group = project.new_group(TEST_TARGET)
     test_target = project.targets.last
+    test_target.add_resources(test_resources.map { |resource| group.new_file(resource) })
     test_target.add_file_references(test_files.map { |file| group.new_file(file) })
     add_swift_version(test_target)
     project.save

From f7e9fe9c2c1ff48a85616dac1808b4d927eef9d4 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 8 Dec 2016 19:09:17 +0000
Subject: [PATCH 154/685] Include function return code in error message

---
 SQLite/Core/Connection.swift      | 11 ++++----
 SQLiteTests/ConnectionTests.swift | 43 ++++++++++++++++++++++++++++++-
 2 files changed, 48 insertions(+), 6 deletions(-)

diff --git a/SQLite/Core/Connection.swift b/SQLite/Core/Connection.swift
index cad25996..87ea3a22 100644
--- a/SQLite/Core/Connection.swift
+++ b/SQLite/Core/Connection.swift
@@ -709,13 +709,14 @@ extension Result : CustomStringConvertible {
 
     public var description: String {
         switch self {
-        case let .error(message, _, statement):
-            guard let statement = statement else { return message }
-
-            return "\(message) (\(statement))"
+        case let .error(message, errorCode, statement):
+            if let statement = statement {
+                return "\(message) (\(statement)) (code: \(errorCode))"
+            } else {
+                return "\(message) (code: \(errorCode))"
+            }
         }
     }
-
 }
 
 #if !SQLITE_SWIFT_SQLCIPHER
diff --git a/SQLiteTests/ConnectionTests.swift b/SQLiteTests/ConnectionTests.swift
index 3b255fd0..33c7610e 100644
--- a/SQLiteTests/ConnectionTests.swift
+++ b/SQLiteTests/ConnectionTests.swift
@@ -1,5 +1,6 @@
 import XCTest
-import SQLite
+@testable import SQLite
+
 #if SQLITE_SWIFT_STANDALONE
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
@@ -341,3 +342,43 @@ class ConnectionTests : SQLiteTestCase {
     }
 
 }
+
+
+class ResultTests : XCTestCase {
+    let connection = try! Connection(.inMemory)
+
+    func test_init_with_ok_code_returns_nil() {
+        XCTAssertNil(Result(errorCode: SQLITE_OK, connection: connection, statement: nil) as Result?)
+    }
+
+    func test_init_with_row_code_returns_nil() {
+        XCTAssertNil(Result(errorCode: SQLITE_ROW, connection: connection, statement: nil) as Result?)
+    }
+
+    func test_init_with_done_code_returns_nil() {
+        XCTAssertNil(Result(errorCode: SQLITE_DONE, connection: connection, statement: nil) as Result?)
+    }
+
+    func test_init_with_other_code_returns_error() {
+        if case .some(.error(let message, let code, let statement)) =
+            Result(errorCode: SQLITE_MISUSE, connection: connection, statement: nil)  {
+            XCTAssertEqual("not an error", message)
+            XCTAssertEqual(SQLITE_MISUSE, code)
+            XCTAssertNil(statement)
+            XCTAssert(self.connection === connection)
+        } else {
+            XCTFail()
+        }
+    }
+
+    func test_description_contains_error_code() {
+        XCTAssertEqual("not an error (code: 21)",
+            Result(errorCode: SQLITE_MISUSE, connection: connection, statement: nil)?.description)
+    }
+
+    func test_description_contains_statement_and_error_code() {
+        let statement = try! Statement(connection, "SELECT 1")
+        XCTAssertEqual("not an error (SELECT 1) (code: 21)",
+            Result(errorCode: SQLITE_MISUSE, connection: connection, statement: statement)?.description)
+    }
+}

From 1ed7070ade294051a3b11bf40cd345d7920258c8 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 9 Dec 2016 17:25:56 +0000
Subject: [PATCH 155/685] Make sure the valid key check works with read-only
 dbs

---
 SQLite/Extensions/Cipher.swift | 5 +----
 SQLiteTests/CipherTests.swift  | 7 ++++++-
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/SQLite/Extensions/Cipher.swift b/SQLite/Extensions/Cipher.swift
index 9be3fa91..6c0d4657 100644
--- a/SQLite/Extensions/Cipher.swift
+++ b/SQLite/Extensions/Cipher.swift
@@ -55,10 +55,7 @@ extension Connection {
     // the key provided is incorrect. To test that the database can be successfully opened with the
     // provided key, it is necessary to perform some operation on the database (i.e. read from it).
     private func cipher_key_check() throws {
-        try execute(
-            "CREATE TABLE \"__SQLCipher.swift__\" (\"cipher key check\");\n" +
-            "DROP TABLE \"__SQLCipher.swift__\";"
-        )
+        try scalar("SELECT count(*) FROM sqlite_master;")
     }
 }
 #endif
diff --git a/SQLiteTests/CipherTests.swift b/SQLiteTests/CipherTests.swift
index b3ff2d33..46e7024e 100644
--- a/SQLiteTests/CipherTests.swift
+++ b/SQLiteTests/CipherTests.swift
@@ -59,11 +59,12 @@ class CipherTests: XCTestCase {
 
         try! connA.key("hello")
 
-        let connB = try! Connection(path)
+        let connB = try! Connection(path, readonly: true)
 
         var rc: Int32?
         do {
             try connB.key("world")
+            XCTFail("expected exception")
         } catch Result.error(_, let code, _) {
             rc = code
         } catch {
@@ -78,6 +79,10 @@ class CipherTests: XCTestCase {
         // sqlite> CREATE TABLE foo (bar TEXT);
         // sqlite> INSERT INTO foo (bar) VALUES ('world');
         let encryptedFile = fixture("encrypted", withExtension: "sqlite")
+
+        try! FileManager.default.setAttributes([FileAttributeKey.immutable : 1], ofItemAtPath: encryptedFile)
+        XCTAssertFalse(FileManager.default.isWritableFile(atPath: encryptedFile))
+
         let conn = try! Connection(encryptedFile)
         try! conn.key("sqlcipher-test")
         XCTAssertEqual(1, try! conn.scalar("SELECT count(*) FROM foo") as? Int64)

From be3dc0b02ca1d3e42ff327818f4befe07ac8152d Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 9 Dec 2016 17:39:50 +0000
Subject: [PATCH 156/685] Update changelog

---
 CHANGELOG.md | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 394f651f..56b84ce4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+0.11.2 (unreleased), [diff][diff-0.11.2]
+========================================
+
+* Fixed SQLCipher integration with read-only databases ([#559][])
 
 0.11.1 (06-12-2016), [diff][diff-0.11.1]
 ========================================
@@ -7,15 +11,17 @@
 * Fix for ~= operator used with Double ranges
 * Various documentation updates
 
-0.11.0 (10-19-2016)
+0.11.0 (19-10-2016)
 ===================
 
 * Swift3 migration ([diff][diff-0.11.0])
 
 
-[diff-0.11.1]: https://github.com/stephencelis/SQLite.swift/compare/0.11.0...0.11.1
 [diff-0.11.0]: https://github.com/stephencelis/SQLite.swift/compare/0.10.1...0.11.0
+[diff-0.11.1]: https://github.com/stephencelis/SQLite.swift/compare/0.11.0...0.11.1
+[diff-0.11.2]: https://github.com/stephencelis/SQLite.swift/compare/0.11.1...0.11.2
 
 [#532]: https://github.com/stephencelis/SQLite.swift/issues/532
 [#546]: https://github.com/stephencelis/SQLite.swift/issues/546
 [#553]: https://github.com/stephencelis/SQLite.swift/pull/553
+[#559]: https://github.com/stephencelis/SQLite.swift/pull/559

From 7b724b05f11d17d278a32c2ad83b08c28ab2a331 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 9 Dec 2016 19:24:23 +0000
Subject: [PATCH 157/685] Fix tests

---
 SQLiteTests/CipherTests.swift | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/SQLiteTests/CipherTests.swift b/SQLiteTests/CipherTests.swift
index 46e7024e..3ee0b135 100644
--- a/SQLiteTests/CipherTests.swift
+++ b/SQLiteTests/CipherTests.swift
@@ -58,19 +58,18 @@ class CipherTests: XCTestCase {
         defer { try! FileManager.default.removeItem(atPath: path) }
 
         try! connA.key("hello")
+        try! connA.run("CREATE TABLE foo (bar TEXT)")
 
         let connB = try! Connection(path, readonly: true)
 
-        var rc: Int32?
         do {
             try connB.key("world")
             XCTFail("expected exception")
         } catch Result.error(_, let code, _) {
-            rc = code
+            XCTAssertEqual(SQLITE_NOTADB, code)
         } catch {
-            XCTFail()
+            XCTFail("unexpected error: \(error)")
         }
-        XCTAssertEqual(SQLITE_NOTADB, rc)
     }
 
     func test_open_db_encrypted_with_sqlcipher() {

From c29247f2147a3595847a592d99ffd11f95b88827 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 13 Dec 2016 12:53:13 +0000
Subject: [PATCH 158/685] Fix null pointer when fetching an empty BLOB

Closes #561
---
 SQLite/Core/Statement.swift      | 4 +++-
 SQLiteTests/StatementTests.swift | 9 +++++++++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/SQLite/Core/Statement.swift b/SQLite/Core/Statement.swift
index 1dc3e93d..7e584ef9 100644
--- a/SQLite/Core/Statement.swift
+++ b/SQLite/Core/Statement.swift
@@ -244,7 +244,9 @@ public struct Cursor {
             let length = Int(sqlite3_column_bytes(handle, Int32(idx)))
             return Blob(bytes: pointer, length: length)
         } else {
-            fatalError("sqlite3_column_blob returned NULL")
+            // The return value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer.
+            // https://www.sqlite.org/c3ref/column_blob.html
+            return Blob(bytes: [])
         }
     }
 
diff --git a/SQLiteTests/StatementTests.swift b/SQLiteTests/StatementTests.swift
index fce3585c..326259b2 100644
--- a/SQLiteTests/StatementTests.swift
+++ b/SQLiteTests/StatementTests.swift
@@ -14,4 +14,13 @@ class StatementTests : SQLiteTestCase {
         let blob = statement.row[0] as Blob
         XCTAssertEqual("alice@example.com", String(bytes: blob.bytes, encoding: .utf8)!)
     }
+
+    func test_zero_sized_blob_returns_null() {
+        let blobs = Table("blobs")
+        let blobColumn = Expression<Blob>("blob_column")
+        try! db.run(blobs.create { $0.column(blobColumn) })
+        try! db.run(blobs.insert(blobColumn <- Blob(bytes: [])))
+        let blobValue = try! db.scalar(blobs.select(blobColumn).limit(1, offset: 0))
+        XCTAssertEqual([], blobValue.bytes)
+    }
 }

From dd0aa4bdf1a19af6d274f256918b853f1d8724e5 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 13 Dec 2016 12:56:05 +0000
Subject: [PATCH 159/685] Changelog

---
 CHANGELOG.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 56b84ce4..185e9a63 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
 ========================================
 
 * Fixed SQLCipher integration with read-only databases ([#559][])
+* Fixed null pointer when fetching an empty BLOB ([#561][])
 
 0.11.1 (06-12-2016), [diff][diff-0.11.1]
 ========================================
@@ -25,3 +26,4 @@
 [#546]: https://github.com/stephencelis/SQLite.swift/issues/546
 [#553]: https://github.com/stephencelis/SQLite.swift/pull/553
 [#559]: https://github.com/stephencelis/SQLite.swift/pull/559
+[#561]: https://github.com/stephencelis/SQLite.swift/issues/561

From cbcef0264d8f4889dd4d028813de003546445708 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 19 Dec 2016 09:39:11 +0000
Subject: [PATCH 160/685] Add note about active Xcode dev directory

#120
---
 Documentation/Index.md | 6 +++++-
 README.md              | 8 ++++++--
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 9f52724f..51348dc3 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -93,7 +93,11 @@ install SQLite.swift with Carthage:
 
 [CocoaPods][] is a dependency manager for Cocoa projects. To install SQLite.swift with CocoaPods:
 
- 1. Verify that your copy of Xcode is installed in the default location (`/Application/Xcode.app`).
+ 1. Verify that your copy of Xcode is installed and active in the default location (`/Application/Xcode.app`).
+
+    ```sh
+    sudo xcode-select --switch /Applications/Xcode.app
+    ```
 
  2. Make sure CocoaPods is [installed][CocoaPods Installation] (SQLite.swift requires version 1.0.0 or greater).
 
diff --git a/README.md b/README.md
index f75aaa31..eb5635ca 100644
--- a/README.md
+++ b/README.md
@@ -145,9 +145,13 @@ install SQLite.swift with Carthage:
 [CocoaPods][] is a dependency manager for Cocoa projects. To install
 SQLite.swift with CocoaPods:
 
- 1. Verify that your copy of Xcode is installed in the default location (`/Application/Xcode.app`).
+ 1. Verify that your copy of Xcode is installed and active in the default location (`/Application/Xcode.app`).
 
- 2. Make sure the latest CocoaPods beta is [installed][CocoaPods Installation]. (SQLite.swift requires version 1.0.0 or greater.)
+    ```sh
+    sudo xcode-select --switch /Applications/Xcode.app
+    ```
+
+ 2. Make sure CocoaPods is [installed][CocoaPods Installation]. (SQLite.swift requires version 1.0.0 or greater.)
 
     ``` sh
     # Using the default Ruby install will require you to use sudo when

From 7f42a6b58c958d7aa755170ad19b0bb1e7a7d819 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 19 Dec 2016 09:40:54 +0000
Subject: [PATCH 161/685] =?UTF-8?q?Missing=20`s=E2=80=99?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 Documentation/Index.md | 2 +-
 README.md              | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 51348dc3..40e9f503 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -93,7 +93,7 @@ install SQLite.swift with Carthage:
 
 [CocoaPods][] is a dependency manager for Cocoa projects. To install SQLite.swift with CocoaPods:
 
- 1. Verify that your copy of Xcode is installed and active in the default location (`/Application/Xcode.app`).
+ 1. Verify that your copy of Xcode is installed and active in the default location (`/Applications/Xcode.app`).
 
     ```sh
     sudo xcode-select --switch /Applications/Xcode.app
diff --git a/README.md b/README.md
index eb5635ca..c0b778df 100644
--- a/README.md
+++ b/README.md
@@ -145,7 +145,7 @@ install SQLite.swift with Carthage:
 [CocoaPods][] is a dependency manager for Cocoa projects. To install
 SQLite.swift with CocoaPods:
 
- 1. Verify that your copy of Xcode is installed and active in the default location (`/Application/Xcode.app`).
+ 1. Verify that your copy of Xcode is installed and active in the default location (`/Applications/Xcode.app`).
 
     ```sh
     sudo xcode-select --switch /Applications/Xcode.app

From 42e0ae83f5896f31cd1f183cd2fd635c08204770 Mon Sep 17 00:00:00 2001
From: Wade Tregaskis <wadetregaskis@mac.com>
Date: Fri, 18 Nov 2016 22:20:22 -0800
Subject: [PATCH 162/685] Moved things around a bit to suit Swift packages.

---
 {SQLite => Sources/SQLite}/Core/Blob.swift                        | 0
 {SQLite => Sources/SQLite}/Core/Connection.swift                  | 0
 {SQLite => Sources/SQLite}/Core/SQLite-Bridging.h                 | 0
 .../SQLite/Core/SQLite-Bridging.m.hidden                          | 0
 {SQLite => Sources/SQLite}/Core/Statement.swift                   | 0
 {SQLite => Sources/SQLite}/Core/Value.swift                       | 0
 {SQLite => Sources/SQLite}/Core/fts3_tokenizer.h                  | 0
 {SQLite => Sources/SQLite}/Extensions/FTS4.swift                  | 0
 {SQLite => Sources/SQLite}/Extensions/FTS5.swift                  | 0
 {SQLite => Sources/SQLite}/Extensions/RTree.swift                 | 0
 {SQLite => Sources/SQLite}/Foundation.swift                       | 0
 {SQLite => Sources/SQLite}/Helpers.swift                          | 0
 {SQLite => Sources/SQLite}/Info.plist                             | 0
 {SQLite => Sources/SQLite}/SQLite.h                               | 0
 {SQLite => Sources/SQLite}/Typed/AggregateFunctions.swift         | 0
 {SQLite => Sources/SQLite}/Typed/Collation.swift                  | 0
 {SQLite => Sources/SQLite}/Typed/CoreFunctions.swift              | 0
 {SQLite => Sources/SQLite}/Typed/CustomFunctions.swift            | 0
 {SQLite => Sources/SQLite}/Typed/Expression.swift                 | 0
 {SQLite => Sources/SQLite}/Typed/Operators.swift                  | 0
 {SQLite => Sources/SQLite}/Typed/Query.swift                      | 0
 {SQLite => Sources/SQLite}/Typed/Schema.swift                     | 0
 {SQLite => Sources/SQLite}/Typed/Setter.swift                     | 0
 {SQLiteTests => Tests/SQLiteTests}/AggregateFunctionsTests.swift  | 0
 {SQLiteTests => Tests/SQLiteTests}/BlobTests.swift                | 0
 {SQLiteTests => Tests/SQLiteTests}/ConnectionTests.swift          | 0
 {SQLiteTests => Tests/SQLiteTests}/CoreFunctionsTests.swift       | 0
 {SQLiteTests => Tests/SQLiteTests}/CustomFunctionsTests.swift     | 0
 {SQLiteTests => Tests/SQLiteTests}/ExpressionTests.swift          | 0
 {SQLiteTests => Tests/SQLiteTests}/FTS4Tests.swift                | 0
 {SQLiteTests => Tests/SQLiteTests}/FTS5Tests.swift                | 0
 {SQLiteTests => Tests/SQLiteTests}/FoundationTests.swift          | 0
 {SQLiteTests => Tests/SQLiteTests}/Info.plist                     | 0
 {SQLiteTests => Tests/SQLiteTests}/OperatorsTests.swift           | 0
 {SQLiteTests => Tests/SQLiteTests}/QueryTests.swift               | 0
 {SQLiteTests => Tests/SQLiteTests}/RTreeTests.swift               | 0
 {SQLiteTests => Tests/SQLiteTests}/SchemaTests.swift              | 0
 {SQLiteTests => Tests/SQLiteTests}/SetterTests.swift              | 0
 {SQLiteTests => Tests/SQLiteTests}/StatementTests.swift           | 0
 {SQLiteTests => Tests/SQLiteTests}/TestHelpers.swift              | 0
 {SQLiteTests => Tests/SQLiteTests}/ValueTests.swift               | 0
 41 files changed, 0 insertions(+), 0 deletions(-)
 rename {SQLite => Sources/SQLite}/Core/Blob.swift (100%)
 rename {SQLite => Sources/SQLite}/Core/Connection.swift (100%)
 rename {SQLite => Sources/SQLite}/Core/SQLite-Bridging.h (100%)
 rename SQLite/Core/SQLite-Bridging.m => Sources/SQLite/Core/SQLite-Bridging.m.hidden (100%)
 rename {SQLite => Sources/SQLite}/Core/Statement.swift (100%)
 rename {SQLite => Sources/SQLite}/Core/Value.swift (100%)
 rename {SQLite => Sources/SQLite}/Core/fts3_tokenizer.h (100%)
 rename {SQLite => Sources/SQLite}/Extensions/FTS4.swift (100%)
 rename {SQLite => Sources/SQLite}/Extensions/FTS5.swift (100%)
 rename {SQLite => Sources/SQLite}/Extensions/RTree.swift (100%)
 rename {SQLite => Sources/SQLite}/Foundation.swift (100%)
 rename {SQLite => Sources/SQLite}/Helpers.swift (100%)
 rename {SQLite => Sources/SQLite}/Info.plist (100%)
 rename {SQLite => Sources/SQLite}/SQLite.h (100%)
 rename {SQLite => Sources/SQLite}/Typed/AggregateFunctions.swift (100%)
 rename {SQLite => Sources/SQLite}/Typed/Collation.swift (100%)
 rename {SQLite => Sources/SQLite}/Typed/CoreFunctions.swift (100%)
 rename {SQLite => Sources/SQLite}/Typed/CustomFunctions.swift (100%)
 rename {SQLite => Sources/SQLite}/Typed/Expression.swift (100%)
 rename {SQLite => Sources/SQLite}/Typed/Operators.swift (100%)
 rename {SQLite => Sources/SQLite}/Typed/Query.swift (100%)
 rename {SQLite => Sources/SQLite}/Typed/Schema.swift (100%)
 rename {SQLite => Sources/SQLite}/Typed/Setter.swift (100%)
 rename {SQLiteTests => Tests/SQLiteTests}/AggregateFunctionsTests.swift (100%)
 rename {SQLiteTests => Tests/SQLiteTests}/BlobTests.swift (100%)
 rename {SQLiteTests => Tests/SQLiteTests}/ConnectionTests.swift (100%)
 rename {SQLiteTests => Tests/SQLiteTests}/CoreFunctionsTests.swift (100%)
 rename {SQLiteTests => Tests/SQLiteTests}/CustomFunctionsTests.swift (100%)
 rename {SQLiteTests => Tests/SQLiteTests}/ExpressionTests.swift (100%)
 rename {SQLiteTests => Tests/SQLiteTests}/FTS4Tests.swift (100%)
 rename {SQLiteTests => Tests/SQLiteTests}/FTS5Tests.swift (100%)
 rename {SQLiteTests => Tests/SQLiteTests}/FoundationTests.swift (100%)
 rename {SQLiteTests => Tests/SQLiteTests}/Info.plist (100%)
 rename {SQLiteTests => Tests/SQLiteTests}/OperatorsTests.swift (100%)
 rename {SQLiteTests => Tests/SQLiteTests}/QueryTests.swift (100%)
 rename {SQLiteTests => Tests/SQLiteTests}/RTreeTests.swift (100%)
 rename {SQLiteTests => Tests/SQLiteTests}/SchemaTests.swift (100%)
 rename {SQLiteTests => Tests/SQLiteTests}/SetterTests.swift (100%)
 rename {SQLiteTests => Tests/SQLiteTests}/StatementTests.swift (100%)
 rename {SQLiteTests => Tests/SQLiteTests}/TestHelpers.swift (100%)
 rename {SQLiteTests => Tests/SQLiteTests}/ValueTests.swift (100%)

diff --git a/SQLite/Core/Blob.swift b/Sources/SQLite/Core/Blob.swift
similarity index 100%
rename from SQLite/Core/Blob.swift
rename to Sources/SQLite/Core/Blob.swift
diff --git a/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
similarity index 100%
rename from SQLite/Core/Connection.swift
rename to Sources/SQLite/Core/Connection.swift
diff --git a/SQLite/Core/SQLite-Bridging.h b/Sources/SQLite/Core/SQLite-Bridging.h
similarity index 100%
rename from SQLite/Core/SQLite-Bridging.h
rename to Sources/SQLite/Core/SQLite-Bridging.h
diff --git a/SQLite/Core/SQLite-Bridging.m b/Sources/SQLite/Core/SQLite-Bridging.m.hidden
similarity index 100%
rename from SQLite/Core/SQLite-Bridging.m
rename to Sources/SQLite/Core/SQLite-Bridging.m.hidden
diff --git a/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
similarity index 100%
rename from SQLite/Core/Statement.swift
rename to Sources/SQLite/Core/Statement.swift
diff --git a/SQLite/Core/Value.swift b/Sources/SQLite/Core/Value.swift
similarity index 100%
rename from SQLite/Core/Value.swift
rename to Sources/SQLite/Core/Value.swift
diff --git a/SQLite/Core/fts3_tokenizer.h b/Sources/SQLite/Core/fts3_tokenizer.h
similarity index 100%
rename from SQLite/Core/fts3_tokenizer.h
rename to Sources/SQLite/Core/fts3_tokenizer.h
diff --git a/SQLite/Extensions/FTS4.swift b/Sources/SQLite/Extensions/FTS4.swift
similarity index 100%
rename from SQLite/Extensions/FTS4.swift
rename to Sources/SQLite/Extensions/FTS4.swift
diff --git a/SQLite/Extensions/FTS5.swift b/Sources/SQLite/Extensions/FTS5.swift
similarity index 100%
rename from SQLite/Extensions/FTS5.swift
rename to Sources/SQLite/Extensions/FTS5.swift
diff --git a/SQLite/Extensions/RTree.swift b/Sources/SQLite/Extensions/RTree.swift
similarity index 100%
rename from SQLite/Extensions/RTree.swift
rename to Sources/SQLite/Extensions/RTree.swift
diff --git a/SQLite/Foundation.swift b/Sources/SQLite/Foundation.swift
similarity index 100%
rename from SQLite/Foundation.swift
rename to Sources/SQLite/Foundation.swift
diff --git a/SQLite/Helpers.swift b/Sources/SQLite/Helpers.swift
similarity index 100%
rename from SQLite/Helpers.swift
rename to Sources/SQLite/Helpers.swift
diff --git a/SQLite/Info.plist b/Sources/SQLite/Info.plist
similarity index 100%
rename from SQLite/Info.plist
rename to Sources/SQLite/Info.plist
diff --git a/SQLite/SQLite.h b/Sources/SQLite/SQLite.h
similarity index 100%
rename from SQLite/SQLite.h
rename to Sources/SQLite/SQLite.h
diff --git a/SQLite/Typed/AggregateFunctions.swift b/Sources/SQLite/Typed/AggregateFunctions.swift
similarity index 100%
rename from SQLite/Typed/AggregateFunctions.swift
rename to Sources/SQLite/Typed/AggregateFunctions.swift
diff --git a/SQLite/Typed/Collation.swift b/Sources/SQLite/Typed/Collation.swift
similarity index 100%
rename from SQLite/Typed/Collation.swift
rename to Sources/SQLite/Typed/Collation.swift
diff --git a/SQLite/Typed/CoreFunctions.swift b/Sources/SQLite/Typed/CoreFunctions.swift
similarity index 100%
rename from SQLite/Typed/CoreFunctions.swift
rename to Sources/SQLite/Typed/CoreFunctions.swift
diff --git a/SQLite/Typed/CustomFunctions.swift b/Sources/SQLite/Typed/CustomFunctions.swift
similarity index 100%
rename from SQLite/Typed/CustomFunctions.swift
rename to Sources/SQLite/Typed/CustomFunctions.swift
diff --git a/SQLite/Typed/Expression.swift b/Sources/SQLite/Typed/Expression.swift
similarity index 100%
rename from SQLite/Typed/Expression.swift
rename to Sources/SQLite/Typed/Expression.swift
diff --git a/SQLite/Typed/Operators.swift b/Sources/SQLite/Typed/Operators.swift
similarity index 100%
rename from SQLite/Typed/Operators.swift
rename to Sources/SQLite/Typed/Operators.swift
diff --git a/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
similarity index 100%
rename from SQLite/Typed/Query.swift
rename to Sources/SQLite/Typed/Query.swift
diff --git a/SQLite/Typed/Schema.swift b/Sources/SQLite/Typed/Schema.swift
similarity index 100%
rename from SQLite/Typed/Schema.swift
rename to Sources/SQLite/Typed/Schema.swift
diff --git a/SQLite/Typed/Setter.swift b/Sources/SQLite/Typed/Setter.swift
similarity index 100%
rename from SQLite/Typed/Setter.swift
rename to Sources/SQLite/Typed/Setter.swift
diff --git a/SQLiteTests/AggregateFunctionsTests.swift b/Tests/SQLiteTests/AggregateFunctionsTests.swift
similarity index 100%
rename from SQLiteTests/AggregateFunctionsTests.swift
rename to Tests/SQLiteTests/AggregateFunctionsTests.swift
diff --git a/SQLiteTests/BlobTests.swift b/Tests/SQLiteTests/BlobTests.swift
similarity index 100%
rename from SQLiteTests/BlobTests.swift
rename to Tests/SQLiteTests/BlobTests.swift
diff --git a/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
similarity index 100%
rename from SQLiteTests/ConnectionTests.swift
rename to Tests/SQLiteTests/ConnectionTests.swift
diff --git a/SQLiteTests/CoreFunctionsTests.swift b/Tests/SQLiteTests/CoreFunctionsTests.swift
similarity index 100%
rename from SQLiteTests/CoreFunctionsTests.swift
rename to Tests/SQLiteTests/CoreFunctionsTests.swift
diff --git a/SQLiteTests/CustomFunctionsTests.swift b/Tests/SQLiteTests/CustomFunctionsTests.swift
similarity index 100%
rename from SQLiteTests/CustomFunctionsTests.swift
rename to Tests/SQLiteTests/CustomFunctionsTests.swift
diff --git a/SQLiteTests/ExpressionTests.swift b/Tests/SQLiteTests/ExpressionTests.swift
similarity index 100%
rename from SQLiteTests/ExpressionTests.swift
rename to Tests/SQLiteTests/ExpressionTests.swift
diff --git a/SQLiteTests/FTS4Tests.swift b/Tests/SQLiteTests/FTS4Tests.swift
similarity index 100%
rename from SQLiteTests/FTS4Tests.swift
rename to Tests/SQLiteTests/FTS4Tests.swift
diff --git a/SQLiteTests/FTS5Tests.swift b/Tests/SQLiteTests/FTS5Tests.swift
similarity index 100%
rename from SQLiteTests/FTS5Tests.swift
rename to Tests/SQLiteTests/FTS5Tests.swift
diff --git a/SQLiteTests/FoundationTests.swift b/Tests/SQLiteTests/FoundationTests.swift
similarity index 100%
rename from SQLiteTests/FoundationTests.swift
rename to Tests/SQLiteTests/FoundationTests.swift
diff --git a/SQLiteTests/Info.plist b/Tests/SQLiteTests/Info.plist
similarity index 100%
rename from SQLiteTests/Info.plist
rename to Tests/SQLiteTests/Info.plist
diff --git a/SQLiteTests/OperatorsTests.swift b/Tests/SQLiteTests/OperatorsTests.swift
similarity index 100%
rename from SQLiteTests/OperatorsTests.swift
rename to Tests/SQLiteTests/OperatorsTests.swift
diff --git a/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
similarity index 100%
rename from SQLiteTests/QueryTests.swift
rename to Tests/SQLiteTests/QueryTests.swift
diff --git a/SQLiteTests/RTreeTests.swift b/Tests/SQLiteTests/RTreeTests.swift
similarity index 100%
rename from SQLiteTests/RTreeTests.swift
rename to Tests/SQLiteTests/RTreeTests.swift
diff --git a/SQLiteTests/SchemaTests.swift b/Tests/SQLiteTests/SchemaTests.swift
similarity index 100%
rename from SQLiteTests/SchemaTests.swift
rename to Tests/SQLiteTests/SchemaTests.swift
diff --git a/SQLiteTests/SetterTests.swift b/Tests/SQLiteTests/SetterTests.swift
similarity index 100%
rename from SQLiteTests/SetterTests.swift
rename to Tests/SQLiteTests/SetterTests.swift
diff --git a/SQLiteTests/StatementTests.swift b/Tests/SQLiteTests/StatementTests.swift
similarity index 100%
rename from SQLiteTests/StatementTests.swift
rename to Tests/SQLiteTests/StatementTests.swift
diff --git a/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
similarity index 100%
rename from SQLiteTests/TestHelpers.swift
rename to Tests/SQLiteTests/TestHelpers.swift
diff --git a/SQLiteTests/ValueTests.swift b/Tests/SQLiteTests/ValueTests.swift
similarity index 100%
rename from SQLiteTests/ValueTests.swift
rename to Tests/SQLiteTests/ValueTests.swift

From 9b1bef9e9ca1d8ac3c91bbdcb18388ddbff3970c Mon Sep 17 00:00:00 2001
From: Wade Tregaskis <wadetregaskis@mac.com>
Date: Fri, 18 Nov 2016 22:21:05 -0800
Subject: [PATCH 163/685] Ignore '.build' folder created by the `swift` command
 line tool.

---
 .gitignore | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/.gitignore b/.gitignore
index 99e4f5e2..b617bcef 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,6 @@ DerivedData
 
 # Carthage
 Carthage
+
+# Swift Package Manager
+.build

From 20bda8f652085dd6d0abf091d0fcffd04b19b052 Mon Sep 17 00:00:00 2001
From: Wade Tregaskis <wadetregaskis@mac.com>
Date: Fri, 18 Nov 2016 22:21:46 -0800
Subject: [PATCH 164/685] Added the CSQLite submodule.

---
 Sources/CSQLite/module.modulemap | 4 ++++
 1 file changed, 4 insertions(+)
 create mode 100644 Sources/CSQLite/module.modulemap

diff --git a/Sources/CSQLite/module.modulemap b/Sources/CSQLite/module.modulemap
new file mode 100644
index 00000000..f4127dce
--- /dev/null
+++ b/Sources/CSQLite/module.modulemap
@@ -0,0 +1,4 @@
+module CSQLite {
+    umbrella header "include/sqlite3.h"
+    export *
+}

From 0d408b6164b9a43db8566d82ff2b123cbf054cc8 Mon Sep 17 00:00:00 2001
From: Wade Tregaskis <wadetregaskis@mac.com>
Date: Fri, 18 Nov 2016 22:21:58 -0800
Subject: [PATCH 165/685] Added an initial Package.swift file.

---
 Package.swift | 14 ++++++++++++++
 1 file changed, 14 insertions(+)
 create mode 100644 Package.swift

diff --git a/Package.swift b/Package.swift
new file mode 100644
index 00000000..372e9441
--- /dev/null
+++ b/Package.swift
@@ -0,0 +1,14 @@
+import PackageDescription
+
+let package = Package(
+    name: "SQLite.swift",
+    targets: [
+        Target(
+            name: "SQLite",
+            dependencies: [
+                .Target(name: "CSQLite")
+            ]),
+        Target(
+            name: "CSQLite")
+    ]
+)

From 4e6b1e00466299136f826ccb7f2c6995eb81b8b2 Mon Sep 17 00:00:00 2001
From: Wade Tregaskis <wadetregaskis@mac.com>
Date: Fri, 18 Nov 2016 22:25:54 -0800
Subject: [PATCH 166/685] Import CSQLite by default, not just when using
 CocoaPods.

---
 Sources/SQLite/Core/Connection.swift | 2 +-
 Sources/SQLite/Core/Statement.swift  | 2 +-
 Sources/SQLite/Helpers.swift         | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 87ea3a22..06611756 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -28,7 +28,7 @@ import Dispatch
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif COCOAPODS
+#else
 import CSQLite
 #endif
 
diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index 7e584ef9..766bd15b 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -26,7 +26,7 @@
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif COCOAPODS
+#else
 import CSQLite
 #endif
 
diff --git a/Sources/SQLite/Helpers.swift b/Sources/SQLite/Helpers.swift
index 08c9a144..81a7507e 100644
--- a/Sources/SQLite/Helpers.swift
+++ b/Sources/SQLite/Helpers.swift
@@ -26,7 +26,7 @@
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif COCOAPODS
+#else
 import CSQLite
 #endif
 

From 0db23c9e73f68ce8e082f410c7d0acd3e489e892 Mon Sep 17 00:00:00 2001
From: Wade Tregaskis <wadetregaskis@mac.com>
Date: Fri, 18 Nov 2016 22:44:54 -0800
Subject: [PATCH 167/685] Broke the ObjC pieces out into a separate module, so
 that they can actually be built and used correctly.

---
 Package.swift                                                | 5 +++++
 Sources/SQLite/Extensions/FTS4.swift                         | 3 +++
 .../SQLite-Bridging.m}                                       | 0
 Sources/{SQLite/Core => SQLiteObjc}/fts3_tokenizer.h         | 0
 .../{SQLite/Core => SQLiteObjc/include}/SQLite-Bridging.h    | 0
 5 files changed, 8 insertions(+)
 rename Sources/{SQLite/Core/SQLite-Bridging.m.hidden => SQLiteObjc/SQLite-Bridging.m} (100%)
 rename Sources/{SQLite/Core => SQLiteObjc}/fts3_tokenizer.h (100%)
 rename Sources/{SQLite/Core => SQLiteObjc/include}/SQLite-Bridging.h (100%)

diff --git a/Package.swift b/Package.swift
index 372e9441..8cbc2f4d 100644
--- a/Package.swift
+++ b/Package.swift
@@ -5,6 +5,11 @@ let package = Package(
     targets: [
         Target(
             name: "SQLite",
+            dependencies: [
+                .Target(name: "SQLiteObjc")
+            ]),
+        Target(
+            name: "SQLiteObjc",
             dependencies: [
                 .Target(name: "CSQLite")
             ]),
diff --git a/Sources/SQLite/Extensions/FTS4.swift b/Sources/SQLite/Extensions/FTS4.swift
index 7bbca7a5..6aec27e1 100644
--- a/Sources/SQLite/Extensions/FTS4.swift
+++ b/Sources/SQLite/Extensions/FTS4.swift
@@ -22,6 +22,9 @@
 // THE SOFTWARE.
 //
 
+import SQLiteObjc
+
+
 extension Module {
 
     public static func FTS4(_ column: Expressible, _ more: Expressible...) -> Module {
diff --git a/Sources/SQLite/Core/SQLite-Bridging.m.hidden b/Sources/SQLiteObjc/SQLite-Bridging.m
similarity index 100%
rename from Sources/SQLite/Core/SQLite-Bridging.m.hidden
rename to Sources/SQLiteObjc/SQLite-Bridging.m
diff --git a/Sources/SQLite/Core/fts3_tokenizer.h b/Sources/SQLiteObjc/fts3_tokenizer.h
similarity index 100%
rename from Sources/SQLite/Core/fts3_tokenizer.h
rename to Sources/SQLiteObjc/fts3_tokenizer.h
diff --git a/Sources/SQLite/Core/SQLite-Bridging.h b/Sources/SQLiteObjc/include/SQLite-Bridging.h
similarity index 100%
rename from Sources/SQLite/Core/SQLite-Bridging.h
rename to Sources/SQLiteObjc/include/SQLite-Bridging.h

From c7ab2629761d020b09a5dbc4879177e901b86fb3 Mon Sep 17 00:00:00 2001
From: Wade Tregaskis <wadetregaskis@mac.com>
Date: Fri, 18 Nov 2016 22:46:17 -0800
Subject: [PATCH 168/685] Corrected dependencies - SQLite also uses CSQLite
 directly, not just indirectly via SQLiteObjc.

---
 Package.swift | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Package.swift b/Package.swift
index 8cbc2f4d..ae5d09c0 100644
--- a/Package.swift
+++ b/Package.swift
@@ -6,7 +6,8 @@ let package = Package(
         Target(
             name: "SQLite",
             dependencies: [
-                .Target(name: "SQLiteObjc")
+                .Target(name: "SQLiteObjc"),
+                .Target(name: "CSQLite")
             ]),
         Target(
             name: "SQLiteObjc",

From c6b167773f4889af1cc0e26ef3bb0360c3f1e35a Mon Sep 17 00:00:00 2001
From: Wade Tregaskis <wadetregaskis@mac.com>
Date: Fri, 18 Nov 2016 22:48:31 -0800
Subject: [PATCH 169/685] Renamed the package to just "SQLite", rather than
 "SQLite.swift", to if nothing else match the existing Xcode project name.

---
 Package.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Package.swift b/Package.swift
index ae5d09c0..f5c5b54f 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,7 +1,7 @@
 import PackageDescription
 
 let package = Package(
-    name: "SQLite.swift",
+    name: "SQLite",
     targets: [
         Target(
             name: "SQLite",

From 441d592320bff3325e028e9e980806d467d95646 Mon Sep 17 00:00:00 2001
From: Wade Tregaskis <wadetregaskis@mac.com>
Date: Fri, 18 Nov 2016 23:02:27 -0800
Subject: [PATCH 170/685] Fixed up file references, given all the moves made to
 support Swift packages.

---
 SQLite.xcodeproj/project.pbxproj | 28 +++++++++++++++-------------
 1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 0a242fbc..40837d37 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -223,8 +223,8 @@
 		EE247AE41C3F04ED00AE3E12 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		EE247AEE1C3F06E900AE3E12 /* Blob.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Blob.swift; sourceTree = "<group>"; };
 		EE247AEF1C3F06E900AE3E12 /* Connection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Connection.swift; sourceTree = "<group>"; };
-		EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fts3_tokenizer.h; sourceTree = "<group>"; };
-		EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "SQLite-Bridging.m"; sourceTree = "<group>"; };
+		EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = fts3_tokenizer.h; path = Sources/SQLiteObjc/fts3_tokenizer.h; sourceTree = "<group>"; };
+		EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "SQLite-Bridging.m"; path = "Sources/SQLiteObjc/SQLite-Bridging.m"; sourceTree = "<group>"; };
 		EE247AF21C3F06E900AE3E12 /* Statement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Statement.swift; sourceTree = "<group>"; };
 		EE247AF31C3F06E900AE3E12 /* Value.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Value.swift; sourceTree = "<group>"; };
 		EE247AF51C3F06E900AE3E12 /* FTS4.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS4.swift; sourceTree = "<group>"; };
@@ -266,7 +266,7 @@
 		EE247B921C3F822600AE3E12 /* playground@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "playground@2x.png"; sourceTree = "<group>"; };
 		EE247B931C3F826100AE3E12 /* SQLite.swift.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; path = SQLite.swift.podspec; sourceTree = "<group>"; };
 		EE91808B1C46E34A0038162A /* usr/include/sqlite3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = usr/include/sqlite3.h; sourceTree = SDKROOT; };
-		EE91808D1C46E5230038162A /* SQLite-Bridging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SQLite-Bridging.h"; sourceTree = "<group>"; };
+		EE91808D1C46E5230038162A /* SQLite-Bridging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "SQLite-Bridging.h"; path = "../../SQLiteObjc/include/SQLite-Bridging.h"; sourceTree = "<group>"; };
 		EE9180911C46E9D30038162A /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
 		EE9180931C46EA210038162A /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; };
 /* End PBXFileReference section */
@@ -448,7 +448,8 @@
 				EE247AF41C3F06E900AE3E12 /* Extensions */,
 				EE247AF91C3F06E900AE3E12 /* Typed */,
 			);
-			path = SQLite;
+			name = SQLite;
+			path = Sources/SQLite;
 			sourceTree = "<group>";
 		};
 		EE247AE11C3F04ED00AE3E12 /* SQLiteTests */ = {
@@ -476,7 +477,8 @@
 				19A17E2695737FAB5D6086E3 /* fixtures */,
 				19A17B93B48B5560E6E51791 /* Fixtures.swift */,
 			);
-			path = SQLiteTests;
+			name = SQLiteTests;
+			path = Tests/SQLiteTests;
 			sourceTree = "<group>";
 		};
 		EE247AED1C3F06E900AE3E12 /* Core */ = {
@@ -1062,7 +1064,7 @@
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
-				INFOPLIST_FILE = SQLite/Info.plist;
+				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
@@ -1085,7 +1087,7 @@
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
-				INFOPLIST_FILE = SQLite/Info.plist;
+				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
@@ -1135,7 +1137,7 @@
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
-				INFOPLIST_FILE = SQLite/Info.plist;
+				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
@@ -1160,7 +1162,7 @@
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
-				INFOPLIST_FILE = SQLite/Info.plist;
+				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
@@ -1283,7 +1285,7 @@
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
-				INFOPLIST_FILE = SQLite/Info.plist;
+				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@@ -1309,7 +1311,7 @@
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
-				INFOPLIST_FILE = SQLite/Info.plist;
+				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@@ -1357,7 +1359,7 @@
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				FRAMEWORK_VERSION = A;
-				INFOPLIST_FILE = SQLite/Info.plist;
+				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
 				MACOSX_DEPLOYMENT_TARGET = 10.9;
@@ -1384,7 +1386,7 @@
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				FRAMEWORK_VERSION = A;
-				INFOPLIST_FILE = SQLite/Info.plist;
+				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
 				MACOSX_DEPLOYMENT_TARGET = 10.9;

From 28dfcc792112609a661e23360e01d5b197886a14 Mon Sep 17 00:00:00 2001
From: Wade Tregaskis <wadetregaskis@mac.com>
Date: Fri, 18 Nov 2016 23:17:23 -0800
Subject: [PATCH 171/685] =?UTF-8?q?=E2=80=A2=C2=A0Fixed=20two=20remaining?=
 =?UTF-8?q?=20file=20references=20that=20I=20missed=20in=20the=20first=20p?=
 =?UTF-8?q?ass.=20=E2=80=A2=C2=A0Added=20a=20[hopefully]=20temporary=20wor?=
 =?UTF-8?q?karound=20to=20allow=20building=20within=20the=20existing=20Xco?=
 =?UTF-8?q?de=20project=20to=20work=20as=20it=20did=20before,=20in=20addit?=
 =?UTF-8?q?ion=20to=20command-line=20builds=20via=20`swift`.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 SQLite.xcodeproj/project.pbxproj     | 6 ++++--
 Sources/SQLite/Extensions/FTS4.swift | 5 ++++-
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 40837d37..b2711828 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -223,8 +223,8 @@
 		EE247AE41C3F04ED00AE3E12 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		EE247AEE1C3F06E900AE3E12 /* Blob.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Blob.swift; sourceTree = "<group>"; };
 		EE247AEF1C3F06E900AE3E12 /* Connection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Connection.swift; sourceTree = "<group>"; };
-		EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = fts3_tokenizer.h; path = Sources/SQLiteObjc/fts3_tokenizer.h; sourceTree = "<group>"; };
-		EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "SQLite-Bridging.m"; path = "Sources/SQLiteObjc/SQLite-Bridging.m"; sourceTree = "<group>"; };
+		EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = fts3_tokenizer.h; path = ../../SQLiteObjc/fts3_tokenizer.h; sourceTree = "<group>"; };
+		EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "SQLite-Bridging.m"; path = "../../SQLiteObjc/SQLite-Bridging.m"; sourceTree = "<group>"; };
 		EE247AF21C3F06E900AE3E12 /* Statement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Statement.swift; sourceTree = "<group>"; };
 		EE247AF31C3F06E900AE3E12 /* Value.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Value.swift; sourceTree = "<group>"; };
 		EE247AF51C3F06E900AE3E12 /* FTS4.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS4.swift; sourceTree = "<group>"; };
@@ -1222,6 +1222,7 @@
 				ONLY_ACTIVE_ARCH = YES;
 				PRODUCT_NAME = "";
 				SDKROOT = iphoneos;
+				SWIFT_ACTIVE_COMPILATION_CONDITIONS = ALL_IN_ONE_BUILD;
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
 				TARGETED_DEVICE_FAMILY = "1,2,3";
 				VERSIONING_SYSTEM = "apple-generic";
@@ -1267,6 +1268,7 @@
 				MTL_ENABLE_DEBUG_INFO = NO;
 				PRODUCT_NAME = "";
 				SDKROOT = iphoneos;
+				SWIFT_ACTIVE_COMPILATION_CONDITIONS = ALL_IN_ONE_BUILD;
 				SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
 				TARGETED_DEVICE_FAMILY = "1,2,3";
 				VALIDATE_PRODUCT = YES;
diff --git a/Sources/SQLite/Extensions/FTS4.swift b/Sources/SQLite/Extensions/FTS4.swift
index 6aec27e1..fe9ee6b8 100644
--- a/Sources/SQLite/Extensions/FTS4.swift
+++ b/Sources/SQLite/Extensions/FTS4.swift
@@ -22,8 +22,11 @@
 // THE SOFTWARE.
 //
 
+#if ALL_IN_ONE_BUILD
+// Nothing required
+#else
 import SQLiteObjc
-
+#endif
 
 extension Module {
 

From c354a7fa71de0f145229fd3fd36703ff15f93cd0 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 10 Dec 2016 09:20:02 +0000
Subject: [PATCH 172/685] Update docs, add tests, fix podspec
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Fix paths

Fix up podspec

Run tests with package manager

missing space

Update changelog

Fix variable expansion

Fix quoting

More quoting

Don’t use env variable

Rename

Update doc

Try build only

Link ref

Add to index

Sans quotes

Doc

Simplify podspec

Update docs

Update planning doc

Missing closing quote

yml

doc

Capitalization

Remove ALL_IN_ONE_BUILD

Use system sqlite3

Fix import

Fix bridging header

Fixing paths
---
 .travis.yml                                   |   1 +
 CHANGELOG.md                                  |   3 ++
 CocoaPodsTests/integration_test.rb            |   4 +-
 Documentation/Index.md                        |  38 +++++++++---------
 Documentation/Planning.md                     |   5 ---
 Package.swift                                 |  14 +++----
 README.md                                     |  20 +++++----
 SQLite.swift.podspec                          |  16 ++++----
 SQLite.xcodeproj/project.pbxproj              |  16 ++++----
 Sources/CSQLite/module.modulemap              |   4 --
 .../SQLite}/Extensions/Cipher.swift           |   0
 Sources/SQLite/Extensions/FTS4.swift          |   4 +-
 Sources/SQLiteObjc/SQLite-Bridging.m          |   1 -
 .../SQLiteTests}/CipherTests.swift            |   0
 Tests/SQLiteTests/ConnectionTests.swift       |   2 +-
 .../SQLiteTests}/Fixtures.swift               |   0
 .../SQLiteTests}/fixtures/encrypted.sqlite    | Bin
 run-tests.sh                                  |   2 +
 18 files changed, 62 insertions(+), 68 deletions(-)
 delete mode 100644 Sources/CSQLite/module.modulemap
 rename {SQLite => Sources/SQLite}/Extensions/Cipher.swift (100%)
 rename {SQLiteTests => Tests/SQLiteTests}/CipherTests.swift (100%)
 rename {SQLiteTests => Tests/SQLiteTests}/Fixtures.swift (100%)
 rename {SQLiteTests => Tests/SQLiteTests}/fixtures/encrypted.sqlite (100%)

diff --git a/.travis.yml b/.travis.yml
index 98975aba..e114b573 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,6 +12,7 @@ matrix:
     - env: VALIDATOR_SUBSPEC="standard"
     - env: VALIDATOR_SUBSPEC="standalone"
     - env: VALIDATOR_SUBSPEC="SQLCipher"
+    - env: PACKAGE_MANAGER_COMMAND="test -Xlinker -lsqlite3"
 before_install:
   - gem update bundler
   - gem install xcpretty --no-document
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 185e9a63..c23af3cc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
 ========================================
 
 * Fixed SQLCipher integration with read-only databases ([#559][])
+* Preliminary Swift Package Manager support ([#548][], [#560][])
 * Fixed null pointer when fetching an empty BLOB ([#561][])
 
 0.11.1 (06-12-2016), [diff][diff-0.11.1]
@@ -24,6 +25,8 @@
 
 [#532]: https://github.com/stephencelis/SQLite.swift/issues/532
 [#546]: https://github.com/stephencelis/SQLite.swift/issues/546
+[#548]: https://github.com/stephencelis/SQLite.swift/pull/548
 [#553]: https://github.com/stephencelis/SQLite.swift/pull/553
 [#559]: https://github.com/stephencelis/SQLite.swift/pull/559
+[#560]: https://github.com/stephencelis/SQLite.swift/pull/560
 [#561]: https://github.com/stephencelis/SQLite.swift/issues/561
diff --git a/CocoaPodsTests/integration_test.rb b/CocoaPodsTests/integration_test.rb
index 7f3e8132..d296c28e 100755
--- a/CocoaPodsTests/integration_test.rb
+++ b/CocoaPodsTests/integration_test.rb
@@ -13,7 +13,7 @@ def test_validate_project
 
   def validator
     @validator ||= TestRunningValidator.new(podspec, []).tap do |validator|
-        validator.test_files = Dir["#{project_test_dir}/*.swift"]
+        validator.test_files = Dir["#{project_test_dir}/**/*.swift"]
         validator.test_resources = Dir["#{project_test_dir}/fixtures"]
         validator.config.verbose = true
         validator.no_clean = true
@@ -38,6 +38,6 @@ def podspec
   end
 
   def project_test_dir
-    File.expand_path(File.dirname(__FILE__) + '/../SQLiteTests')
+    File.expand_path(File.dirname(__FILE__) + '/../Tests/SQLiteTests')
   end
 end
diff --git a/Documentation/Index.md b/Documentation/Index.md
index 40e9f503..63c8d903 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -3,8 +3,8 @@
   - [Installation](#installation)
     - [Carthage](#carthage)
     - [CocoaPods](#cocoapods)
+    - [Swift Package Manager](#swift-package-manager)
     - [Manual](#manual)
-    - [Frameworkless Targets](#frameworkless-targets)
   - [Getting Started](#getting-started)
     - [Connecting to a Database](#connecting-to-a-database)
       - [Read-Write Databases](#read-write-databases)
@@ -162,6 +162,24 @@ try db.rekey("another secret")
 [sqlite3pod]: https://github.com/clemensg/sqlite3pod
 [SQLCipher]: https://www.zetetic.net/sqlcipher/
 
+### Swift Package Manager
+
+The [Swift Package Manager][] is a tool for managing the distribution of Swift code.
+It’s integrated with the Swift build system to automate the process of
+downloading, compiling, and linking dependencies.
+
+It is the recommended approach for using SQLite.swift in OSX CLI applications.
+
+1. Add the following to your `Package.swift` file:
+
+```swift
+dependencies: [
+    .Package(url: "https://github.com/stephencelis/SQLite.swift.git", majorVersion: 0, minor: 11)
+]
+```
+
+[Swift Package Manager]: https://swift.org/package-manager
+
 ### Manual
 
 To install SQLite.swift as an Xcode sub-project:
@@ -186,24 +204,6 @@ Some additional steps are required to install the application on an actual devic
 
  7. **Add**.
 
-### Frameworkless Targets
-
-It’s possible to use SQLite.swift in a target that doesn’t support frameworks, including iOS 7 apps and OS X command line tools, though it takes a little extra work.
-
- 1. In your target’s **Build Phases**, add **libsqlite3.dylib** to the **Link Binary With Libraries** build phase.
-
- 2. Copy the SQLite.swift source files (from its **SQLite** directory) into your Xcode project.
-
- 3. Add the following lines to your project’s [bridging header](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html#//apple_ref/doc/uid/TP40014216-CH10-XID_79) (a file usually in the form of `$(TARGET_NAME)-Bridging-Header.h`).
-
-    ``` swift
-    #import <sqlite3.h>
-    #import "SQLite-Bridging.h"
-    ```
-
-> _Note:_ Adding SQLite.swift source files directly to your application will both remove the `SQLite` module namespace (no need—or ability—to `import SQLite`) and expose internal functions and variables. You will need to rename anything that conflicts with code of your own. Please [report any bugs](https://github.com/stephencelis/SQLite.swift/issues/new) (_e.g._, segfaults) you encounter.
-
-
 ## Getting Started
 
 To use SQLite.swift classes or structures in your target’s source file, first import the `SQLite` module.
diff --git a/Documentation/Planning.md b/Documentation/Planning.md
index a0c6d049..d814d26b 100644
--- a/Documentation/Planning.md
+++ b/Documentation/Planning.md
@@ -11,15 +11,10 @@ _Lists agreed upon next steps in approximate priority order._
 
 _A gathering point for ideas for new features. In general, the corresponding issue will be closed once it is added here, with the assumption that it will be referred to when it comes time to add the corresponding feature._
 
-### Packaging
-
- * linux support via Swift Package Manager, per [#315](https://github.com/stephencelis/SQLite.swift/issues/315), _in progress_: [#548](https://github.com/stephencelis/SQLite.swift/pull/548)
-
 ### Features
 
  * encapsulate ATTACH DATABASE / DETACH DATABASE as methods, per [#30](https://github.com/stephencelis/SQLite.swift/issues/30)
  * provide separate threads for update vs read, so updates don't block reads, per [#236](https://github.com/stephencelis/SQLite.swift/issues/236)
- * expose more FTS4 options, e.g. virtual table support per [#164](https://github.com/stephencelis/SQLite.swift/issues/164)
  * expose triggers, per [#164](https://github.com/stephencelis/SQLite.swift/issues/164)
 
 ## Suspended Feature Requests
diff --git a/Package.swift b/Package.swift
index f5c5b54f..966ebfde 100644
--- a/Package.swift
+++ b/Package.swift
@@ -6,15 +6,11 @@ let package = Package(
         Target(
             name: "SQLite",
             dependencies: [
-                .Target(name: "SQLiteObjc"),
-                .Target(name: "CSQLite")
+                .Target(name: "SQLiteObjc")
             ]),
-        Target(
-            name: "SQLiteObjc",
-            dependencies: [
-                .Target(name: "CSQLite")
-            ]),
-        Target(
-            name: "CSQLite")
+        Target(name: "SQLiteObjc")
+    ],
+    dependencies: [
+        .Package(url: "https://github.com/jberkel/CSQLite.git", majorVersion: 0)
     ]
 )
diff --git a/README.md b/README.md
index c0b778df..488e964b 100644
--- a/README.md
+++ b/README.md
@@ -112,12 +112,6 @@ For a more comprehensive example, see [this article](http://masteringswift.blogs
 > _Note:_ SQLite.swift requires Swift 3 (and [Xcode][] 8) or greater. If you absolutely
 > need compatibility with Swift 2.3 you can use the [swift-2.3][] branch or older
 > released versions. New development will happen exclusively on the master/Swift 3 branch.
->
-> The following instructions apply to targets that support embedded
-> Swift frameworks. To use SQLite.swift in iOS 7 or an OS X command line
-> tool, please read the [Frameworkless Targets][] section of the
-> documentation.
-
 
 ### Carthage
 
@@ -174,6 +168,19 @@ SQLite.swift with CocoaPods:
 [CocoaPods]: https://cocoapods.org
 [CocoaPods Installation]: https://guides.cocoapods.org/using/getting-started.html#getting-started
 
+### Swift Package Manager
+
+The [Swift Package Manager][] is a tool for managing the distribution of Swift code.
+
+1. Add the following to your `Package.swift` file:
+
+```swift
+dependencies: [
+    .Package(url: "https://github.com/stephencelis/SQLite.swift.git", majorVersion: 0, minor: 11)
+]
+```
+
+[Swift Package Manager]: https://swift.org/package-manager
 
 ### Manual
 
@@ -200,7 +207,6 @@ Some additional steps are required to install the application on an actual devic
  7. **Add**.
 
 
-[Frameworkless Targets]: Documentation/Index.md#frameworkless-targets
 [Xcode]: https://developer.apple.com/xcode/downloads/
 [Submodule]: http://git-scm.com/book/en/Git-Tools-Submodules
 [download]: https://github.com/stephencelis/SQLite.swift/archive/master.zip
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index ad423298..b5ed4559 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -25,9 +25,9 @@ Pod::Spec.new do |s|
   }
 
   s.subspec 'standard' do |ss|
-    ss.source_files = 'SQLite/**/*.{c,h,m,swift}'
-    ss.exclude_files = 'SQLite/Extensions/Cipher.swift'
-    ss.private_header_files = 'SQLite/Core/fts3_tokenizer.h'
+    ss.source_files = 'Sources/{SQLite,SQLiteObjc}/**/*.{c,h,m,swift}'
+    ss.exclude_files = 'Sources/**/Cipher.swift'
+    ss.private_header_files = 'Sources/SQLiteObjc/*.h'
 
     ss.library = 'sqlite3'
     ss.preserve_paths = 'CocoaPods/**/*'
@@ -47,9 +47,9 @@ Pod::Spec.new do |s|
   end
 
   s.subspec 'standalone' do |ss|
-    ss.source_files = 'SQLite/**/*.{c,h,m,swift}'
-    ss.exclude_files = 'SQLite/Extensions/Cipher.swift'
-    ss.private_header_files = 'SQLite/Core/fts3_tokenizer.h'
+    ss.source_files = 'Sources/{SQLite,SQLiteObjc}/**/*.{c,h,m,swift}'
+    ss.exclude_files = 'Sources/**/Cipher.swift'
+    ss.private_header_files = 'Sources/SQLiteObjc/*.h'
     ss.xcconfig = {
       'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_SWIFT_STANDALONE'
     }
@@ -58,8 +58,8 @@ Pod::Spec.new do |s|
   end
 
   s.subspec 'SQLCipher' do |ss|
-    ss.source_files = 'SQLite/**/*.{c,h,m,swift}'
-    ss.private_header_files = 'SQLite/Core/fts3_tokenizer.h'
+    ss.source_files = 'Sources/{SQLite,SQLiteObjc}/**/*.{c,h,m,swift}'
+    ss.private_header_files = 'Sources/SQLiteObjc/*.h'
     ss.xcconfig = {
       'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_SWIFT_SQLCIPHER',
       'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SQLITE_HAS_CODEC=1'
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index b2711828..153295cc 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -455,6 +455,7 @@
 		EE247AE11C3F04ED00AE3E12 /* SQLiteTests */ = {
 			isa = PBXGroup;
 			children = (
+				19A17E2695737FAB5D6086E3 /* fixtures */,
 				EE247B1A1C3F137700AE3E12 /* AggregateFunctionsTests.swift */,
 				EE247B1B1C3F137700AE3E12 /* BlobTests.swift */,
 				EE247B1D1C3F137700AE3E12 /* ConnectionTests.swift */,
@@ -474,7 +475,6 @@
 				19A1721B8984686B9963B45D /* FTS5Tests.swift */,
 				19A1794CC4D7827E997E32A7 /* FoundationTests.swift */,
 				19A17399EA9E61235D5D77BF /* CipherTests.swift */,
-				19A17E2695737FAB5D6086E3 /* fixtures */,
 				19A17B93B48B5560E6E51791 /* Fixtures.swift */,
 			);
 			name = SQLiteTests;
@@ -1104,7 +1104,7 @@
 		03A65E6D1C6BB0F60062603F /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				INFOPLIST_FILE = SQLite/Info.plist;
+				INFOPLIST_FILE = Tests/SQLite/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1117,7 +1117,7 @@
 		03A65E6E1C6BB0F60062603F /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				INFOPLIST_FILE = SQLite/Info.plist;
+				INFOPLIST_FILE = Tests/SQLite/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1222,7 +1222,6 @@
 				ONLY_ACTIVE_ARCH = YES;
 				PRODUCT_NAME = "";
 				SDKROOT = iphoneos;
-				SWIFT_ACTIVE_COMPILATION_CONDITIONS = ALL_IN_ONE_BUILD;
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
 				TARGETED_DEVICE_FAMILY = "1,2,3";
 				VERSIONING_SYSTEM = "apple-generic";
@@ -1268,7 +1267,6 @@
 				MTL_ENABLE_DEBUG_INFO = NO;
 				PRODUCT_NAME = "";
 				SDKROOT = iphoneos;
-				SWIFT_ACTIVE_COMPILATION_CONDITIONS = ALL_IN_ONE_BUILD;
 				SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
 				TARGETED_DEVICE_FAMILY = "1,2,3";
 				VALIDATE_PRODUCT = YES;
@@ -1331,7 +1329,7 @@
 		EE247AEB1C3F04ED00AE3E12 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				INFOPLIST_FILE = SQLiteTests/Info.plist;
+				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1342,7 +1340,7 @@
 		EE247AEC1C3F04ED00AE3E12 /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				INFOPLIST_FILE = SQLiteTests/Info.plist;
+				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1409,7 +1407,7 @@
 			buildSettings = {
 				CODE_SIGN_IDENTITY = "-";
 				COMBINE_HIDPI_IMAGES = YES;
-				INFOPLIST_FILE = SQLiteTests/Info.plist;
+				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
 				MACOSX_DEPLOYMENT_TARGET = 10.11;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
@@ -1424,7 +1422,7 @@
 			buildSettings = {
 				CODE_SIGN_IDENTITY = "-";
 				COMBINE_HIDPI_IMAGES = YES;
-				INFOPLIST_FILE = SQLiteTests/Info.plist;
+				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
 				MACOSX_DEPLOYMENT_TARGET = 10.11;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
diff --git a/Sources/CSQLite/module.modulemap b/Sources/CSQLite/module.modulemap
deleted file mode 100644
index f4127dce..00000000
--- a/Sources/CSQLite/module.modulemap
+++ /dev/null
@@ -1,4 +0,0 @@
-module CSQLite {
-    umbrella header "include/sqlite3.h"
-    export *
-}
diff --git a/SQLite/Extensions/Cipher.swift b/Sources/SQLite/Extensions/Cipher.swift
similarity index 100%
rename from SQLite/Extensions/Cipher.swift
rename to Sources/SQLite/Extensions/Cipher.swift
diff --git a/Sources/SQLite/Extensions/FTS4.swift b/Sources/SQLite/Extensions/FTS4.swift
index fe9ee6b8..152a2921 100644
--- a/Sources/SQLite/Extensions/FTS4.swift
+++ b/Sources/SQLite/Extensions/FTS4.swift
@@ -22,9 +22,7 @@
 // THE SOFTWARE.
 //
 
-#if ALL_IN_ONE_BUILD
-// Nothing required
-#else
+#if SWIFT_PACKAGE
 import SQLiteObjc
 #endif
 
diff --git a/Sources/SQLiteObjc/SQLite-Bridging.m b/Sources/SQLiteObjc/SQLite-Bridging.m
index a5702cc7..d8fe6b68 100644
--- a/Sources/SQLiteObjc/SQLite-Bridging.m
+++ b/Sources/SQLiteObjc/SQLite-Bridging.m
@@ -23,7 +23,6 @@
 //
 
 #import "SQLite-Bridging.h"
-#import "sqlite3.h"
 #import "fts3_tokenizer.h"
 
 #pragma mark - FTS
diff --git a/SQLiteTests/CipherTests.swift b/Tests/SQLiteTests/CipherTests.swift
similarity index 100%
rename from SQLiteTests/CipherTests.swift
rename to Tests/SQLiteTests/CipherTests.swift
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index 33c7610e..59514a25 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -5,7 +5,7 @@ import XCTest
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif COCOAPODS
+#else
 import CSQLite
 #endif
 
diff --git a/SQLiteTests/Fixtures.swift b/Tests/SQLiteTests/Fixtures.swift
similarity index 100%
rename from SQLiteTests/Fixtures.swift
rename to Tests/SQLiteTests/Fixtures.swift
diff --git a/SQLiteTests/fixtures/encrypted.sqlite b/Tests/SQLiteTests/fixtures/encrypted.sqlite
similarity index 100%
rename from SQLiteTests/fixtures/encrypted.sqlite
rename to Tests/SQLiteTests/fixtures/encrypted.sqlite
diff --git a/run-tests.sh b/run-tests.sh
index bc8cd773..571bb6e2 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -8,4 +8,6 @@ if [ -n "$BUILD_SCHEME" ]; then
     fi
 elif [ -n "$VALIDATOR_SUBSPEC" ]; then
     cd CocoaPodsTests && make test
+elif [ -n "${PACKAGE_MANAGER_COMMAND}" ]; then
+    swift ${PACKAGE_MANAGER_COMMAND}
 fi

From a58eac718a3ecd17690302d018d355cd163f5c94 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 11 Dec 2016 01:44:59 +0000
Subject: [PATCH 173/685] Add build step to docs

---
 Documentation/Index.md | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 63c8d903..540b7167 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -178,6 +178,12 @@ dependencies: [
 ]
 ```
 
+2. Build your project:
+
+```shell
+$ swift build -Xlinker -lsqlite3
+```
+
 [Swift Package Manager]: https://swift.org/package-manager
 
 ### Manual

From ddace3e66fa554ea32c6c9fe3f2e943481006f0d Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 11 Dec 2016 01:45:24 +0000
Subject: [PATCH 174/685] Ignore package dir

---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index b617bcef..25ac055b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,3 +24,4 @@ Carthage
 
 # Swift Package Manager
 .build
+Packages/

From 3656d9ef1d3fdf34de19cbbce00bad59e85c1818 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 11 Dec 2016 01:50:12 +0000
Subject: [PATCH 175/685] Formatting

---
 Documentation/Index.md | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 540b7167..050db1a4 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -170,19 +170,19 @@ downloading, compiling, and linking dependencies.
 
 It is the recommended approach for using SQLite.swift in OSX CLI applications.
 
-1. Add the following to your `Package.swift` file:
+ 1. Add the following to your `Package.swift` file:
 
-```swift
-dependencies: [
+  ``` swift
+  dependencies: [
     .Package(url: "https://github.com/stephencelis/SQLite.swift.git", majorVersion: 0, minor: 11)
-]
-```
+  ]
+  ```
 
-2. Build your project:
+ 2. Build your project:
 
-```shell
-$ swift build -Xlinker -lsqlite3
-```
+  ``` sh
+  $ swift build -Xlinker -lsqlite3
+  ```
 
 [Swift Package Manager]: https://swift.org/package-manager
 

From 66f199281549902961d5b9c0dbbddc3e1d2587de Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 19 Dec 2016 19:04:53 +0000
Subject: [PATCH 176/685] Move CocoaPods test

---
 Package.swift                                                 | 3 ++-
 {CocoaPodsTests => Tests/CocoaPods}/.gitignore                | 0
 {CocoaPodsTests => Tests/CocoaPods}/Gemfile                   | 0
 {CocoaPodsTests => Tests/CocoaPods}/Gemfile.lock              | 0
 {CocoaPodsTests => Tests/CocoaPods}/Makefile                  | 0
 {CocoaPodsTests => Tests/CocoaPods}/integration_test.rb       | 0
 {CocoaPodsTests => Tests/CocoaPods}/test_running_validator.rb | 0
 run-tests.sh                                                  | 2 +-
 8 files changed, 3 insertions(+), 2 deletions(-)
 rename {CocoaPodsTests => Tests/CocoaPods}/.gitignore (100%)
 rename {CocoaPodsTests => Tests/CocoaPods}/Gemfile (100%)
 rename {CocoaPodsTests => Tests/CocoaPods}/Gemfile.lock (100%)
 rename {CocoaPodsTests => Tests/CocoaPods}/Makefile (100%)
 rename {CocoaPodsTests => Tests/CocoaPods}/integration_test.rb (100%)
 rename {CocoaPodsTests => Tests/CocoaPods}/test_running_validator.rb (100%)

diff --git a/Package.swift b/Package.swift
index 966ebfde..7d698370 100644
--- a/Package.swift
+++ b/Package.swift
@@ -12,5 +12,6 @@ let package = Package(
     ],
     dependencies: [
         .Package(url: "https://github.com/jberkel/CSQLite.git", majorVersion: 0)
-    ]
+    ],
+    exclude: ["Tests/CocoaPods"]
 )
diff --git a/CocoaPodsTests/.gitignore b/Tests/CocoaPods/.gitignore
similarity index 100%
rename from CocoaPodsTests/.gitignore
rename to Tests/CocoaPods/.gitignore
diff --git a/CocoaPodsTests/Gemfile b/Tests/CocoaPods/Gemfile
similarity index 100%
rename from CocoaPodsTests/Gemfile
rename to Tests/CocoaPods/Gemfile
diff --git a/CocoaPodsTests/Gemfile.lock b/Tests/CocoaPods/Gemfile.lock
similarity index 100%
rename from CocoaPodsTests/Gemfile.lock
rename to Tests/CocoaPods/Gemfile.lock
diff --git a/CocoaPodsTests/Makefile b/Tests/CocoaPods/Makefile
similarity index 100%
rename from CocoaPodsTests/Makefile
rename to Tests/CocoaPods/Makefile
diff --git a/CocoaPodsTests/integration_test.rb b/Tests/CocoaPods/integration_test.rb
similarity index 100%
rename from CocoaPodsTests/integration_test.rb
rename to Tests/CocoaPods/integration_test.rb
diff --git a/CocoaPodsTests/test_running_validator.rb b/Tests/CocoaPods/test_running_validator.rb
similarity index 100%
rename from CocoaPodsTests/test_running_validator.rb
rename to Tests/CocoaPods/test_running_validator.rb
diff --git a/run-tests.sh b/run-tests.sh
index 571bb6e2..6ec6bacf 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -7,7 +7,7 @@ if [ -n "$BUILD_SCHEME" ]; then
         make test BUILD_SCHEME="$BUILD_SCHEME"
     fi
 elif [ -n "$VALIDATOR_SUBSPEC" ]; then
-    cd CocoaPodsTests && make test
+    cd Tests/CocoaPods && make test
 elif [ -n "${PACKAGE_MANAGER_COMMAND}" ]; then
     swift ${PACKAGE_MANAGER_COMMAND}
 fi

From 98be8593a9ec2387f27375b8486e72e58d356619 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 19 Dec 2016 20:04:38 +0000
Subject: [PATCH 177/685] Absolute path

---
 .gitignore | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitignore b/.gitignore
index 25ac055b..5882e0cb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,7 +20,7 @@ DerivedData
 *.xcuserstate
 
 # Carthage
-Carthage
+/Carthage/
 
 # Swift Package Manager
 .build

From 4066660ffaab86ee070a4388efbfee44070d312d Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 19 Dec 2016 20:09:16 +0000
Subject: [PATCH 178/685] Add tests for Carthage

---
 .travis.yml               |  2 ++
 Package.swift             |  2 +-
 Tests/Carthage/.gitignore |  2 ++
 Tests/Carthage/Cartfile   |  1 +
 Tests/Carthage/Makefile   | 10 ++++++++++
 run-tests.sh              |  2 ++
 6 files changed, 18 insertions(+), 1 deletion(-)
 create mode 100644 Tests/Carthage/.gitignore
 create mode 100644 Tests/Carthage/Cartfile
 create mode 100644 Tests/Carthage/Makefile

diff --git a/.travis.yml b/.travis.yml
index e114b573..f9618e2e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,6 +12,8 @@ matrix:
     - env: VALIDATOR_SUBSPEC="standard"
     - env: VALIDATOR_SUBSPEC="standalone"
     - env: VALIDATOR_SUBSPEC="SQLCipher"
+    - env: CARTHAGE_PLATFORM="iOS"
+    - env: CARTHAGE_PLATFORM="Mac"
     - env: PACKAGE_MANAGER_COMMAND="test -Xlinker -lsqlite3"
 before_install:
   - gem update bundler
diff --git a/Package.swift b/Package.swift
index 7d698370..4d4c1504 100644
--- a/Package.swift
+++ b/Package.swift
@@ -13,5 +13,5 @@ let package = Package(
     dependencies: [
         .Package(url: "https://github.com/jberkel/CSQLite.git", majorVersion: 0)
     ],
-    exclude: ["Tests/CocoaPods"]
+    exclude: ["Tests/CocoaPods", "Tests/Carthage"]
 )
diff --git a/Tests/Carthage/.gitignore b/Tests/Carthage/.gitignore
new file mode 100644
index 00000000..3b8ec70c
--- /dev/null
+++ b/Tests/Carthage/.gitignore
@@ -0,0 +1,2 @@
+Carthage/
+Cartfile.resolved
diff --git a/Tests/Carthage/Cartfile b/Tests/Carthage/Cartfile
new file mode 100644
index 00000000..a750e057
--- /dev/null
+++ b/Tests/Carthage/Cartfile
@@ -0,0 +1 @@
+github "stephencelis/SQLite.swift" "master"
diff --git a/Tests/Carthage/Makefile b/Tests/Carthage/Makefile
new file mode 100644
index 00000000..04df397a
--- /dev/null
+++ b/Tests/Carthage/Makefile
@@ -0,0 +1,10 @@
+CARTHAGE := /usr/local/bin/carthage
+CARTHAGE_PLATFORM := iOS
+CARTHAGE_CONFIGURATION := Release
+CARTHAGE_DIR := Carthage
+CARTHAGE_ARGS := --no-use-binaries
+CARTHAGE_TOOLCHAIN := com.apple.dt.toolchain.Swift_3_0
+CARTHAGE_CMDLINE := --configuration $(CARTHAGE_CONFIGURATION) --platform $(CARTHAGE_PLATFORM) --toolchain $(CARTHAGE_TOOLCHAIN) $(CARTHAGE_ARGS)
+
+test: $(CARTHAGE) Cartfile
+	$< bootstrap $(CARTHAGE_CMDLINE)
diff --git a/run-tests.sh b/run-tests.sh
index 6ec6bacf..ddd7d678 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -8,6 +8,8 @@ if [ -n "$BUILD_SCHEME" ]; then
     fi
 elif [ -n "$VALIDATOR_SUBSPEC" ]; then
     cd Tests/CocoaPods && make test
+elif [ -n "$CARTHAGE_PLATFORM" ]; then
+    cd Tests/Carthage && make test CARTHAGE_PLATFORM="$CARTHAGE_PLATFORM"
 elif [ -n "${PACKAGE_MANAGER_COMMAND}" ]; then
     swift ${PACKAGE_MANAGER_COMMAND}
 fi

From 0b29b2691b7576ba63e1dffdb12a9624e54af38d Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 20 Dec 2016 00:37:31 +0000
Subject: [PATCH 179/685] Fix paths

---
 Tests/CocoaPods/integration_test.rb | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Tests/CocoaPods/integration_test.rb b/Tests/CocoaPods/integration_test.rb
index d296c28e..192aff90 100755
--- a/Tests/CocoaPods/integration_test.rb
+++ b/Tests/CocoaPods/integration_test.rb
@@ -34,10 +34,10 @@ def validator
   end
 
   def podspec
-    File.expand_path(File.dirname(__FILE__) + '/../SQLite.swift.podspec')
+    File.expand_path(File.dirname(__FILE__) + '/../../SQLite.swift.podspec')
   end
 
   def project_test_dir
-    File.expand_path(File.dirname(__FILE__) + '/../Tests/SQLiteTests')
+    File.expand_path(File.dirname(__FILE__) + '/../SQLiteTests')
   end
 end

From 8bf692bf2d16639fba3e7276ccc23c3ac358cf75 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 20 Dec 2016 01:28:48 +0000
Subject: [PATCH 180/685] Update carthage; use correct git sha to test

---
 .travis.yml             | 2 ++
 Tests/Carthage/Cartfile | 1 -
 Tests/Carthage/Makefile | 5 +++++
 3 files changed, 7 insertions(+), 1 deletion(-)
 delete mode 100644 Tests/Carthage/Cartfile

diff --git a/.travis.yml b/.travis.yml
index f9618e2e..30617d47 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -18,5 +18,7 @@ matrix:
 before_install:
   - gem update bundler
   - gem install xcpretty --no-document
+  - brew update
+  - brew outdated carthage || brew upgrade carthage
 script:
   - ./run-tests.sh
diff --git a/Tests/Carthage/Cartfile b/Tests/Carthage/Cartfile
deleted file mode 100644
index a750e057..00000000
--- a/Tests/Carthage/Cartfile
+++ /dev/null
@@ -1 +0,0 @@
-github "stephencelis/SQLite.swift" "master"
diff --git a/Tests/Carthage/Makefile b/Tests/Carthage/Makefile
index 04df397a..57644f8e 100644
--- a/Tests/Carthage/Makefile
+++ b/Tests/Carthage/Makefile
@@ -5,6 +5,11 @@ CARTHAGE_DIR := Carthage
 CARTHAGE_ARGS := --no-use-binaries
 CARTHAGE_TOOLCHAIN := com.apple.dt.toolchain.Swift_3_0
 CARTHAGE_CMDLINE := --configuration $(CARTHAGE_CONFIGURATION) --platform $(CARTHAGE_PLATFORM) --toolchain $(CARTHAGE_TOOLCHAIN) $(CARTHAGE_ARGS)
+TRAVIS_COMMIT ?= master
+TRAVIS_REPO_SLUG ?= stephencelis/SQLite.swift
 
 test: $(CARTHAGE) Cartfile
 	$< bootstrap $(CARTHAGE_CMDLINE)
+
+Cartfile:
+	echo 'github "$(TRAVIS_REPO_SLUG)" "$(TRAVIS_COMMIT)"' > $@

From 8a1aa20aa112df6394f8727dc41184ccb35a08c2 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 20 Dec 2016 02:00:55 +0000
Subject: [PATCH 181/685] Reference build dir to get correct sha

---
 Tests/Carthage/.gitignore | 1 +
 Tests/Carthage/Makefile   | 7 +++++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/Tests/Carthage/.gitignore b/Tests/Carthage/.gitignore
index 3b8ec70c..2d43454a 100644
--- a/Tests/Carthage/.gitignore
+++ b/Tests/Carthage/.gitignore
@@ -1,2 +1,3 @@
 Carthage/
+Cartfile
 Cartfile.resolved
diff --git a/Tests/Carthage/Makefile b/Tests/Carthage/Makefile
index 57644f8e..a4a14925 100644
--- a/Tests/Carthage/Makefile
+++ b/Tests/Carthage/Makefile
@@ -6,10 +6,13 @@ CARTHAGE_ARGS := --no-use-binaries
 CARTHAGE_TOOLCHAIN := com.apple.dt.toolchain.Swift_3_0
 CARTHAGE_CMDLINE := --configuration $(CARTHAGE_CONFIGURATION) --platform $(CARTHAGE_PLATFORM) --toolchain $(CARTHAGE_TOOLCHAIN) $(CARTHAGE_ARGS)
 TRAVIS_COMMIT ?= master
-TRAVIS_REPO_SLUG ?= stephencelis/SQLite.swift
+TRAVIS_BUILD_DIR ?= https://github.com/stephencelis/SQLite.swift.git
 
 test: $(CARTHAGE) Cartfile
 	$< bootstrap $(CARTHAGE_CMDLINE)
 
 Cartfile:
-	echo 'github "$(TRAVIS_REPO_SLUG)" "$(TRAVIS_COMMIT)"' > $@
+	echo 'git "$(TRAVIS_BUILD_DIR)" "$(TRAVIS_COMMIT)"' > $@
+
+clean:
+	@rm -f Cartfile Cartfile.resolved

From bcd4be7e4bb939c85f7a6f9a9f6cbb407b51ae4b Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 20 Dec 2016 02:29:54 +0000
Subject: [PATCH 182/685] Carthage: test all platforms

---
 .travis.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.travis.yml b/.travis.yml
index 30617d47..3747ac7b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,6 +14,8 @@ matrix:
     - env: VALIDATOR_SUBSPEC="SQLCipher"
     - env: CARTHAGE_PLATFORM="iOS"
     - env: CARTHAGE_PLATFORM="Mac"
+    - env: CARTHAGE_PLATFORM="watchOS"
+    - env: CARTHAGE_PLATFORM="tvOS"
     - env: PACKAGE_MANAGER_COMMAND="test -Xlinker -lsqlite3"
 before_install:
   - gem update bundler

From 845ad5af63faa83a14558cd69f228f30877936ea Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 20 Dec 2016 04:15:53 +0000
Subject: [PATCH 183/685] Use head commit

---
 Tests/Carthage/Makefile | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/Tests/Carthage/Makefile b/Tests/Carthage/Makefile
index a4a14925..f28eb25b 100644
--- a/Tests/Carthage/Makefile
+++ b/Tests/Carthage/Makefile
@@ -5,14 +5,12 @@ CARTHAGE_DIR := Carthage
 CARTHAGE_ARGS := --no-use-binaries
 CARTHAGE_TOOLCHAIN := com.apple.dt.toolchain.Swift_3_0
 CARTHAGE_CMDLINE := --configuration $(CARTHAGE_CONFIGURATION) --platform $(CARTHAGE_PLATFORM) --toolchain $(CARTHAGE_TOOLCHAIN) $(CARTHAGE_ARGS)
-TRAVIS_COMMIT ?= master
-TRAVIS_BUILD_DIR ?= https://github.com/stephencelis/SQLite.swift.git
 
 test: $(CARTHAGE) Cartfile
 	$< bootstrap $(CARTHAGE_CMDLINE)
 
 Cartfile:
-	echo 'git "$(TRAVIS_BUILD_DIR)" "$(TRAVIS_COMMIT)"' > $@
+	echo 'git "$(TRAVIS_BUILD_DIR)" "HEAD"' > $@
 
 clean:
 	@rm -f Cartfile Cartfile.resolved

From bd80bb2208e3ba37c97a802f1f84266dc74eca77 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 21 Dec 2016 10:19:42 +0000
Subject: [PATCH 184/685] Allow `where` as alias for `filter`

---
 CHANGELOG.md                       |  2 ++
 Documentation/Index.md             |  6 +++++-
 Sources/SQLite/Typed/Query.swift   | 12 ++++++++++++
 Tests/SQLiteTests/QueryTests.swift | 29 +++++++++++++++++++++++++++++
 4 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c23af3cc..5a11ea00 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,7 @@
 * Fixed SQLCipher integration with read-only databases ([#559][])
 * Preliminary Swift Package Manager support ([#548][], [#560][])
 * Fixed null pointer when fetching an empty BLOB ([#561][])
+* Allow `where` as alias for `filter` ([#571][])
 
 0.11.1 (06-12-2016), [diff][diff-0.11.1]
 ========================================
@@ -30,3 +31,4 @@
 [#559]: https://github.com/stephencelis/SQLite.swift/pull/559
 [#560]: https://github.com/stephencelis/SQLite.swift/pull/560
 [#561]: https://github.com/stephencelis/SQLite.swift/issues/561
+[#571]: https://github.com/stephencelis/SQLite.swift/issues/571
diff --git a/Documentation/Index.md b/Documentation/Index.md
index 050db1a4..3ab27a29 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -755,8 +755,12 @@ users.filter(verified || balance >= 10_000)
 
 We can build our own boolean expressions by using one of the many [filter operators and functions](#filter-operators-and-functions).
 
-> _Note:_ SQLite.swift defines `filter` instead of `where` because `where` is [a reserved keyword](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-ID413).
+Instead of `filter` we can also use the `where` function which is an alias:
 
+``` swift
+users.where(id == 1)
+// SELECT * FROM "users" WHERE ("id" = 1)
+```
 
 ##### Filter Operators and Functions
 
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index 288768c1..c9d2ea9c 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -306,6 +306,18 @@ extension QueryType {
         return query
     }
 
+    /// Adds a condition to the query’s `WHERE` clause.
+    /// This is an alias for `filter(predicate)`
+    public func `where`(_ predicate: Expression<Bool>) -> Self {
+        return `where`(Expression<Bool?>(predicate))
+    }
+
+    /// Adds a condition to the query’s `WHERE` clause.
+    /// This is an alias for `filter(predicate)`
+    public func `where`(_ predicate: Expression<Bool?>) -> Self {
+        return filter(predicate)
+    }
+
     // MARK: GROUP BY
 
     /// Sets a `GROUP BY` clause on the query.
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index ed34921e..2cf164c6 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -8,6 +8,7 @@ class QueryTests : XCTestCase {
     let email = Expression<String>("email")
     let age = Expression<Int?>("age")
     let admin = Expression<Bool>("admin")
+    let optionalAdmin = Expression<Bool?>("admin")
 
     let posts = Table("posts")
     let userId = Expression<Int64>("user_id")
@@ -88,6 +89,34 @@ class QueryTests : XCTestCase {
         AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 1)", users.filter(admin == true))
     }
 
+    func test_filter_compilesWhereClause_false() {
+        AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 0)", users.filter(admin == false))
+    }
+
+    func test_filter_compilesWhereClause_optional() {
+        AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 1)", users.filter(optionalAdmin == true))
+    }
+
+    func test_filter_compilesWhereClause_optional_false() {
+        AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 0)", users.filter(optionalAdmin == false))
+    }
+
+    func test_where_compilesWhereClause() {
+        AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 1)", users.where(admin == true))
+    }
+
+    func test_where_compilesWhereClause_false() {
+        AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 0)", users.where(admin == false))
+    }
+
+    func test_where_compilesWhereClause_optional() {
+        AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 1)", users.where(optionalAdmin == true))
+    }
+
+    func test_where_compilesWhereClause_optional_false() {
+        AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 0)", users.where(optionalAdmin == false))
+    }
+
     func test_filter_whenChained_compilesAggregateWhereClause() {
         AssertSQL(
             "SELECT * FROM \"users\" WHERE ((\"age\" >= 35) AND \"admin\")",

From a19b29b9e0202cfef340928ac01407260af537d1 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 21 Dec 2016 14:47:37 +0000
Subject: [PATCH 185/685] Make it clear that pod needs to be included once

---
 Documentation/Index.md | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 3ab27a29..4bb51eed 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -125,14 +125,18 @@ install SQLite.swift with Carthage:
  If you want to use a more recent version of SQLite than what is provided with the OS you can require the `standalone` subspec:
 
 ``` ruby
-    pod 'SQLite.swift/standalone', '~> 0.11.1'
+    target 'YourAppTargetName' do
+      pod 'SQLite.swift/standalone', '~> 0.11.1'
+    end
 ```
 
 By default this will use the most recent version of SQLite without any extras. If you want you can further customize this by adding another dependency to sqlite3 or one of its subspecs:
 
 ``` ruby
-    pod 'SQLite.swift/standalone', '~> 0.11.1'
-    pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
+    target 'YourAppTargetName' do
+      pod 'SQLite.swift/standalone', '~> 0.11.1'
+      pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
+    end
 ```
 
 See the [sqlite3 podspec][sqlite3pod] for more details.
@@ -143,7 +147,9 @@ If you want to use [SQLCipher][] with SQLite.swift you can require the `SQLCiphe
 subspec in your Podfile:
 
 ``` ruby
-    pod 'SQLite.swift/SQLCipher', '~> 0.11.1'
+    target 'YourAppTargetName' do
+      pod 'SQLite.swift/SQLCipher', '~> 0.11.1'
+    end
 ```
 
 This will automatically add a dependency to the SQLCipher pod as well as extend

From 9953dea614b701cdb5a873eceea28b55f776bfc6 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 21 Dec 2016 15:13:37 +0000
Subject: [PATCH 186/685] Indent

---
 Documentation/Index.md | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 4bb51eed..c407f06f 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -125,18 +125,18 @@ install SQLite.swift with Carthage:
  If you want to use a more recent version of SQLite than what is provided with the OS you can require the `standalone` subspec:
 
 ``` ruby
-    target 'YourAppTargetName' do
-      pod 'SQLite.swift/standalone', '~> 0.11.1'
-    end
+target 'YourAppTargetName' do
+  pod 'SQLite.swift/standalone', '~> 0.11.1'
+end
 ```
 
 By default this will use the most recent version of SQLite without any extras. If you want you can further customize this by adding another dependency to sqlite3 or one of its subspecs:
 
 ``` ruby
-    target 'YourAppTargetName' do
-      pod 'SQLite.swift/standalone', '~> 0.11.1'
-      pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
-    end
+target 'YourAppTargetName' do
+  pod 'SQLite.swift/standalone', '~> 0.11.1'
+  pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
+end
 ```
 
 See the [sqlite3 podspec][sqlite3pod] for more details.
@@ -147,9 +147,9 @@ If you want to use [SQLCipher][] with SQLite.swift you can require the `SQLCiphe
 subspec in your Podfile:
 
 ``` ruby
-    target 'YourAppTargetName' do
-      pod 'SQLite.swift/SQLCipher', '~> 0.11.1'
-    end
+target 'YourAppTargetName' do
+  pod 'SQLite.swift/SQLCipher', '~> 0.11.1'
+end
 ```
 
 This will automatically add a dependency to the SQLCipher pod as well as extend

From e3816fd44ac53c0fd72329a75357878f3717b6eb Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 24 Dec 2016 22:47:42 +0000
Subject: [PATCH 187/685] Switch repo

---
 Package.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Package.swift b/Package.swift
index 4d4c1504..fc7c5a0e 100644
--- a/Package.swift
+++ b/Package.swift
@@ -11,7 +11,7 @@ let package = Package(
         Target(name: "SQLiteObjc")
     ],
     dependencies: [
-        .Package(url: "https://github.com/jberkel/CSQLite.git", majorVersion: 0)
+        .Package(url: "https://github.com/stephencelis/CSQLite.git", majorVersion: 0)
     ],
     exclude: ["Tests/CocoaPods", "Tests/Carthage"]
 )

From 1b09ca46b0c75c839994cb0225d227aaaa6ef234 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 25 Dec 2016 19:15:32 +0100
Subject: [PATCH 188/685] Prepare release

---
 CHANGELOG.md              |  2 +-
 Documentation/Index.md    | 10 +++++-----
 README.md                 |  4 ++--
 SQLite.swift.podspec      |  2 +-
 Sources/SQLite/Info.plist |  2 +-
 5 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5a11ea00..f3298d68 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,4 @@
-0.11.2 (unreleased), [diff][diff-0.11.2]
+0.11.2 (25-12-2016), [diff][diff-0.11.2]
 ========================================
 
 * Fixed SQLCipher integration with read-only databases ([#559][])
diff --git a/Documentation/Index.md b/Documentation/Index.md
index c407f06f..3e13ad4e 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -78,7 +78,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```
-    github "stephencelis/SQLite.swift" ~> 0.11.1
+    github "stephencelis/SQLite.swift" ~> 0.11.2
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -113,7 +113,7 @@ install SQLite.swift with Carthage:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.11.1'
+        pod 'SQLite.swift', '~> 0.11.2'
     end
     ```
 
@@ -126,7 +126,7 @@ install SQLite.swift with Carthage:
 
 ``` ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.11.1'
+  pod 'SQLite.swift/standalone', '~> 0.11.2'
 end
 ```
 
@@ -134,7 +134,7 @@ By default this will use the most recent version of SQLite without any extras. I
 
 ``` ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.11.1'
+  pod 'SQLite.swift/standalone', '~> 0.11.2'
   pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
 end
 ```
@@ -148,7 +148,7 @@ subspec in your Podfile:
 
 ``` ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/SQLCipher', '~> 0.11.1'
+  pod 'SQLite.swift/SQLCipher', '~> 0.11.2'
 end
 ```
 
diff --git a/README.md b/README.md
index 488e964b..89917b36 100644
--- a/README.md
+++ b/README.md
@@ -123,7 +123,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```
-    github "stephencelis/SQLite.swift" ~> 0.11.1
+    github "stephencelis/SQLite.swift" ~> 0.11.2
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -159,7 +159,7 @@ SQLite.swift with CocoaPods:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.11.1'
+        pod 'SQLite.swift', '~> 0.11.2'
     end
     ```
 
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index b5ed4559..3c61aa1f 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.11.1"
+  s.version          = "0.11.2"
   s.summary          = "A type-safe, Swift-language layer over SQLite3 for iOS and OS X."
 
   s.description      = <<-DESC
diff --git a/Sources/SQLite/Info.plist b/Sources/SQLite/Info.plist
index 21f24d9d..588139c4 100644
--- a/Sources/SQLite/Info.plist
+++ b/Sources/SQLite/Info.plist
@@ -15,7 +15,7 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>0.11.1</string>
+	<string>0.11.2</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>

From 97e6a660e3a41ef4db43a3a33249d2c10f083fc8 Mon Sep 17 00:00:00 2001
From: Fred Cox <fred@ekreative.com>
Date: Mon, 16 Jan 2017 11:28:59 +0200
Subject: [PATCH 189/685] Add possibility to have expression on other side of
 like

---
 Sources/SQLite/Typed/CoreFunctions.swift   | 50 ++++++++++++++++++++++
 Tests/SQLiteTests/CoreFunctionsTests.swift |  6 +++
 2 files changed, 56 insertions(+)

diff --git a/Sources/SQLite/Typed/CoreFunctions.swift b/Sources/SQLite/Typed/CoreFunctions.swift
index 9d17a326..dc450abd 100644
--- a/Sources/SQLite/Typed/CoreFunctions.swift
+++ b/Sources/SQLite/Typed/CoreFunctions.swift
@@ -223,6 +223,31 @@ extension ExpressionType where UnderlyingType == String {
         return Expression("(\(template) LIKE ? ESCAPE ?)", bindings + [pattern, String(character)])
     }
 
+    /// Builds a copy of the expression appended with a `LIKE` query against the
+    /// given pattern.
+    ///
+    ///     let email = Expression<String>("email")
+    ///     let pattern = Expression<String>("pattern")
+    ///     email.like(pattern)
+    ///     // "email" LIKE "pattern"
+    ///
+    /// - Parameters:
+    ///
+    ///   - pattern: A pattern to match.
+    ///
+    ///   - escape: An (optional) character designated for escaping
+    ///     pattern-matching characters (*i.e.*, the `%` and `_` characters).
+    ///
+    /// - Returns: A copy of the expression appended with a `LIKE` query against
+    ///   the given pattern.
+    public func like(_ pattern: Expression<String>, escape character: Character? = nil) -> Expression<Bool> {
+        guard let character = character else {
+            return "LIKE".infix(self, pattern)
+        }
+        let like: Expression<Bool> = "LIKE".infix(self, pattern, wrap: false)
+        return Expression("(\(like.template) ESCAPE ?)", like.bindings + [String(character)])
+    }
+
     /// Builds a copy of the expression appended with a `GLOB` query against the
     /// given pattern.
     ///
@@ -422,6 +447,31 @@ extension ExpressionType where UnderlyingType == String? {
         }
         return Expression("(\(template) LIKE ? ESCAPE ?)", bindings + [pattern, String(character)])
     }
+    
+    /// Builds a copy of the expression appended with a `LIKE` query against the
+    /// given pattern.
+    ///
+    ///     let email = Expression<String>("email")
+    ///     let pattern = Expression<String>("pattern")
+    ///     email.like(pattern)
+    ///     // "email" LIKE "pattern"
+    ///
+    /// - Parameters:
+    ///
+    ///   - pattern: A pattern to match.
+    ///
+    ///   - escape: An (optional) character designated for escaping
+    ///     pattern-matching characters (*i.e.*, the `%` and `_` characters).
+    ///
+    /// - Returns: A copy of the expression appended with a `LIKE` query against
+    ///   the given pattern.
+    public func like(_ pattern: Expression<String>, escape character: Character? = nil) -> Expression<Bool?> {
+        guard let character = character else {
+            return "LIKE".infix(self, pattern)
+        }
+        let like: Expression<Bool> = "LIKE".infix(self, pattern, wrap: false)
+        return Expression("(\(like.template) ESCAPE ?)", like.bindings + [String(character)])
+    }
 
     /// Builds a copy of the expression appended with a `GLOB` query against the
     /// given pattern.
diff --git a/Tests/SQLiteTests/CoreFunctionsTests.swift b/Tests/SQLiteTests/CoreFunctionsTests.swift
index db37ff7f..82c59c61 100644
--- a/Tests/SQLiteTests/CoreFunctionsTests.swift
+++ b/Tests/SQLiteTests/CoreFunctionsTests.swift
@@ -37,6 +37,12 @@ class CoreFunctionsTests : XCTestCase {
 
         AssertSQL("(\"string\" LIKE '%\\%' ESCAPE '\\')", string.like("%\\%", escape: "\\"))
         AssertSQL("(\"stringOptional\" LIKE '_\\_' ESCAPE '\\')", stringOptional.like("_\\_", escape: "\\"))
+        
+        AssertSQL("(\"string\" LIKE \"a\")", string.like(Expression<String>("a")))
+        AssertSQL("(\"stringOptional\" LIKE \"a\")", stringOptional.like(Expression<String>("a")))
+        
+        AssertSQL("(\"string\" LIKE \"a\" ESCAPE '\\')", string.like(Expression<String>("a"), escape: "\\"))
+        AssertSQL("(\"stringOptional\" LIKE \"a\" ESCAPE '\\')", stringOptional.like(Expression<String>("a"), escape: "\\"))
     }
 
     func test_glob_buildsExpressionWithGlobOperator() {

From 5800d139597b5ffa8ba747d059fbeb9f6dd425eb Mon Sep 17 00:00:00 2001
From: Fred Cox <fred@ekreative.com>
Date: Mon, 16 Jan 2017 12:14:25 +0200
Subject: [PATCH 190/685] Allow use of string on left hand side of like
 expresssion

---
 Sources/SQLite/Typed/CoreFunctions.swift   | 29 ++++++++++++++++++++++
 Tests/SQLiteTests/CoreFunctionsTests.swift |  3 +++
 2 files changed, 32 insertions(+)

diff --git a/Sources/SQLite/Typed/CoreFunctions.swift b/Sources/SQLite/Typed/CoreFunctions.swift
index dc450abd..2e00c44a 100644
--- a/Sources/SQLite/Typed/CoreFunctions.swift
+++ b/Sources/SQLite/Typed/CoreFunctions.swift
@@ -673,6 +673,35 @@ extension Collection where Iterator.Element : Value, IndexDistance == Int {
 
 }
 
+extension String {
+    
+    /// Builds a copy of the expression appended with a `LIKE` query against the
+    /// given pattern.
+    ///
+    ///     let email = "some@thing.com"
+    ///     let pattern = Expression<String>("pattern")
+    ///     email.like(pattern)
+    ///     // 'some@thing.com' LIKE "pattern"
+    ///
+    /// - Parameters:
+    ///
+    ///   - pattern: A pattern to match.
+    ///
+    ///   - escape: An (optional) character designated for escaping
+    ///     pattern-matching characters (*i.e.*, the `%` and `_` characters).
+    ///
+    /// - Returns: A copy of the expression appended with a `LIKE` query against
+    ///   the given pattern.
+    public func like(_ pattern: Expression<String>, escape character: Character? = nil) -> Expression<Bool> {
+        guard let character = character else {
+            return "LIKE".infix(self, pattern)
+        }
+        let like: Expression<Bool> = "LIKE".infix(self, pattern, wrap: false)
+        return Expression("(\(like.template) ESCAPE ?)", like.bindings + [String(character)])
+    }
+
+}
+
 /// Builds a copy of the given expressions wrapped with the `ifnull` function.
 ///
 ///     let name = Expression<String?>("name")
diff --git a/Tests/SQLiteTests/CoreFunctionsTests.swift b/Tests/SQLiteTests/CoreFunctionsTests.swift
index 82c59c61..7cf046a3 100644
--- a/Tests/SQLiteTests/CoreFunctionsTests.swift
+++ b/Tests/SQLiteTests/CoreFunctionsTests.swift
@@ -43,6 +43,9 @@ class CoreFunctionsTests : XCTestCase {
         
         AssertSQL("(\"string\" LIKE \"a\" ESCAPE '\\')", string.like(Expression<String>("a"), escape: "\\"))
         AssertSQL("(\"stringOptional\" LIKE \"a\" ESCAPE '\\')", stringOptional.like(Expression<String>("a"), escape: "\\"))
+        
+        AssertSQL("('string' LIKE \"a\")", "string".like(Expression<String>("a")))
+        AssertSQL("('string' LIKE \"a\" ESCAPE '\\')", "string".like(Expression<String>("a"), escape: "\\"))
     }
 
     func test_glob_buildsExpressionWithGlobOperator() {

From 9843f5e7a1e72deec830fbb696127f9f92226455 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 17 Jan 2017 00:16:18 +0100
Subject: [PATCH 191/685] Mention linker flag in READNE

---
 README.md | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index 89917b36..e0cbcf60 100644
--- a/README.md
+++ b/README.md
@@ -174,11 +174,17 @@ The [Swift Package Manager][] is a tool for managing the distribution of Swift c
 
 1. Add the following to your `Package.swift` file:
 
-```swift
-dependencies: [
-    .Package(url: "https://github.com/stephencelis/SQLite.swift.git", majorVersion: 0, minor: 11)
-]
-```
+  ```swift
+  dependencies: [
+      .Package(url: "https://github.com/stephencelis/SQLite.swift.git", majorVersion: 0, minor: 11)
+  ]
+  ```
+
+2. Build your project:
+
+  ``` sh
+  $ swift build -Xlinker -lsqlite3
+  ```
 
 [Swift Package Manager]: https://swift.org/package-manager
 

From f3da195d1a7701785509124b98ef8ed8b32eda25 Mon Sep 17 00:00:00 2001
From: Warif Akhand Rishi <rishi420@gmail.com>
Date: Sat, 28 Jan 2017 12:48:15 +0600
Subject: [PATCH 192/685] Update Index.md

let wonderfulEmails = emails.match("wonder*")  // doesn't compile in Swift 3
changed to
let wonderfulEmails: QueryType = emails.match("wonder*") // compiles ok
---
 Documentation/Index.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 3e13ad4e..fa3dfeb7 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1471,7 +1471,7 @@ try db.run(emails.insert(
     body <- "Hey, I was just wondering...did you get my last email?"
 ))
 
-let wonderfulEmails = emails.match("wonder*")
+let wonderfulEmails: QueryType = emails.match("wonder*")
 // SELECT * FROM "emails" WHERE "emails" MATCH 'wonder*'
 
 let replies = emails.filter(subject.match("Re:*"))

From 61f805126a4dd93f89b678895c40f5af313a0b4e Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 14 Mar 2017 11:48:07 +0100
Subject: [PATCH 193/685] Fix regression introduced in
 4e6b1e00466299136f826ccb7f2c6995eb81b8b2

---
 Sources/SQLite/Core/Connection.swift    | 2 +-
 Sources/SQLite/Core/Statement.swift     | 2 +-
 Sources/SQLite/Helpers.swift            | 2 +-
 Tests/SQLiteTests/ConnectionTests.swift | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 06611756..c0678387 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -28,7 +28,7 @@ import Dispatch
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#else
+#elseif SWIFT_PACKAGE || COCOAPODS
 import CSQLite
 #endif
 
diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index 766bd15b..a9232bba 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -26,7 +26,7 @@
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#else
+#elseif SWIFT_PACKAGE || COCOAPODS
 import CSQLite
 #endif
 
diff --git a/Sources/SQLite/Helpers.swift b/Sources/SQLite/Helpers.swift
index 81a7507e..50b21d0d 100644
--- a/Sources/SQLite/Helpers.swift
+++ b/Sources/SQLite/Helpers.swift
@@ -26,7 +26,7 @@
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#else
+#elseif SWIFT_PACKAGE || COCOAPODS
 import CSQLite
 #endif
 
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index 59514a25..2f033bad 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -5,7 +5,7 @@ import XCTest
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#else
+#elseif SWIFT_PACKAGE || COCOAPODS
 import CSQLite
 #endif
 

From a51a6babb99a5ab9f32ab74eb350ffa3cdeac3df Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 14 Mar 2017 13:14:34 +0100
Subject: [PATCH 194/685] update changelog

---
 CHANGELOG.md | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f3298d68..da5e6a50 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+0.11.3 (tba), [diff][diff-0.11.3]
+========================================
+
+* Fix compilation problems when using Carthage ([#615][])
+* Documentation updates
+
 0.11.2 (25-12-2016), [diff][diff-0.11.2]
 ========================================
 
@@ -23,6 +29,7 @@
 [diff-0.11.0]: https://github.com/stephencelis/SQLite.swift/compare/0.10.1...0.11.0
 [diff-0.11.1]: https://github.com/stephencelis/SQLite.swift/compare/0.11.0...0.11.1
 [diff-0.11.2]: https://github.com/stephencelis/SQLite.swift/compare/0.11.1...0.11.2
+[diff-0.11.3]: https://github.com/stephencelis/SQLite.swift/compare/0.11.2...0.11.3
 
 [#532]: https://github.com/stephencelis/SQLite.swift/issues/532
 [#546]: https://github.com/stephencelis/SQLite.swift/issues/546
@@ -32,3 +39,4 @@
 [#560]: https://github.com/stephencelis/SQLite.swift/pull/560
 [#561]: https://github.com/stephencelis/SQLite.swift/issues/561
 [#571]: https://github.com/stephencelis/SQLite.swift/issues/571
+[#615]: https://github.com/stephencelis/SQLite.swift/pull/615

From 9a9a05a7b3d905f84621e7a591fa2b6b5f12d2a7 Mon Sep 17 00:00:00 2001
From: Kevin Koltzau <kevin@plop.org>
Date: Thu, 10 Nov 2016 13:58:15 -0500
Subject: [PATCH 195/685] Add "WITHOUT ROWID" table option. See:
 https://www.sqlite.org/withoutrowid.html

---
 Sources/SQLite/Typed/Schema.swift   | 5 +++--
 Tests/SQLiteTests/SchemaTests.swift | 9 +++++++++
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/Sources/SQLite/Typed/Schema.swift b/Sources/SQLite/Typed/Schema.swift
index 1388170e..65509292 100644
--- a/Sources/SQLite/Typed/Schema.swift
+++ b/Sources/SQLite/Typed/Schema.swift
@@ -36,14 +36,15 @@ extension Table {
 
     // MARK: - CREATE TABLE
 
-    public func create(temporary: Bool = false, ifNotExists: Bool = false, block: (TableBuilder) -> Void) -> String {
+    public func create(temporary: Bool = false, ifNotExists: Bool = false, withoutRowid: Bool = false, block: (TableBuilder) -> Void) -> String {
         let builder = TableBuilder()
 
         block(builder)
 
         let clauses: [Expressible?] = [
             create(Table.identifier, tableName(), temporary ? .Temporary : nil, ifNotExists),
-            "".wrap(builder.definitions) as Expression<Void>
+            "".wrap(builder.definitions) as Expression<Void>,
+            withoutRowid ? Expression<Void>(literal: "WITHOUT ROWID") : nil
         ]
 
         return " ".join(clauses.flatMap { $0 }).asSQL()
diff --git a/Tests/SQLiteTests/SchemaTests.swift b/Tests/SQLiteTests/SchemaTests.swift
index 371459c7..e59b569b 100644
--- a/Tests/SQLiteTests/SchemaTests.swift
+++ b/Tests/SQLiteTests/SchemaTests.swift
@@ -53,6 +53,15 @@ class SchemaTests : XCTestCase {
             "CREATE TEMPORARY TABLE IF NOT EXISTS \"table\" (\"int64\" INTEGER NOT NULL)",
             table.create(temporary: true, ifNotExists: true) { $0.column(int64) }
         )
+
+        XCTAssertEqual(
+            "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL) WITHOUT ROWID",
+            table.create(withoutRowid: true) { $0.column(int64) }
+        )
+        XCTAssertEqual(
+            "CREATE TEMPORARY TABLE IF NOT EXISTS \"table\" (\"int64\" INTEGER NOT NULL) WITHOUT ROWID",
+            table.create(temporary: true, ifNotExists: true, withoutRowid: true) { $0.column(int64) }
+        )
     }
 
     func test_create_withQuery_compilesCreateTableExpression() {

From 82451a29326bc5db23987c696002e6e9fbe48a91 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 15 Mar 2017 12:55:25 +0100
Subject: [PATCH 196/685] Changelog

---
 CHANGELOG.md | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index da5e6a50..4b8f1785 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
 ========================================
 
 * Fix compilation problems when using Carthage ([#615][])
+* Add "WITHOUT ROWID" table option ([#541][])
 * Documentation updates
 
 0.11.2 (25-12-2016), [diff][diff-0.11.2]
@@ -31,7 +32,8 @@
 [diff-0.11.2]: https://github.com/stephencelis/SQLite.swift/compare/0.11.1...0.11.2
 [diff-0.11.3]: https://github.com/stephencelis/SQLite.swift/compare/0.11.2...0.11.3
 
-[#532]: https://github.com/stephencelis/SQLite.swift/issues/532
+[#532]: https://github.com/stephencelis/SQLit1e.swift/issues/532
+[#541]: https://github.com/stephencelis/SQLit1e.swift/issues/541
 [#546]: https://github.com/stephencelis/SQLite.swift/issues/546
 [#548]: https://github.com/stephencelis/SQLite.swift/pull/548
 [#553]: https://github.com/stephencelis/SQLite.swift/pull/553

From 47e109aab50308e71504aa4b1ea2d0cdf527b983 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 15 Mar 2017 22:06:59 +0100
Subject: [PATCH 197/685] Argument count fixed for binary custom functions

Closes #481
---
 CHANGELOG.md                                 |   2 +
 Sources/SQLite/Typed/CustomFunctions.swift   |  22 +--
 Tests/SQLiteTests/CustomFunctionsTests.swift | 133 ++++++++++++++++++-
 3 files changed, 145 insertions(+), 12 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4b8f1785..9d23ddc5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,7 @@
 
 * Fix compilation problems when using Carthage ([#615][])
 * Add "WITHOUT ROWID" table option ([#541][])
+* Argument count fixed for binary custom functions ([#481][])
 * Documentation updates
 
 0.11.2 (25-12-2016), [diff][diff-0.11.2]
@@ -32,6 +33,7 @@
 [diff-0.11.2]: https://github.com/stephencelis/SQLite.swift/compare/0.11.1...0.11.2
 [diff-0.11.3]: https://github.com/stephencelis/SQLite.swift/compare/0.11.2...0.11.3
 
+[#481]: https://github.com/stephencelis/SQLit1e.swift/pull/481
 [#532]: https://github.com/stephencelis/SQLit1e.swift/issues/532
 [#541]: https://github.com/stephencelis/SQLit1e.swift/issues/541
 [#546]: https://github.com/stephencelis/SQLite.swift/issues/546
diff --git a/Sources/SQLite/Typed/CustomFunctions.swift b/Sources/SQLite/Typed/CustomFunctions.swift
index 64b54edb..2389901f 100644
--- a/Sources/SQLite/Typed/CustomFunctions.swift
+++ b/Sources/SQLite/Typed/CustomFunctions.swift
@@ -56,17 +56,17 @@ public extension Connection {
         return { arg in fn([arg]) }
     }
 
-    public func createFunction<Z : Value, A : Value>(function: String, deterministic: Bool = false, _ block: @escaping (A?) -> Z) throws -> ((Expression<A?>) -> Expression<Z>) {
+    public func createFunction<Z : Value, A : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?) -> Z) throws -> ((Expression<A?>) -> Expression<Z>) {
         let fn = try createFunction(function, 1, deterministic) { args in block(args[0].map(value)) }
         return { arg in fn([arg]) }
     }
 
-    public func createFunction<Z : Value, A : Value>(function: String, deterministic: Bool = false, _ block: @escaping (A) -> Z?) throws -> ((Expression<A>) -> Expression<Z?>) {
+    public func createFunction<Z : Value, A : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A) -> Z?) throws -> ((Expression<A>) -> Expression<Z?>) {
         let fn = try createFunction(function, 1, deterministic) { args in block(value(args[0])) }
         return { arg in fn([arg]) }
     }
 
-    public func createFunction<Z : Value, A : Value>(function: String, deterministic: Bool = false, _ block: @escaping (A?) -> Z?) throws -> ((Expression<A?>) -> Expression<Z?>) {
+    public func createFunction<Z : Value, A : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?) -> Z?) throws -> ((Expression<A?>) -> Expression<Z?>) {
         let fn = try createFunction(function, 1, deterministic) { args in block(args[0].map(value)) }
         return { arg in fn([arg]) }
     }
@@ -74,42 +74,42 @@ public extension Connection {
     // MARK: -
 
     public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B) -> Z) throws -> (Expression<A>, Expression<B>) -> Expression<Z> {
-        let fn = try createFunction(function, 1, deterministic) { args in block(value(args[0]), value(args[1])) }
+        let fn = try createFunction(function, 2, deterministic) { args in block(value(args[0]), value(args[1])) }
         return { a, b in fn([a, b]) }
     }
 
     public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B) -> Z) throws -> (Expression<A?>, Expression<B>) -> Expression<Z> {
-        let fn = try createFunction(function, 1, deterministic) { args in block(args[0].map(value), value(args[1])) }
+        let fn = try createFunction(function, 2, deterministic) { args in block(args[0].map(value), value(args[1])) }
         return { a, b in fn([a, b]) }
     }
 
     public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B?) -> Z) throws -> (Expression<A>, Expression<B?>) -> Expression<Z> {
-        let fn = try createFunction(function, 1, deterministic) { args in block(value(args[0]), args[1].map(value)) }
+        let fn = try createFunction(function, 2, deterministic) { args in block(value(args[0]), args[1].map(value)) }
         return { a, b in fn([a, b]) }
     }
 
     public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B) -> Z?) throws -> (Expression<A>, Expression<B>) -> Expression<Z?> {
-        let fn = try createFunction(function, 1, deterministic) { args in block(value(args[0]), value(args[1])) }
+        let fn = try createFunction(function, 2, deterministic) { args in block(value(args[0]), value(args[1])) }
         return { a, b in fn([a, b]) }
     }
 
     public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B?) -> Z) throws -> (Expression<A?>, Expression<B?>) -> Expression<Z> {
-        let fn = try createFunction(function, 1, deterministic) { args in block(args[0].map(value), args[1].map(value)) }
+        let fn = try createFunction(function, 2, deterministic) { args in block(args[0].map(value), args[1].map(value)) }
         return { a, b in fn([a, b]) }
     }
 
     public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B) -> Z?) throws -> (Expression<A?>, Expression<B>) -> Expression<Z?> {
-        let fn = try createFunction(function, 1, deterministic) { args in block(args[0].map(value), value(args[1])) }
+        let fn = try createFunction(function, 2, deterministic) { args in block(args[0].map(value), value(args[1])) }
         return { a, b in fn([a, b]) }
     }
 
     public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B?) -> Z?) throws -> (Expression<A>, Expression<B?>) -> Expression<Z?> {
-        let fn = try createFunction(function, 1, deterministic) { args in block(value(args[0]), args[1].map(value)) }
+        let fn = try createFunction(function, 2, deterministic) { args in block(value(args[0]), args[1].map(value)) }
         return { a, b in fn([a, b]) }
     }
 
     public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B?) -> Z?) throws -> (Expression<A?>, Expression<B?>) -> Expression<Z?> {
-        let fn = try createFunction(function, 1, deterministic) { args in block(args[0].map(value), args[1].map(value)) }
+        let fn = try createFunction(function, 2, deterministic) { args in block(args[0].map(value), args[1].map(value)) }
         return { a, b in fn([a, b]) }
     }
 
diff --git a/Tests/SQLiteTests/CustomFunctionsTests.swift b/Tests/SQLiteTests/CustomFunctionsTests.swift
index 67150ccf..919986b6 100644
--- a/Tests/SQLiteTests/CustomFunctionsTests.swift
+++ b/Tests/SQLiteTests/CustomFunctionsTests.swift
@@ -1,6 +1,137 @@
 import XCTest
 import SQLite
 
-class CustomFunctionsTests : XCTestCase {
+class CustomFunctionNoArgsTests : SQLiteTestCase {
+    typealias FunctionNoOptional              = ()  -> Expression<String>
+    typealias FunctionResultOptional          = ()  -> Expression<String?>
 
+    func testFunctionNoOptional() {
+        let _: FunctionNoOptional = try! db.createFunction("test", deterministic: true) {
+            return "a"
+        }
+        let result = try! db.prepare("SELECT test()").scalar() as! String
+        XCTAssertEqual("a", result)
+    }
+
+    func testFunctionResultOptional() {
+        let _: FunctionResultOptional = try! db.createFunction("test", deterministic: true) {
+            return "a"
+        }
+        let result = try! db.prepare("SELECT test()").scalar() as! String?
+        XCTAssertEqual("a", result)
+    }
+}
+
+class CustomFunctionWithOneArgTests : SQLiteTestCase {
+    typealias FunctionNoOptional              = (Expression<String>)  -> Expression<String>
+    typealias FunctionLeftOptional            = (Expression<String?>) -> Expression<String>
+    typealias FunctionResultOptional          = (Expression<String>)  -> Expression<String?>
+    typealias FunctionLeftResultOptional      = (Expression<String?>) -> Expression<String?>
+
+    func testFunctionNoOptional() {
+        let _: FunctionNoOptional = try! db.createFunction("test", deterministic: true) { a in
+            return "b"+a
+        }
+        let result = try! db.prepare("SELECT test(?)").scalar("a") as! String
+        XCTAssertEqual("ba", result)
+    }
+
+    func testFunctionLeftOptional() {
+        let _: FunctionLeftOptional = try! db.createFunction("test", deterministic: true) { a in
+            return "b"+a!
+        }
+        let result = try! db.prepare("SELECT test(?)").scalar("a") as! String
+        XCTAssertEqual("ba", result)
+    }
+
+    func testFunctionResultOptional() {
+        let _: FunctionResultOptional = try! db.createFunction("test", deterministic: true) { a in
+            return "b"+a
+        }
+        let result = try! db.prepare("SELECT test(?)").scalar("a") as! String
+        XCTAssertEqual("ba", result)
+    }
+
+    func testFunctionLeftResultOptional() {
+        let _: FunctionLeftResultOptional = try! db.createFunction("test", deterministic: true) { (a:String?) -> String? in
+            return "b"+a!
+        }
+        let result = try! db.prepare("SELECT test(?)").scalar("a") as! String
+        XCTAssertEqual("ba", result)
+    }
+}
+
+class CustomFunctionWithTwoArgsTests : SQLiteTestCase {
+    typealias FunctionNoOptional              = (Expression<String>,  Expression<String>)  -> Expression<String>
+    typealias FunctionLeftOptional            = (Expression<String?>, Expression<String>)  -> Expression<String>
+    typealias FunctionRightOptional           = (Expression<String>,  Expression<String?>) -> Expression<String>
+    typealias FunctionResultOptional          = (Expression<String>,  Expression<String>)  -> Expression<String?>
+    typealias FunctionLeftRightOptional       = (Expression<String?>, Expression<String?>) -> Expression<String>
+    typealias FunctionLeftResultOptional      = (Expression<String?>, Expression<String>)  -> Expression<String?>
+    typealias FunctionRightResultOptional     = (Expression<String>,  Expression<String?>) -> Expression<String?>
+    typealias FunctionLeftRightResultOptional = (Expression<String?>, Expression<String?>) -> Expression<String?>
+
+    func testNoOptional() {
+        let _: FunctionNoOptional = try! db.createFunction("test", deterministic: true) { a, b in
+            return a+b
+        }
+        let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String
+        XCTAssertEqual("ab", result)
+    }
+
+    func testLeftOptional() {
+        let _: FunctionLeftOptional = try! db.createFunction("test", deterministic: true) { a, b in
+            return a!+b
+        }
+        let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String
+        XCTAssertEqual("ab", result)
+    }
+
+    func testRightOptional() {
+        let _: FunctionRightOptional = try! db.createFunction("test", deterministic: true) { a, b in
+            return a+b!
+        }
+        let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String
+        XCTAssertEqual("ab", result)
+    }
+
+    func testResultOptional() {
+        let _: FunctionResultOptional = try! db.createFunction("test", deterministic: true) { a, b in
+            return a+b
+        }
+        let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String?
+        XCTAssertEqual("ab", result)
+    }
+
+    func testFunctionLeftRightOptional() {
+        let _: FunctionLeftRightOptional = try! db.createFunction("test", deterministic: true) { a, b in
+            return a!+b!
+        }
+        let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String
+        XCTAssertEqual("ab", result)
+    }
+
+    func testFunctionLeftResultOptional() {
+        let _: FunctionLeftResultOptional = try! db.createFunction("test", deterministic: true) { a, b in
+            return a!+b
+        }
+        let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String?
+        XCTAssertEqual("ab", result)
+    }
+
+    func testFunctionRightResultOptional() {
+        let _: FunctionRightResultOptional = try! db.createFunction("test", deterministic: true) { a, b in
+            return a+b!
+        }
+        let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String?
+        XCTAssertEqual("ab", result)
+    }
+
+    func testFunctionLeftRightResultOptional() {
+        let _: FunctionLeftRightResultOptional = try! db.createFunction("test", deterministic: true) { a, b in
+            return a!+b!
+        }
+        let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String?
+        XCTAssertEqual("ab", result)
+    }
 }

From c0dbbfc122cf7dd036ad842d46fa075e3e8c9d57 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 15 Mar 2017 22:12:27 +0100
Subject: [PATCH 198/685] Fix documentation

Closes #266
---
 Documentation/Index.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index fa3dfeb7..bf8fa796 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1359,7 +1359,7 @@ For example, to give queries access to [`MobileCoreServices.UTTypeConformsTo`](h
 ``` swift
 import MobileCoreServices
 
-let typeConformsTo: (Expression<String>, String) -> Expression<Bool> = (
+let typeConformsTo: (Expression<String>, Expression<String>) -> Expression<Bool> = (
     try db.createFunction("typeConformsTo", deterministic: true) { UTI, conformsToUTI in
         return UTTypeConformsTo(UTI, conformsToUTI)
     }
@@ -1371,7 +1371,7 @@ let typeConformsTo: (Expression<String>, String) -> Expression<Bool> = (
 Note `typeConformsTo`’s signature:
 
 ``` swift
-(Expression<String>, String) -> Expression<Bool>
+(Expression<String>, Expression<String>) -> Expression<Bool>
 ```
 
 Because of this, `createFunction` expects a block with the following signature:

From 7af6e8ae7f73e2b7f285589ce8938d100711c1f7 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 29 Mar 2017 22:13:55 +0200
Subject: [PATCH 199/685] Fix warnings

---
 Sources/SQLite/Core/Connection.swift    | 2 +-
 Sources/SQLite/Extensions/FTS4.swift    | 5 +++--
 Tests/SQLiteTests/ConnectionTests.swift | 2 +-
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index c0678387..490a1592 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -579,7 +579,7 @@ public final class Connection {
             } else if result == nil {
                 sqlite3_result_null(context)
             } else {
-                fatalError("unsupported result type: \(result)")
+                fatalError("unsupported result type: \(String(describing: result))")
             }
         }
         var flags = SQLITE_UTF8
diff --git a/Sources/SQLite/Extensions/FTS4.swift b/Sources/SQLite/Extensions/FTS4.swift
index 152a2921..3f28d33b 100644
--- a/Sources/SQLite/Extensions/FTS4.swift
+++ b/Sources/SQLite/Extensions/FTS4.swift
@@ -145,13 +145,14 @@ extension Tokenizer : CustomStringConvertible {
 extension Connection {
 
     public func registerTokenizer(_ submoduleName: String, next: @escaping (String) -> (String, Range<String.Index>)?) throws {
-        try check(_SQLiteRegisterTokenizer(handle, Tokenizer.moduleName, submoduleName) { input, offset, length in
+        try check(_SQLiteRegisterTokenizer(handle, Tokenizer.moduleName, submoduleName) { (
+                input: UnsafePointer<Int8>, offset: UnsafeMutablePointer<Int32>, length: UnsafeMutablePointer<Int32>) in
             let string = String(cString: input)
 
             guard let (token, range) = next(string) else { return nil }
 
             let view = string.utf8
-            offset.pointee += string.substring(to: range.lowerBound).utf8.count
+            offset.pointee += Int32(string.substring(to: range.lowerBound).utf8.count)
             length.pointee = Int32(view.distance(from: range.lowerBound.samePosition(in: view), to: range.upperBound.samePosition(in: view)))
             return token
         })
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index 2f033bad..d05c5ece 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -337,7 +337,7 @@ class ConnectionTests : SQLiteTestCase {
         try! stmt.run()
 
         let deadline = DispatchTime.now() + Double(Int64(10 * NSEC_PER_MSEC)) / Double(NSEC_PER_SEC)
-        _ = DispatchQueue.global(priority: .background).asyncAfter(deadline: deadline, execute: db.interrupt)
+        _ = DispatchQueue(label: "queue", qos: .background).asyncAfter(deadline: deadline, execute: db.interrupt)
         AssertThrows(try stmt.run())
     }
 

From 05ca19433efa68e1e93041ed400ae70b62071382 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 29 Mar 2017 22:17:31 +0200
Subject: [PATCH 200/685] Switch to 8.3 image

---
 .travis.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index 3747ac7b..88e75fa4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,6 @@
 language: objective-c
 rvm: 2.2
-osx_image: xcode8.2
+osx_image: xcode8.3
 env:
   global:
     - IOS_SIMULATOR="iPhone 6s"

From bd9413ad43024f365d87c5665041c08f77cc95cf Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 30 Mar 2017 07:55:58 +0200
Subject: [PATCH 201/685] Adjust deployment targets

---
 SQLite.swift.podspec             |  8 ++++----
 SQLite.xcodeproj/project.pbxproj | 12 ++++++------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 3c61aa1f..3e43d196 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -15,10 +15,10 @@ Pod::Spec.new do |s|
   s.social_media_url = 'https://twitter.com/stephencelis'
 
   s.module_name      = 'SQLite'
-  s.ios.deployment_target = "8.0"
-  s.tvos.deployment_target = "9.0"
-  s.osx.deployment_target = "10.9"
-  s.watchos.deployment_target = "2.0"
+  s.ios.deployment_target = "9.0"
+  s.tvos.deployment_target = "9.1"
+  s.osx.deployment_target = "10.10"
+  s.watchos.deployment_target = "2.2"
   s.default_subspec  = 'standard'
   s.pod_target_xcconfig = {
     'SWIFT_VERSION' => '3.0',
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 153295cc..13146ba0 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1287,7 +1287,7 @@
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
-				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
@@ -1313,7 +1313,7 @@
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
-				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
@@ -1362,7 +1362,7 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
-				MACOSX_DEPLOYMENT_TARGET = 10.9;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SDKROOT = macosx;
@@ -1389,7 +1389,7 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
-				MACOSX_DEPLOYMENT_TARGET = 10.9;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SDKROOT = macosx;
@@ -1409,7 +1409,7 @@
 				COMBINE_HIDPI_IMAGES = YES;
 				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
-				MACOSX_DEPLOYMENT_TARGET = 10.11;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = macosx;
@@ -1424,7 +1424,7 @@
 				COMBINE_HIDPI_IMAGES = YES;
 				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
-				MACOSX_DEPLOYMENT_TARGET = 10.11;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = macosx;

From 104e2f11ad49c3840ecc582b40a83417d8628abd Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 30 Mar 2017 08:05:11 +0200
Subject: [PATCH 202/685] Bump version number

---
 Documentation/Index.md    | 10 +++++-----
 README.md                 |  4 ++--
 SQLite.swift.podspec      |  2 +-
 Sources/SQLite/Info.plist |  2 +-
 4 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index bf8fa796..ddd20b42 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -78,7 +78,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```
-    github "stephencelis/SQLite.swift" ~> 0.11.2
+    github "stephencelis/SQLite.swift" ~> 0.11.3
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -113,7 +113,7 @@ install SQLite.swift with Carthage:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.11.2'
+        pod 'SQLite.swift', '~> 0.11.3'
     end
     ```
 
@@ -126,7 +126,7 @@ install SQLite.swift with Carthage:
 
 ``` ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.11.2'
+  pod 'SQLite.swift/standalone', '~> 0.11.3'
 end
 ```
 
@@ -134,7 +134,7 @@ By default this will use the most recent version of SQLite without any extras. I
 
 ``` ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.11.2'
+  pod 'SQLite.swift/standalone', '~> 0.11.3'
   pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
 end
 ```
@@ -148,7 +148,7 @@ subspec in your Podfile:
 
 ``` ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/SQLCipher', '~> 0.11.2'
+  pod 'SQLite.swift/SQLCipher', '~> 0.11.3'
 end
 ```
 
diff --git a/README.md b/README.md
index e0cbcf60..a7fe6080 100644
--- a/README.md
+++ b/README.md
@@ -123,7 +123,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```
-    github "stephencelis/SQLite.swift" ~> 0.11.2
+    github "stephencelis/SQLite.swift" ~> 0.11.3
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -159,7 +159,7 @@ SQLite.swift with CocoaPods:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.11.2'
+        pod 'SQLite.swift', '~> 0.11.3'
     end
     ```
 
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 3e43d196..06aa043b 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.11.2"
+  s.version          = "0.11.3"
   s.summary          = "A type-safe, Swift-language layer over SQLite3 for iOS and OS X."
 
   s.description      = <<-DESC
diff --git a/Sources/SQLite/Info.plist b/Sources/SQLite/Info.plist
index 588139c4..8c55becd 100644
--- a/Sources/SQLite/Info.plist
+++ b/Sources/SQLite/Info.plist
@@ -15,7 +15,7 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>0.11.2</string>
+	<string>0.11.3</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>

From 4229b04fce8e0db440cafbc077837efde359ad04 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 30 Mar 2017 08:06:33 +0200
Subject: [PATCH 203/685] Bump CocoaPods

---
 Tests/CocoaPods/Gemfile      |  2 +-
 Tests/CocoaPods/Gemfile.lock | 48 ++++++++++++++++++------------------
 2 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/Tests/CocoaPods/Gemfile b/Tests/CocoaPods/Gemfile
index 94018f18..e40770e8 100644
--- a/Tests/CocoaPods/Gemfile
+++ b/Tests/CocoaPods/Gemfile
@@ -1,4 +1,4 @@
 source 'https://rubygems.org'
 
-gem 'cocoapods', '~> 1.1.0'
+gem 'cocoapods', '~> 1.2.0'
 gem 'minitest'
diff --git a/Tests/CocoaPods/Gemfile.lock b/Tests/CocoaPods/Gemfile.lock
index e8879f13..869ae3dc 100644
--- a/Tests/CocoaPods/Gemfile.lock
+++ b/Tests/CocoaPods/Gemfile.lock
@@ -1,43 +1,43 @@
 GEM
   remote: https://rubygems.org/
   specs:
-    CFPropertyList (2.3.3)
-    activesupport (4.2.7.1)
+    CFPropertyList (2.3.5)
+    activesupport (4.2.8)
       i18n (~> 0.7)
-      json (~> 1.7, >= 1.7.7)
       minitest (~> 5.1)
       thread_safe (~> 0.3, >= 0.3.4)
       tzinfo (~> 1.1)
     claide (1.0.1)
-    cocoapods (1.1.1)
+    cocoapods (1.2.0)
       activesupport (>= 4.0.2, < 5)
       claide (>= 1.0.1, < 2.0)
-      cocoapods-core (= 1.1.1)
+      cocoapods-core (= 1.2.0)
       cocoapods-deintegrate (>= 1.0.1, < 2.0)
-      cocoapods-downloader (>= 1.1.2, < 2.0)
+      cocoapods-downloader (>= 1.1.3, < 2.0)
       cocoapods-plugins (>= 1.0.0, < 2.0)
       cocoapods-search (>= 1.0.0, < 2.0)
       cocoapods-stats (>= 1.0.0, < 2.0)
-      cocoapods-trunk (>= 1.1.1, < 2.0)
+      cocoapods-trunk (>= 1.1.2, < 2.0)
       cocoapods-try (>= 1.1.0, < 2.0)
       colored (~> 1.2)
       escape (~> 0.0.4)
       fourflusher (~> 2.0.1)
       gh_inspector (~> 1.0)
-      molinillo (~> 0.5.1)
+      molinillo (~> 0.5.5)
       nap (~> 1.0)
-      xcodeproj (>= 1.3.3, < 2.0)
-    cocoapods-core (1.1.1)
+      ruby-macho (~> 0.2.5)
+      xcodeproj (>= 1.4.1, < 2.0)
+    cocoapods-core (1.2.0)
       activesupport (>= 4.0.2, < 5)
       fuzzy_match (~> 2.0.4)
       nap (~> 1.0)
     cocoapods-deintegrate (1.0.1)
-    cocoapods-downloader (1.1.2)
+    cocoapods-downloader (1.1.3)
     cocoapods-plugins (1.0.0)
       nap
     cocoapods-search (1.0.0)
     cocoapods-stats (1.0.0)
-    cocoapods-trunk (1.1.1)
+    cocoapods-trunk (1.1.2)
       nap (>= 0.8, < 2.0)
       netrc (= 0.7.8)
     cocoapods-try (1.1.0)
@@ -45,30 +45,30 @@ GEM
     escape (0.0.4)
     fourflusher (2.0.1)
     fuzzy_match (2.0.4)
-    gh_inspector (1.0.2)
-    i18n (0.7.0)
-    json (1.8.3)
-    minitest (5.9.1)
-    molinillo (0.5.4)
-    nanaimo (0.2.2)
+    gh_inspector (1.0.3)
+    i18n (0.8.1)
+    minitest (5.10.1)
+    molinillo (0.5.7)
+    nanaimo (0.2.3)
     nap (1.1.0)
     netrc (0.7.8)
-    thread_safe (0.3.5)
-    tzinfo (1.2.2)
+    ruby-macho (0.2.6)
+    thread_safe (0.3.6)
+    tzinfo (1.2.3)
       thread_safe (~> 0.1)
-    xcodeproj (1.4.1)
+    xcodeproj (1.4.2)
       CFPropertyList (~> 2.3.3)
       activesupport (>= 3)
       claide (>= 1.0.1, < 2.0)
       colored (~> 1.2)
-      nanaimo (~> 0.2.0)
+      nanaimo (~> 0.2.3)
 
 PLATFORMS
   ruby
 
 DEPENDENCIES
-  cocoapods (~> 1.1.0)
+  cocoapods (~> 1.2.0)
   minitest
 
 BUNDLED WITH
-   1.13.3
+   1.13.6

From 1fc4548708e661bffa9ebf62bc1f88f2494045e5 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 30 Mar 2017 08:20:29 +0200
Subject: [PATCH 204/685] Set test deployment target

---
 SQLite.xcodeproj/project.pbxproj | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 13146ba0..78b43249 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1330,6 +1330,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
+				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1341,6 +1342,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
+				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";

From a7e325f91cd6b7e989dc1140fb19987b10f59698 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 30 Mar 2017 08:24:01 +0200
Subject: [PATCH 205/685] Bump iOS version

---
 Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index d4f51d53..adab1d81 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 BUILD_TOOL = xcodebuild
 BUILD_SCHEME = SQLite Mac
 IOS_SIMULATOR = iPhone 6s
-IOS_VERSION = 9.3
+IOS_VERSION = 10.3
 ifeq ($(BUILD_SCHEME),SQLite iOS)
 	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -destination "platform=iOS Simulator,name=$(IOS_SIMULATOR),OS=$(IOS_VERSION)"
 else

From f389b6a36e8385c6d651827ab6893eb0f8de2a44 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 30 Mar 2017 10:56:41 +0200
Subject: [PATCH 206/685] Update changelog

---
 CHANGELOG.md | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9d23ddc5..d6387a56 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,10 +1,11 @@
-0.11.3 (tba), [diff][diff-0.11.3]
+0.11.3 (30-03-2017), [diff][diff-0.11.3]
 ========================================
 
 * Fix compilation problems when using Carthage ([#615][])
 * Add "WITHOUT ROWID" table option ([#541][])
 * Argument count fixed for binary custom functions ([#481][])
 * Documentation updates
+* Tested with Xcode 8.3 / iOS 10.3
 
 0.11.2 (25-12-2016), [diff][diff-0.11.2]
 ========================================

From 426e7d606f8011574d46fe21c7d27351dff90031 Mon Sep 17 00:00:00 2001
From: Josh Friend <josh@fueledbycaffeine.com>
Date: Sun, 21 May 2017 09:57:42 -0400
Subject: [PATCH 207/685] Fix usages of old Swift 2 enum case names

---
 Sources/SQLite/Core/Connection.swift | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 490a1592..bba9a358 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -38,12 +38,12 @@ public final class Connection {
     /// The location of a SQLite database.
     public enum Location {
 
-        /// An in-memory database (equivalent to `.URI(":memory:")`).
+        /// An in-memory database (equivalent to `.uri(":memory:")`).
         ///
         /// See: <https://www.sqlite.org/inmemorydb.html#sharedmemdb>
         case inMemory
 
-        /// A temporary, file-backed database (equivalent to `.URI("")`).
+        /// A temporary, file-backed database (equivalent to `.uri("")`).
         ///
         /// See: <https://www.sqlite.org/inmemorydb.html#temp_db>
         case temporary
@@ -93,7 +93,7 @@ public final class Connection {
     ///   - location: The location of the database. Creates a new database if it
     ///     doesn’t already exist (unless in read-only mode).
     ///
-    ///     Default: `.InMemory`.
+    ///     Default: `.inMemory`.
     ///
     ///   - readonly: Whether or not to open the database in a read-only state.
     ///
@@ -321,7 +321,7 @@ public final class Connection {
     ///
     ///   - mode: The mode in which a transaction acquires a lock.
     ///
-    ///     Default: `.Deferred`
+    ///     Default: `.deferred`
     ///
     ///   - block: A closure to run SQL statements within the transaction.
     ///     The transaction will be committed when the block returns. The block

From 89630b2de78d9dfec31b6258f23917f8f4352317 Mon Sep 17 00:00:00 2001
From: Josh Friend <josh@fueledbycaffeine.com>
Date: Sun, 21 May 2017 10:11:55 -0400
Subject: [PATCH 208/685] Apply Swift3 case convention to internal enum
 `Modifier`

---
 Sources/SQLite/Typed/Schema.swift | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/Sources/SQLite/Typed/Schema.swift b/Sources/SQLite/Typed/Schema.swift
index 65509292..7bf70fe4 100644
--- a/Sources/SQLite/Typed/Schema.swift
+++ b/Sources/SQLite/Typed/Schema.swift
@@ -42,7 +42,7 @@ extension Table {
         block(builder)
 
         let clauses: [Expressible?] = [
-            create(Table.identifier, tableName(), temporary ? .Temporary : nil, ifNotExists),
+            create(Table.identifier, tableName(), temporary ? .temporary : nil, ifNotExists),
             "".wrap(builder.definitions) as Expression<Void>,
             withoutRowid ? Expression<Void>(literal: "WITHOUT ROWID") : nil
         ]
@@ -52,7 +52,7 @@ extension Table {
 
     public func create(_ query: QueryType, temporary: Bool = false, ifNotExists: Bool = false) -> String {
         let clauses: [Expressible?] = [
-            create(Table.identifier, tableName(), temporary ? .Temporary : nil, ifNotExists),
+            create(Table.identifier, tableName(), temporary ? .temporary : nil, ifNotExists),
             Expression<Void>(literal: "AS"),
             query
         ]
@@ -133,7 +133,7 @@ extension Table {
 
     public func createIndex(_ columns: [Expressible], unique: Bool = false, ifNotExists: Bool = false) -> String {
         let clauses: [Expressible?] = [
-            create("INDEX", indexName(columns), unique ? .Unique : nil, ifNotExists),
+            create("INDEX", indexName(columns), unique ? .unique : nil, ifNotExists),
             Expression<Void>(literal: "ON"),
             tableName(qualified: false),
             "".wrap(columns) as Expression<Void>
@@ -176,7 +176,7 @@ extension View {
 
     public func create(_ query: QueryType, temporary: Bool = false, ifNotExists: Bool = false) -> String {
         let clauses: [Expressible?] = [
-            create(View.identifier, tableName(), temporary ? .Temporary : nil, ifNotExists),
+            create(View.identifier, tableName(), temporary ? .temporary : nil, ifNotExists),
             Expression<Void>(literal: "AS"),
             query
         ]
@@ -513,8 +513,8 @@ private func reference(_ primary: (QueryType, Expressible)) -> Expressible {
 
 private enum Modifier : String {
 
-    case Unique = "UNIQUE"
+    case unique = "UNIQUE"
 
-    case Temporary = "TEMPORARY"
+    case temporary = "TEMPORARY"
 
 }

From 2b067d4ee162c137f52da306824df7cc232c9435 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 16 Jun 2017 07:45:08 +0200
Subject: [PATCH 209/685] Travis sneakily replaced the Xcode 8.3 image.

https://blog.travis-ci.com/2017-06-06-xcode-833-is-here
---
 .travis.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.travis.yml b/.travis.yml
index 88e75fa4..2eb85311 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,6 +4,7 @@ osx_image: xcode8.3
 env:
   global:
     - IOS_SIMULATOR="iPhone 6s"
+    - IOS_VERSION="10.3.1"
 matrix:
   include:
     - env: BUILD_SCHEME="SQLite iOS"

From ca627720edb6aae00200c17024e998f21da690a5 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 16 Jun 2017 08:08:49 +0200
Subject: [PATCH 210/685] Set iOS version

---
 run-tests.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/run-tests.sh b/run-tests.sh
index ddd7d678..0a105c41 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -2,7 +2,7 @@
 set -ev
 if [ -n "$BUILD_SCHEME" ]; then
     if [ -n "$IOS_SIMULATOR" ]; then
-        make test BUILD_SCHEME="$BUILD_SCHEME" IOS_SIMULATOR="$IOS_SIMULATOR"
+        make test BUILD_SCHEME="$BUILD_SCHEME" IOS_SIMULATOR="$IOS_SIMULATOR" IOS_VERSION="$IOS_VERSION"
     else
         make test BUILD_SCHEME="$BUILD_SCHEME"
     fi

From f24bc5db861c61f1d9a808ee24f4755852651ac1 Mon Sep 17 00:00:00 2001
From: Eoin Kelly <eoin@rabidtech.co.nz>
Date: Fri, 16 Jun 2017 10:43:53 +1200
Subject: [PATCH 211/685] Fix demonstration of how to trace SQL statements in
 docs

The old way shown causes a build error in swift 3 (XCode8):

  Ambiguous reference to member 'print(_:separator:terminator:)'
---
 Documentation/Index.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index ddd20b42..07bb5f33 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1578,7 +1578,7 @@ We can log SQL using the database’s `trace` function.
 
 ``` swift
 #if DEBUG
-    db.trace(print)
+    db.trace { print($0) }
 #endif
 ```
 

From 1848964a0a5d31945045c6fe294d3a7961cad6f7 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 1 Jul 2017 22:29:26 +0200
Subject: [PATCH 212/685] Mention swift-4 branch

---
 README.md | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index a7fe6080..5a424689 100644
--- a/README.md
+++ b/README.md
@@ -109,9 +109,7 @@ For a more comprehensive example, see [this article](http://masteringswift.blogs
 
 ## Installation
 
-> _Note:_ SQLite.swift requires Swift 3 (and [Xcode][] 8) or greater. If you absolutely
-> need compatibility with Swift 2.3 you can use the [swift-2.3][] branch or older
-> released versions. New development will happen exclusively on the master/Swift 3 branch.
+> _Note:_ SQLite.swift requires Swift 3 (and [Xcode][] 8). Use the [swift-4][] branch for Xcode 9 Beta.
 
 ### Carthage
 
@@ -266,4 +264,4 @@ Looking for something else? Try another Swift wrapper (or [FMDB][]):
  - [SwiftSQLite](https://github.com/chrismsimpson/SwiftSQLite)
 
 [FMDB]: https://github.com/ccgus/fmdb
-[swift-2.3]: https://github.com/stephencelis/SQLite.swift/tree/swift-2.3
+[swift-4]: https://github.com/stephencelis/SQLite.swift/tree/swift-4

From 8a8da02a15366f5c6c2ff3d2384881f49cb7ab9f Mon Sep 17 00:00:00 2001
From: avinassh <avinassh@users.noreply.github.com>
Date: Fri, 21 Jul 2017 17:52:08 +0530
Subject: [PATCH 213/685] Fix OS X database path

---
 Documentation/Index.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 07bb5f33..491a5938 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -251,7 +251,7 @@ On OS X, you can use your app’s **Application Support** directory:
 ``` swift
 var path = NSSearchPathForDirectoriesInDomains(
     .applicationSupportDirectory, .userDomainMask, true
-).first! + Bundle.main.bundleIdentifier!
+).first! + "/" + Bundle.main.bundleIdentifier!
 
 // create parent directory iff it doesn’t exist
 try FileManager.default.createDirectoryAtPath(

From 2b3f71c861c8d34c5058a6443cd45afc7a9c563c Mon Sep 17 00:00:00 2001
From: Igor de Oliveira Sa <igordeoliveirasa@gmail.com>
Date: Fri, 28 Jul 2017 15:24:44 -0300
Subject: [PATCH 214/685] missing try clause on db.scalar line of example

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 5a424689..e435bfed 100644
--- a/README.md
+++ b/README.md
@@ -97,7 +97,7 @@ for row in try db.prepare("SELECT id, email FROM users") {
     // id: Optional(3), email: Optional("cathy@icloud.com")
 }
 
-db.scalar("SELECT count(*) FROM users") // 2
+try db.scalar("SELECT count(*) FROM users") // 2
 ```
 
 [Read the documentation][See Documentation] or explore more,

From 01de138c85b4b2ee7ea6e3ac087cd9827f8fded8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Igor=20de=20Oliveira=20S=C3=A1?=
 <igordeoliveirasa@gmail.com>
Date: Thu, 3 Aug 2017 16:16:29 -0300
Subject: [PATCH 215/685] try was missing before db.scalar

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index e435bfed..8c3affd9 100644
--- a/README.md
+++ b/README.md
@@ -74,7 +74,7 @@ try db.run(alice.update(email <- email.replace("mac.com", with: "me.com")))
 try db.run(alice.delete())
 // DELETE FROM "users" WHERE ("id" = 1)
 
-db.scalar(users.count) // 0
+try db.scalar(users.count) // 0
 // SELECT count(*) FROM "users"
 ```
 

From 8e3fd559622f96b59f1cc9882dcfd6361635f3de Mon Sep 17 00:00:00 2001
From: Ross MacLeod <ross@confer.care>
Date: Thu, 7 Sep 2017 12:06:49 -0400
Subject: [PATCH 216/685] add support for ORDER and LIMIT on UPDATE and DELETE

---
 Sources/SQLite/Typed/Query.swift   |  8 ++++++--
 Tests/SQLiteTests/QueryTests.swift | 14 ++++++++++++++
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index c9d2ea9c..2ab51e45 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -648,7 +648,9 @@ extension QueryType {
             tableName(),
             Expression<Void>(literal: "SET"),
             ", ".join(values.map { " = ".join([$0.column, $0.value]) }),
-            whereClause
+            whereClause,
+            orderClause,
+            limitOffsetClause
         ]
 
         return Update(" ".join(clauses.flatMap { $0 }).expression)
@@ -660,7 +662,9 @@ extension QueryType {
         let clauses: [Expressible?] = [
             Expression<Void>(literal: "DELETE FROM"),
             tableName(),
-            whereClause
+            whereClause,
+            orderClause,
+            limitOffsetClause
         ]
 
         return Delete(" ".join(clauses.flatMap { $0 }).expression)
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index 2cf164c6..e725105b 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -245,6 +245,13 @@ class QueryTests : XCTestCase {
         )
     }
 
+    func test_update_compilesUpdateLimitOrderExpression() {
+        AssertSQL(
+            "UPDATE \"users\" SET \"age\" = 30 ORDER BY \"id\" LIMIT 1",
+            users.order(id).limit(1).update(age <- 30)
+        )
+    }
+
     func test_delete_compilesDeleteExpression() {
         AssertSQL(
             "DELETE FROM \"users\" WHERE (\"id\" = 1)",
@@ -252,6 +259,13 @@ class QueryTests : XCTestCase {
         )
     }
 
+    func test_delete_compilesDeleteLimitOrderExpression() {
+        AssertSQL(
+            "DELETE FROM \"users\" ORDER BY \"id\" LIMIT 1",
+            users.order(id).limit(1).delete()
+        )
+    }
+
     func test_delete_compilesExistsExpression() {
         AssertSQL(
             "SELECT EXISTS (SELECT * FROM \"users\")",

From 59b8dd7a0ef4d5db96607dcd3a4a11fe05624c45 Mon Sep 17 00:00:00 2001
From: Stephan Heilner <stephanheilner@gmail.com>
Date: Thu, 7 Sep 2017 13:30:03 -0600
Subject: [PATCH 217/685] Added support for the union query clause

---
 Sources/SQLite/Typed/Query.swift   | 37 ++++++++++++++++++++++++++++++
 Tests/SQLiteTests/QueryTests.swift | 22 +++++++++++++++++-
 2 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index c9d2ea9c..e13d054d 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -180,6 +180,27 @@ extension QueryType {
         return query
     }
 
+    // MARK: UNION
+    
+    /// Adds a `UNION` clause to the query.
+    ///
+    ///     let users = Table("users")
+    ///     let email = Expression<String>("email")
+    ///
+    ///     users.filter(email == "alice@example.com").union(users.filter(email == "sally@example.com"))
+    ///     // SELECT * FROM "users" WHERE email = 'alice@example.com' UNION SELECT * FROM "users" WHERE email = 'sally@example.com'
+    ///
+    /// - Parameters:
+    ///
+    ///   - table: A query representing the other table.
+    ///
+    /// - Returns: A query with the given `UNION` clause applied.
+    public func union(_ table: QueryType) -> Self {
+        var query = self
+        query.clauses.union.append(table)
+        return query
+    }
+    
     // MARK: JOIN
 
     /// Adds a `JOIN` clause to the query.
@@ -565,6 +586,19 @@ extension QueryType {
             Expression<Void>(literal: "OFFSET \(offset)")
         ])
     }
+    
+    fileprivate var unionClause: Expressible? {
+        guard !clauses.union.isEmpty else {
+            return nil
+        }
+        
+        return " ".join(clauses.union.map { query in
+            " ".join([
+                Expression<Void>(literal: "UNION"),
+                query
+            ])
+        })
+    }
 
     // MARK: -
 
@@ -779,6 +813,7 @@ extension QueryType {
             joinClause,
             whereClause,
             groupByClause,
+            unionClause,
             orderClause,
             limitOffsetClause
         ]
@@ -1154,6 +1189,8 @@ public struct QueryClauses {
     var order = [Expressible]()
 
     var limit: (length: Int, offset: Int?)?
+    
+    var union = [QueryType]()
 
     fileprivate init(_ name: String, alias: String?, database: String?) {
         self.from = (name, alias, database)
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index 2cf164c6..cac32b28 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -361,5 +361,25 @@ class QueryIntegrationTests : SQLiteTestCase {
         let changes = try! db.run(users.delete())
         XCTAssertEqual(0, changes)
     }
-
+    
+    func test_union() throws {
+        let expectedIDs = [
+            try db.run(users.insert(email <- "alice@example.com")),
+            try db.run(users.insert(email <- "sally@example.com"))
+        ]
+        
+        let query1 = users.filter(email == "alice@example.com")
+        let query2 = users.filter(email == "sally@example.com")
+        
+        let actualIDs = try db.prepare(query1.union(query2)).map { $0[id] }
+        XCTAssertEqual(expectedIDs, actualIDs)
+        
+        let query3 = users.select(users[*], Expression<Int>(literal: "1 AS weight")).filter(email == "sally@example.com")
+        let query4 = users.select(users[*], Expression<Int>(literal: "2 AS weight")).filter(email == "alice@example.com")
+        
+        print(query3.union(query4).order(Expression<Int>(literal: "weight")).asSQL())
+        
+        let orderedIDs = try db.prepare(query3.union(query4).order(Expression<Int>(literal: "weight"), email)).map { $0[id] }
+        XCTAssertEqual(Array(expectedIDs.reversed()), orderedIDs)
+    }
 }

From 5dbe70f5003691f5c0a081cfd49ccf7b4acacc77 Mon Sep 17 00:00:00 2001
From: Jonas Zaugg <jonas.zaugg@yahoo.com>
Date: Thu, 15 Jun 2017 11:06:10 +0200
Subject: [PATCH 218/685] Update for Swift 4, removing module maps and fixing
 the map issue

---
 CocoaPods/appletvos/module.modulemap          |  4 ---
 CocoaPods/appletvsimulator/module.modulemap   |  4 ---
 CocoaPods/iphoneos-10.0/module.modulemap      |  4 ---
 CocoaPods/iphoneos/module.modulemap           |  4 ---
 .../iphonesimulator-10.0/module.modulemap     |  4 ---
 CocoaPods/iphonesimulator/module.modulemap    |  4 ---
 CocoaPods/macosx-10.11/module.modulemap       |  4 ---
 CocoaPods/macosx-10.12/module.modulemap       |  4 ---
 CocoaPods/macosx/module.modulemap             |  4 ---
 CocoaPods/watchos/module.modulemap            |  4 ---
 CocoaPods/watchsimulator/module.modulemap     |  4 ---
 SQLite.xcodeproj/project.pbxproj              | 30 ++++++++++++++-----
 .../xcschemes/SQLite Mac.xcscheme             |  2 +-
 .../xcschemes/SQLite iOS.xcscheme             |  2 +-
 .../xcschemes/SQLite tvOS.xcscheme            |  2 +-
 .../xcschemes/SQLite watchOS.xcscheme         |  2 +-
 Sources/SQLite/Core/Connection.swift          |  2 +-
 Sources/SQLite/Core/Statement.swift           |  2 +-
 Sources/SQLite/Helpers.swift                  |  2 +-
 Sources/SQLite/Typed/Query.swift              |  5 ++--
 Tests/SQLiteTests/ConnectionTests.swift       |  2 +-
 21 files changed, 34 insertions(+), 61 deletions(-)
 delete mode 100644 CocoaPods/appletvos/module.modulemap
 delete mode 100644 CocoaPods/appletvsimulator/module.modulemap
 delete mode 100644 CocoaPods/iphoneos-10.0/module.modulemap
 delete mode 100644 CocoaPods/iphoneos/module.modulemap
 delete mode 100644 CocoaPods/iphonesimulator-10.0/module.modulemap
 delete mode 100644 CocoaPods/iphonesimulator/module.modulemap
 delete mode 100644 CocoaPods/macosx-10.11/module.modulemap
 delete mode 100644 CocoaPods/macosx-10.12/module.modulemap
 delete mode 100644 CocoaPods/macosx/module.modulemap
 delete mode 100644 CocoaPods/watchos/module.modulemap
 delete mode 100644 CocoaPods/watchsimulator/module.modulemap

diff --git a/CocoaPods/appletvos/module.modulemap b/CocoaPods/appletvos/module.modulemap
deleted file mode 100644
index 637d9935..00000000
--- a/CocoaPods/appletvos/module.modulemap
+++ /dev/null
@@ -1,4 +0,0 @@
-module CSQLite [system] {
-    header "/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk/usr/include/sqlite3.h"
-    export *
-}
diff --git a/CocoaPods/appletvsimulator/module.modulemap b/CocoaPods/appletvsimulator/module.modulemap
deleted file mode 100644
index f8b9b671..00000000
--- a/CocoaPods/appletvsimulator/module.modulemap
+++ /dev/null
@@ -1,4 +0,0 @@
-module CSQLite [system] {
-    header "/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVSimulator.platform/Developer/SDKs/AppleTVSimulator.sdk/usr/include/sqlite3.h"
-    export *
-}
diff --git a/CocoaPods/iphoneos-10.0/module.modulemap b/CocoaPods/iphoneos-10.0/module.modulemap
deleted file mode 100644
index 67a6c203..00000000
--- a/CocoaPods/iphoneos-10.0/module.modulemap
+++ /dev/null
@@ -1,4 +0,0 @@
-module CSQLite [system] {
-    header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.sdk/usr/include/sqlite3.h"
-    export *
-}
diff --git a/CocoaPods/iphoneos/module.modulemap b/CocoaPods/iphoneos/module.modulemap
deleted file mode 100644
index 043db6c4..00000000
--- a/CocoaPods/iphoneos/module.modulemap
+++ /dev/null
@@ -1,4 +0,0 @@
-module CSQLite [system] {
-    header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/sqlite3.h"
-    export *
-}
diff --git a/CocoaPods/iphonesimulator-10.0/module.modulemap b/CocoaPods/iphonesimulator-10.0/module.modulemap
deleted file mode 100644
index c8b84ab8..00000000
--- a/CocoaPods/iphonesimulator-10.0/module.modulemap
+++ /dev/null
@@ -1,4 +0,0 @@
-module CSQLite [system] {
-    header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator10.0.sdk/usr/include/sqlite3.h"
-    export *
-}
diff --git a/CocoaPods/iphonesimulator/module.modulemap b/CocoaPods/iphonesimulator/module.modulemap
deleted file mode 100644
index a7b14cbb..00000000
--- a/CocoaPods/iphonesimulator/module.modulemap
+++ /dev/null
@@ -1,4 +0,0 @@
-module CSQLite [system] {
-    header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/sqlite3.h"
-    export *
-}
diff --git a/CocoaPods/macosx-10.11/module.modulemap b/CocoaPods/macosx-10.11/module.modulemap
deleted file mode 100644
index 9e091297..00000000
--- a/CocoaPods/macosx-10.11/module.modulemap
+++ /dev/null
@@ -1,4 +0,0 @@
-module CSQLite [system] {
-    header "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/sqlite3.h"
-    export *
-}
diff --git a/CocoaPods/macosx-10.12/module.modulemap b/CocoaPods/macosx-10.12/module.modulemap
deleted file mode 100644
index 8fc958e6..00000000
--- a/CocoaPods/macosx-10.12/module.modulemap
+++ /dev/null
@@ -1,4 +0,0 @@
-module CSQLite [system] {
-    header "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/include/sqlite3.h"
-    export *
-}
diff --git a/CocoaPods/macosx/module.modulemap b/CocoaPods/macosx/module.modulemap
deleted file mode 100644
index cc8370ec..00000000
--- a/CocoaPods/macosx/module.modulemap
+++ /dev/null
@@ -1,4 +0,0 @@
-module CSQLite [system] {
-    header "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sqlite3.h"
-    export *
-}
diff --git a/CocoaPods/watchos/module.modulemap b/CocoaPods/watchos/module.modulemap
deleted file mode 100644
index 62a6c4ee..00000000
--- a/CocoaPods/watchos/module.modulemap
+++ /dev/null
@@ -1,4 +0,0 @@
-module CSQLite [system] {
-    header "/Applications/Xcode.app/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs/WatchOS.sdk/usr/include/sqlite3.h"
-    export *
-}
diff --git a/CocoaPods/watchsimulator/module.modulemap b/CocoaPods/watchsimulator/module.modulemap
deleted file mode 100644
index 086fbab2..00000000
--- a/CocoaPods/watchsimulator/module.modulemap
+++ /dev/null
@@ -1,4 +0,0 @@
-module CSQLite [system] {
-    header "/Applications/Xcode.app/Contents/Developer/Platforms/WatchSimulator.platform/Developer/SDKs/WatchSimulator.sdk/usr/include/sqlite3.h"
-    export *
-}
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 78b43249..c4d702c7 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -740,7 +740,7 @@
 			isa = PBXProject;
 			attributes = {
 				LastSwiftUpdateCheck = 0720;
-				LastUpgradeCheck = 0800;
+				LastUpgradeCheck = 0900;
 				TargetAttributes = {
 					03A65E591C6BB0F50062603F = {
 						CreatedOnToolsVersion = 7.2;
@@ -753,11 +753,11 @@
 					};
 					EE247AD21C3F04ED00AE3E12 = {
 						CreatedOnToolsVersion = 7.2;
-						LastSwiftMigration = 0800;
+						LastSwiftMigration = 0900;
 					};
 					EE247ADC1C3F04ED00AE3E12 = {
 						CreatedOnToolsVersion = 7.2;
-						LastSwiftMigration = 0800;
+						LastSwiftMigration = 0900;
 					};
 					EE247B3B1C3F3ED000AE3E12 = {
 						CreatedOnToolsVersion = 7.2;
@@ -1185,14 +1185,20 @@
 				CLANG_CXX_LIBRARY = "libc++";
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
 				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
 				CLANG_WARN_EMPTY_BODY = YES;
 				CLANG_WARN_ENUM_CONVERSION = YES;
 				CLANG_WARN_INFINITE_RECURSION = YES;
 				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
 				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
 				CLANG_WARN_SUSPICIOUS_MOVE = YES;
 				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -1237,14 +1243,20 @@
 				CLANG_CXX_LIBRARY = "libc++";
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
 				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
 				CLANG_WARN_EMPTY_BODY = YES;
 				CLANG_WARN_ENUM_CONVERSION = YES;
 				CLANG_WARN_INFINITE_RECURSION = YES;
 				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
 				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
 				CLANG_WARN_SUSPICIOUS_MOVE = YES;
 				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -1297,7 +1309,8 @@
 				"SWIFT_INCLUDE_PATHS[sdk=iphonesimulator*]" = "$(SRCROOT)/CocoaPods/iphonesimulator";
 				"SWIFT_INCLUDE_PATHS[sdk=iphonesimulator10.0]" = "$(SRCROOT)/CocoaPods/iphonesimulator-10.0";
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
-				SWIFT_VERSION = 3.0;
+				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_VERSION = 4.0;
 			};
 			name = Debug;
 		};
@@ -1322,7 +1335,8 @@
 				"SWIFT_INCLUDE_PATHS[sdk=iphoneos10.0]" = "$(SRCROOT)/CocoaPods/iphoneos-10.0";
 				"SWIFT_INCLUDE_PATHS[sdk=iphonesimulator*]" = "$(SRCROOT)/CocoaPods/iphonesimulator";
 				"SWIFT_INCLUDE_PATHS[sdk=iphonesimulator10.0]" = "$(SRCROOT)/CocoaPods/iphonesimulator-10.0";
-				SWIFT_VERSION = 3.0;
+				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_VERSION = 4.0;
 			};
 			name = Release;
 		};
@@ -1334,7 +1348,8 @@
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
-				SWIFT_VERSION = 3.0;
+				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_VERSION = 4.0;
 			};
 			name = Debug;
 		};
@@ -1346,7 +1361,8 @@
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
-				SWIFT_VERSION = 3.0;
+				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_VERSION = 4.0;
 			};
 			name = Release;
 		};
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme
index 606b5a10..2c3c431f 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme	
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0800"
+   LastUpgradeVersion = "0900"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme
index 64f32011..e6cb416a 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme	
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0800"
+   LastUpgradeVersion = "0900"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme
index 71ba5f16..cfa4e0fa 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme	
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0800"
+   LastUpgradeVersion = "0900"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite watchOS.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite watchOS.xcscheme
index d2088e81..92cc9126 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite watchOS.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite watchOS.xcscheme	
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0800"
+   LastUpgradeVersion = "0900"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index bba9a358..51b68ed8 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -29,7 +29,7 @@ import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
 #elseif SWIFT_PACKAGE || COCOAPODS
-import CSQLite
+import SQLite3
 #endif
 
 /// A connection to SQLite.
diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index a9232bba..8c13ff6c 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -27,7 +27,7 @@ import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
 #elseif SWIFT_PACKAGE || COCOAPODS
-import CSQLite
+import SQLite3
 #endif
 
 /// A single SQL statement.
diff --git a/Sources/SQLite/Helpers.swift b/Sources/SQLite/Helpers.swift
index 50b21d0d..52b158b1 100644
--- a/Sources/SQLite/Helpers.swift
+++ b/Sources/SQLite/Helpers.swift
@@ -27,7 +27,7 @@ import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
 #elseif SWIFT_PACKAGE || COCOAPODS
-import CSQLite
+import SQLite3
 #endif
 
 public typealias Star = (Expression<Binding>?, Expression<Binding>?) -> Expression<Void>
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index c9d2ea9c..6a8d885b 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -494,8 +494,9 @@ extension QueryType {
             return nil
         }
 
-        return " ".join(clauses.join.map { type, query, condition in
-            " ".join([
+        return " ".join(clauses.join.map { arg in
+            let (type, query, condition) = arg
+            return " ".join([
                 Expression<Void>(literal: "\(type.rawValue) JOIN"),
                 query.tableName(alias: true),
                 Expression<Void>(literal: "ON"),
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index d05c5ece..373cba0a 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -6,7 +6,7 @@ import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
 #elseif SWIFT_PACKAGE || COCOAPODS
-import CSQLite
+import SQLite3
 #endif
 
 class ConnectionTests : SQLiteTestCase {

From 53f18574ca6500d1ad44a7f083aa179daf9559d4 Mon Sep 17 00:00:00 2001
From: Jonas Zaugg <jonas.zaugg@yahoo.com>
Date: Thu, 15 Jun 2017 11:11:16 +0200
Subject: [PATCH 219/685] Remove reference to deleted files

---
 SQLite.swift.podspec | 13 -------------
 1 file changed, 13 deletions(-)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 06aa043b..6e9145c8 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -31,19 +31,6 @@ Pod::Spec.new do |s|
 
     ss.library = 'sqlite3'
     ss.preserve_paths = 'CocoaPods/**/*'
-    ss.pod_target_xcconfig = {
-      'SWIFT_INCLUDE_PATHS[sdk=macosx*]'             => '$(SRCROOT)/SQLite.swift/CocoaPods/macosx',
-      'SWIFT_INCLUDE_PATHS[sdk=macosx10.11]'         => '$(SRCROOT)/SQLite.swift/CocoaPods/macosx-10.11',
-      'SWIFT_INCLUDE_PATHS[sdk=macosx10.12]'         => '$(SRCROOT)/SQLite.swift/CocoaPods/macosx-10.12',
-      'SWIFT_INCLUDE_PATHS[sdk=iphoneos*]'           => '$(SRCROOT)/SQLite.swift/CocoaPods/iphoneos',
-      'SWIFT_INCLUDE_PATHS[sdk=iphoneos10.0]'        => '$(SRCROOT)/SQLite.swift/CocoaPods/iphoneos-10.0',
-      'SWIFT_INCLUDE_PATHS[sdk=iphonesimulator*]'    => '$(SRCROOT)/SQLite.swift/CocoaPods/iphonesimulator',
-      'SWIFT_INCLUDE_PATHS[sdk=iphonesimulator10.0]' => '$(SRCROOT)/SQLite.swift/CocoaPods/iphonesimulator-10.0',
-      'SWIFT_INCLUDE_PATHS[sdk=appletvos*]'          => '$(SRCROOT)/SQLite.swift/CocoaPods/appletvos',
-      'SWIFT_INCLUDE_PATHS[sdk=appletvsimulator*]'   => '$(SRCROOT)/SQLite.swift/CocoaPods/appletvsimulator',
-      'SWIFT_INCLUDE_PATHS[sdk=watchos*]'            => '$(SRCROOT)/SQLite.swift/CocoaPods/watchos',
-      'SWIFT_INCLUDE_PATHS[sdk=watchsimulator*]'     => '$(SRCROOT)/SQLite.swift/CocoaPods/watchsimulator'
-    }
   end
 
   s.subspec 'standalone' do |ss|

From 53e768ab0db413a5f0dbbb1166736eb9e89802fa Mon Sep 17 00:00:00 2001
From: Jonas Zaugg <jonas.zaugg@yahoo.com>
Date: Thu, 15 Jun 2017 11:21:17 +0200
Subject: [PATCH 220/685] Remove deleted paths

---
 SQLite.swift.podspec | 1 -
 1 file changed, 1 deletion(-)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 6e9145c8..808e8a46 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -30,7 +30,6 @@ Pod::Spec.new do |s|
     ss.private_header_files = 'Sources/SQLiteObjc/*.h'
 
     ss.library = 'sqlite3'
-    ss.preserve_paths = 'CocoaPods/**/*'
   end
 
   s.subspec 'standalone' do |ss|

From 034093fc45c638525163c3bbfb0076ca698f73d7 Mon Sep 17 00:00:00 2001
From: Jonas Zaugg <jonas.zaugg@yahoo.com>
Date: Thu, 15 Jun 2017 11:27:27 +0200
Subject: [PATCH 221/685] Remove dependency

---
 SQLite.swift.podspec | 2 --
 1 file changed, 2 deletions(-)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 808e8a46..ce31843e 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -28,8 +28,6 @@ Pod::Spec.new do |s|
     ss.source_files = 'Sources/{SQLite,SQLiteObjc}/**/*.{c,h,m,swift}'
     ss.exclude_files = 'Sources/**/Cipher.swift'
     ss.private_header_files = 'Sources/SQLiteObjc/*.h'
-
-    ss.library = 'sqlite3'
   end
 
   s.subspec 'standalone' do |ss|

From 3033a4ddc6a8ed2d98b7488a51bbb553a7287036 Mon Sep 17 00:00:00 2001
From: Jonas Zaugg <jonas.zaugg@yahoo.com>
Date: Thu, 15 Jun 2017 11:32:24 +0200
Subject: [PATCH 222/685] Undo

---
 SQLite.swift.podspec | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index ce31843e..808e8a46 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -28,6 +28,8 @@ Pod::Spec.new do |s|
     ss.source_files = 'Sources/{SQLite,SQLiteObjc}/**/*.{c,h,m,swift}'
     ss.exclude_files = 'Sources/**/Cipher.swift'
     ss.private_header_files = 'Sources/SQLiteObjc/*.h'
+
+    ss.library = 'sqlite3'
   end
 
   s.subspec 'standalone' do |ss|

From 2211bce8dea454b48b9df94715f1526d3b9276ed Mon Sep 17 00:00:00 2001
From: Jonas Zaugg <jonas.zaugg@yahoo.com>
Date: Fri, 16 Jun 2017 23:52:47 +0200
Subject: [PATCH 223/685] More cleanup

---
 .swift-version                   |   2 +-
 SQLite.xcodeproj/project.pbxproj | 125 +++++++------------------------
 2 files changed, 26 insertions(+), 101 deletions(-)

diff --git a/.swift-version b/.swift-version
index 9f55b2cc..5186d070 100644
--- a/.swift-version
+++ b/.swift-version
@@ -1 +1 @@
-3.0
+4.0
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index c4d702c7..30295edb 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -8,7 +8,6 @@
 
 /* Begin PBXBuildFile section */
 		03A65E641C6BB0F60062603F /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03A65E5A1C6BB0F50062603F /* SQLite.framework */; };
-		03A65E711C6BB2CD0062603F /* usr/include/sqlite3.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808B1C46E34A0038162A /* usr/include/sqlite3.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		03A65E721C6BB2D30062603F /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		03A65E731C6BB2D80062603F /* Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF71C3F06E900AE3E12 /* Foundation.swift */; };
 		03A65E741C6BB2DA0062603F /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF81C3F06E900AE3E12 /* Helpers.swift */; };
@@ -88,7 +87,6 @@
 		3D67B3F71DB246D700A4F4C6 /* Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF71C3F06E900AE3E12 /* Foundation.swift */; };
 		3D67B3F81DB246D700A4F4C6 /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF81C3F06E900AE3E12 /* Helpers.swift */; };
 		3D67B3F91DB246E700A4F4C6 /* SQLite-Bridging.m in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */; };
-		3D67B3FA1DB2470600A4F4C6 /* usr/include/sqlite3.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808B1C46E34A0038162A /* usr/include/sqlite3.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		3D67B3FB1DB2470600A4F4C6 /* SQLite-Bridging.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808D1C46E5230038162A /* SQLite-Bridging.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		3D67B3FC1DB2471B00A4F4C6 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		3D67B3FD1DB2472D00A4F4C6 /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */; };
@@ -164,10 +162,8 @@
 		EE247B731C3F3FEC00AE3E12 /* Query.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B001C3F06E900AE3E12 /* Query.swift */; };
 		EE247B741C3F3FEC00AE3E12 /* Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B011C3F06E900AE3E12 /* Schema.swift */; };
 		EE247B751C3F3FEC00AE3E12 /* Setter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B021C3F06E900AE3E12 /* Setter.swift */; };
-		EE91808C1C46E34A0038162A /* usr/include/sqlite3.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808B1C46E34A0038162A /* usr/include/sqlite3.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		EE91808E1C46E5230038162A /* SQLite-Bridging.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808D1C46E5230038162A /* SQLite-Bridging.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		EE91808F1C46E76D0038162A /* SQLite-Bridging.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808D1C46E5230038162A /* SQLite-Bridging.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		EE9180901C46E8980038162A /* usr/include/sqlite3.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808B1C46E34A0038162A /* usr/include/sqlite3.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		EE9180941C46EA210038162A /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = EE9180931C46EA210038162A /* libsqlite3.tbd */; };
 		EE9180951C46EBCC0038162A /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = EE9180911C46E9D30038162A /* libsqlite3.tbd */; };
 /* End PBXBuildFile section */
@@ -207,13 +203,6 @@
 		19A1794CC4D7827E997E32A7 /* FoundationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationTests.swift; sourceTree = "<group>"; };
 		19A17B93B48B5560E6E51791 /* Fixtures.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Fixtures.swift; sourceTree = "<group>"; };
 		19A17E2695737FAB5D6086E3 /* fixtures */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = folder; path = fixtures; sourceTree = "<group>"; };
-		39548A631CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
-		39548A651CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
-		39548A671CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
-		39548A691CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
-		39548A6B1CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
-		39548A6D1CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
-		39548A6F1CA63C740003E3B5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
 		3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.0.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
 		A121AC451CA35C79005A31D1 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AD31C3F04ED00AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -265,7 +254,6 @@
 		EE247B911C3F822500AE3E12 /* installation@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "installation@2x.png"; sourceTree = "<group>"; };
 		EE247B921C3F822600AE3E12 /* playground@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "playground@2x.png"; sourceTree = "<group>"; };
 		EE247B931C3F826100AE3E12 /* SQLite.swift.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; path = SQLite.swift.podspec; sourceTree = "<group>"; };
-		EE91808B1C46E34A0038162A /* usr/include/sqlite3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = usr/include/sqlite3.h; sourceTree = SDKROOT; };
 		EE91808D1C46E5230038162A /* SQLite-Bridging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "SQLite-Bridging.h"; path = "../../SQLiteObjc/include/SQLite-Bridging.h"; sourceTree = "<group>"; };
 		EE9180911C46E9D30038162A /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
 		EE9180931C46EA210038162A /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; };
@@ -331,76 +319,6 @@
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
-		39548A611CA63C740003E3B5 /* CocoaPods */ = {
-			isa = PBXGroup;
-			children = (
-				39548A621CA63C740003E3B5 /* appletvos */,
-				39548A641CA63C740003E3B5 /* appletvsimulator */,
-				39548A661CA63C740003E3B5 /* iphoneos */,
-				39548A681CA63C740003E3B5 /* iphonesimulator */,
-				39548A6A1CA63C740003E3B5 /* macosx */,
-				39548A6C1CA63C740003E3B5 /* watchos */,
-				39548A6E1CA63C740003E3B5 /* watchsimulator */,
-			);
-			path = CocoaPods;
-			sourceTree = "<group>";
-		};
-		39548A621CA63C740003E3B5 /* appletvos */ = {
-			isa = PBXGroup;
-			children = (
-				39548A631CA63C740003E3B5 /* module.modulemap */,
-			);
-			path = appletvos;
-			sourceTree = "<group>";
-		};
-		39548A641CA63C740003E3B5 /* appletvsimulator */ = {
-			isa = PBXGroup;
-			children = (
-				39548A651CA63C740003E3B5 /* module.modulemap */,
-			);
-			path = appletvsimulator;
-			sourceTree = "<group>";
-		};
-		39548A661CA63C740003E3B5 /* iphoneos */ = {
-			isa = PBXGroup;
-			children = (
-				39548A671CA63C740003E3B5 /* module.modulemap */,
-			);
-			path = iphoneos;
-			sourceTree = "<group>";
-		};
-		39548A681CA63C740003E3B5 /* iphonesimulator */ = {
-			isa = PBXGroup;
-			children = (
-				39548A691CA63C740003E3B5 /* module.modulemap */,
-			);
-			path = iphonesimulator;
-			sourceTree = "<group>";
-		};
-		39548A6A1CA63C740003E3B5 /* macosx */ = {
-			isa = PBXGroup;
-			children = (
-				39548A6B1CA63C740003E3B5 /* module.modulemap */,
-			);
-			path = macosx;
-			sourceTree = "<group>";
-		};
-		39548A6C1CA63C740003E3B5 /* watchos */ = {
-			isa = PBXGroup;
-			children = (
-				39548A6D1CA63C740003E3B5 /* module.modulemap */,
-			);
-			path = watchos;
-			sourceTree = "<group>";
-		};
-		39548A6E1CA63C740003E3B5 /* watchsimulator */ = {
-			isa = PBXGroup;
-			children = (
-				39548A6F1CA63C740003E3B5 /* module.modulemap */,
-			);
-			path = watchsimulator;
-			sourceTree = "<group>";
-		};
 		3D67B3E41DB2469200A4F4C6 /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
@@ -439,7 +357,6 @@
 		EE247AD51C3F04ED00AE3E12 /* SQLite */ = {
 			isa = PBXGroup;
 			children = (
-				EE91808B1C46E34A0038162A /* usr/include/sqlite3.h */,
 				EE247AD61C3F04ED00AE3E12 /* SQLite.h */,
 				EE247AF71C3F06E900AE3E12 /* Foundation.swift */,
 				EE247AF81C3F06E900AE3E12 /* Helpers.swift */,
@@ -525,7 +442,6 @@
 		EE247B8A1C3F81D000AE3E12 /* Metadata */ = {
 			isa = PBXGroup;
 			children = (
-				39548A611CA63C740003E3B5 /* CocoaPods */,
 				EE247B771C3F40D700AE3E12 /* README.md */,
 				EE247B8B1C3F820300AE3E12 /* CONTRIBUTING.md */,
 				EE247B931C3F826100AE3E12 /* SQLite.swift.podspec */,
@@ -566,7 +482,6 @@
 			files = (
 				03A65E781C6BB2EA0062603F /* fts3_tokenizer.h in Headers */,
 				03A65E751C6BB2DF0062603F /* SQLite-Bridging.h in Headers */,
-				03A65E711C6BB2CD0062603F /* usr/include/sqlite3.h in Headers */,
 				03A65E721C6BB2D30062603F /* SQLite.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -575,7 +490,6 @@
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				3D67B3FA1DB2470600A4F4C6 /* usr/include/sqlite3.h in Headers */,
 				3D67B3FB1DB2470600A4F4C6 /* SQLite-Bridging.h in Headers */,
 				3D67B3FC1DB2471B00A4F4C6 /* SQLite.h in Headers */,
 				3D67B3FD1DB2472D00A4F4C6 /* fts3_tokenizer.h in Headers */,
@@ -588,7 +502,6 @@
 			files = (
 				EE91808E1C46E5230038162A /* SQLite-Bridging.h in Headers */,
 				EE247B051C3F06E900AE3E12 /* fts3_tokenizer.h in Headers */,
-				EE91808C1C46E34A0038162A /* usr/include/sqlite3.h in Headers */,
 				EE247AD71C3F04ED00AE3E12 /* SQLite.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -597,7 +510,6 @@
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				EE9180901C46E8980038162A /* usr/include/sqlite3.h in Headers */,
 				EE247B671C3F3FEC00AE3E12 /* fts3_tokenizer.h in Headers */,
 				EE247B621C3F3FDB00AE3E12 /* SQLite.h in Headers */,
 				EE91808F1C46E76D0038162A /* SQLite-Bridging.h in Headers */,
@@ -744,12 +656,15 @@
 				TargetAttributes = {
 					03A65E591C6BB0F50062603F = {
 						CreatedOnToolsVersion = 7.2;
+						LastSwiftMigration = 0900;
 					};
 					03A65E621C6BB0F60062603F = {
 						CreatedOnToolsVersion = 7.2;
+						LastSwiftMigration = 0900;
 					};
 					A121AC441CA35C79005A31D1 = {
 						CreatedOnToolsVersion = 7.3;
+						LastSwiftMigration = 0900;
 					};
 					EE247AD21C3F04ED00AE3E12 = {
 						CreatedOnToolsVersion = 7.2;
@@ -761,11 +676,11 @@
 					};
 					EE247B3B1C3F3ED000AE3E12 = {
 						CreatedOnToolsVersion = 7.2;
-						LastSwiftMigration = 0800;
+						LastSwiftMigration = 0900;
 					};
 					EE247B441C3F3ED000AE3E12 = {
 						CreatedOnToolsVersion = 7.2;
-						LastSwiftMigration = 0800;
+						LastSwiftMigration = 0900;
 					};
 				};
 			};
@@ -1073,7 +988,8 @@
 				SKIP_INSTALL = YES;
 				"SWIFT_INCLUDE_PATHS[sdk=appletvos*]" = "$(SRCROOT)/CocoaPods/appletvos";
 				"SWIFT_INCLUDE_PATHS[sdk=appletvsimulator*]" = "$(SRCROOT)/CocoaPods/appletvsimulator";
-				SWIFT_VERSION = 3.0;
+				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_VERSION = 4.0;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
 			name = Debug;
@@ -1096,7 +1012,8 @@
 				SKIP_INSTALL = YES;
 				"SWIFT_INCLUDE_PATHS[sdk=appletvos*]" = "$(SRCROOT)/CocoaPods/appletvos";
 				"SWIFT_INCLUDE_PATHS[sdk=appletvsimulator*]" = "$(SRCROOT)/CocoaPods/appletvsimulator";
-				SWIFT_VERSION = 3.0;
+				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_VERSION = 4.0;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
 			name = Release;
@@ -1109,7 +1026,8 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = appletvos;
-				SWIFT_VERSION = 3.0;
+				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_VERSION = 4.0;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
 			name = Debug;
@@ -1122,7 +1040,8 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = appletvos;
-				SWIFT_VERSION = 3.0;
+				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_VERSION = 4.0;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
 			name = Release;
@@ -1146,7 +1065,8 @@
 				SKIP_INSTALL = YES;
 				"SWIFT_INCLUDE_PATHS[sdk=watchos*]" = "$(SRCROOT)/CocoaPods/watchos";
 				"SWIFT_INCLUDE_PATHS[sdk=watchsimulator*]" = "$(SRCROOT)/CocoaPods/watchsimulator";
-				SWIFT_VERSION = 3.0;
+				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_VERSION = 4.0;
 				TARGETED_DEVICE_FAMILY = 4;
 				WATCHOS_DEPLOYMENT_TARGET = 2.2;
 			};
@@ -1171,7 +1091,8 @@
 				SKIP_INSTALL = YES;
 				"SWIFT_INCLUDE_PATHS[sdk=watchos*]" = "$(SRCROOT)/CocoaPods/watchos";
 				"SWIFT_INCLUDE_PATHS[sdk=watchsimulator*]" = "$(SRCROOT)/CocoaPods/watchsimulator";
-				SWIFT_VERSION = 3.0;
+				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_VERSION = 4.0;
 				TARGETED_DEVICE_FAMILY = 4;
 				WATCHOS_DEPLOYMENT_TARGET = 2.2;
 			};
@@ -1389,7 +1310,8 @@
 				"SWIFT_INCLUDE_PATHS[sdk=macosx*]" = "$(SRCROOT)/CocoaPods/macosx";
 				"SWIFT_INCLUDE_PATHS[sdk=macosx10.11]" = "$(SRCROOT)/CocoaPods/macosx-10.11";
 				"SWIFT_INCLUDE_PATHS[sdk=macosx10.12]" = "$(SRCROOT)/CocoaPods/macosx-10.12";
-				SWIFT_VERSION = 3.0;
+				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_VERSION = 4.0;
 			};
 			name = Debug;
 		};
@@ -1416,7 +1338,8 @@
 				"SWIFT_INCLUDE_PATHS[sdk=macosx*]" = "$(SRCROOT)/CocoaPods/macosx";
 				"SWIFT_INCLUDE_PATHS[sdk=macosx10.11]" = "$(SRCROOT)/CocoaPods/macosx-10.11";
 				"SWIFT_INCLUDE_PATHS[sdk=macosx10.12]" = "$(SRCROOT)/CocoaPods/macosx-10.12";
-				SWIFT_VERSION = 3.0;
+				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_VERSION = 4.0;
 			};
 			name = Release;
 		};
@@ -1431,7 +1354,8 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = macosx;
-				SWIFT_VERSION = 3.0;
+				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_VERSION = 4.0;
 			};
 			name = Debug;
 		};
@@ -1446,7 +1370,8 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = macosx;
-				SWIFT_VERSION = 3.0;
+				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_VERSION = 4.0;
 			};
 			name = Release;
 		};

From 52e02ae7c3e7ab7be0404c3739ec925def785ab0 Mon Sep 17 00:00:00 2001
From: Jonas Zaugg <jonas.zaugg@yahoo.com>
Date: Fri, 30 Jun 2017 19:17:46 +0200
Subject: [PATCH 224/685] Update Travis CI to use Xcode 9 beta 2

---
 .travis.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index 2eb85311..5dba809f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,6 @@
 language: objective-c
 rvm: 2.2
-osx_image: xcode8.3
+osx_image: xcode9
 env:
   global:
     - IOS_SIMULATOR="iPhone 6s"

From f780ba16a2511760b694d7c8a179610e4198614f Mon Sep 17 00:00:00 2001
From: Jonas Zaugg <jonas.zaugg@yahoo.com>
Date: Fri, 30 Jun 2017 23:00:59 +0200
Subject: [PATCH 225/685] Fix for iOS version not found on Travis

---
 Makefile                                                    | 2 +-
 SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index adab1d81..ebd38494 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 BUILD_TOOL = xcodebuild
 BUILD_SCHEME = SQLite Mac
 IOS_SIMULATOR = iPhone 6s
-IOS_VERSION = 10.3
+IOS_VERSION = 11.0
 ifeq ($(BUILD_SCHEME),SQLite iOS)
 	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -destination "platform=iOS Simulator,name=$(IOS_SIMULATOR),OS=$(IOS_VERSION)"
 else
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme
index e6cb416a..fb00f5bb 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme	
@@ -26,6 +26,7 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      language = ""
       shouldUseLaunchSchemeArgsEnv = "YES"
       codeCoverageEnabled = "YES">
       <Testables>
@@ -56,6 +57,7 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      language = ""
       launchStyle = "0"
       useCustomWorkingDirectory = "NO"
       ignoresPersistentStateOnLaunch = "NO"

From ede1af7baad71344dc323e3d54b0e22995992694 Mon Sep 17 00:00:00 2001
From: thebluepotato <jonas.zaugg@yahoo.com>
Date: Sat, 1 Jul 2017 01:33:14 +0200
Subject: [PATCH 226/685] Enforce iOS 11.0 after update from master

---
 .travis.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index 5dba809f..62f36185 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,7 +4,7 @@ osx_image: xcode9
 env:
   global:
     - IOS_SIMULATOR="iPhone 6s"
-    - IOS_VERSION="10.3.1"
+    - IOS_VERSION="11.0"
 matrix:
   include:
     - env: BUILD_SCHEME="SQLite iOS"

From 0bbb4ca9bcc091a42bc6a60ff6c0410a70b75d18 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 22 Aug 2017 08:45:27 +0200
Subject: [PATCH 227/685] Fix compiler warnings

- objc inference
- substring(to:) deprecation
- redundant conformance constraint
---
 SQLite.xcodeproj/project.pbxproj     | 28 ++++++++++++++--------------
 Sources/SQLite/Extensions/FTS4.swift | 15 ++++++++++-----
 Sources/SQLite/Typed/Operators.swift |  4 ++--
 3 files changed, 26 insertions(+), 21 deletions(-)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 30295edb..8e3162d9 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -988,7 +988,7 @@
 				SKIP_INSTALL = YES;
 				"SWIFT_INCLUDE_PATHS[sdk=appletvos*]" = "$(SRCROOT)/CocoaPods/appletvos";
 				"SWIFT_INCLUDE_PATHS[sdk=appletvsimulator*]" = "$(SRCROOT)/CocoaPods/appletvsimulator";
-				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
@@ -1012,7 +1012,7 @@
 				SKIP_INSTALL = YES;
 				"SWIFT_INCLUDE_PATHS[sdk=appletvos*]" = "$(SRCROOT)/CocoaPods/appletvos";
 				"SWIFT_INCLUDE_PATHS[sdk=appletvsimulator*]" = "$(SRCROOT)/CocoaPods/appletvsimulator";
-				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
@@ -1026,7 +1026,7 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = appletvos;
-				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
@@ -1040,7 +1040,7 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = appletvos;
-				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
@@ -1065,7 +1065,7 @@
 				SKIP_INSTALL = YES;
 				"SWIFT_INCLUDE_PATHS[sdk=watchos*]" = "$(SRCROOT)/CocoaPods/watchos";
 				"SWIFT_INCLUDE_PATHS[sdk=watchsimulator*]" = "$(SRCROOT)/CocoaPods/watchsimulator";
-				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
 				TARGETED_DEVICE_FAMILY = 4;
 				WATCHOS_DEPLOYMENT_TARGET = 2.2;
@@ -1091,7 +1091,7 @@
 				SKIP_INSTALL = YES;
 				"SWIFT_INCLUDE_PATHS[sdk=watchos*]" = "$(SRCROOT)/CocoaPods/watchos";
 				"SWIFT_INCLUDE_PATHS[sdk=watchsimulator*]" = "$(SRCROOT)/CocoaPods/watchsimulator";
-				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
 				TARGETED_DEVICE_FAMILY = 4;
 				WATCHOS_DEPLOYMENT_TARGET = 2.2;
@@ -1230,7 +1230,7 @@
 				"SWIFT_INCLUDE_PATHS[sdk=iphonesimulator*]" = "$(SRCROOT)/CocoaPods/iphonesimulator";
 				"SWIFT_INCLUDE_PATHS[sdk=iphonesimulator10.0]" = "$(SRCROOT)/CocoaPods/iphonesimulator-10.0";
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
-				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
 			};
 			name = Debug;
@@ -1256,7 +1256,7 @@
 				"SWIFT_INCLUDE_PATHS[sdk=iphoneos10.0]" = "$(SRCROOT)/CocoaPods/iphoneos-10.0";
 				"SWIFT_INCLUDE_PATHS[sdk=iphonesimulator*]" = "$(SRCROOT)/CocoaPods/iphonesimulator";
 				"SWIFT_INCLUDE_PATHS[sdk=iphonesimulator10.0]" = "$(SRCROOT)/CocoaPods/iphonesimulator-10.0";
-				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
 			};
 			name = Release;
@@ -1269,7 +1269,7 @@
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
-				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
 			};
 			name = Debug;
@@ -1282,7 +1282,7 @@
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
-				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
 			};
 			name = Release;
@@ -1310,7 +1310,7 @@
 				"SWIFT_INCLUDE_PATHS[sdk=macosx*]" = "$(SRCROOT)/CocoaPods/macosx";
 				"SWIFT_INCLUDE_PATHS[sdk=macosx10.11]" = "$(SRCROOT)/CocoaPods/macosx-10.11";
 				"SWIFT_INCLUDE_PATHS[sdk=macosx10.12]" = "$(SRCROOT)/CocoaPods/macosx-10.12";
-				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
 			};
 			name = Debug;
@@ -1338,7 +1338,7 @@
 				"SWIFT_INCLUDE_PATHS[sdk=macosx*]" = "$(SRCROOT)/CocoaPods/macosx";
 				"SWIFT_INCLUDE_PATHS[sdk=macosx10.11]" = "$(SRCROOT)/CocoaPods/macosx-10.11";
 				"SWIFT_INCLUDE_PATHS[sdk=macosx10.12]" = "$(SRCROOT)/CocoaPods/macosx-10.12";
-				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
 			};
 			name = Release;
@@ -1354,7 +1354,7 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = macosx;
-				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
 			};
 			name = Debug;
@@ -1370,7 +1370,7 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = macosx;
-				SWIFT_SWIFT3_OBJC_INFERENCE = On;
+				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
 			};
 			name = Release;
diff --git a/Sources/SQLite/Extensions/FTS4.swift b/Sources/SQLite/Extensions/FTS4.swift
index 3f28d33b..5ef84dd7 100644
--- a/Sources/SQLite/Extensions/FTS4.swift
+++ b/Sources/SQLite/Extensions/FTS4.swift
@@ -151,13 +151,18 @@ extension Connection {
 
             guard let (token, range) = next(string) else { return nil }
 
-            let view = string.utf8
-            offset.pointee += Int32(string.substring(to: range.lowerBound).utf8.count)
-            length.pointee = Int32(view.distance(from: range.lowerBound.samePosition(in: view), to: range.upperBound.samePosition(in: view)))
-            return token
+            let view:String.UTF8View = string.utf8
+
+            if let from = range.lowerBound.samePosition(in: view),
+               let to = range.upperBound.samePosition(in: view) {
+                offset.pointee += Int32(string[string.startIndex..<range.lowerBound].utf8.count)
+                length.pointee = Int32(view.distance(from: from, to: to))
+                return token
+            } else {
+                return nil
+            }
         })
     }
-
 }
 
 /// Configuration options shared between the [FTS4](https://www.sqlite.org/fts3.html) and
diff --git a/Sources/SQLite/Typed/Operators.swift b/Sources/SQLite/Typed/Operators.swift
index fdd293be..01381bb8 100644
--- a/Sources/SQLite/Typed/Operators.swift
+++ b/Sources/SQLite/Typed/Operators.swift
@@ -474,10 +474,10 @@ public func <=<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> wher
     return infix(lhs, rhs)
 }
 
-public func ~=<V : Value>(lhs: ClosedRange<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Binding & Comparable {
+public func ~=<V : Value>(lhs: ClosedRange<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
     return Expression("\(rhs.template) BETWEEN ? AND ?", rhs.bindings + [lhs.lowerBound as? Binding, lhs.upperBound as? Binding])
 }
-public func ~=<V : Value>(lhs: ClosedRange<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Binding & Comparable {
+public func ~=<V : Value>(lhs: ClosedRange<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
     return Expression("\(rhs.template) BETWEEN ? AND ?", rhs.bindings + [lhs.lowerBound as? Binding, lhs.upperBound as? Binding])
 }
 

From f898813ccf9f4966e6889ae74bb4a67104df7d69 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 14 Sep 2017 20:55:01 +0200
Subject: [PATCH 228/685] replace custom validator w/ new test_specs

---
 SQLite.swift.podspec                      |  23 ++++-
 Tests/CocoaPods/Gemfile                   |   2 +-
 Tests/CocoaPods/Gemfile.lock              |  41 ++++----
 Tests/CocoaPods/integration_test.rb       |  18 ++--
 Tests/CocoaPods/test_running_validator.rb | 120 ----------------------
 Tests/SQLiteTests/Fixtures.swift          |   2 +-
 6 files changed, 49 insertions(+), 157 deletions(-)
 delete mode 100644 Tests/CocoaPods/test_running_validator.rb

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 808e8a46..9ffb885f 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.11.3"
+  s.version          = "0.11.4"
   s.summary          = "A type-safe, Swift-language layer over SQLite3 for iOS and OS X."
 
   s.description      = <<-DESC
@@ -21,26 +21,35 @@ Pod::Spec.new do |s|
   s.watchos.deployment_target = "2.2"
   s.default_subspec  = 'standard'
   s.pod_target_xcconfig = {
-    'SWIFT_VERSION' => '3.0',
+    'SWIFT_VERSION' => '4.0',
   }
 
   s.subspec 'standard' do |ss|
     ss.source_files = 'Sources/{SQLite,SQLiteObjc}/**/*.{c,h,m,swift}'
     ss.exclude_files = 'Sources/**/Cipher.swift'
     ss.private_header_files = 'Sources/SQLiteObjc/*.h'
-
     ss.library = 'sqlite3'
+
+    ss.test_spec 'tests' do |test_spec|
+      test_spec.resources = 'Tests/SQLiteTests/fixtures/*'
+      test_spec.source_files = 'Tests/SQLiteTests/*.swift'
+    end
   end
 
   s.subspec 'standalone' do |ss|
     ss.source_files = 'Sources/{SQLite,SQLiteObjc}/**/*.{c,h,m,swift}'
     ss.exclude_files = 'Sources/**/Cipher.swift'
     ss.private_header_files = 'Sources/SQLiteObjc/*.h'
+
     ss.xcconfig = {
       'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_SWIFT_STANDALONE'
     }
+    ss.dependency 'sqlite3'
 
-    ss.dependency 'sqlite3', '>= 3.14.0'
+    ss.test_spec 'tests' do |test_spec|
+      test_spec.resources = 'Tests/SQLiteTests/fixtures/*'
+      test_spec.source_files = 'Tests/SQLiteTests/*.swift'
+    end
   end
 
   s.subspec 'SQLCipher' do |ss|
@@ -50,7 +59,11 @@ Pod::Spec.new do |s|
       'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_SWIFT_SQLCIPHER',
       'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SQLITE_HAS_CODEC=1'
     }
-
     ss.dependency 'SQLCipher', '>= 3.4.0'
+
+    ss.test_spec 'tests' do |test_spec|
+      test_spec.resources = 'Tests/SQLiteTests/fixtures/*'
+      test_spec.source_files = 'Tests/SQLiteTests/*.swift'
+    end
   end
 end
diff --git a/Tests/CocoaPods/Gemfile b/Tests/CocoaPods/Gemfile
index e40770e8..04f0155a 100644
--- a/Tests/CocoaPods/Gemfile
+++ b/Tests/CocoaPods/Gemfile
@@ -1,4 +1,4 @@
 source 'https://rubygems.org'
 
-gem 'cocoapods', '~> 1.2.0'
+gem 'cocoapods', '~> 1.3.1'
 gem 'minitest'
diff --git a/Tests/CocoaPods/Gemfile.lock b/Tests/CocoaPods/Gemfile.lock
index 869ae3dc..47a2db58 100644
--- a/Tests/CocoaPods/Gemfile.lock
+++ b/Tests/CocoaPods/Gemfile.lock
@@ -2,33 +2,33 @@ GEM
   remote: https://rubygems.org/
   specs:
     CFPropertyList (2.3.5)
-    activesupport (4.2.8)
+    activesupport (4.2.9)
       i18n (~> 0.7)
       minitest (~> 5.1)
       thread_safe (~> 0.3, >= 0.3.4)
       tzinfo (~> 1.1)
-    claide (1.0.1)
-    cocoapods (1.2.0)
+    claide (1.0.2)
+    cocoapods (1.3.1)
       activesupport (>= 4.0.2, < 5)
-      claide (>= 1.0.1, < 2.0)
-      cocoapods-core (= 1.2.0)
+      claide (>= 1.0.2, < 2.0)
+      cocoapods-core (= 1.3.1)
       cocoapods-deintegrate (>= 1.0.1, < 2.0)
       cocoapods-downloader (>= 1.1.3, < 2.0)
       cocoapods-plugins (>= 1.0.0, < 2.0)
       cocoapods-search (>= 1.0.0, < 2.0)
       cocoapods-stats (>= 1.0.0, < 2.0)
-      cocoapods-trunk (>= 1.1.2, < 2.0)
+      cocoapods-trunk (>= 1.2.0, < 2.0)
       cocoapods-try (>= 1.1.0, < 2.0)
-      colored (~> 1.2)
+      colored2 (~> 3.1)
       escape (~> 0.0.4)
       fourflusher (~> 2.0.1)
       gh_inspector (~> 1.0)
-      molinillo (~> 0.5.5)
+      molinillo (~> 0.5.7)
       nap (~> 1.0)
-      ruby-macho (~> 0.2.5)
-      xcodeproj (>= 1.4.1, < 2.0)
-    cocoapods-core (1.2.0)
-      activesupport (>= 4.0.2, < 5)
+      ruby-macho (~> 1.1)
+      xcodeproj (>= 1.5.1, < 2.0)
+    cocoapods-core (1.3.1)
+      activesupport (>= 4.0.2, < 6)
       fuzzy_match (~> 2.0.4)
       nap (~> 1.0)
     cocoapods-deintegrate (1.0.1)
@@ -37,37 +37,36 @@ GEM
       nap
     cocoapods-search (1.0.0)
     cocoapods-stats (1.0.0)
-    cocoapods-trunk (1.1.2)
+    cocoapods-trunk (1.2.0)
       nap (>= 0.8, < 2.0)
       netrc (= 0.7.8)
     cocoapods-try (1.1.0)
-    colored (1.2)
+    colored2 (3.1.2)
     escape (0.0.4)
     fourflusher (2.0.1)
     fuzzy_match (2.0.4)
     gh_inspector (1.0.3)
-    i18n (0.8.1)
+    i18n (0.8.6)
     minitest (5.10.1)
     molinillo (0.5.7)
     nanaimo (0.2.3)
     nap (1.1.0)
     netrc (0.7.8)
-    ruby-macho (0.2.6)
+    ruby-macho (1.1.0)
     thread_safe (0.3.6)
     tzinfo (1.2.3)
       thread_safe (~> 0.1)
-    xcodeproj (1.4.2)
+    xcodeproj (1.5.1)
       CFPropertyList (~> 2.3.3)
-      activesupport (>= 3)
-      claide (>= 1.0.1, < 2.0)
-      colored (~> 1.2)
+      claide (>= 1.0.2, < 2.0)
+      colored2 (~> 3.1)
       nanaimo (~> 0.2.3)
 
 PLATFORMS
   ruby
 
 DEPENDENCIES
-  cocoapods (~> 1.2.0)
+  cocoapods (~> 1.3.1)
   minitest
 
 BUNDLED WITH
diff --git a/Tests/CocoaPods/integration_test.rb b/Tests/CocoaPods/integration_test.rb
index 192aff90..9792b570 100755
--- a/Tests/CocoaPods/integration_test.rb
+++ b/Tests/CocoaPods/integration_test.rb
@@ -1,7 +1,8 @@
 #!/usr/bin/env ruby
 
+require 'cocoapods'
+require 'cocoapods/validator'
 require 'minitest/autorun'
-require_relative 'test_running_validator'
 
 class IntegrationTest < Minitest::Test
 
@@ -12,9 +13,7 @@ def test_validate_project
   private
 
   def validator
-    @validator ||= TestRunningValidator.new(podspec, []).tap do |validator|
-        validator.test_files = Dir["#{project_test_dir}/**/*.swift"]
-        validator.test_resources = Dir["#{project_test_dir}/fixtures"]
+    @validator ||= CustomValidator.new(podspec, ['https://github.com/CocoaPods/Specs.git']).tap do |validator|
         validator.config.verbose = true
         validator.no_clean = true
         validator.use_frameworks = true
@@ -27,9 +26,6 @@ def validator
         else
           validator.only_subspec = subspec
         end
-        if ENV['IOS_SIMULATOR']
-          validator.ios_simulator = ENV['IOS_SIMULATOR']
-        end
     end
   end
 
@@ -37,7 +33,11 @@ def podspec
     File.expand_path(File.dirname(__FILE__) + '/../../SQLite.swift.podspec')
   end
 
-  def project_test_dir
-    File.expand_path(File.dirname(__FILE__) + '/../SQLiteTests')
+
+  class CustomValidator < Pod::Validator
+    def test_pod
+      # https://github.com/CocoaPods/CocoaPods/issues/7009
+      super unless consumer.platform_name == :watchos
+    end
   end
 end
diff --git a/Tests/CocoaPods/test_running_validator.rb b/Tests/CocoaPods/test_running_validator.rb
deleted file mode 100644
index fcfd3c28..00000000
--- a/Tests/CocoaPods/test_running_validator.rb
+++ /dev/null
@@ -1,120 +0,0 @@
-require 'cocoapods'
-require 'cocoapods/validator'
-require 'fileutils'
-
-class TestRunningValidator < Pod::Validator
-  APP_TARGET = 'App'
-  TEST_TARGET = 'Tests'
-
-  attr_accessor :test_files
-  attr_accessor :test_resources
-  attr_accessor :ios_simulator
-  attr_accessor :tvos_simulator
-  attr_accessor :watchos_simulator
-
-  def initialize(spec_or_path, source_urls)
-    super(spec_or_path, source_urls)
-    self.test_files = []
-    self.test_resources = []
-    self.ios_simulator = :oldest
-    self.tvos_simulator = :oldest
-    self.watchos_simulator = :oldest
-  end
-
-  def create_app_project
-    super
-    project = Xcodeproj::Project.open(validation_dir + "#{APP_TARGET}.xcodeproj")
-    create_test_target(project)
-    project.save
-  end
-
-  def add_app_project_import
-    super
-    project = Xcodeproj::Project.open(validation_dir + 'App.xcodeproj')
-    group = project.new_group(TEST_TARGET)
-    test_target = project.targets.last
-    test_target.add_resources(test_resources.map { |resource| group.new_file(resource) })
-    test_target.add_file_references(test_files.map { |file| group.new_file(file) })
-    add_swift_version(test_target)
-    project.save
-  end
-
-  def install_pod
-    super
-    if local?
-      FileUtils.ln_s file.dirname, validation_dir + "Pods/#{spec.name}"
-    end
-  end
-
-  def podfile_from_spec(*args)
-    super(*args).tap do |pod_file|
-      add_test_target(pod_file)
-    end
-  end
-
-  def build_pod
-    super
-    Pod::UI.message "\Testing with xcodebuild.\n".yellow do
-      run_tests
-    end
-  end
-
-  private
-  def create_test_target(project)
-    test_target = project.new_target(:unit_test_bundle, TEST_TARGET, consumer.platform_name, deployment_target)
-    create_test_scheme(project, test_target)
-  end
-
-  def create_test_scheme(project, test_target)
-    project.recreate_user_schemes
-    test_scheme = Xcodeproj::XCScheme.new(test_scheme_path(project))
-    test_scheme.add_test_target(test_target)
-    test_scheme.save!
-  end
-
-  def test_scheme_path(project)
-    Xcodeproj::XCScheme.user_data_dir(project.path) + "#{TEST_TARGET}.xcscheme"
-  end
-
-  def add_test_target(pod_file)
-    app_target = pod_file.target_definitions[APP_TARGET]
-    Pod::Podfile::TargetDefinition.new(TEST_TARGET, app_target)
-  end
-
-  def run_tests
-    command = [
-      'clean', 'build', 'build-for-testing', 'test-without-building',
-      '-workspace', File.join(validation_dir, "#{APP_TARGET}.xcworkspace"),
-      '-scheme', TEST_TARGET,
-      '-configuration', 'Debug'
-    ]
-    case consumer.platform_name
-    when :ios
-      command += %w(CODE_SIGN_IDENTITY=- -sdk iphonesimulator)
-      command += Fourflusher::SimControl.new.destination(ios_simulator, 'iOS', deployment_target)
-    when :osx
-      command += %w(LD_RUNPATH_SEARCH_PATHS=@loader_path/../Frameworks)
-    when :tvos
-      command += %w(CODE_SIGN_IDENTITY=- -sdk appletvsimulator)
-      command += Fourflusher::SimControl.new.destination(tvos_simulator, 'tvOS', deployment_target)
-    when :watchos
-      # there's no XCTest on watchOS (https://openradar.appspot.com/21760513)
-      return
-    else
-      return
-    end
-
-    output, status = _xcodebuild(command)
-
-    unless status.success?
-      message = 'Returned an unsuccessful exit code.'
-      if config.verbose?
-        message += "\nXcode output: \n#{output}\n"
-      else
-        message += ' You can use `--verbose` for more information.'
-      end
-      error('xcodebuild', message)
-    end
-    output
-  end
-end
diff --git a/Tests/SQLiteTests/Fixtures.swift b/Tests/SQLiteTests/Fixtures.swift
index 13f83f77..d0683130 100644
--- a/Tests/SQLiteTests/Fixtures.swift
+++ b/Tests/SQLiteTests/Fixtures.swift
@@ -3,6 +3,6 @@ import Foundation
 func fixture(_ name: String, withExtension: String?) -> String {
     let testBundle = Bundle(for: SQLiteTestCase.self)
     return testBundle.url(
-        forResource: URL(string: "fixtures")?.appendingPathComponent(name).path,
+        forResource: name,
         withExtension: withExtension)!.path
 }

From c7656a6d90caffb92717da735182daa51dabfabd Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 15 Sep 2017 17:59:39 +0200
Subject: [PATCH 229/685] Lower deployment target

#624, #671, #717
---
 SQLite.swift.podspec             | 2 +-
 SQLite.xcodeproj/project.pbxproj | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 9ffb885f..4a329338 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -15,7 +15,7 @@ Pod::Spec.new do |s|
   s.social_media_url = 'https://twitter.com/stephencelis'
 
   s.module_name      = 'SQLite'
-  s.ios.deployment_target = "9.0"
+  s.ios.deployment_target = "8.0"
   s.tvos.deployment_target = "9.1"
   s.osx.deployment_target = "10.10"
   s.watchos.deployment_target = "2.2"
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 8e3162d9..fc92eeff 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1220,7 +1220,7 @@
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
-				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
@@ -1247,7 +1247,7 @@
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
-				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;

From ac52569861e6ced88f168be1fca2e20bcd1118cd Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 16 Sep 2017 09:58:25 +0200
Subject: [PATCH 230/685] fix create/drop index functions

---
 Sources/SQLite/Typed/Schema.swift   | 11 ++---------
 Tests/SQLiteTests/SchemaTests.swift | 10 +++++-----
 2 files changed, 7 insertions(+), 14 deletions(-)

diff --git a/Sources/SQLite/Typed/Schema.swift b/Sources/SQLite/Typed/Schema.swift
index 7bf70fe4..690a26a5 100644
--- a/Sources/SQLite/Typed/Schema.swift
+++ b/Sources/SQLite/Typed/Schema.swift
@@ -127,11 +127,7 @@ extension Table {
 
     // MARK: - CREATE INDEX
 
-    public func createIndex(_ columns: Expressible...) -> String {
-        return createIndex(columns)
-    }
-
-    public func createIndex(_ columns: [Expressible], unique: Bool = false, ifNotExists: Bool = false) -> String {
+    public func createIndex(_ columns: Expressible..., unique: Bool = false, ifNotExists: Bool = false) -> String {
         let clauses: [Expressible?] = [
             create("INDEX", indexName(columns), unique ? .unique : nil, ifNotExists),
             Expression<Void>(literal: "ON"),
@@ -144,11 +140,8 @@ extension Table {
 
     // MARK: - DROP INDEX
 
-    public func dropIndex(_ columns: Expressible...) -> String {
-        return dropIndex(columns)
-    }
 
-    public func dropIndex(_ columns: [Expressible], ifExists: Bool = false) -> String {
+    public func dropIndex(_ columns: Expressible..., ifExists: Bool = false) -> String {
         return drop("INDEX", indexName(columns), ifExists)
     }
 
diff --git a/Tests/SQLiteTests/SchemaTests.swift b/Tests/SQLiteTests/SchemaTests.swift
index e59b569b..34226b3c 100644
--- a/Tests/SQLiteTests/SchemaTests.swift
+++ b/Tests/SQLiteTests/SchemaTests.swift
@@ -727,25 +727,25 @@ class SchemaTests : XCTestCase {
 
         XCTAssertEqual(
             "CREATE UNIQUE INDEX \"index_table_on_int64\" ON \"table\" (\"int64\")",
-            table.createIndex([int64], unique: true)
+            table.createIndex(int64, unique: true)
         )
         XCTAssertEqual(
             "CREATE INDEX IF NOT EXISTS \"index_table_on_int64\" ON \"table\" (\"int64\")",
-            table.createIndex([int64], ifNotExists: true)
+            table.createIndex(int64, ifNotExists: true)
         )
         XCTAssertEqual(
             "CREATE UNIQUE INDEX IF NOT EXISTS \"index_table_on_int64\" ON \"table\" (\"int64\")",
-            table.createIndex([int64], unique: true, ifNotExists: true)
+            table.createIndex(int64, unique: true, ifNotExists: true)
         )
         XCTAssertEqual(
             "CREATE UNIQUE INDEX IF NOT EXISTS \"main\".\"index_table_on_int64\" ON \"table\" (\"int64\")",
-            qualifiedTable.createIndex([int64], unique: true, ifNotExists: true)
+            qualifiedTable.createIndex(int64, unique: true, ifNotExists: true)
         )
     }
 
     func test_dropIndex_compilesCreateIndexExpression() {
         XCTAssertEqual("DROP INDEX \"index_table_on_int64\"", table.dropIndex(int64))
-        XCTAssertEqual("DROP INDEX IF EXISTS \"index_table_on_int64\"", table.dropIndex([int64], ifExists: true))
+        XCTAssertEqual("DROP INDEX IF EXISTS \"index_table_on_int64\"", table.dropIndex(int64, ifExists: true))
     }
 
     func test_create_onView_compilesCreateViewExpression() {

From 0bb468359a9e8e709741c85ca4daa85067a7a6a6 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 16 Sep 2017 09:59:44 +0200
Subject: [PATCH 231/685] Changelog

---
 CHANGELOG.md | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d6387a56..495034a5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,12 @@
+0.11.4 (xx-09-2017), [diff][diff-0.11.4]
+========================================
+
+* Fix create/drop index functions ([#666][])
+* Set deployment target to 8.0 (#624, #671, #717)
+* Added support for the union query clause ([#723][])
+* Add support for ORDER and LIMIT on UPDATE and DELETE ([#722][])
+* Swift 4 support [(#668][])
+
 0.11.3 (30-03-2017), [diff][diff-0.11.3]
 ========================================
 
@@ -33,6 +42,7 @@
 [diff-0.11.1]: https://github.com/stephencelis/SQLite.swift/compare/0.11.0...0.11.1
 [diff-0.11.2]: https://github.com/stephencelis/SQLite.swift/compare/0.11.1...0.11.2
 [diff-0.11.3]: https://github.com/stephencelis/SQLite.swift/compare/0.11.2...0.11.3
+[diff-0.11.4]: https://github.com/stephencelis/SQLite.swift/compare/0.11.3...0.11.4
 
 [#481]: https://github.com/stephencelis/SQLit1e.swift/pull/481
 [#532]: https://github.com/stephencelis/SQLit1e.swift/issues/532
@@ -45,3 +55,7 @@
 [#561]: https://github.com/stephencelis/SQLite.swift/issues/561
 [#571]: https://github.com/stephencelis/SQLite.swift/issues/571
 [#615]: https://github.com/stephencelis/SQLite.swift/pull/615
+[#666]: https://github.com/stephencelis/SQLite.swift/pull/666
+[#668]: https://github.com/stephencelis/SQLite.swift/pull/668
+[#722]: https://github.com/stephencelis/SQLite.swift/pull/722
+[#723]: https://github.com/stephencelis/SQLite.swift/pull/723

From 3708a962dadcd46dfc9d47f44c826029d4c0c4c1 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 16 Sep 2017 12:01:01 +0200
Subject: [PATCH 232/685] Bump version number

---
 Documentation/Index.md    | 10 +++++-----
 README.md                 |  8 ++++----
 Sources/SQLite/Info.plist |  2 +-
 3 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 491a5938..2255373c 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -78,7 +78,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```
-    github "stephencelis/SQLite.swift" ~> 0.11.3
+    github "stephencelis/SQLite.swift" ~> 0.11.4
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -113,7 +113,7 @@ install SQLite.swift with Carthage:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.11.3'
+        pod 'SQLite.swift', '~> 0.11.4'
     end
     ```
 
@@ -126,7 +126,7 @@ install SQLite.swift with Carthage:
 
 ``` ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.11.3'
+  pod 'SQLite.swift/standalone', '~> 0.11.4'
 end
 ```
 
@@ -134,7 +134,7 @@ By default this will use the most recent version of SQLite without any extras. I
 
 ``` ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.11.3'
+  pod 'SQLite.swift/standalone', '~> 0.11.4'
   pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
 end
 ```
@@ -148,7 +148,7 @@ subspec in your Podfile:
 
 ``` ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/SQLCipher', '~> 0.11.3'
+  pod 'SQLite.swift/SQLCipher', '~> 0.11.4'
 end
 ```
 
diff --git a/README.md b/README.md
index 8c3affd9..420da81d 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # SQLite.swift
 
-[![Build Status][Badge]][Travis] [![CocoaPods Version](https://cocoapod-badges.herokuapp.com/v/SQLite.swift/badge.png)](http://cocoadocs.org/docsets/SQLite.swift) [![Swift](https://img.shields.io/badge/swift-3-orange.svg?style=flat)](https://developer.apple.com/swift/) [![Platform](https://cocoapod-badges.herokuapp.com/p/SQLite.swift/badge.png)](http://cocoadocs.org/docsets/SQLite.swift) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![Join the chat at https://gitter.im/stephencelis/SQLite.swift](https://badges.gitter.im/stephencelis/SQLite.swift.svg)](https://gitter.im/stephencelis/SQLite.swift)
+[![Build Status][Badge]][Travis] [![CocoaPods Version](https://cocoapod-badges.herokuapp.com/v/SQLite.swift/badge.png)](http://cocoadocs.org/docsets/SQLite.swift) [![Swift](https://img.shields.io/badge/swift-4-orange.svg?style=flat)](https://developer.apple.com/swift/) [![Platform](https://cocoapod-badges.herokuapp.com/p/SQLite.swift/badge.png)](http://cocoadocs.org/docsets/SQLite.swift) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![Join the chat at https://gitter.im/stephencelis/SQLite.swift](https://badges.gitter.im/stephencelis/SQLite.swift.svg)](https://gitter.im/stephencelis/SQLite.swift)
 
 A type-safe, [Swift][]-language layer over [SQLite3][].
 
@@ -109,7 +109,7 @@ For a more comprehensive example, see [this article](http://masteringswift.blogs
 
 ## Installation
 
-> _Note:_ SQLite.swift requires Swift 3 (and [Xcode][] 8). Use the [swift-4][] branch for Xcode 9 Beta.
+> _Note:_ SQLite.swift requires Swift 4 (and [Xcode][] 9).
 
 ### Carthage
 
@@ -121,7 +121,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```
-    github "stephencelis/SQLite.swift" ~> 0.11.3
+    github "stephencelis/SQLite.swift" ~> 0.11.4
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -157,7 +157,7 @@ SQLite.swift with CocoaPods:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.11.3'
+        pod 'SQLite.swift', '~> 0.11.4'
     end
     ```
 
diff --git a/Sources/SQLite/Info.plist b/Sources/SQLite/Info.plist
index 8c55becd..7347d842 100644
--- a/Sources/SQLite/Info.plist
+++ b/Sources/SQLite/Info.plist
@@ -15,7 +15,7 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>0.11.3</string>
+	<string>0.11.4</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>

From 70c06c6624599a9bb78197e100d03a62cafd46cb Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 16 Sep 2017 12:08:31 +0200
Subject: [PATCH 233/685] Fix link

---
 CHANGELOG.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 495034a5..2473b6ba 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,7 +5,7 @@
 * Set deployment target to 8.0 (#624, #671, #717)
 * Added support for the union query clause ([#723][])
 * Add support for ORDER and LIMIT on UPDATE and DELETE ([#722][])
-* Swift 4 support [(#668][])
+* Swift 4 support ([#668][])
 
 0.11.3 (30-03-2017), [diff][diff-0.11.3]
 ========================================

From 9d42763509956cea05959f7b16c96bf4428a5202 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 16 Sep 2017 18:16:26 +0200
Subject: [PATCH 234/685] Add ticket

---
 CHANGELOG.md | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2473b6ba..b70b1403 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,7 +4,7 @@
 * Fix create/drop index functions ([#666][])
 * Set deployment target to 8.0 (#624, #671, #717)
 * Added support for the union query clause ([#723][])
-* Add support for ORDER and LIMIT on UPDATE and DELETE ([#722][])
+* Add support for ORDER and LIMIT on UPDATE and DELETE ([#657][], [#722][])
 * Swift 4 support ([#668][])
 
 0.11.3 (30-03-2017), [diff][diff-0.11.3]
@@ -55,6 +55,7 @@
 [#561]: https://github.com/stephencelis/SQLite.swift/issues/561
 [#571]: https://github.com/stephencelis/SQLite.swift/issues/571
 [#615]: https://github.com/stephencelis/SQLite.swift/pull/615
+[#657]: https://github.com/stephencelis/SQLite.swift/issues/657
 [#666]: https://github.com/stephencelis/SQLite.swift/pull/666
 [#668]: https://github.com/stephencelis/SQLite.swift/pull/668
 [#722]: https://github.com/stephencelis/SQLite.swift/pull/722

From b8d6a9cf9495358dd917d5270a1efef345ea0796 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 16 Sep 2017 19:42:31 +0200
Subject: [PATCH 235/685] Generics work as expected now

---
 Sources/SQLite/Foundation.swift    | 38 --------------
 Sources/SQLite/Typed/Query.swift   | 81 ++----------------------------
 Tests/SQLiteTests/QueryTests.swift | 16 ++++++
 3 files changed, 20 insertions(+), 115 deletions(-)

diff --git a/Sources/SQLite/Foundation.swift b/Sources/SQLite/Foundation.swift
index 5e102297..5638bc5b 100644
--- a/Sources/SQLite/Foundation.swift
+++ b/Sources/SQLite/Foundation.swift
@@ -68,41 +68,3 @@ public var dateFormatter: DateFormatter = {
     formatter.timeZone = TimeZone(secondsFromGMT: 0)
     return formatter
 }()
-
-// FIXME: rdar://problem/18673897 // subscript<T>…
-
-extension QueryType {
-
-    public subscript(column: Expression<Data>) -> Expression<Data> {
-        return namespace(column)
-    }
-    public subscript(column: Expression<Data?>) -> Expression<Data?> {
-        return namespace(column)
-    }
-
-    public subscript(column: Expression<Date>) -> Expression<Date> {
-        return namespace(column)
-    }
-    public subscript(column: Expression<Date?>) -> Expression<Date?> {
-        return namespace(column)
-    }
-
-}
-
-extension Row {
-
-    public subscript(column: Expression<Data>) -> Data {
-        return get(column)
-    }
-    public subscript(column: Expression<Data?>) -> Data? {
-        return get(column)
-    }
-
-    public subscript(column: Expression<Date>) -> Date {
-        return get(column)
-    }
-    public subscript(column: Expression<Date?>) -> Date? {
-        return get(column)
-    }
-
-}
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index 79fdbc66..7c0a055f 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -726,47 +726,11 @@ extension QueryType {
         return Expression(".".join([tableName(), column]).expression)
     }
 
-    // FIXME: rdar://problem/18673897 // subscript<T>…
-
-    public subscript(column: Expression<Blob>) -> Expression<Blob> {
-        return namespace(column)
-    }
-    public subscript(column: Expression<Blob?>) -> Expression<Blob?> {
-        return namespace(column)
-    }
-
-    public subscript(column: Expression<Bool>) -> Expression<Bool> {
-        return namespace(column)
-    }
-    public subscript(column: Expression<Bool?>) -> Expression<Bool?> {
-        return namespace(column)
-    }
-
-    public subscript(column: Expression<Double>) -> Expression<Double> {
-        return namespace(column)
-    }
-    public subscript(column: Expression<Double?>) -> Expression<Double?> {
+    public subscript<T>(column: Expression<T>) -> Expression<T> {
         return namespace(column)
     }
 
-    public subscript(column: Expression<Int>) -> Expression<Int> {
-        return namespace(column)
-    }
-    public subscript(column: Expression<Int?>) -> Expression<Int?> {
-        return namespace(column)
-    }
-
-    public subscript(column: Expression<Int64>) -> Expression<Int64> {
-        return namespace(column)
-    }
-    public subscript(column: Expression<Int64?>) -> Expression<Int64?> {
-        return namespace(column)
-    }
-
-    public subscript(column: Expression<String>) -> Expression<String> {
-        return namespace(column)
-    }
-    public subscript(column: Expression<String?>) -> Expression<String?> {
+    public subscript<T>(column: Expression<T?>) -> Expression<T?> {
         return namespace(column)
     }
 
@@ -1102,50 +1066,13 @@ public struct Row {
         return valueAtIndex(idx)
     }
 
-    // FIXME: rdar://problem/18673897 // subscript<T>…
-
-    public subscript(column: Expression<Blob>) -> Blob {
-        return get(column)
-    }
-    public subscript(column: Expression<Blob?>) -> Blob? {
-        return get(column)
-    }
-
-    public subscript(column: Expression<Bool>) -> Bool {
-        return get(column)
-    }
-    public subscript(column: Expression<Bool?>) -> Bool? {
+    public subscript<T : Value>(column: Expression<T>) -> T {
         return get(column)
     }
 
-    public subscript(column: Expression<Double>) -> Double {
+    public subscript<T : Value>(column: Expression<T?>) -> T? {
         return get(column)
     }
-    public subscript(column: Expression<Double?>) -> Double? {
-        return get(column)
-    }
-
-    public subscript(column: Expression<Int>) -> Int {
-        return get(column)
-    }
-    public subscript(column: Expression<Int?>) -> Int? {
-        return get(column)
-    }
-
-    public subscript(column: Expression<Int64>) -> Int64 {
-        return get(column)
-    }
-    public subscript(column: Expression<Int64?>) -> Int64? {
-        return get(column)
-    }
-
-    public subscript(column: Expression<String>) -> String {
-        return get(column)
-    }
-    public subscript(column: Expression<String?>) -> String? {
-        return get(column)
-    }
-
 }
 
 /// Determines the join operator for a query’s `JOIN` clause.
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index 6bb109bb..813173ad 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -348,6 +348,22 @@ class QueryIntegrationTests : SQLiteTestCase {
         }
     }
 
+    func test_select_optional() {
+        for _ in try! db.prepare(users) {
+            // FIXME
+        }
+
+        let managerId = Expression<Int64?>("manager_id")
+        let managers = users.alias("managers")
+
+        let alice = try! db.run(users.insert(email <- "alice@example.com"))
+        _ = try! db.run(users.insert(email <- "betsy@example.com", managerId <- alice))
+
+        for user in try! db.prepare(users.join(managers, on: managers[id] == users[managerId])) {
+            _ = user[users[managerId]]
+        }
+    }
+
     func test_scalar() {
         XCTAssertEqual(0, try! db.scalar(users.count))
         XCTAssertEqual(false, try! db.scalar(users.exists))

From bd1fc80414c89b8d7b756899cff2a153d5fd04f1 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 16 Sep 2017 20:43:28 +0200
Subject: [PATCH 236/685] Row.get should throw, not crash

#649, #413
---
 SQLite.xcodeproj/project.pbxproj   | 10 ++++++++++
 Sources/SQLite/Core/Errors.swift   | 18 ++++++++++++++++++
 Sources/SQLite/Typed/Query.swift   | 19 ++++++++++---------
 Tests/SQLiteTests/QueryTests.swift | 14 ++++++++++++++
 4 files changed, 52 insertions(+), 9 deletions(-)
 create mode 100644 Sources/SQLite/Core/Errors.swift

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index fc92eeff..e246e76d 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -51,22 +51,26 @@
 		19A171F12AB8B07F2FD7201A /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
 		19A17254FBA7894891F7297B /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
 		19A17408007B182F884E3A53 /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; };
+		19A17490543609FCED53CACC /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
 		19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
 		19A1750CEE9B05267995CF3D /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
 		19A175DFF47B84757E547C62 /* fixtures in Resources */ = {isa = PBXBuildFile; fileRef = 19A17E2695737FAB5D6086E3 /* fixtures */; };
 		19A177CC33F2E6A24AF90B02 /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
 		19A178072B371489E6A1E839 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
 		19A17835FD5886FDC5A3228F /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
+		19A1792C0520D4E83C2EB075 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
 		19A179A0C45377CB09BB358C /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
 		19A179CCF9671E345E5A9811 /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
 		19A179E76EA6207669B60C1B /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
 		19A17C4B951CB054EE48AB1C /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
+		19A17DC282E36C4F41AA440B /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
 		19A17E04C4C0956715C5676A /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
 		19A17EC0D68BA8C03288ADF7 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
 		19A17F3E1F7ACA33BD43E138 /* fixtures in Resources */ = {isa = PBXBuildFile; fileRef = 19A17E2695737FAB5D6086E3 /* fixtures */; };
 		19A17F60B685636D1F83C2DD /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; };
 		19A17FB80B94E882050AA908 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
 		19A17FDA323BAFDEC627E76F /* fixtures in Resources */ = {isa = PBXBuildFile; fileRef = 19A17E2695737FAB5D6086E3 /* fixtures */; };
+		19A17FF4A10B44D3937C8CAC /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
 		3D67B3E61DB2469200A4F4C6 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */; };
 		3D67B3E71DB246BA00A4F4C6 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
 		3D67B3E81DB246BA00A4F4C6 /* Connection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEF1C3F06E900AE3E12 /* Connection.swift */; };
@@ -196,6 +200,7 @@
 		03A65E5A1C6BB0F50062603F /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		03A65E631C6BB0F60062603F /* SQLiteTests tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SQLiteTests tvOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
 		03A65E961C6BB3210062603F /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
+		19A1710E73A46D5AC721CDA9 /* Errors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = "<group>"; };
 		19A1721B8984686B9963B45D /* FTS5Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5Tests.swift; sourceTree = "<group>"; };
 		19A1730E4390C775C25677D1 /* FTS5.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5.swift; sourceTree = "<group>"; };
 		19A17399EA9E61235D5D77BF /* CipherTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CipherTests.swift; sourceTree = "<group>"; };
@@ -408,6 +413,7 @@
 				EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */,
 				EE247AF21C3F06E900AE3E12 /* Statement.swift */,
 				EE247AF31C3F06E900AE3E12 /* Value.swift */,
+				19A1710E73A46D5AC721CDA9 /* Errors.swift */,
 			);
 			path = Core;
 			sourceTree = "<group>";
@@ -787,6 +793,7 @@
 				03A65E7E1C6BB2FB0062603F /* AggregateFunctions.swift in Sources */,
 				19A17EC0D68BA8C03288ADF7 /* FTS5.swift in Sources */,
 				19A179E76EA6207669B60C1B /* Cipher.swift in Sources */,
+				19A17FF4A10B44D3937C8CAC /* Errors.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -840,6 +847,7 @@
 				3D67B3E71DB246BA00A4F4C6 /* Blob.swift in Sources */,
 				3D67B3E81DB246BA00A4F4C6 /* Connection.swift in Sources */,
 				19A179CCF9671E345E5A9811 /* Cipher.swift in Sources */,
+				19A17DC282E36C4F41AA440B /* Errors.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -867,6 +875,7 @@
 				EE247B0D1C3F06E900AE3E12 /* AggregateFunctions.swift in Sources */,
 				19A1717B10CC941ACB5533D6 /* FTS5.swift in Sources */,
 				19A171F12AB8B07F2FD7201A /* Cipher.swift in Sources */,
+				19A1792C0520D4E83C2EB075 /* Errors.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -920,6 +929,7 @@
 				EE247B6D1C3F3FEC00AE3E12 /* AggregateFunctions.swift in Sources */,
 				19A1750CEE9B05267995CF3D /* FTS5.swift in Sources */,
 				19A17835FD5886FDC5A3228F /* Cipher.swift in Sources */,
+				19A17490543609FCED53CACC /* Errors.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/Sources/SQLite/Core/Errors.swift b/Sources/SQLite/Core/Errors.swift
new file mode 100644
index 00000000..e069f50e
--- /dev/null
+++ b/Sources/SQLite/Core/Errors.swift
@@ -0,0 +1,18 @@
+import Foundation
+
+public enum QueryError: Error, CustomStringConvertible {
+    case noSuchTable(name: String)
+    case noSuchColumn(name: String, columns: [String])
+    case ambiguousColumn(name: String, similar: [String])
+
+    public var description: String {
+        switch self {
+        case .noSuchTable(let name):
+            return "No such table: \(name)"
+        case .noSuchColumn(let name, let columns):
+            return "No such column `\(name)` in columns \(columns)"
+        case .ambiguousColumn(let name, let similar):
+            return "Ambiguous column `\(name)` (please disambiguate: \(similar))"
+        }
+    }
+}
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index 7c0a055f..7bcda40b 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -929,7 +929,7 @@ extension Connection {
                                 continue column
                             }
                         }
-                        fatalError("no such table: \(namespace)")
+                        throw QueryError.noSuchTable(name: namespace)
                     }
                     for q in queries {
                         try expandGlob(query.clauses.join.count > 0)(q)
@@ -1041,13 +1041,14 @@ public struct Row {
     /// - Parameter column: An expression representing a column selected in a Query.
     ///
     /// - Returns: The value for the given column.
-    public func get<V: Value>(_ column: Expression<V>) -> V {
-        return get(Expression<V?>(column))!
+    public func get<V: Value>(_ column: Expression<V>) throws -> V {
+        return try get(Expression<V?>(column))!
     }
-    public func get<V: Value>(_ column: Expression<V?>) -> V? {
+
+    public func get<V: Value>(_ column: Expression<V?>) throws -> V? {
         func valueAtIndex(_ idx: Int) -> V? {
             guard let value = values[idx] as? V.Datatype else { return nil }
-            return (V.fromDatatypeValue(value) as? V)!
+            return V.fromDatatypeValue(value) as? V
         }
 
         guard let idx = columnNames[column.template] else {
@@ -1055,11 +1056,11 @@ public struct Row {
 
             switch similar.count {
             case 0:
-                fatalError("no such column '\(column.template)' in columns: \(columnNames.keys.sorted())")
+                throw QueryError.noSuchColumn(name: column.template, columns: columnNames.keys.sorted())
             case 1:
                 return valueAtIndex(columnNames[similar[0]]!)
             default:
-                fatalError("ambiguous column '\(column.template)' (please disambiguate: \(similar))")
+                throw QueryError.ambiguousColumn(name: column.template, similar: similar)
             }
         }
 
@@ -1067,11 +1068,11 @@ public struct Row {
     }
 
     public subscript<T : Value>(column: Expression<T>) -> T {
-        return get(column)
+        return try! get(column)
     }
 
     public subscript<T : Value>(column: Expression<T?>) -> T? {
-        return get(column)
+        return try! get(column)
     }
 }
 
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index 813173ad..3ab0419a 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -412,4 +412,18 @@ class QueryIntegrationTests : SQLiteTestCase {
         let orderedIDs = try db.prepare(query3.union(query4).order(Expression<Int>(literal: "weight"), email)).map { $0[id] }
         XCTAssertEqual(Array(expectedIDs.reversed()), orderedIDs)
     }
+
+    func test_no_such_column() throws {
+        let doesNotExist = Expression<String>("doesNotExist")
+        try! InsertUser("alice")
+        let row = try! db.pluck(users.filter(email == "alice@example.com"))!
+
+        XCTAssertThrowsError(try row.get(doesNotExist)) { error in
+            if case QueryError.noSuchColumn(let name, _) = error {
+                XCTAssertEqual("\"doesNotExist\"", name)
+            } else {
+                XCTFail("unexpected error: \(error)")
+            }
+        }
+    }
 }

From b286edee9b1244094b130d39e8b634b70d966b08 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 16 Sep 2017 20:50:19 +0200
Subject: [PATCH 237/685] changelog

---
 CHANGELOG.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b70b1403..e59e221c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
 0.11.4 (xx-09-2017), [diff][diff-0.11.4]
 ========================================
 
+* Make Row.get throw instead of crash ([#649][])
 * Fix create/drop index functions ([#666][])
 * Set deployment target to 8.0 (#624, #671, #717)
 * Added support for the union query clause ([#723][])
@@ -55,6 +56,7 @@
 [#561]: https://github.com/stephencelis/SQLite.swift/issues/561
 [#571]: https://github.com/stephencelis/SQLite.swift/issues/571
 [#615]: https://github.com/stephencelis/SQLite.swift/pull/615
+[#649]: https://github.com/stephencelis/SQLite.swift/pull/649
 [#657]: https://github.com/stephencelis/SQLite.swift/issues/657
 [#666]: https://github.com/stephencelis/SQLite.swift/pull/666
 [#668]: https://github.com/stephencelis/SQLite.swift/pull/668

From 5d1c7936ba63d68e5aeb3560590d124a6911ee7d Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 16 Sep 2017 21:09:11 +0200
Subject: [PATCH 238/685] No longer applies

---
 Documentation/Index.md | 12 +++---------
 README.md              | 12 +++---------
 2 files changed, 6 insertions(+), 18 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 2255373c..7d13b5a7 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -93,13 +93,7 @@ install SQLite.swift with Carthage:
 
 [CocoaPods][] is a dependency manager for Cocoa projects. To install SQLite.swift with CocoaPods:
 
- 1. Verify that your copy of Xcode is installed and active in the default location (`/Applications/Xcode.app`).
-
-    ```sh
-    sudo xcode-select --switch /Applications/Xcode.app
-    ```
-
- 2. Make sure CocoaPods is [installed][CocoaPods Installation] (SQLite.swift requires version 1.0.0 or greater).
+ 1. Make sure CocoaPods is [installed][CocoaPods Installation] (SQLite.swift requires version 1.0.0 or greater).
 
     ``` sh
     # Using the default Ruby install will require you to use sudo when
@@ -107,7 +101,7 @@ install SQLite.swift with Carthage:
     [sudo] gem install cocoapods
     ```
 
- 3. Update your Podfile to include the following:
+ 2. Update your Podfile to include the following:
 
     ``` ruby
     use_frameworks!
@@ -117,7 +111,7 @@ install SQLite.swift with Carthage:
     end
     ```
 
- 4. Run `pod install --repo-update`.
+ 3. Run `pod install --repo-update`.
 
 
 #### Requiring a specific version of SQLite
diff --git a/README.md b/README.md
index 420da81d..fe06c6f7 100644
--- a/README.md
+++ b/README.md
@@ -137,13 +137,7 @@ install SQLite.swift with Carthage:
 [CocoaPods][] is a dependency manager for Cocoa projects. To install
 SQLite.swift with CocoaPods:
 
- 1. Verify that your copy of Xcode is installed and active in the default location (`/Applications/Xcode.app`).
-
-    ```sh
-    sudo xcode-select --switch /Applications/Xcode.app
-    ```
-
- 2. Make sure CocoaPods is [installed][CocoaPods Installation]. (SQLite.swift requires version 1.0.0 or greater.)
+ 1. Make sure CocoaPods is [installed][CocoaPods Installation]. (SQLite.swift requires version 1.0.0 or greater.)
 
     ``` sh
     # Using the default Ruby install will require you to use sudo when
@@ -151,7 +145,7 @@ SQLite.swift with CocoaPods:
     [sudo] gem install cocoapods
     ```
 
- 3. Update your Podfile to include the following:
+ 2. Update your Podfile to include the following:
 
     ``` ruby
     use_frameworks!
@@ -161,7 +155,7 @@ SQLite.swift with CocoaPods:
     end
     ```
 
- 4. Run `pod install --repo-update`.
+ 3. Run `pod install --repo-update`.
 
 [CocoaPods]: https://cocoapods.org
 [CocoaPods Installation]: https://guides.cocoapods.org/using/getting-started.html#getting-started

From dc1b643b509605e90a37ebf687d3905fd06b026b Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 17 Sep 2017 08:51:08 +0200
Subject: [PATCH 239/685] Handle null value case

---
 SQLite.xcodeproj/project.pbxproj |  8 +++
 Sources/SQLite/Core/Errors.swift |  3 ++
 Sources/SQLite/Typed/Query.swift |  8 ++-
 Tests/SQLiteTests/RowTests.swift | 88 ++++++++++++++++++++++++++++++++
 4 files changed, 105 insertions(+), 2 deletions(-)
 create mode 100644 Tests/SQLiteTests/RowTests.swift

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index e246e76d..c033cf3a 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -47,8 +47,10 @@
 		03A65E971C6BB3210062603F /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 03A65E961C6BB3210062603F /* libsqlite3.tbd */; };
 		19A1709C3E7A406E62293B2A /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; };
 		19A1717B10CC941ACB5533D6 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
+		19A171967CC511C4F6F773C9 /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */; };
 		19A171E6FA242F72A308C594 /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
 		19A171F12AB8B07F2FD7201A /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
+		19A1720B67ED13E6150C6A3D /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */; };
 		19A17254FBA7894891F7297B /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
 		19A17408007B182F884E3A53 /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; };
 		19A17490543609FCED53CACC /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
@@ -58,6 +60,7 @@
 		19A177CC33F2E6A24AF90B02 /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
 		19A178072B371489E6A1E839 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
 		19A17835FD5886FDC5A3228F /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
+		19A1785195182AF8731A8BDA /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */; };
 		19A1792C0520D4E83C2EB075 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
 		19A179A0C45377CB09BB358C /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
 		19A179CCF9671E345E5A9811 /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
@@ -204,6 +207,7 @@
 		19A1721B8984686B9963B45D /* FTS5Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5Tests.swift; sourceTree = "<group>"; };
 		19A1730E4390C775C25677D1 /* FTS5.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5.swift; sourceTree = "<group>"; };
 		19A17399EA9E61235D5D77BF /* CipherTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CipherTests.swift; sourceTree = "<group>"; };
+		19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RowTests.swift; sourceTree = "<group>"; };
 		19A178A39ACA9667A62663CC /* Cipher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cipher.swift; sourceTree = "<group>"; };
 		19A1794CC4D7827E997E32A7 /* FoundationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationTests.swift; sourceTree = "<group>"; };
 		19A17B93B48B5560E6E51791 /* Fixtures.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Fixtures.swift; sourceTree = "<group>"; };
@@ -398,6 +402,7 @@
 				19A1794CC4D7827E997E32A7 /* FoundationTests.swift */,
 				19A17399EA9E61235D5D77BF /* CipherTests.swift */,
 				19A17B93B48B5560E6E51791 /* Fixtures.swift */,
+				19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */,
 			);
 			name = SQLiteTests;
 			path = Tests/SQLiteTests;
@@ -820,6 +825,7 @@
 				19A17E04C4C0956715C5676A /* FoundationTests.swift in Sources */,
 				19A179A0C45377CB09BB358C /* CipherTests.swift in Sources */,
 				19A17F60B685636D1F83C2DD /* Fixtures.swift in Sources */,
+				19A1785195182AF8731A8BDA /* RowTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -902,6 +908,7 @@
 				19A17FB80B94E882050AA908 /* FoundationTests.swift in Sources */,
 				19A177CC33F2E6A24AF90B02 /* CipherTests.swift in Sources */,
 				19A17408007B182F884E3A53 /* Fixtures.swift in Sources */,
+				19A1720B67ED13E6150C6A3D /* RowTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -956,6 +963,7 @@
 				19A178072B371489E6A1E839 /* FoundationTests.swift in Sources */,
 				19A17C4B951CB054EE48AB1C /* CipherTests.swift in Sources */,
 				19A1709C3E7A406E62293B2A /* Fixtures.swift in Sources */,
+				19A171967CC511C4F6F773C9 /* RowTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/Sources/SQLite/Core/Errors.swift b/Sources/SQLite/Core/Errors.swift
index e069f50e..3cd7ae9f 100644
--- a/Sources/SQLite/Core/Errors.swift
+++ b/Sources/SQLite/Core/Errors.swift
@@ -4,6 +4,7 @@ public enum QueryError: Error, CustomStringConvertible {
     case noSuchTable(name: String)
     case noSuchColumn(name: String, columns: [String])
     case ambiguousColumn(name: String, similar: [String])
+    case unexpectedNullValue(name: String)
 
     public var description: String {
         switch self {
@@ -13,6 +14,8 @@ public enum QueryError: Error, CustomStringConvertible {
             return "No such column `\(name)` in columns \(columns)"
         case .ambiguousColumn(let name, let similar):
             return "Ambiguous column `\(name)` (please disambiguate: \(similar))"
+        case .unexpectedNullValue(let name):
+            return "Unexpected null value for column `\(name)`"
         }
     }
 }
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index 7bcda40b..8fa2c539 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -1031,7 +1031,7 @@ public struct Row {
 
     fileprivate let values: [Binding?]
 
-    fileprivate init(_ columnNames: [String: Int], _ values: [Binding?]) {
+    internal init(_ columnNames: [String: Int], _ values: [Binding?]) {
         self.columnNames = columnNames
         self.values = values
     }
@@ -1042,7 +1042,11 @@ public struct Row {
     ///
     /// - Returns: The value for the given column.
     public func get<V: Value>(_ column: Expression<V>) throws -> V {
-        return try get(Expression<V?>(column))!
+        if let value = try get(Expression<V?>(column)) {
+            return value
+        } else {
+            throw QueryError.unexpectedNullValue(name: column.template)
+        }
     }
 
     public func get<V: Value>(_ column: Expression<V?>) throws -> V? {
diff --git a/Tests/SQLiteTests/RowTests.swift b/Tests/SQLiteTests/RowTests.swift
new file mode 100644
index 00000000..4ef5dc2d
--- /dev/null
+++ b/Tests/SQLiteTests/RowTests.swift
@@ -0,0 +1,88 @@
+import XCTest
+@testable import SQLite
+
+class RowTests : XCTestCase {
+
+    public func test_get_value() {
+        let row = Row(["\"foo\"": 0], ["value"])
+        let result = try! row.get(Expression<String>("foo"))
+
+        XCTAssertEqual("value", result)
+    }
+
+    public func test_get_value_subscript() {
+        let row = Row(["\"foo\"": 0], ["value"])
+        let result = row[Expression<String>("foo")]
+
+        XCTAssertEqual("value", result)
+    }
+
+    public func test_get_value_optional() {
+        let row = Row(["\"foo\"": 0], ["value"])
+        let result = try! row.get(Expression<String?>("foo"))
+
+        XCTAssertEqual("value", result)
+    }
+
+    public func test_get_value_optional_subscript() {
+        let row = Row(["\"foo\"": 0], ["value"])
+        let result = row[Expression<String?>("foo")]
+
+        XCTAssertEqual("value", result)
+    }
+
+    public func test_get_value_optional_nil() {
+        let row = Row(["\"foo\"": 0], [nil])
+        let result = try! row.get(Expression<String?>("foo"))
+
+        XCTAssertNil(result)
+    }
+
+    public func test_get_value_optional_nil_subscript() {
+        let row = Row(["\"foo\"": 0], [nil])
+        let result = row[Expression<String?>("foo")]
+
+        XCTAssertNil(result)
+    }
+
+    public func test_get_type_mismatch_throws_unexpected_null_value() {
+        let row = Row(["\"foo\"": 0], ["value"])
+        XCTAssertThrowsError(try row.get(Expression<Int>("foo"))) { error in
+            if case QueryError.unexpectedNullValue(let name) = error {
+                XCTAssertEqual("\"foo\"", name)
+            } else {
+                XCTFail("unexpected error: \(error)")
+            }
+        }
+    }
+
+    public func test_get_type_mismatch_optional_returns_nil() {
+        let row = Row(["\"foo\"": 0], ["value"])
+        let result = try! row.get(Expression<Int?>("foo"))
+        XCTAssertNil(result)
+    }
+
+    public func test_get_non_existent_column_throws_no_such_column() {
+        let row = Row(["\"foo\"": 0], ["value"])
+        XCTAssertThrowsError(try row.get(Expression<Int>("bar"))) { error in
+            if case QueryError.noSuchColumn(let name, let columns) = error {
+                XCTAssertEqual("\"bar\"", name)
+                XCTAssertEqual(["\"foo\""], columns)
+            } else {
+                XCTFail("unexpected error: \(error)")
+            }
+        }
+    }
+
+    public func test_get_ambiguous_column_throws() {
+        let row = Row(["table1.\"foo\"": 0, "table2.\"foo\"": 1], ["value"])
+        XCTAssertThrowsError(try row.get(Expression<Int>("foo"))) { error in
+            if case QueryError.ambiguousColumn(let name, let columns) = error {
+                XCTAssertEqual("\"foo\"", name)
+                XCTAssertEqual(["table1.\"foo\"", "table2.\"foo\""], columns)
+            } else {
+                XCTFail("unexpected error: \(error)")
+            }
+        }
+    }
+}

From d79d52c74ed138280c36314f0e1e42757679fc6d Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 17 Sep 2017 09:04:20 +0200
Subject: [PATCH 240/685] Simplify `sync`

#640
---
 Sources/SQLite/Core/Connection.swift | 23 +++--------------------
 1 file changed, 3 insertions(+), 20 deletions(-)

diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 51b68ed8..a2e7dcf2 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -626,29 +626,12 @@ public final class Connection {
 
     // MARK: - Error Handling
 
-    func sync<T>(_ block: @escaping () throws -> T) rethrows -> T {
-        var success: T?
-        var failure: Error?
-
-        let box: () -> Void = {
-            do {
-                success = try block()
-            } catch {
-                failure = error
-            }
-        }
-
+    func sync<T>(_ block: () throws -> T) rethrows -> T {
         if DispatchQueue.getSpecific(key: Connection.queueKey) == queueContext {
-            box()
+            return try block()
         } else {
-            queue.sync(execute: box) // FIXME: rdar://problem/21389236
-        }
-
-        if let failure = failure {
-            try { () -> Void in throw failure }()
+            return try queue.sync(execute: block)
         }
-
-        return success!
     }
 
     @discardableResult func check(_ resultCode: Int32, statement: Statement? = nil) throws -> Int32 {

From a1dc335fee02985a4af08e2e32421b28e9cfac7b Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 17 Sep 2017 09:08:17 +0200
Subject: [PATCH 241/685] Fix FIXMEs

---
 Sources/SQLite/Typed/Expression.swift      |  3 +--
 Tests/SQLiteTests/CoreFunctionsTests.swift |  2 +-
 Tests/SQLiteTests/QueryTests.swift         | 10 +---------
 Tests/SQLiteTests/TestHelpers.swift        |  2 +-
 4 files changed, 4 insertions(+), 13 deletions(-)

diff --git a/Sources/SQLite/Typed/Expression.swift b/Sources/SQLite/Typed/Expression.swift
index 3198901c..d26b6692 100644
--- a/Sources/SQLite/Typed/Expression.swift
+++ b/Sources/SQLite/Typed/Expression.swift
@@ -73,8 +73,7 @@ public protocol Expressible {
 extension Expressible {
 
     // naïve compiler for statements that can’t be bound, e.g., CREATE TABLE
-    // FIXME: use @testable and make internal
-    public func asSQL() -> String {
+    internal func asSQL() -> String {
         let expressed = expression
         var idx = 0
         return expressed.template.characters.reduce("") { template, character in
diff --git a/Tests/SQLiteTests/CoreFunctionsTests.swift b/Tests/SQLiteTests/CoreFunctionsTests.swift
index db37ff7f..4a2b511e 100644
--- a/Tests/SQLiteTests/CoreFunctionsTests.swift
+++ b/Tests/SQLiteTests/CoreFunctionsTests.swift
@@ -1,5 +1,5 @@
 import XCTest
-import SQLite
+@testable import SQLite
 
 class CoreFunctionsTests : XCTestCase {
 
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index 3ab0419a..7dde0c53 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -1,5 +1,5 @@
 import XCTest
-import SQLite
+@testable import SQLite
 
 class QueryTests : XCTestCase {
 
@@ -333,10 +333,6 @@ class QueryIntegrationTests : SQLiteTestCase {
     // MARK: -
 
     func test_select() {
-        for _ in try! db.prepare(users) {
-            // FIXME
-        }
-
         let managerId = Expression<Int64>("manager_id")
         let managers = users.alias("managers")
 
@@ -349,10 +345,6 @@ class QueryIntegrationTests : SQLiteTestCase {
     }
 
     func test_select_optional() {
-        for _ in try! db.prepare(users) {
-            // FIXME
-        }
-
         let managerId = Expression<Int64?>("manager_id")
         let managers = users.alias("managers")
 
diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index 8c33bf6a..b66144b3 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -1,5 +1,5 @@
 import XCTest
-import SQLite
+@testable import SQLite
 
 class SQLiteTestCase : XCTestCase {
 

From 9b8cc16114f25a8b8e8541f3524a38434cbdf554 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 17 Sep 2017 09:12:20 +0200
Subject: [PATCH 242/685] Drop `@escaping`

---
 Sources/SQLite/Core/Connection.swift | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index a2e7dcf2..0189d300 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -328,7 +328,7 @@ public final class Connection {
     ///     must throw to roll the transaction back.
     ///
     /// - Throws: `Result.Error`, and rethrows.
-    public func transaction(_ mode: TransactionMode = .deferred, block: @escaping () throws -> Void) throws {
+    public func transaction(_ mode: TransactionMode = .deferred, block: () throws -> Void) throws {
         try transaction("BEGIN \(mode.rawValue) TRANSACTION", block, "COMMIT TRANSACTION", or: "ROLLBACK TRANSACTION")
     }
 
@@ -348,14 +348,14 @@ public final class Connection {
     ///     The block must throw to roll the savepoint back.
     ///
     /// - Throws: `SQLite.Result.Error`, and rethrows.
-    public func savepoint(_ name: String = UUID().uuidString, block: @escaping () throws -> Void) throws {
+    public func savepoint(_ name: String = UUID().uuidString, block: () throws -> Void) throws {
         let name = name.quote("'")
         let savepoint = "SAVEPOINT \(name)"
 
         try transaction(savepoint, block, "RELEASE \(savepoint)", or: "ROLLBACK TO \(savepoint)")
     }
 
-    fileprivate func transaction(_ begin: String, _ block: @escaping () throws -> Void, _ commit: String, or rollback: String) throws {
+    fileprivate func transaction(_ begin: String, _ block: () throws -> Void, _ commit: String, or rollback: String) throws {
         return try sync {
             try self.run(begin)
             do {

From 5850d8397d846814e58d74cdab5710ebfa639b8a Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 17 Sep 2017 09:41:28 +0200
Subject: [PATCH 243/685] Fix test

---
 Tests/SQLiteTests/RowTests.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Tests/SQLiteTests/RowTests.swift b/Tests/SQLiteTests/RowTests.swift
index 4ef5dc2d..17873e71 100644
--- a/Tests/SQLiteTests/RowTests.swift
+++ b/Tests/SQLiteTests/RowTests.swift
@@ -79,7 +79,7 @@ class RowTests : XCTestCase {
         XCTAssertThrowsError(try row.get(Expression<Int>("foo"))) { error in
             if case QueryError.ambiguousColumn(let name, let columns) = error {
                 XCTAssertEqual("\"foo\"", name)
-                XCTAssertEqual(["table1.\"foo\"", "table2.\"foo\""], columns)
+                XCTAssertEqual(["table1.\"foo\"", "table2.\"foo\""], columns.sorted())
             } else {
                 XCTFail("unexpected error: \(error)")
             }

From 9f1735a52898a3cae23020a76e2003357712c38c Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 17 Sep 2017 10:31:56 +0200
Subject: [PATCH 244/685] Keep API compatibility

---
 Sources/SQLite/Typed/Expression.swift | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Sources/SQLite/Typed/Expression.swift b/Sources/SQLite/Typed/Expression.swift
index d26b6692..33329b73 100644
--- a/Sources/SQLite/Typed/Expression.swift
+++ b/Sources/SQLite/Typed/Expression.swift
@@ -73,7 +73,8 @@ public protocol Expressible {
 extension Expressible {
 
     // naïve compiler for statements that can’t be bound, e.g., CREATE TABLE
-    internal func asSQL() -> String {
+    // FIXME: make internal (0.12.0)
+    public func asSQL() -> String {
         let expressed = expression
         var idx = 0
         return expressed.template.characters.reduce("") { template, character in

From feb26b06cd29584bba59c5db5f84b958a476d9bc Mon Sep 17 00:00:00 2001
From: Nick Shelley <nickmshelley@gmail.com>
Date: Fri, 5 May 2017 14:48:18 -0600
Subject: [PATCH 245/685] Add cursor type for more safety.

---
 Sources/SQLite/Core/Statement.swift |   8 ++
 Sources/SQLite/Typed/Query.swift    | 111 ++++++++++++++++++----------
 Tests/SQLiteTests/QueryTests.swift  |  10 +++
 3 files changed, 89 insertions(+), 40 deletions(-)

diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index 8c13ff6c..c817e887 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -191,6 +191,14 @@ public final class Statement {
 
 }
 
+extension Statement {
+    
+    func rowCursorNext() throws -> [Binding?]? {
+        return try step() ? Array(row) : nil
+    }
+    
+}
+
 extension Statement : Sequence {
 
     public func makeIterator() -> Statement {
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index 8fa2c539..199e5ef8 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -894,58 +894,89 @@ public struct Delete : ExpressionType {
 
 }
 
+public struct RowCursor {
+    let statement: Statement
+    let columnNames: [String: Int]
+    
+    public func next() throws -> Row? {
+        return try statement.rowCursorNext().flatMap { Row(columnNames, $0) }
+    }
+    
+    public func map<T>(_ transform: (Row) throws -> T) throws -> [T] {
+        var elements = [T]()
+        while true {
+            if let row = try next() {
+                elements.append(try transform(row))
+            } else {
+                break
+            }
+        }
+        
+        return elements
+    }
+}
+
 extension Connection {
+    
+    public func prepareCursor(_ query: QueryType) throws -> RowCursor {
+        let expression = query.expression
+        let statement = try prepare(expression.template, expression.bindings)
+        return RowCursor(statement: statement, columnNames: try columnNamesForQuery(query))
+    }
 
     public func prepare(_ query: QueryType) throws -> AnySequence<Row> {
         let expression = query.expression
         let statement = try prepare(expression.template, expression.bindings)
 
-        let columnNames: [String: Int] = try {
-            var (columnNames, idx) = ([String: Int](), 0)
-            column: for each in query.clauses.select.columns {
-                var names = each.expression.template.characters.split { $0 == "." }.map(String.init)
-                let column = names.removeLast()
-                let namespace = names.joined(separator: ".")
-
-                func expandGlob(_ namespace: Bool) -> ((QueryType) throws -> Void) {
-                    return { (query: QueryType) throws -> (Void) in
-                        var q = type(of: query).init(query.clauses.from.name, database: query.clauses.from.database)
-                        q.clauses.select = query.clauses.select
-                        let e = q.expression
-                        var names = try self.prepare(e.template, e.bindings).columnNames.map { $0.quote() }
-                        if namespace { names = names.map { "\(query.tableName().expression.template).\($0)" } }
-                        for name in names { columnNames[name] = idx; idx += 1 }
-                    }
-                }
+        let columnNames = try columnNamesForQuery(query)
 
-                if column == "*" {
-                    var select = query
-                    select.clauses.select = (false, [Expression<Void>(literal: "*") as Expressible])
-                    let queries = [select] + query.clauses.join.map { $0.query }
-                    if !namespace.isEmpty {
-                        for q in queries {
-                            if q.tableName().expression.template == namespace {
-                                try expandGlob(true)(q)
-                                continue column
-                            }
+        return AnySequence {
+            AnyIterator { statement.next().map { Row(columnNames, $0) } }
+        }
+    }
+    
+    private func columnNamesForQuery(_ query: QueryType) throws -> [String: Int] {
+        var (columnNames, idx) = ([String: Int](), 0)
+        column: for each in query.clauses.select.columns {
+            var names = each.expression.template.characters.split { $0 == "." }.map(String.init)
+            let column = names.removeLast()
+            let namespace = names.joined(separator: ".")
+            
+            func expandGlob(_ namespace: Bool) -> ((QueryType) throws -> Void) {
+                return { (query: QueryType) throws -> (Void) in
+                    var q = type(of: query).init(query.clauses.from.name, database: query.clauses.from.database)
+                    q.clauses.select = query.clauses.select
+                    let e = q.expression
+                    var names = try self.prepare(e.template, e.bindings).columnNames.map { $0.quote() }
+                    if namespace { names = names.map { "\(query.tableName().expression.template).\($0)" } }
+                    for name in names { columnNames[name] = idx; idx += 1 }
+                }
+            }
+            
+            if column == "*" {
+                var select = query
+                select.clauses.select = (false, [Expression<Void>(literal: "*") as Expressible])
+                let queries = [select] + query.clauses.join.map { $0.query }
+                if !namespace.isEmpty {
+                    for q in queries {
+                        if q.tableName().expression.template == namespace {
+                            try expandGlob(true)(q)
+                            continue column
                         }
                         throw QueryError.noSuchTable(name: namespace)
                     }
-                    for q in queries {
-                        try expandGlob(query.clauses.join.count > 0)(q)
-                    }
-                    continue
+                    fatalError("no such table: \(namespace)")
                 }
-
-                columnNames[each.expression.template] = idx
-                idx += 1
+                for q in queries {
+                    try expandGlob(query.clauses.join.count > 0)(q)
+                }
+                continue
             }
-            return columnNames
-        }()
-
-        return AnySequence {
-            AnyIterator { statement.next().map { Row(columnNames, $0) } }
+            
+            columnNames[each.expression.template] = idx
+            idx += 1
         }
+        return columnNames
     }
 
     public func scalar<V : Value>(_ query: ScalarQuery<V>) throws -> V {
@@ -971,7 +1002,7 @@ extension Connection {
     }
 
     public func pluck(_ query: QueryType) throws -> Row? {
-        return try prepare(query.limit(1, query.clauses.limit?.offset)).makeIterator().next()
+        return try prepareCursor(query.limit(1, query.clauses.limit?.offset)).next()
     }
 
     /// Runs an `Insert` query.
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index 7dde0c53..feb0596d 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -343,6 +343,16 @@ class QueryIntegrationTests : SQLiteTestCase {
             _ = user[users[managerId]]
         }
     }
+    
+    func test_prepareCursor() {
+        let names = ["a", "b", "c"]
+        try! InsertUsers(names)
+        
+        let emailColumn = Expression<String>("email")
+        let emails = try! db.prepareCursor(users).map { $0[emailColumn] }
+        
+        XCTAssertEqual(names.map({ "\($0)@example.com" }), emails.sorted())
+    }
 
     func test_select_optional() {
         let managerId = Expression<Int64?>("manager_id")

From 28e2cfa1cc9a0251abdbd707bec11f265a62c0a9 Mon Sep 17 00:00:00 2001
From: Nick Shelley <nickmshelley@gmail.com>
Date: Wed, 20 Sep 2017 07:53:39 -0600
Subject: [PATCH 246/685] Change fatalError to throw.

---
 Sources/SQLite/Typed/Query.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index 199e5ef8..e9fa941c 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -965,7 +965,7 @@ extension Connection {
                         }
                         throw QueryError.noSuchTable(name: namespace)
                     }
-                    fatalError("no such table: \(namespace)")
+                    throw QueryError.noSuchTable(name: namespace)
                 }
                 for q in queries {
                     try expandGlob(query.clauses.join.count > 0)(q)

From 5a9b583d2a28d12bc8523b204e75a0da6c8b04ff Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 24 Sep 2017 22:53:16 +0200
Subject: [PATCH 247/685] Introduce FailableIterator

---
 Sources/SQLite/Core/Statement.swift | 40 +++++++++++++++++++++--------
 Sources/SQLite/Typed/Query.swift    | 38 ++++++++++-----------------
 Tests/SQLiteTests/QueryTests.swift  | 10 ++++----
 3 files changed, 48 insertions(+), 40 deletions(-)

diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index c817e887..5df00791 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -191,14 +191,6 @@ public final class Statement {
 
 }
 
-extension Statement {
-    
-    func rowCursorNext() throws -> [Binding?]? {
-        return try step() ? Array(row) : nil
-    }
-    
-}
-
 extension Statement : Sequence {
 
     public func makeIterator() -> Statement {
@@ -208,12 +200,38 @@ extension Statement : Sequence {
 
 }
 
-extension Statement : IteratorProtocol {
+public protocol FailableIterator : IteratorProtocol {
+    func failableNext() throws -> Self.Element?
+}
 
-    public func next() -> [Binding?]? {
-        return try! step() ? Array(row) : nil
+extension FailableIterator {
+    public func next() -> Element? {
+        return try! failableNext()
     }
 
+    public func map<T>(_ transform: (Element) throws -> T) throws -> [T] {
+        var elements = [T]()
+        while let row = try failableNext() {
+            elements.append(try transform(row))
+        }
+        return elements
+    }
+}
+
+extension Array {
+    public init<I: FailableIterator>(_ failableIterator: I) throws where I.Element == Element {
+        self.init()
+        while let row = try failableIterator.failableNext() {
+            append(row)
+        }
+    }
+}
+
+extension Statement : FailableIterator {
+    public typealias Element = [Binding?]
+    public func failableNext() throws -> [Binding?]? {
+        return try step() ? Array(row) : nil
+    }
 }
 
 extension Statement : CustomStringConvertible {
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index e9fa941c..cc54649e 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -894,35 +894,19 @@ public struct Delete : ExpressionType {
 
 }
 
-public struct RowCursor {
+
+public struct RowCursor: FailableIterator {
+    public typealias Element = Row
     let statement: Statement
     let columnNames: [String: Int]
-    
-    public func next() throws -> Row? {
-        return try statement.rowCursorNext().flatMap { Row(columnNames, $0) }
-    }
-    
-    public func map<T>(_ transform: (Row) throws -> T) throws -> [T] {
-        var elements = [T]()
-        while true {
-            if let row = try next() {
-                elements.append(try transform(row))
-            } else {
-                break
-            }
-        }
-        
-        return elements
+
+    public func failableNext() throws -> Row? {
+        return try statement.failableNext().flatMap { Row(columnNames, $0) }
     }
 }
 
+
 extension Connection {
-    
-    public func prepareCursor(_ query: QueryType) throws -> RowCursor {
-        let expression = query.expression
-        let statement = try prepare(expression.template, expression.bindings)
-        return RowCursor(statement: statement, columnNames: try columnNamesForQuery(query))
-    }
 
     public func prepare(_ query: QueryType) throws -> AnySequence<Row> {
         let expression = query.expression
@@ -935,6 +919,12 @@ extension Connection {
         }
     }
     
+    public func prepareRowCursor(_ query: QueryType) throws -> RowCursor {
+        let expression = query.expression
+        let statement = try prepare(expression.template, expression.bindings)
+        return RowCursor(statement: statement, columnNames: try columnNamesForQuery(query))
+    }
+
     private func columnNamesForQuery(_ query: QueryType) throws -> [String: Int] {
         var (columnNames, idx) = ([String: Int](), 0)
         column: for each in query.clauses.select.columns {
@@ -1002,7 +992,7 @@ extension Connection {
     }
 
     public func pluck(_ query: QueryType) throws -> Row? {
-        return try prepareCursor(query.limit(1, query.clauses.limit?.offset)).next()
+        return try prepareRowCursor(query.limit(1, query.clauses.limit?.offset)).failableNext()
     }
 
     /// Runs an `Insert` query.
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index feb0596d..2c026b9b 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -343,14 +343,14 @@ class QueryIntegrationTests : SQLiteTestCase {
             _ = user[users[managerId]]
         }
     }
-    
-    func test_prepareCursor() {
+
+    func test_prepareRowCursor() {
         let names = ["a", "b", "c"]
         try! InsertUsers(names)
-        
+
         let emailColumn = Expression<String>("email")
-        let emails = try! db.prepareCursor(users).map { $0[emailColumn] }
-        
+        let emails = try! db.prepareRowCursor(users).map { $0[emailColumn] }
+
         XCTAssertEqual(names.map({ "\($0)@example.com" }), emails.sorted())
     }
 

From 30b78fdcf995cbe75dd3469188de6b326cfb2f08 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 25 Sep 2017 17:53:18 +0200
Subject: [PATCH 248/685] Update changelog

---
 CHANGELOG.md | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e59e221c..2963d8d4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
 0.11.4 (xx-09-2017), [diff][diff-0.11.4]
 ========================================
 
+* Add cursor type for more safety ([#647](), [#726][])
 * Make Row.get throw instead of crash ([#649][])
 * Fix create/drop index functions ([#666][])
 * Set deployment target to 8.0 (#624, #671, #717)
@@ -56,9 +57,11 @@
 [#561]: https://github.com/stephencelis/SQLite.swift/issues/561
 [#571]: https://github.com/stephencelis/SQLite.swift/issues/571
 [#615]: https://github.com/stephencelis/SQLite.swift/pull/615
+[#647]: https://github.com/stephencelis/SQLite.swift/pull/647
 [#649]: https://github.com/stephencelis/SQLite.swift/pull/649
 [#657]: https://github.com/stephencelis/SQLite.swift/issues/657
 [#666]: https://github.com/stephencelis/SQLite.swift/pull/666
 [#668]: https://github.com/stephencelis/SQLite.swift/pull/668
 [#722]: https://github.com/stephencelis/SQLite.swift/pull/722
 [#723]: https://github.com/stephencelis/SQLite.swift/pull/723
+[#726]: https://github.com/stephencelis/SQLite.swift/pull/726

From 2ebdf7802bbea4b009c6d8493842d5eeccf3113d Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 25 Sep 2017 18:18:17 +0200
Subject: [PATCH 249/685] RowCursor -> RowIterator

---
 CHANGELOG.md                       | 2 +-
 Sources/SQLite/Typed/Query.swift   | 9 +++++----
 Tests/SQLiteTests/QueryTests.swift | 4 ++--
 3 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2963d8d4..3fa68dfe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,7 @@
 0.11.4 (xx-09-2017), [diff][diff-0.11.4]
 ========================================
 
-* Add cursor type for more safety ([#647](), [#726][])
+* Add `RowIterator` for more safety ([#647][], [#726][])
 * Make Row.get throw instead of crash ([#649][])
 * Fix create/drop index functions ([#666][])
 * Set deployment target to 8.0 (#624, #671, #717)
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index cc54649e..a08561cb 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -895,7 +895,7 @@ public struct Delete : ExpressionType {
 }
 
 
-public struct RowCursor: FailableIterator {
+public struct RowIterator: FailableIterator {
     public typealias Element = Row
     let statement: Statement
     let columnNames: [String: Int]
@@ -919,10 +919,11 @@ extension Connection {
         }
     }
     
-    public func prepareRowCursor(_ query: QueryType) throws -> RowCursor {
+
+    public func prepareRowIterator(_ query: QueryType) throws -> RowIterator {
         let expression = query.expression
         let statement = try prepare(expression.template, expression.bindings)
-        return RowCursor(statement: statement, columnNames: try columnNamesForQuery(query))
+        return RowIterator(statement: statement, columnNames: try columnNamesForQuery(query))
     }
 
     private func columnNamesForQuery(_ query: QueryType) throws -> [String: Int] {
@@ -992,7 +993,7 @@ extension Connection {
     }
 
     public func pluck(_ query: QueryType) throws -> Row? {
-        return try prepareRowCursor(query.limit(1, query.clauses.limit?.offset)).failableNext()
+        return try prepareRowIterator(query.limit(1, query.clauses.limit?.offset)).failableNext()
     }
 
     /// Runs an `Insert` query.
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index 2c026b9b..df0e7bec 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -344,12 +344,12 @@ class QueryIntegrationTests : SQLiteTestCase {
         }
     }
 
-    func test_prepareRowCursor() {
+    func test_prepareRowIterator() {
         let names = ["a", "b", "c"]
         try! InsertUsers(names)
 
         let emailColumn = Expression<String>("email")
-        let emails = try! db.prepareRowCursor(users).map { $0[emailColumn] }
+        let emails = try! db.prepareRowIterator(users).map { $0[emailColumn] }
 
         XCTAssertEqual(names.map({ "\($0)@example.com" }), emails.sorted())
     }

From c3c8360e89cd47a500622ded3268c77ca77f839f Mon Sep 17 00:00:00 2001
From: Andrew J Wagner <andrew@drewagllc.com>
Date: Tue, 19 Sep 2017 22:33:38 -0600
Subject: [PATCH 250/685] Add Coding support

- Insert or update from an Encodable type
- Decode a row into a Decodable type

Closes stephencelis/SQLite.swift#727
---
 Sources/SQLite/Typed/Query.swift    | 321 ++++++++++++++++++++++++++++
 Tests/SQLiteTests/QueryTests.swift  |  77 +++++++
 Tests/SQLiteTests/TestHelpers.swift |  20 ++
 3 files changed, 418 insertions(+)

diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index 8fa2c539..45d15c79 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -22,6 +22,8 @@
 // THE SOFTWARE.
 //
 
+import Foundation
+
 public protocol QueryType : Expressible {
 
     var clauses: QueryClauses { get set }
@@ -671,6 +673,26 @@ extension QueryType {
         ]).expression)
     }
 
+    /// Creates an `INSERT` statement by encoding the given object
+    /// This method converts any custom nested types to JSON data and does not handle any sort
+    /// of object relationships. If you want to support relationships between objects you will
+    /// have to provide your own Encodable implementations that encode the correct ids.
+    ///
+    /// - Parameters:
+    ///
+    ///   - encodable: An encodable object to insert
+    ///
+    ///   - userInfo: User info to be passed to encoder
+    ///
+    ///   - otherSetters: Any other setters to include in the insert
+    ///
+    /// - Returns: An `INSERT` statement fort the encodable object
+    public func insert(_ encodable: Encodable, userInfo: [CodingUserInfoKey:Any] = [:], otherSetters: [Setter] = []) throws -> Insert {
+        let encoder = SQLiteEncoder(userInfo: userInfo)
+        try encodable.encode(to: encoder)
+        return self.insert(encoder.setters + otherSetters)
+    }
+
     // MARK: UPDATE
 
     public func update(_ values: Setter...) -> Update {
@@ -691,6 +713,26 @@ extension QueryType {
         return Update(" ".join(clauses.flatMap { $0 }).expression)
     }
 
+    /// Creates an `UPDATE` statement by encoding the given object
+    /// This method converts any custom nested types to JSON data and does not handle any sort
+    /// of object relationships. If you want to support relationships between objects you will
+    /// have to provide your own Encodable implementations that encode the correct ids.
+    ///
+    /// - Parameters:
+    ///
+    ///   - encodable: An encodable object to insert
+    ///
+    ///   - userInfo: User info to be passed to encoder
+    ///
+    ///   - otherSetters: Any other setters to include in the insert
+    ///
+    /// - Returns: An `UPDATE` statement fort the encodable object
+    public func update(_ encodable: Encodable, userInfo: [CodingUserInfoKey:Any] = [:], otherSetters: [Setter] = []) throws -> Update {
+        let encoder = SQLiteEncoder(userInfo: userInfo)
+        try encodable.encode(to: encoder)
+        return self.update(encoder.setters + otherSetters)
+    }
+
     // MARK: DELETE
 
     public func delete() -> Delete {
@@ -1036,6 +1078,13 @@ public struct Row {
         self.values = values
     }
 
+    fileprivate func hasValue(for column: String) -> Bool {
+        guard let idx = columnNames[column.quote()] else {
+            return false
+        }
+        return values[idx] != nil
+    }
+
     /// Returns a row’s value for the given column.
     ///
     /// - Parameter column: An expression representing a column selected in a Query.
@@ -1071,6 +1120,22 @@ public struct Row {
         return valueAtIndex(idx)
     }
 
+    /// Decode an object from this row
+    /// This method expects any custom nested types to be in the form of JSON data and does not handle
+    /// any sort of object relationships. If you want to support relationships between objects you will
+    /// have to provide your own Decodable implementations that decodes the correct columns.
+    ///
+    /// - Parameter: userInfo
+    ///
+    /// - Returns: a decoded object from this row
+    public func decode<V: Decodable>(userInfo: [CodingUserInfoKey: Any] = [:]) throws -> V {
+        return try V(from: self.decoder(userInfo: userInfo))
+    }
+
+    public func decoder(userInfo: [CodingUserInfoKey: Any] = [:]) -> Decoder {
+        return SQLiteDecoder(row: self, userInfo: userInfo)
+    }
+
     public subscript<T : Value>(column: Expression<T>) -> T {
         return try! get(column)
     }
@@ -1134,3 +1199,259 @@ public struct QueryClauses {
     }
 
 }
+
+/// Generates a list of settings for an Encodable object
+fileprivate class SQLiteEncoder: Encoder {
+    struct EncodingError: Error, CustomStringConvertible {
+        let description: String
+    }
+
+    class SQLiteKeyedEncodingContainer<MyKey: CodingKey>: KeyedEncodingContainerProtocol {
+        typealias Key = MyKey
+
+        let encoder: SQLiteEncoder
+        let codingPath: [CodingKey] = []
+
+        init(encoder: SQLiteEncoder) {
+            self.encoder = encoder
+        }
+
+        func superEncoder() -> Swift.Encoder {
+            fatalError("SQLiteEncoding does not support super encoders")
+        }
+
+        func superEncoder(forKey key: Key) -> Swift.Encoder {
+            fatalError("SQLiteEncoding does not support super encoders")
+        }
+
+        func encodeNil(forKey key: SQLiteEncoder.SQLiteKeyedEncodingContainer<Key>.Key) throws {
+            self.encoder.setters.append(Expression<String?>(key.stringValue) <- nil)
+        }
+
+        func encode(_ value: Int, forKey key: SQLiteEncoder.SQLiteKeyedEncodingContainer<Key>.Key) throws {
+            self.encoder.setters.append(Expression(key.stringValue) <- value)
+        }
+
+        func encode(_ value: Bool, forKey key: Key) throws {
+            self.encoder.setters.append(Expression(key.stringValue) <- value)
+        }
+
+        func encode(_ value: Float, forKey key: Key) throws {
+            self.encoder.setters.append(Expression(key.stringValue) <- Double(value))
+        }
+
+        func encode(_ value: Double, forKey key: Key) throws {
+            self.encoder.setters.append(Expression(key.stringValue) <- value)
+        }
+
+        func encode(_ value: String, forKey key: Key) throws {
+            self.encoder.setters.append(Expression(key.stringValue) <- value)
+        }
+
+        func encode<T>(_ value: T, forKey key: Key) throws where T : Swift.Encodable {
+            if let data = value as? Data {
+                self.encoder.setters.append(Expression(key.stringValue) <- data)
+            }
+            else {
+                let encoded = try JSONEncoder().encode(value)
+                self.encoder.setters.append(Expression(key.stringValue) <- encoded)
+            }
+        }
+
+        func encode(_ value: Int8, forKey key: Key) throws {
+            throw EncodingError(description: "encoding an Int8 is not supported")
+        }
+
+        func encode(_ value: Int16, forKey key: Key) throws {
+            throw EncodingError(description: "encoding an Int16 is not supported")
+        }
+
+        func encode(_ value: Int32, forKey key: Key) throws {
+            throw EncodingError(description: "encoding an Int32 is not supported")
+        }
+
+        func encode(_ value: Int64, forKey key: Key) throws {
+            throw EncodingError(description: "encoding an Int64 is not supported")
+        }
+
+        func encode(_ value: UInt, forKey key: Key) throws {
+            throw EncodingError(description: "encoding an UInt is not supported")
+        }
+
+        func encode(_ value: UInt8, forKey key: Key) throws {
+            throw EncodingError(description: "encoding an UInt8 is not supported")
+        }
+
+        func encode(_ value: UInt16, forKey key: Key) throws {
+            throw EncodingError(description: "encoding an UInt16 is not supported")
+        }
+
+        func encode(_ value: UInt32, forKey key: Key) throws {
+            throw EncodingError(description: "encoding an UInt32 is not supported")
+        }
+
+        func encode(_ value: UInt64, forKey key: Key) throws {
+            throw EncodingError(description: "encoding an UInt64 is not supported")
+        }
+
+        func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> where NestedKey : CodingKey {
+            fatalError("encoding a nested container is not supported")
+        }
+
+        func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
+            fatalError("encoding nested values is not supported")
+        }
+    }
+
+    fileprivate var setters: [SQLite.Setter] = []
+    let codingPath: [CodingKey] = []
+    let userInfo: [CodingUserInfoKey: Any]
+
+    init(userInfo: [CodingUserInfoKey: Any]) {
+        self.userInfo = userInfo
+    }
+
+    func singleValueContainer() -> SingleValueEncodingContainer {
+        fatalError("not supported")
+    }
+
+    func unkeyedContainer() -> UnkeyedEncodingContainer {
+        fatalError("not supported")
+    }
+
+    func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key : CodingKey {
+        return KeyedEncodingContainer(SQLiteKeyedEncodingContainer(encoder: self))
+    }
+}
+
+class SQLiteDecoder : Decoder {
+    struct DecodingError : Error, CustomStringConvertible {
+        let description: String
+    }
+
+    class SQLiteKeyedDecodingContainer<MyKey: CodingKey> : KeyedDecodingContainerProtocol {
+        typealias Key = MyKey
+
+        let codingPath: [CodingKey] = []
+        let row: Row
+
+        init(row: Row) {
+            self.row = row
+        }
+
+        var allKeys: [Key] {
+            return self.row.columnNames.keys.flatMap({Key(stringValue: $0)})
+        }
+
+        func contains(_ key: Key) -> Bool {
+            return self.row.hasValue(for: key.stringValue)
+        }
+
+        func decodeNil(forKey key: Key) throws -> Bool {
+            return !self.contains(key)
+        }
+
+        func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool {
+            return try self.row.get(Expression(key.stringValue))
+        }
+
+        func decode(_ type: Int.Type, forKey key: Key) throws -> Int {
+            return try self.row.get(Expression(key.stringValue))
+        }
+
+        func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 {
+            throw DecodingError(description: "decoding an Int8 is not supported")
+        }
+
+        func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 {
+            throw DecodingError(description: "decoding an Int16 is not supported")
+        }
+
+        func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 {
+            throw DecodingError(description: "decoding an Int32 is not supported")
+        }
+
+        func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
+            throw DecodingError(description: "decoding an Int64 is not supported")
+        }
+
+        func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {
+            throw DecodingError(description: "decoding an UInt is not supported")
+        }
+
+        func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 {
+            throw DecodingError(description: "decoding an UInt8 is not supported")
+        }
+
+        func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 {
+            throw DecodingError(description: "decoding an UInt16 is not supported")
+        }
+
+        func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 {
+            throw DecodingError(description: "decoding an UInt32 is not supported")
+        }
+
+        func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 {
+            throw DecodingError(description: "decoding an UInt64 is not supported")
+        }
+
+        func decode(_ type: Float.Type, forKey key: Key) throws -> Float {
+            return Float(try self.row.get(Expression<Double>(key.stringValue)))
+        }
+
+        func decode(_ type: Double.Type, forKey key: Key) throws -> Double {
+            return try self.row.get(Expression(key.stringValue))
+        }
+
+        func decode(_ type: String.Type, forKey key: Key) throws -> String {
+            return try self.row.get(Expression(key.stringValue))
+        }
+
+        func decode<T>(_ type: T.Type, forKey key: Key) throws -> T where T: Swift.Decodable {
+            guard let data = try self.row.get(Expression<Data?>(key.stringValue)) else {
+                throw DecodingError(description: "an unsupported type was found")
+            }
+            if type == Data.self {
+                return data as! T
+            }
+            return try JSONDecoder().decode(type, from: data)
+        }
+
+        func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer<NestedKey> where NestedKey : CodingKey {
+            throw DecodingError(description: "decoding nested containers is not supported")
+        }
+
+        func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
+            throw DecodingError(description: "decoding unkeyed containers is not supported")
+        }
+
+        func superDecoder() throws -> Swift.Decoder {
+            throw DecodingError(description: "decoding super encoders is not supported")
+        }
+
+        func superDecoder(forKey key: Key) throws -> Swift.Decoder {
+            throw DecodingError(description: "decoding super encoders is not supported")
+        }
+    }
+
+    let row: Row
+    let codingPath: [CodingKey] = []
+    let userInfo: [CodingUserInfoKey: Any]
+
+    init(row: Row, userInfo: [CodingUserInfoKey: Any]) {
+        self.row = row
+        self.userInfo = userInfo
+    }
+
+    func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> where Key : CodingKey {
+        return KeyedDecodingContainer(SQLiteKeyedDecodingContainer(row: self.row))
+    }
+
+    func unkeyedContainer() throws -> UnkeyedDecodingContainer {
+        throw DecodingError(description: "decoding an unkeyed container is not supported by the SQLiteDecoder")
+    }
+
+    func singleValueContainer() throws -> SingleValueDecodingContainer {
+        throw DecodingError(description: "decoding a single value is not supported by the SQLiteDecoder")
+    }
+}
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index 7dde0c53..be414735 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -238,6 +238,27 @@ class QueryTests : XCTestCase {
         )
     }
 
+    func test_insert_encodable() throws {
+        let emails = Table("emails")
+        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil)
+        let insert = try emails.insert(value)
+        AssertSQL(
+            "INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\") VALUES (1, '2', 1, 3.0, 4.0)",
+            insert
+        )
+    }
+
+    func test_insert_encodable_with_nested_encodable() throws {
+        let emails = Table("emails")
+        let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil)
+        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: "optional", sub: value1)
+        let insert = try emails.insert(value)
+        AssertSQL(
+            "INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"optional\", \"sub\") VALUES (1, '2', 1, 3.0, 4.0, 'optional', x'7b22626f6f6c223a747275652c22737472696e67223a2232222c22666c6f6174223a332c22696e74223a312c22646f75626c65223a347d')",
+            insert
+        )
+    }
+
     func test_update_compilesUpdateExpression() {
         AssertSQL(
             "UPDATE \"users\" SET \"age\" = 30, \"admin\" = 1 WHERE (\"id\" = 1)",
@@ -252,6 +273,27 @@ class QueryTests : XCTestCase {
         )
     }
 
+    func test_update_encodable() throws {
+        let emails = Table("emails")
+        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil)
+        let update = try emails.update(value)
+        AssertSQL(
+            "UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0",
+            update
+        )
+    }
+
+    func test_update_encodable_with_nested_encodable() throws {
+        let emails = Table("emails")
+        let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil)
+        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: value1)
+        let update = try emails.update(value)
+        AssertSQL(
+            "UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0, \"sub\" = x'7b22626f6f6c223a747275652c22737472696e67223a2232222c22666c6f6174223a332c22696e74223a312c22646f75626c65223a347d'",
+            update
+        )
+    }
+
     func test_delete_compilesDeleteExpression() {
         AssertSQL(
             "DELETE FROM \"users\" WHERE (\"id\" = 1)",
@@ -356,6 +398,41 @@ class QueryIntegrationTests : SQLiteTestCase {
         }
     }
 
+    func test_select_codable() throws {
+        let table = Table("codable")
+        try db.run(table.create { builder in
+            builder.column(Expression<Int>("int"))
+            builder.column(Expression<String>("string"))
+            builder.column(Expression<Bool>("bool"))
+            builder.column(Expression<Double>("float"))
+            builder.column(Expression<Double>("double"))
+            builder.column(Expression<String?>("optional"))
+            builder.column(Expression<Data>("sub"))
+        })
+
+        let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil)
+        let value = TestCodable(int: 5, string: "6", bool: true, float: 7, double: 8, optional: "optional", sub: value1)
+
+        try db.run(table.insert(value))
+
+        let rows = try db.prepare(table)
+        let values: [TestCodable] = try rows.map({ try $0.decode() })
+        XCTAssertEqual(values.count, 1)
+        XCTAssertEqual(values[0].int, 5)
+        XCTAssertEqual(values[0].string, "6")
+        XCTAssertEqual(values[0].bool, true)
+        XCTAssertEqual(values[0].float, 7)
+        XCTAssertEqual(values[0].double, 8)
+        XCTAssertEqual(values[0].optional, "optional")
+        XCTAssertEqual(values[0].sub?.int, 1)
+        XCTAssertEqual(values[0].sub?.string, "2")
+        XCTAssertEqual(values[0].sub?.bool, true)
+        XCTAssertEqual(values[0].sub?.float, 3)
+        XCTAssertEqual(values[0].sub?.double, 4)
+        XCTAssertNil(values[0].sub?.optional)
+        XCTAssertNil(values[0].sub?.sub)
+    }
+
     func test_scalar() {
         XCTAssertEqual(0, try! db.scalar(users.count))
         XCTAssertEqual(false, try! db.scalar(users.exists))
diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index b66144b3..4572f6fe 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -113,3 +113,23 @@ let table = Table("table")
 let qualifiedTable = Table("table", database: "main")
 let virtualTable = VirtualTable("virtual_table")
 let _view = View("view") // avoid Mac XCTestCase collision
+
+class TestCodable: Codable {
+    let int: Int
+    let string: String
+    let bool: Bool
+    let float: Float
+    let double: Double
+    let optional: String?
+    let sub: TestCodable?
+
+    init(int: Int, string: String, bool: Bool, float: Float, double: Double, optional: String?, sub: TestCodable?) {
+        self.int = int
+        self.string = string
+        self.bool = bool
+        self.float = float
+        self.double = double
+        self.optional = optional
+        self.sub = sub
+    }
+}

From 7312423d83bb713591a0d827a89fe664eba14451 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 26 Sep 2017 01:28:01 +0200
Subject: [PATCH 251/685] Avoid ambiguity

---
 Sources/SQLite/Core/Statement.swift | 8 --------
 Sources/SQLite/Typed/Query.swift    | 9 ++++++++-
 Tests/SQLiteTests/QueryTests.swift  | 9 +++++++++
 3 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index 5df00791..1e48d3e8 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -208,14 +208,6 @@ extension FailableIterator {
     public func next() -> Element? {
         return try! failableNext()
     }
-
-    public func map<T>(_ transform: (Element) throws -> T) throws -> [T] {
-        var elements = [T]()
-        while let row = try failableNext() {
-            elements.append(try transform(row))
-        }
-        return elements
-    }
 }
 
 extension Array {
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index a08561cb..d5680cd0 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -903,8 +903,15 @@ public struct RowIterator: FailableIterator {
     public func failableNext() throws -> Row? {
         return try statement.failableNext().flatMap { Row(columnNames, $0) }
     }
-}
 
+    public func map<T>(_ transform: (Element) throws -> T) throws -> [T] {
+        var elements = [T]()
+        while let row = try failableNext() {
+            elements.append(try transform(row))
+        }
+        return elements
+    }
+}
 
 extension Connection {
 
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index df0e7bec..0ba469a9 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -354,6 +354,15 @@ class QueryIntegrationTests : SQLiteTestCase {
         XCTAssertEqual(names.map({ "\($0)@example.com" }), emails.sorted())
     }
 
+    func test_ambiguousMap() {
+        let names = ["a", "b", "c"]
+        try! InsertUsers(names)
+
+        let emails = try! db.prepare("select email from users", []).map { $0[0] as! String  }
+
+        XCTAssertEqual(names.map({ "\($0)@example.com" }), emails.sorted())
+    }
+
     func test_select_optional() {
         let managerId = Expression<Int64?>("manager_id")
         let managers = users.alias("managers")

From 87b16d77db5df72d4c414658cc76d85f41914510 Mon Sep 17 00:00:00 2001
From: Andrew J Wagner <andrew@drewagllc.com>
Date: Mon, 25 Sep 2017 19:29:35 -0600
Subject: [PATCH 252/685] Store embedded Codable objects as JSON text instead
 of data

---
 Sources/SQLite/Typed/Query.swift   | 13 +++++++++----
 Tests/SQLiteTests/QueryTests.swift |  8 ++++++--
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index 45d15c79..0b257fbe 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -1254,7 +1254,8 @@ fileprivate class SQLiteEncoder: Encoder {
             }
             else {
                 let encoded = try JSONEncoder().encode(value)
-                self.encoder.setters.append(Expression(key.stringValue) <- encoded)
+                let string = String(data: encoded, encoding: .utf8)
+                self.encoder.setters.append(Expression(key.stringValue) <- string)
             }
         }
 
@@ -1408,12 +1409,16 @@ class SQLiteDecoder : Decoder {
         }
 
         func decode<T>(_ type: T.Type, forKey key: Key) throws -> T where T: Swift.Decodable {
-            guard let data = try self.row.get(Expression<Data?>(key.stringValue)) else {
-                throw DecodingError(description: "an unsupported type was found")
-            }
             if type == Data.self {
+                let data = try self.row.get(Expression<Data>(key.stringValue))
                 return data as! T
             }
+            guard let JSONString = try self.row.get(Expression<String?>(key.stringValue)) else {
+                throw DecodingError(description: "an unsupported type was found")
+            }
+            guard let data = JSONString.data(using: .utf8) else {
+                throw DecodingError(description: "invalid utf8 data found")
+            }
             return try JSONDecoder().decode(type, from: data)
         }
 
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index be414735..6ba55d16 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -253,8 +253,10 @@ class QueryTests : XCTestCase {
         let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil)
         let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: "optional", sub: value1)
         let insert = try emails.insert(value)
+        let encodedJSON = try JSONEncoder().encode(value1)
+        let encodedJSONString = String(data: encodedJSON, encoding: .utf8)!
         AssertSQL(
-            "INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"optional\", \"sub\") VALUES (1, '2', 1, 3.0, 4.0, 'optional', x'7b22626f6f6c223a747275652c22737472696e67223a2232222c22666c6f6174223a332c22696e74223a312c22646f75626c65223a347d')",
+            "INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"optional\", \"sub\") VALUES (1, '2', 1, 3.0, 4.0, 'optional', '\(encodedJSONString)')",
             insert
         )
     }
@@ -288,8 +290,10 @@ class QueryTests : XCTestCase {
         let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil)
         let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: value1)
         let update = try emails.update(value)
+        let encodedJSON = try JSONEncoder().encode(value1)
+        let encodedJSONString = String(data: encodedJSON, encoding: .utf8)!
         AssertSQL(
-            "UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0, \"sub\" = x'7b22626f6f6c223a747275652c22737472696e67223a2232222c22666c6f6174223a332c22696e74223a312c22646f75626c65223a347d'",
+            "UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0, \"sub\" = '\(encodedJSONString)'",
             update
         )
     }

From 96e55b19d31e30e4f3369d2ba077494c2c3d20b3 Mon Sep 17 00:00:00 2001
From: Andrew J Wagner <andrew@drewagllc.com>
Date: Tue, 26 Sep 2017 20:01:00 -0600
Subject: [PATCH 253/685] Extract Coding code to a separate file

---
 SQLite.xcodeproj/project.pbxproj  |  10 +
 Sources/SQLite/Typed/Coding.swift | 345 ++++++++++++++++++++++++++++++
 Sources/SQLite/Typed/Query.swift  | 320 +--------------------------
 3 files changed, 357 insertions(+), 318 deletions(-)
 create mode 100644 Sources/SQLite/Typed/Coding.swift

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index c033cf3a..3093b11d 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -97,6 +97,10 @@
 		3D67B3FB1DB2470600A4F4C6 /* SQLite-Bridging.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808D1C46E5230038162A /* SQLite-Bridging.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		3D67B3FC1DB2471B00A4F4C6 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		3D67B3FD1DB2472D00A4F4C6 /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */; };
+		49EB68C41F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
+		49EB68C51F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
+		49EB68C61F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
+		49EB68C71F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
 		EE247AD71C3F04ED00AE3E12 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		EE247ADE1C3F04ED00AE3E12 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE247AD31C3F04ED00AE3E12 /* SQLite.framework */; };
 		EE247B031C3F06E900AE3E12 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
@@ -213,6 +217,7 @@
 		19A17B93B48B5560E6E51791 /* Fixtures.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Fixtures.swift; sourceTree = "<group>"; };
 		19A17E2695737FAB5D6086E3 /* fixtures */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = folder; path = fixtures; sourceTree = "<group>"; };
 		3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.0.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
+		49EB68C31F7B3CB400D89D40 /* Coding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coding.swift; sourceTree = "<group>"; };
 		A121AC451CA35C79005A31D1 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AD31C3F04ED00AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AD61C3F04ED00AE3E12 /* SQLite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLite.h; sourceTree = "<group>"; };
@@ -446,6 +451,7 @@
 				EE247B001C3F06E900AE3E12 /* Query.swift */,
 				EE247B011C3F06E900AE3E12 /* Schema.swift */,
 				EE247B021C3F06E900AE3E12 /* Setter.swift */,
+				49EB68C31F7B3CB400D89D40 /* Coding.swift */,
 			);
 			path = Typed;
 			sourceTree = "<group>";
@@ -779,6 +785,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				03A65E801C6BB2FB0062603F /* CoreFunctions.swift in Sources */,
+				49EB68C61F7B3CB400D89D40 /* Coding.swift in Sources */,
 				03A65E761C6BB2E60062603F /* Blob.swift in Sources */,
 				03A65E7D1C6BB2F70062603F /* RTree.swift in Sources */,
 				03A65E791C6BB2EF0062603F /* SQLite-Bridging.m in Sources */,
@@ -834,6 +841,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				3D67B3F91DB246E700A4F4C6 /* SQLite-Bridging.m in Sources */,
+				49EB68C71F7B3CB400D89D40 /* Coding.swift in Sources */,
 				3D67B3F71DB246D700A4F4C6 /* Foundation.swift in Sources */,
 				3D67B3F81DB246D700A4F4C6 /* Helpers.swift in Sources */,
 				3D67B3E91DB246D100A4F4C6 /* Statement.swift in Sources */,
@@ -862,6 +870,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				EE247B0F1C3F06E900AE3E12 /* CoreFunctions.swift in Sources */,
+				49EB68C41F7B3CB400D89D40 /* Coding.swift in Sources */,
 				EE247B0A1C3F06E900AE3E12 /* RTree.swift in Sources */,
 				EE247B031C3F06E900AE3E12 /* Blob.swift in Sources */,
 				EE247B0B1C3F06E900AE3E12 /* Foundation.swift in Sources */,
@@ -917,6 +926,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				EE247B6F1C3F3FEC00AE3E12 /* CoreFunctions.swift in Sources */,
+				49EB68C51F7B3CB400D89D40 /* Coding.swift in Sources */,
 				EE247B651C3F3FEC00AE3E12 /* Blob.swift in Sources */,
 				EE247B6C1C3F3FEC00AE3E12 /* RTree.swift in Sources */,
 				EE247B681C3F3FEC00AE3E12 /* SQLite-Bridging.m in Sources */,
diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
new file mode 100644
index 00000000..68f0a998
--- /dev/null
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -0,0 +1,345 @@
+//
+// SQLite.swift
+// https://github.com/stephencelis/SQLite.swift
+// Copyright © 2014-2015 Stephen Celis.
+//
+// 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.
+//
+
+extension QueryType {
+    /// Creates an `INSERT` statement by encoding the given object
+    /// This method converts any custom nested types to JSON data and does not handle any sort
+    /// of object relationships. If you want to support relationships between objects you will
+    /// have to provide your own Encodable implementations that encode the correct ids.
+    ///
+    /// - Parameters:
+    ///
+    ///   - encodable: An encodable object to insert
+    ///
+    ///   - userInfo: User info to be passed to encoder
+    ///
+    ///   - otherSetters: Any other setters to include in the insert
+    ///
+    /// - Returns: An `INSERT` statement fort the encodable object
+    public func insert(_ encodable: Encodable, userInfo: [CodingUserInfoKey:Any] = [:], otherSetters: [Setter] = []) throws -> Insert {
+        let encoder = SQLiteEncoder(userInfo: userInfo)
+        try encodable.encode(to: encoder)
+        return self.insert(encoder.setters + otherSetters)
+    }
+
+    /// Creates an `UPDATE` statement by encoding the given object
+    /// This method converts any custom nested types to JSON data and does not handle any sort
+    /// of object relationships. If you want to support relationships between objects you will
+    /// have to provide your own Encodable implementations that encode the correct ids.
+    ///
+    /// - Parameters:
+    ///
+    ///   - encodable: An encodable object to insert
+    ///
+    ///   - userInfo: User info to be passed to encoder
+    ///
+    ///   - otherSetters: Any other setters to include in the insert
+    ///
+    /// - Returns: An `UPDATE` statement fort the encodable object
+    public func update(_ encodable: Encodable, userInfo: [CodingUserInfoKey:Any] = [:], otherSetters: [Setter] = []) throws -> Update {
+        let encoder = SQLiteEncoder(userInfo: userInfo)
+        try encodable.encode(to: encoder)
+        return self.update(encoder.setters + otherSetters)
+    }
+}
+
+extension Row {
+    /// Decode an object from this row
+    /// This method expects any custom nested types to be in the form of JSON data and does not handle
+    /// any sort of object relationships. If you want to support relationships between objects you will
+    /// have to provide your own Decodable implementations that decodes the correct columns.
+    ///
+    /// - Parameter: userInfo
+    ///
+    /// - Returns: a decoded object from this row
+    public func decode<V: Decodable>(userInfo: [CodingUserInfoKey: Any] = [:]) throws -> V {
+        return try V(from: self.decoder(userInfo: userInfo))
+    }
+
+    public func decoder(userInfo: [CodingUserInfoKey: Any] = [:]) -> Decoder {
+        return SQLiteDecoder(row: self, userInfo: userInfo)
+    }
+}
+
+/// Generates a list of settings for an Encodable object
+fileprivate class SQLiteEncoder: Encoder {
+    struct EncodingError: Error, CustomStringConvertible {
+        let description: String
+    }
+
+    class SQLiteKeyedEncodingContainer<MyKey: CodingKey>: KeyedEncodingContainerProtocol {
+        typealias Key = MyKey
+
+        let encoder: SQLiteEncoder
+        let codingPath: [CodingKey] = []
+
+        init(encoder: SQLiteEncoder) {
+            self.encoder = encoder
+        }
+
+        func superEncoder() -> Swift.Encoder {
+            fatalError("SQLiteEncoding does not support super encoders")
+        }
+
+        func superEncoder(forKey key: Key) -> Swift.Encoder {
+            fatalError("SQLiteEncoding does not support super encoders")
+        }
+
+        func encodeNil(forKey key: SQLiteEncoder.SQLiteKeyedEncodingContainer<Key>.Key) throws {
+            self.encoder.setters.append(Expression<String?>(key.stringValue) <- nil)
+        }
+
+        func encode(_ value: Int, forKey key: SQLiteEncoder.SQLiteKeyedEncodingContainer<Key>.Key) throws {
+            self.encoder.setters.append(Expression(key.stringValue) <- value)
+        }
+
+        func encode(_ value: Bool, forKey key: Key) throws {
+            self.encoder.setters.append(Expression(key.stringValue) <- value)
+        }
+
+        func encode(_ value: Float, forKey key: Key) throws {
+            self.encoder.setters.append(Expression(key.stringValue) <- Double(value))
+        }
+
+        func encode(_ value: Double, forKey key: Key) throws {
+            self.encoder.setters.append(Expression(key.stringValue) <- value)
+        }
+
+        func encode(_ value: String, forKey key: Key) throws {
+            self.encoder.setters.append(Expression(key.stringValue) <- value)
+        }
+
+        func encode<T>(_ value: T, forKey key: Key) throws where T : Swift.Encodable {
+            if let data = value as? Data {
+                self.encoder.setters.append(Expression(key.stringValue) <- data)
+            }
+            else {
+                let encoded = try JSONEncoder().encode(value)
+                let string = String(data: encoded, encoding: .utf8)
+                self.encoder.setters.append(Expression(key.stringValue) <- string)
+            }
+        }
+
+        func encode(_ value: Int8, forKey key: Key) throws {
+            throw EncodingError(description: "encoding an Int8 is not supported")
+        }
+
+        func encode(_ value: Int16, forKey key: Key) throws {
+            throw EncodingError(description: "encoding an Int16 is not supported")
+        }
+
+        func encode(_ value: Int32, forKey key: Key) throws {
+            throw EncodingError(description: "encoding an Int32 is not supported")
+        }
+
+        func encode(_ value: Int64, forKey key: Key) throws {
+            throw EncodingError(description: "encoding an Int64 is not supported")
+        }
+
+        func encode(_ value: UInt, forKey key: Key) throws {
+            throw EncodingError(description: "encoding an UInt is not supported")
+        }
+
+        func encode(_ value: UInt8, forKey key: Key) throws {
+            throw EncodingError(description: "encoding an UInt8 is not supported")
+        }
+
+        func encode(_ value: UInt16, forKey key: Key) throws {
+            throw EncodingError(description: "encoding an UInt16 is not supported")
+        }
+
+        func encode(_ value: UInt32, forKey key: Key) throws {
+            throw EncodingError(description: "encoding an UInt32 is not supported")
+        }
+
+        func encode(_ value: UInt64, forKey key: Key) throws {
+            throw EncodingError(description: "encoding an UInt64 is not supported")
+        }
+
+        func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> where NestedKey : CodingKey {
+            fatalError("encoding a nested container is not supported")
+        }
+
+        func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
+            fatalError("encoding nested values is not supported")
+        }
+    }
+
+    fileprivate var setters: [SQLite.Setter] = []
+    let codingPath: [CodingKey] = []
+    let userInfo: [CodingUserInfoKey: Any]
+
+    init(userInfo: [CodingUserInfoKey: Any]) {
+        self.userInfo = userInfo
+    }
+
+    func singleValueContainer() -> SingleValueEncodingContainer {
+        fatalError("not supported")
+    }
+
+    func unkeyedContainer() -> UnkeyedEncodingContainer {
+        fatalError("not supported")
+    }
+
+    func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key : CodingKey {
+        return KeyedEncodingContainer(SQLiteKeyedEncodingContainer(encoder: self))
+    }
+}
+
+fileprivate class SQLiteDecoder : Decoder {
+    struct DecodingError : Error, CustomStringConvertible {
+        let description: String
+    }
+
+    class SQLiteKeyedDecodingContainer<MyKey: CodingKey> : KeyedDecodingContainerProtocol {
+        typealias Key = MyKey
+
+        let codingPath: [CodingKey] = []
+        let row: Row
+
+        init(row: Row) {
+            self.row = row
+        }
+
+        var allKeys: [Key] {
+            return self.row.columnNames.keys.flatMap({Key(stringValue: $0)})
+        }
+
+        func contains(_ key: Key) -> Bool {
+            return self.row.hasValue(for: key.stringValue)
+        }
+
+        func decodeNil(forKey key: Key) throws -> Bool {
+            return !self.contains(key)
+        }
+
+        func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool {
+            return try self.row.get(Expression(key.stringValue))
+        }
+
+        func decode(_ type: Int.Type, forKey key: Key) throws -> Int {
+            return try self.row.get(Expression(key.stringValue))
+        }
+
+        func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 {
+            throw DecodingError(description: "decoding an Int8 is not supported")
+        }
+
+        func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 {
+            throw DecodingError(description: "decoding an Int16 is not supported")
+        }
+
+        func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 {
+            throw DecodingError(description: "decoding an Int32 is not supported")
+        }
+
+        func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
+            throw DecodingError(description: "decoding an Int64 is not supported")
+        }
+
+        func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {
+            throw DecodingError(description: "decoding an UInt is not supported")
+        }
+
+        func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 {
+            throw DecodingError(description: "decoding an UInt8 is not supported")
+        }
+
+        func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 {
+            throw DecodingError(description: "decoding an UInt16 is not supported")
+        }
+
+        func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 {
+            throw DecodingError(description: "decoding an UInt32 is not supported")
+        }
+
+        func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 {
+            throw DecodingError(description: "decoding an UInt64 is not supported")
+        }
+
+        func decode(_ type: Float.Type, forKey key: Key) throws -> Float {
+            return Float(try self.row.get(Expression<Double>(key.stringValue)))
+        }
+
+        func decode(_ type: Double.Type, forKey key: Key) throws -> Double {
+            return try self.row.get(Expression(key.stringValue))
+        }
+
+        func decode(_ type: String.Type, forKey key: Key) throws -> String {
+            return try self.row.get(Expression(key.stringValue))
+        }
+
+        func decode<T>(_ type: T.Type, forKey key: Key) throws -> T where T: Swift.Decodable {
+            if type == Data.self {
+                let data = try self.row.get(Expression<Data>(key.stringValue))
+                return data as! T
+            }
+            guard let JSONString = try self.row.get(Expression<String?>(key.stringValue)) else {
+                throw DecodingError(description: "an unsupported type was found")
+            }
+            guard let data = JSONString.data(using: .utf8) else {
+                throw DecodingError(description: "invalid utf8 data found")
+            }
+            return try JSONDecoder().decode(type, from: data)
+        }
+
+        func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer<NestedKey> where NestedKey : CodingKey {
+            throw DecodingError(description: "decoding nested containers is not supported")
+        }
+
+        func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
+            throw DecodingError(description: "decoding unkeyed containers is not supported")
+        }
+
+        func superDecoder() throws -> Swift.Decoder {
+            throw DecodingError(description: "decoding super encoders is not supported")
+        }
+
+        func superDecoder(forKey key: Key) throws -> Swift.Decoder {
+            throw DecodingError(description: "decoding super encoders is not supported")
+        }
+    }
+
+    let row: Row
+    let codingPath: [CodingKey] = []
+    let userInfo: [CodingUserInfoKey: Any]
+
+    init(row: Row, userInfo: [CodingUserInfoKey: Any]) {
+        self.row = row
+        self.userInfo = userInfo
+    }
+
+    func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> where Key : CodingKey {
+        return KeyedDecodingContainer(SQLiteKeyedDecodingContainer(row: self.row))
+    }
+
+    func unkeyedContainer() throws -> UnkeyedDecodingContainer {
+        throw DecodingError(description: "decoding an unkeyed container is not supported by the SQLiteDecoder")
+    }
+
+    func singleValueContainer() throws -> SingleValueDecodingContainer {
+        throw DecodingError(description: "decoding a single value is not supported by the SQLiteDecoder")
+    }
+}
+
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index 0b257fbe..5b778431 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -673,26 +673,6 @@ extension QueryType {
         ]).expression)
     }
 
-    /// Creates an `INSERT` statement by encoding the given object
-    /// This method converts any custom nested types to JSON data and does not handle any sort
-    /// of object relationships. If you want to support relationships between objects you will
-    /// have to provide your own Encodable implementations that encode the correct ids.
-    ///
-    /// - Parameters:
-    ///
-    ///   - encodable: An encodable object to insert
-    ///
-    ///   - userInfo: User info to be passed to encoder
-    ///
-    ///   - otherSetters: Any other setters to include in the insert
-    ///
-    /// - Returns: An `INSERT` statement fort the encodable object
-    public func insert(_ encodable: Encodable, userInfo: [CodingUserInfoKey:Any] = [:], otherSetters: [Setter] = []) throws -> Insert {
-        let encoder = SQLiteEncoder(userInfo: userInfo)
-        try encodable.encode(to: encoder)
-        return self.insert(encoder.setters + otherSetters)
-    }
-
     // MARK: UPDATE
 
     public func update(_ values: Setter...) -> Update {
@@ -713,26 +693,6 @@ extension QueryType {
         return Update(" ".join(clauses.flatMap { $0 }).expression)
     }
 
-    /// Creates an `UPDATE` statement by encoding the given object
-    /// This method converts any custom nested types to JSON data and does not handle any sort
-    /// of object relationships. If you want to support relationships between objects you will
-    /// have to provide your own Encodable implementations that encode the correct ids.
-    ///
-    /// - Parameters:
-    ///
-    ///   - encodable: An encodable object to insert
-    ///
-    ///   - userInfo: User info to be passed to encoder
-    ///
-    ///   - otherSetters: Any other setters to include in the insert
-    ///
-    /// - Returns: An `UPDATE` statement fort the encodable object
-    public func update(_ encodable: Encodable, userInfo: [CodingUserInfoKey:Any] = [:], otherSetters: [Setter] = []) throws -> Update {
-        let encoder = SQLiteEncoder(userInfo: userInfo)
-        try encodable.encode(to: encoder)
-        return self.update(encoder.setters + otherSetters)
-    }
-
     // MARK: DELETE
 
     public func delete() -> Delete {
@@ -1069,7 +1029,7 @@ extension Connection {
 
 public struct Row {
 
-    fileprivate let columnNames: [String: Int]
+    let columnNames: [String: Int]
 
     fileprivate let values: [Binding?]
 
@@ -1078,7 +1038,7 @@ public struct Row {
         self.values = values
     }
 
-    fileprivate func hasValue(for column: String) -> Bool {
+    func hasValue(for column: String) -> Bool {
         guard let idx = columnNames[column.quote()] else {
             return false
         }
@@ -1120,22 +1080,6 @@ public struct Row {
         return valueAtIndex(idx)
     }
 
-    /// Decode an object from this row
-    /// This method expects any custom nested types to be in the form of JSON data and does not handle
-    /// any sort of object relationships. If you want to support relationships between objects you will
-    /// have to provide your own Decodable implementations that decodes the correct columns.
-    ///
-    /// - Parameter: userInfo
-    ///
-    /// - Returns: a decoded object from this row
-    public func decode<V: Decodable>(userInfo: [CodingUserInfoKey: Any] = [:]) throws -> V {
-        return try V(from: self.decoder(userInfo: userInfo))
-    }
-
-    public func decoder(userInfo: [CodingUserInfoKey: Any] = [:]) -> Decoder {
-        return SQLiteDecoder(row: self, userInfo: userInfo)
-    }
-
     public subscript<T : Value>(column: Expression<T>) -> T {
         return try! get(column)
     }
@@ -1200,263 +1144,3 @@ public struct QueryClauses {
 
 }
 
-/// Generates a list of settings for an Encodable object
-fileprivate class SQLiteEncoder: Encoder {
-    struct EncodingError: Error, CustomStringConvertible {
-        let description: String
-    }
-
-    class SQLiteKeyedEncodingContainer<MyKey: CodingKey>: KeyedEncodingContainerProtocol {
-        typealias Key = MyKey
-
-        let encoder: SQLiteEncoder
-        let codingPath: [CodingKey] = []
-
-        init(encoder: SQLiteEncoder) {
-            self.encoder = encoder
-        }
-
-        func superEncoder() -> Swift.Encoder {
-            fatalError("SQLiteEncoding does not support super encoders")
-        }
-
-        func superEncoder(forKey key: Key) -> Swift.Encoder {
-            fatalError("SQLiteEncoding does not support super encoders")
-        }
-
-        func encodeNil(forKey key: SQLiteEncoder.SQLiteKeyedEncodingContainer<Key>.Key) throws {
-            self.encoder.setters.append(Expression<String?>(key.stringValue) <- nil)
-        }
-
-        func encode(_ value: Int, forKey key: SQLiteEncoder.SQLiteKeyedEncodingContainer<Key>.Key) throws {
-            self.encoder.setters.append(Expression(key.stringValue) <- value)
-        }
-
-        func encode(_ value: Bool, forKey key: Key) throws {
-            self.encoder.setters.append(Expression(key.stringValue) <- value)
-        }
-
-        func encode(_ value: Float, forKey key: Key) throws {
-            self.encoder.setters.append(Expression(key.stringValue) <- Double(value))
-        }
-
-        func encode(_ value: Double, forKey key: Key) throws {
-            self.encoder.setters.append(Expression(key.stringValue) <- value)
-        }
-
-        func encode(_ value: String, forKey key: Key) throws {
-            self.encoder.setters.append(Expression(key.stringValue) <- value)
-        }
-
-        func encode<T>(_ value: T, forKey key: Key) throws where T : Swift.Encodable {
-            if let data = value as? Data {
-                self.encoder.setters.append(Expression(key.stringValue) <- data)
-            }
-            else {
-                let encoded = try JSONEncoder().encode(value)
-                let string = String(data: encoded, encoding: .utf8)
-                self.encoder.setters.append(Expression(key.stringValue) <- string)
-            }
-        }
-
-        func encode(_ value: Int8, forKey key: Key) throws {
-            throw EncodingError(description: "encoding an Int8 is not supported")
-        }
-
-        func encode(_ value: Int16, forKey key: Key) throws {
-            throw EncodingError(description: "encoding an Int16 is not supported")
-        }
-
-        func encode(_ value: Int32, forKey key: Key) throws {
-            throw EncodingError(description: "encoding an Int32 is not supported")
-        }
-
-        func encode(_ value: Int64, forKey key: Key) throws {
-            throw EncodingError(description: "encoding an Int64 is not supported")
-        }
-
-        func encode(_ value: UInt, forKey key: Key) throws {
-            throw EncodingError(description: "encoding an UInt is not supported")
-        }
-
-        func encode(_ value: UInt8, forKey key: Key) throws {
-            throw EncodingError(description: "encoding an UInt8 is not supported")
-        }
-
-        func encode(_ value: UInt16, forKey key: Key) throws {
-            throw EncodingError(description: "encoding an UInt16 is not supported")
-        }
-
-        func encode(_ value: UInt32, forKey key: Key) throws {
-            throw EncodingError(description: "encoding an UInt32 is not supported")
-        }
-
-        func encode(_ value: UInt64, forKey key: Key) throws {
-            throw EncodingError(description: "encoding an UInt64 is not supported")
-        }
-
-        func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> where NestedKey : CodingKey {
-            fatalError("encoding a nested container is not supported")
-        }
-
-        func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
-            fatalError("encoding nested values is not supported")
-        }
-    }
-
-    fileprivate var setters: [SQLite.Setter] = []
-    let codingPath: [CodingKey] = []
-    let userInfo: [CodingUserInfoKey: Any]
-
-    init(userInfo: [CodingUserInfoKey: Any]) {
-        self.userInfo = userInfo
-    }
-
-    func singleValueContainer() -> SingleValueEncodingContainer {
-        fatalError("not supported")
-    }
-
-    func unkeyedContainer() -> UnkeyedEncodingContainer {
-        fatalError("not supported")
-    }
-
-    func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key : CodingKey {
-        return KeyedEncodingContainer(SQLiteKeyedEncodingContainer(encoder: self))
-    }
-}
-
-class SQLiteDecoder : Decoder {
-    struct DecodingError : Error, CustomStringConvertible {
-        let description: String
-    }
-
-    class SQLiteKeyedDecodingContainer<MyKey: CodingKey> : KeyedDecodingContainerProtocol {
-        typealias Key = MyKey
-
-        let codingPath: [CodingKey] = []
-        let row: Row
-
-        init(row: Row) {
-            self.row = row
-        }
-
-        var allKeys: [Key] {
-            return self.row.columnNames.keys.flatMap({Key(stringValue: $0)})
-        }
-
-        func contains(_ key: Key) -> Bool {
-            return self.row.hasValue(for: key.stringValue)
-        }
-
-        func decodeNil(forKey key: Key) throws -> Bool {
-            return !self.contains(key)
-        }
-
-        func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool {
-            return try self.row.get(Expression(key.stringValue))
-        }
-
-        func decode(_ type: Int.Type, forKey key: Key) throws -> Int {
-            return try self.row.get(Expression(key.stringValue))
-        }
-
-        func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 {
-            throw DecodingError(description: "decoding an Int8 is not supported")
-        }
-
-        func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 {
-            throw DecodingError(description: "decoding an Int16 is not supported")
-        }
-
-        func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 {
-            throw DecodingError(description: "decoding an Int32 is not supported")
-        }
-
-        func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
-            throw DecodingError(description: "decoding an Int64 is not supported")
-        }
-
-        func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {
-            throw DecodingError(description: "decoding an UInt is not supported")
-        }
-
-        func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 {
-            throw DecodingError(description: "decoding an UInt8 is not supported")
-        }
-
-        func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 {
-            throw DecodingError(description: "decoding an UInt16 is not supported")
-        }
-
-        func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 {
-            throw DecodingError(description: "decoding an UInt32 is not supported")
-        }
-
-        func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 {
-            throw DecodingError(description: "decoding an UInt64 is not supported")
-        }
-
-        func decode(_ type: Float.Type, forKey key: Key) throws -> Float {
-            return Float(try self.row.get(Expression<Double>(key.stringValue)))
-        }
-
-        func decode(_ type: Double.Type, forKey key: Key) throws -> Double {
-            return try self.row.get(Expression(key.stringValue))
-        }
-
-        func decode(_ type: String.Type, forKey key: Key) throws -> String {
-            return try self.row.get(Expression(key.stringValue))
-        }
-
-        func decode<T>(_ type: T.Type, forKey key: Key) throws -> T where T: Swift.Decodable {
-            if type == Data.self {
-                let data = try self.row.get(Expression<Data>(key.stringValue))
-                return data as! T
-            }
-            guard let JSONString = try self.row.get(Expression<String?>(key.stringValue)) else {
-                throw DecodingError(description: "an unsupported type was found")
-            }
-            guard let data = JSONString.data(using: .utf8) else {
-                throw DecodingError(description: "invalid utf8 data found")
-            }
-            return try JSONDecoder().decode(type, from: data)
-        }
-
-        func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer<NestedKey> where NestedKey : CodingKey {
-            throw DecodingError(description: "decoding nested containers is not supported")
-        }
-
-        func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
-            throw DecodingError(description: "decoding unkeyed containers is not supported")
-        }
-
-        func superDecoder() throws -> Swift.Decoder {
-            throw DecodingError(description: "decoding super encoders is not supported")
-        }
-
-        func superDecoder(forKey key: Key) throws -> Swift.Decoder {
-            throw DecodingError(description: "decoding super encoders is not supported")
-        }
-    }
-
-    let row: Row
-    let codingPath: [CodingKey] = []
-    let userInfo: [CodingUserInfoKey: Any]
-
-    init(row: Row, userInfo: [CodingUserInfoKey: Any]) {
-        self.row = row
-        self.userInfo = userInfo
-    }
-
-    func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> where Key : CodingKey {
-        return KeyedDecodingContainer(SQLiteKeyedDecodingContainer(row: self.row))
-    }
-
-    func unkeyedContainer() throws -> UnkeyedDecodingContainer {
-        throw DecodingError(description: "decoding an unkeyed container is not supported by the SQLiteDecoder")
-    }
-
-    func singleValueContainer() throws -> SingleValueDecodingContainer {
-        throw DecodingError(description: "decoding a single value is not supported by the SQLiteDecoder")
-    }
-}

From 6751ed293efb3b92e5f0e9369c440ffe55e40a34 Mon Sep 17 00:00:00 2001
From: Andrew J Wagner <andrew@drewagllc.com>
Date: Tue, 26 Sep 2017 20:34:13 -0600
Subject: [PATCH 254/685] Add documentation for coding functionality

---
 Documentation/Index.md | 90 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 89 insertions(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 7d13b5a7..cf673d05 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -50,6 +50,7 @@
     - [Date-Time Values](#date-time-values)
     - [Binary Data](#binary-data)
     - [Custom Type Caveats](#custom-type-caveats)
+  - [Codable Types](#codable-types)
   - [Other Operators](#other-operators)
   - [Core SQLite Functions](#core-sqlite-functions)
   - [Aggregate SQLite Functions](#aggregate-sqlite-functions)
@@ -72,7 +73,7 @@
 
 [Carthage][] is a simple, decentralized dependency manager for Cocoa. To
 install SQLite.swift with Carthage:
-
+## Custom Types
  1. Make sure Carthage is [installed][Carthage Installation].
 
  2. Update your Cartfile to include the following:
@@ -1296,6 +1297,93 @@ extension Row {
 }
 ```
 
+## Codable Types
+
+Codable types were introduced as a part of Swift 4 to allow serializing and deserializing types. SQLite.swift
+supports the insertion, updating, and retrieval of basic Codable types.
+
+### Inserting Codable Types
+
+Queries have a method to allow inserting an Encodable type.
+
+``` swift
+try db.run(users.insert(user))
+
+```
+
+There are two other parameters also available to this method:
+
+- `userInfo` is a dictionary that is passed to the encoder and made available to encodable types to allow customizing their behavior.
+- `otherSetters` allows you to specify additional setters on top of those that are generated from the encodable types themselves.
+
+### Updating Codable Types
+
+Queries have a method to allow updating an Encodable type.
+
+``` swift
+try db.run(users.update(user))
+
+```
+
+There are two other parameters also available to this method:
+
+- `userInfo` is a dictionary that is passed to the encoder and made available to encodable types to allow customizing their behavior.
+- `otherSetters` allows you to specify additional setters on top of those that are generated from the encodable types themselves.
+
+### Retrieving Codable Types
+
+Rows have a method to decode a Decodable type.
+
+``` swift
+let loadedUsers: [User] = try db.prepare(users).map { row in
+    return try row.decode()
+}
+```
+
+You can also create a decoder to use manually yourself. This can be useful for example if you are using
+the [Facade pattern](https://en.wikipedia.org/wiki/Facade_pattern) to hide subclasses behind a super class.
+For example, you may want to encode an Image type that can be multiple different formats such as PNGImage, JPGImage,
+or HEIFIamge. You will need to determine the correct subclass before you know which type to decode.
+
+``` swift
+enum ImageCodingKeys: String, CodingKey {
+    case kind
+}
+
+enum ImageKind: Int, Codable {
+    case png, jpg, heif
+}
+
+let loadedImages: [Image] = try db.prepare(images).map { row in
+    let decoder = row.decoder()
+    let container = try decoder.container(keyedBy: ImageCodingKeys.self)
+    switch try container.decode(ImageKind.self, forKey: .kind) {
+    case .png:
+        return try PNGImage(from: decoder)
+    case .jpg:
+        return try JPGImage(from: decoder)
+    case .heif:
+        return try HEIFImage(from: decoder)
+    }
+}
+```
+
+Both of the above methods also have the following optional parameter:
+
+- `userInfo` is a dictionary that is passed to the decoder and made available to decodable types to allow customizing their behavior.
+
+### Restrictions
+
+There are a few restrictions on using Codable types:
+
+- The encodable and decodable objects can only use the following types:
+    - Int, Bool, Float, Double, String
+    - Nested Codable types that will be encoded as JSON to a single column
+- These methods will not handle object relationships for you. You must write your own Codable and Decodable
+implementations if you wish to support this.
+- The Codable types may not try to access nested containers or nested unkeyed containers
+- The Codable types may not access single value containers or unkeyed containers
+- The Codable types may not access super decoders or encoders
 
 ## Other Operators
 

From c614d80b5eca8c29b64f8e64405397361b17f08a Mon Sep 17 00:00:00 2001
From: Andrew J Wagner <andrew@drewagllc.com>
Date: Tue, 26 Sep 2017 22:36:58 -0600
Subject: [PATCH 255/685] Fix CI

---
 Sources/SQLite/Typed/Coding.swift | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index 68f0a998..1e049666 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -22,6 +22,8 @@
 // THE SOFTWARE.
 //
 
+import Foundation
+
 extension QueryType {
     /// Creates an `INSERT` statement by encoding the given object
     /// This method converts any custom nested types to JSON data and does not handle any sort

From 7cb407d43d7446740ef2cad8716c74d8525f1594 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 27 Sep 2017 12:45:11 +0200
Subject: [PATCH 256/685] use PackageDescription API Version 4

---
 .travis.yml            |  2 +-
 Documentation/Index.md |  6 +++---
 Package.swift          | 18 +++++++-----------
 README.md              |  4 ++--
 4 files changed, 13 insertions(+), 17 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 62f36185..7ff85f9a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -17,7 +17,7 @@ matrix:
     - env: CARTHAGE_PLATFORM="Mac"
     - env: CARTHAGE_PLATFORM="watchOS"
     - env: CARTHAGE_PLATFORM="tvOS"
-    - env: PACKAGE_MANAGER_COMMAND="test -Xlinker -lsqlite3"
+    - env: PACKAGE_MANAGER_COMMAND="test"
 before_install:
   - gem update bundler
   - gem install xcpretty --no-document
diff --git a/Documentation/Index.md b/Documentation/Index.md
index 7d13b5a7..42c247b5 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -172,16 +172,16 @@ It is the recommended approach for using SQLite.swift in OSX CLI applications.
 
  1. Add the following to your `Package.swift` file:
 
-  ``` swift
+  ```swift
   dependencies: [
-    .Package(url: "https://github.com/stephencelis/SQLite.swift.git", majorVersion: 0, minor: 11)
+    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.11.4")
   ]
   ```
 
  2. Build your project:
 
   ``` sh
-  $ swift build -Xlinker -lsqlite3
+  $ swift build
   ```
 
 [Swift Package Manager]: https://swift.org/package-manager
diff --git a/Package.swift b/Package.swift
index fc7c5a0e..bab00031 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,17 +1,13 @@
+// swift-tools-version:4.0
 import PackageDescription
 
 let package = Package(
-    name: "SQLite",
+    name: "SQLite.swift",
+    products: [.library(name: "SQLite", targets: ["SQLite"])],
     targets: [
-        Target(
-            name: "SQLite",
-            dependencies: [
-                .Target(name: "SQLiteObjc")
-            ]),
-        Target(name: "SQLiteObjc")
+        .target(name: "SQLite", dependencies: ["SQLiteObjc"]),
+        .target(name: "SQLiteObjc"),
+        .testTarget(name: "SQLiteTests", dependencies: ["SQLite"], path: "Tests/SQLiteTests")
     ],
-    dependencies: [
-        .Package(url: "https://github.com/stephencelis/CSQLite.git", majorVersion: 0)
-    ],
-    exclude: ["Tests/CocoaPods", "Tests/Carthage"]
+    swiftLanguageVersions: [4]
 )
diff --git a/README.md b/README.md
index fe06c6f7..a10f2c09 100644
--- a/README.md
+++ b/README.md
@@ -168,14 +168,14 @@ The [Swift Package Manager][] is a tool for managing the distribution of Swift c
 
   ```swift
   dependencies: [
-      .Package(url: "https://github.com/stephencelis/SQLite.swift.git", majorVersion: 0, minor: 11)
+      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.11.4")
   ]
   ```
 
 2. Build your project:
 
   ``` sh
-  $ swift build -Xlinker -lsqlite3
+  $ swift build
   ```
 
 [Swift Package Manager]: https://swift.org/package-manager

From 7d3714deb0dbaed58ca718d7d1d8dc137f725045 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 27 Sep 2017 14:47:52 +0200
Subject: [PATCH 257/685] Workaround no longer needed

---
 Sources/SQLite/Core/Connection.swift         | 2 +-
 Sources/SQLite/Core/Statement.swift          | 2 +-
 Sources/SQLite/Helpers.swift                 | 2 +-
 Sources/SQLiteObjc/SQLite-Bridging.m         | 4 ++--
 Sources/SQLiteObjc/include/SQLite-Bridging.h | 8 ++------
 Tests/SQLiteTests/ConnectionTests.swift      | 2 +-
 6 files changed, 8 insertions(+), 12 deletions(-)

diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 0189d300..13e62fa1 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -28,7 +28,7 @@ import Dispatch
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif SWIFT_PACKAGE || COCOAPODS
+#elseif SWIFT_PACKAGE
 import SQLite3
 #endif
 
diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index 1e48d3e8..0ad5cd45 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -26,7 +26,7 @@
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif SWIFT_PACKAGE || COCOAPODS
+#elseif SWIFT_PACKAGE
 import SQLite3
 #endif
 
diff --git a/Sources/SQLite/Helpers.swift b/Sources/SQLite/Helpers.swift
index 52b158b1..4748ee53 100644
--- a/Sources/SQLite/Helpers.swift
+++ b/Sources/SQLite/Helpers.swift
@@ -26,7 +26,7 @@
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif SWIFT_PACKAGE || COCOAPODS
+#elseif SWIFT_PACKAGE
 import SQLite3
 #endif
 
diff --git a/Sources/SQLiteObjc/SQLite-Bridging.m b/Sources/SQLiteObjc/SQLite-Bridging.m
index d8fe6b68..e00a7315 100644
--- a/Sources/SQLiteObjc/SQLite-Bridging.m
+++ b/Sources/SQLiteObjc/SQLite-Bridging.m
@@ -112,14 +112,14 @@ static int __SQLiteTokenizerNext(sqlite3_tokenizer_cursor * pCursor, const char
     __SQLiteTokenizerNext
 };
 
-int _SQLiteRegisterTokenizer(SQLiteHandle * db, const char * moduleName, const char * submoduleName, _SQLiteTokenizerNextCallback callback) {
+int _SQLiteRegisterTokenizer(sqlite3 *db, const char * moduleName, const char * submoduleName, _SQLiteTokenizerNextCallback callback) {
     static dispatch_once_t onceToken;
     dispatch_once(&onceToken, ^{
         __SQLiteTokenizerMap = [NSMutableDictionary new];
     });
 
     sqlite3_stmt * stmt;
-    int status = sqlite3_prepare_v2((sqlite3 *)db, "SELECT fts3_tokenizer(?, ?)", -1, &stmt, 0);
+    int status = sqlite3_prepare_v2(db, "SELECT fts3_tokenizer(?, ?)", -1, &stmt, 0);
     if (status != SQLITE_OK ){
         return status;
     }
diff --git a/Sources/SQLiteObjc/include/SQLite-Bridging.h b/Sources/SQLiteObjc/include/SQLite-Bridging.h
index d15e8d56..5b356593 100644
--- a/Sources/SQLiteObjc/include/SQLite-Bridging.h
+++ b/Sources/SQLiteObjc/include/SQLite-Bridging.h
@@ -24,14 +24,10 @@
 
 @import Foundation;
 
-#ifndef COCOAPODS
 #import "sqlite3.h"
-#endif
-
-typedef struct SQLiteHandle SQLiteHandle; // CocoaPods workaround
 
 NS_ASSUME_NONNULL_BEGIN
-typedef NSString * _Nullable (^_SQLiteTokenizerNextCallback)(const char * input, int * inputOffset, int * inputLength);
-int _SQLiteRegisterTokenizer(SQLiteHandle * db, const char * module, const char * tokenizer, _Nullable _SQLiteTokenizerNextCallback callback);
+typedef NSString * _Nullable (^_SQLiteTokenizerNextCallback)(const char *input, int *inputOffset, int *inputLength);
+int _SQLiteRegisterTokenizer(sqlite3 *db, const char *module, const char *tokenizer, _Nullable _SQLiteTokenizerNextCallback callback);
 NS_ASSUME_NONNULL_END
 
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index 373cba0a..84620f4e 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -5,7 +5,7 @@ import XCTest
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif SWIFT_PACKAGE || COCOAPODS
+#elseif SWIFT_PACKAGE
 import SQLite3
 #endif
 

From bc005192d93eb92dc5ff6a7fd6cccc7ff025c2a6 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 27 Sep 2017 15:36:50 +0200
Subject: [PATCH 258/685] Linux support

---
 CHANGELOG.md                             |  3 +++
 Package.swift                            | 11 +++++++++++
 Sources/SQLite/Core/Connection.swift     | 12 ++++++++----
 Sources/SQLite/Core/Statement.swift      |  4 +++-
 Sources/SQLite/Helpers.swift             |  4 +++-
 Sources/SQLite/Typed/CoreFunctions.swift |  2 +-
 Tests/LinuxMain.swift                    |  6 ++++++
 Tests/SQLiteTests/ConnectionTests.swift  |  8 ++++++--
 Tests/SQLiteTests/TestHelpers.swift      |  2 +-
 9 files changed, 42 insertions(+), 10 deletions(-)
 create mode 100644 Tests/LinuxMain.swift

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3fa68dfe..bbb5d671 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
 0.11.4 (xx-09-2017), [diff][diff-0.11.4]
 ========================================
 
+* Preliminary Linux support ([#315][], [#681][])
 * Add `RowIterator` for more safety ([#647][], [#726][])
 * Make Row.get throw instead of crash ([#649][])
 * Fix create/drop index functions ([#666][])
@@ -46,6 +47,7 @@
 [diff-0.11.3]: https://github.com/stephencelis/SQLite.swift/compare/0.11.2...0.11.3
 [diff-0.11.4]: https://github.com/stephencelis/SQLite.swift/compare/0.11.3...0.11.4
 
+[#315]: https://github.com/stephencelis/SQLit1e.swift/issues/315
 [#481]: https://github.com/stephencelis/SQLit1e.swift/pull/481
 [#532]: https://github.com/stephencelis/SQLit1e.swift/issues/532
 [#541]: https://github.com/stephencelis/SQLit1e.swift/issues/541
@@ -62,6 +64,7 @@
 [#657]: https://github.com/stephencelis/SQLite.swift/issues/657
 [#666]: https://github.com/stephencelis/SQLite.swift/pull/666
 [#668]: https://github.com/stephencelis/SQLite.swift/pull/668
+[#681]: https://github.com/stephencelis/SQLite.swift/issues/681
 [#722]: https://github.com/stephencelis/SQLite.swift/pull/722
 [#723]: https://github.com/stephencelis/SQLite.swift/pull/723
 [#726]: https://github.com/stephencelis/SQLite.swift/pull/726
diff --git a/Package.swift b/Package.swift
index bab00031..c008e482 100644
--- a/Package.swift
+++ b/Package.swift
@@ -11,3 +11,14 @@ let package = Package(
     ],
     swiftLanguageVersions: [4]
 )
+
+#if os(Linux)
+    package.dependencies = [.package(url: "https://github.com/stephencelis/CSQLite.git", from: "0.0.3")]
+    package.targets = [
+        .target(name: "SQLite", exclude: ["Extensions/FTS4.swift", "Extensions/FTS5.swift"]),
+        .testTarget(name: "SQLiteTests", dependencies: ["SQLite"], path: "Tests/SQLiteTests", exclude: [
+            "FTS4Tests.swift",
+            "FTS5Tests.swift"
+        ])
+    ]
+#endif
diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 13e62fa1..a3b2f362 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -22,13 +22,15 @@
 // THE SOFTWARE.
 //
 
-import Foundation.NSUUID
+import Foundation
 import Dispatch
 #if SQLITE_SWIFT_STANDALONE
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif SWIFT_PACKAGE
+#elseif os(Linux)
+import CSQLite
+#else
 import SQLite3
 #endif
 
@@ -413,7 +415,7 @@ public final class Connection {
     ///
     ///       db.trace { SQL in print(SQL) }
     public func trace(_ callback: ((String) -> Void)?) {
-        #if SQLITE_SWIFT_SQLCIPHER
+        #if SQLITE_SWIFT_SQLCIPHER || os(Linux)
             trace_v1(callback)
         #else
             if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) {
@@ -583,9 +585,11 @@ public final class Connection {
             }
         }
         var flags = SQLITE_UTF8
+        #if !os(Linux)
         if deterministic {
             flags |= SQLITE_DETERMINISTIC
         }
+        #endif
         sqlite3_create_function_v2(handle, function, Int32(argc), flags, unsafeBitCast(box, to: UnsafeMutableRawPointer.self), { context, argc, value in
             let function = unsafeBitCast(sqlite3_user_data(context), to: Function.self)
             function(context, argc, value)
@@ -702,7 +706,7 @@ extension Result : CustomStringConvertible {
     }
 }
 
-#if !SQLITE_SWIFT_SQLCIPHER
+#if !SQLITE_SWIFT_SQLCIPHER && !os(Linux)
 @available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *)
 extension Connection {
     fileprivate func trace_v2(_ callback: ((String) -> Void)?) {
diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index 0ad5cd45..dc91d3d8 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -26,7 +26,9 @@
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif SWIFT_PACKAGE
+#elseif os(Linux)
+import CSQLite
+#else
 import SQLite3
 #endif
 
diff --git a/Sources/SQLite/Helpers.swift b/Sources/SQLite/Helpers.swift
index 4748ee53..64e5eca8 100644
--- a/Sources/SQLite/Helpers.swift
+++ b/Sources/SQLite/Helpers.swift
@@ -26,7 +26,9 @@
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif SWIFT_PACKAGE
+#elseif os(Linux)
+import CSQLite
+#else
 import SQLite3
 #endif
 
diff --git a/Sources/SQLite/Typed/CoreFunctions.swift b/Sources/SQLite/Typed/CoreFunctions.swift
index 9d17a326..be260ec8 100644
--- a/Sources/SQLite/Typed/CoreFunctions.swift
+++ b/Sources/SQLite/Typed/CoreFunctions.swift
@@ -22,7 +22,7 @@
 // THE SOFTWARE.
 //
 
-import Foundation.NSData
+import Foundation
 
 
 extension ExpressionType where UnderlyingType : Number {
diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift
new file mode 100644
index 00000000..59796fde
--- /dev/null
+++ b/Tests/LinuxMain.swift
@@ -0,0 +1,6 @@
+import XCTest
+@testable import SQLiteTests
+
+XCTMain([
+testCase([
+])])
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index 84620f4e..157fbe9f 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -1,11 +1,15 @@
 import XCTest
+import Foundation
+import Dispatch
 @testable import SQLite
 
 #if SQLITE_SWIFT_STANDALONE
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif SWIFT_PACKAGE
+#elseif os(Linux)
+import CSQLite
+#else
 import SQLite3
 #endif
 
@@ -336,7 +340,7 @@ class ConnectionTests : SQLiteTestCase {
         let stmt = try! db.prepare("SELECT *, sleep(?) FROM users", 0.1)
         try! stmt.run()
 
-        let deadline = DispatchTime.now() + Double(Int64(10 * NSEC_PER_MSEC)) / Double(NSEC_PER_SEC)
+        let deadline = DispatchTime.now() + 0.01
         _ = DispatchQueue(label: "queue", qos: .background).asyncAfter(deadline: deadline, execute: db.interrupt)
         AssertThrows(try stmt.run())
     }
diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index b66144b3..2ebbc56e 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -69,7 +69,7 @@ class SQLiteTestCase : XCTestCase {
 
     func async(expect description: String = "async", timeout: Double = 5, block: (@escaping () -> Void) -> Void) {
         let expectation = self.expectation(description: description)
-        block(expectation.fulfill)
+        block({ expectation.fulfill() })
         waitForExpectations(timeout: timeout, handler: nil)
     }
 

From 112bc6fbc28e4db26afcd63b1c36e979d8f9e198 Mon Sep 17 00:00:00 2001
From: Andrew Wagner <coding-git@drewag.me>
Date: Wed, 27 Sep 2017 14:05:47 -0600
Subject: [PATCH 259/685] Use native decoding and encoding errors

---
 Documentation/Index.md            |  1 -
 Sources/SQLite/Typed/Coding.swift | 61 ++++++++++++++-----------------
 2 files changed, 27 insertions(+), 35 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index cf673d05..a1370cd5 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -73,7 +73,6 @@
 
 [Carthage][] is a simple, decentralized dependency manager for Cocoa. To
 install SQLite.swift with Carthage:
-## Custom Types
  1. Make sure Carthage is [installed][Carthage Installation].
 
  2. Update your Cartfile to include the following:
diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index 1e049666..dd6a4ec2 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -86,10 +86,6 @@ extension Row {
 
 /// Generates a list of settings for an Encodable object
 fileprivate class SQLiteEncoder: Encoder {
-    struct EncodingError: Error, CustomStringConvertible {
-        let description: String
-    }
-
     class SQLiteKeyedEncodingContainer<MyKey: CodingKey>: KeyedEncodingContainerProtocol {
         typealias Key = MyKey
 
@@ -144,39 +140,39 @@ fileprivate class SQLiteEncoder: Encoder {
         }
 
         func encode(_ value: Int8, forKey key: Key) throws {
-            throw EncodingError(description: "encoding an Int8 is not supported")
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an Int8 is not supported"))
         }
 
         func encode(_ value: Int16, forKey key: Key) throws {
-            throw EncodingError(description: "encoding an Int16 is not supported")
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an Int16 is not supported"))
         }
 
         func encode(_ value: Int32, forKey key: Key) throws {
-            throw EncodingError(description: "encoding an Int32 is not supported")
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an Int32 is not supported"))
         }
 
         func encode(_ value: Int64, forKey key: Key) throws {
-            throw EncodingError(description: "encoding an Int64 is not supported")
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an Int64 is not supported"))
         }
 
         func encode(_ value: UInt, forKey key: Key) throws {
-            throw EncodingError(description: "encoding an UInt is not supported")
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an UInt is not supported"))
         }
 
         func encode(_ value: UInt8, forKey key: Key) throws {
-            throw EncodingError(description: "encoding an UInt8 is not supported")
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an UInt8 is not supported"))
         }
 
         func encode(_ value: UInt16, forKey key: Key) throws {
-            throw EncodingError(description: "encoding an UInt16 is not supported")
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an UInt16 is not supported"))
         }
 
         func encode(_ value: UInt32, forKey key: Key) throws {
-            throw EncodingError(description: "encoding an UInt32 is not supported")
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an UInt32 is not supported"))
         }
 
         func encode(_ value: UInt64, forKey key: Key) throws {
-            throw EncodingError(description: "encoding an UInt64 is not supported")
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an UInt64 is not supported"))
         }
 
         func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> where NestedKey : CodingKey {
@@ -210,10 +206,6 @@ fileprivate class SQLiteEncoder: Encoder {
 }
 
 fileprivate class SQLiteDecoder : Decoder {
-    struct DecodingError : Error, CustomStringConvertible {
-        let description: String
-    }
-
     class SQLiteKeyedDecodingContainer<MyKey: CodingKey> : KeyedDecodingContainerProtocol {
         typealias Key = MyKey
 
@@ -245,39 +237,40 @@ fileprivate class SQLiteDecoder : Decoder {
         }
 
         func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 {
-            throw DecodingError(description: "decoding an Int8 is not supported")
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an Int8 is not supported"))
         }
 
         func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 {
-            throw DecodingError(description: "decoding an Int16 is not supported")
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an Int16 is not supported"))
         }
 
         func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 {
-            throw DecodingError(description: "decoding an Int32 is not supported")
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an Int32 is not supported"))
         }
 
         func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
-            throw DecodingError(description: "decoding an Int64 is not supported")
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an UInt64 is not supported"))
         }
 
         func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {
-            throw DecodingError(description: "decoding an UInt is not supported")
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an UInt is not supported"))
+
         }
 
         func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 {
-            throw DecodingError(description: "decoding an UInt8 is not supported")
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an UInt8 is not supported"))
         }
 
         func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 {
-            throw DecodingError(description: "decoding an UInt16 is not supported")
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an UInt16 is not supported"))
         }
 
         func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 {
-            throw DecodingError(description: "decoding an UInt32 is not supported")
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an UInt32 is not supported"))
         }
 
         func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 {
-            throw DecodingError(description: "decoding an UInt64 is not supported")
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an UInt64 is not supported"))
         }
 
         func decode(_ type: Float.Type, forKey key: Key) throws -> Float {
@@ -298,28 +291,28 @@ fileprivate class SQLiteDecoder : Decoder {
                 return data as! T
             }
             guard let JSONString = try self.row.get(Expression<String?>(key.stringValue)) else {
-                throw DecodingError(description: "an unsupported type was found")
+                throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "an unsupported type was found"))
             }
             guard let data = JSONString.data(using: .utf8) else {
-                throw DecodingError(description: "invalid utf8 data found")
+                throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "invalid utf8 data found"))
             }
             return try JSONDecoder().decode(type, from: data)
         }
 
         func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer<NestedKey> where NestedKey : CodingKey {
-            throw DecodingError(description: "decoding nested containers is not supported")
+            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding nested containers is not supported"))
         }
 
         func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
-            throw DecodingError(description: "decoding unkeyed containers is not supported")
+            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding unkeyed containers is not supported"))
         }
 
         func superDecoder() throws -> Swift.Decoder {
-            throw DecodingError(description: "decoding super encoders is not supported")
+            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding super encoders containers is not supported"))
         }
 
         func superDecoder(forKey key: Key) throws -> Swift.Decoder {
-            throw DecodingError(description: "decoding super encoders is not supported")
+            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding super decoders is not supported"))
         }
     }
 
@@ -337,11 +330,11 @@ fileprivate class SQLiteDecoder : Decoder {
     }
 
     func unkeyedContainer() throws -> UnkeyedDecodingContainer {
-        throw DecodingError(description: "decoding an unkeyed container is not supported by the SQLiteDecoder")
+        throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an unkeyed container is not supported"))
     }
 
     func singleValueContainer() throws -> SingleValueDecodingContainer {
-        throw DecodingError(description: "decoding a single value is not supported by the SQLiteDecoder")
+        throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding a single value container is not supported"))
     }
 }
 

From 364a240a6217d4d1b6fd7c237a3cf9039cbad6ec Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 28 Sep 2017 02:09:47 +0200
Subject: [PATCH 260/685] Add date and time functions

Closes #142
---
 CHANGELOG.md                                  |   2 +
 Documentation/Index.md                        |  13 +++
 SQLite.xcodeproj/project.pbxproj              |  18 +++
 .../SQLite/Typed/DateAndTimeFunctions.swift   | 106 ++++++++++++++++++
 Sources/SQLite/Typed/Operators.swift          |  17 ++-
 .../DateAndTimeFunctionTests.swift            |  66 +++++++++++
 Tests/SQLiteTests/OperatorsTests.swift        |  31 +++++
 7 files changed, 249 insertions(+), 4 deletions(-)
 create mode 100644 Sources/SQLite/Typed/DateAndTimeFunctions.swift
 create mode 100644 Tests/SQLiteTests/DateAndTimeFunctionTests.swift

diff --git a/CHANGELOG.md b/CHANGELOG.md
index bbb5d671..e36e40d7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
 0.11.4 (xx-09-2017), [diff][diff-0.11.4]
 ========================================
 
+* Added Date and Time functions ([#142][])
 * Preliminary Linux support ([#315][], [#681][])
 * Add `RowIterator` for more safety ([#647][], [#726][])
 * Make Row.get throw instead of crash ([#649][])
@@ -47,6 +48,7 @@
 [diff-0.11.3]: https://github.com/stephencelis/SQLite.swift/compare/0.11.2...0.11.3
 [diff-0.11.4]: https://github.com/stephencelis/SQLite.swift/compare/0.11.3...0.11.4
 
+[#142]: https://github.com/stephencelis/SQLit1e.swift/issues/142
 [#315]: https://github.com/stephencelis/SQLit1e.swift/issues/315
 [#481]: https://github.com/stephencelis/SQLit1e.swift/pull/481
 [#532]: https://github.com/stephencelis/SQLit1e.swift/issues/532
diff --git a/Documentation/Index.md b/Documentation/Index.md
index eb5cbc53..9a6d07ad 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -54,6 +54,7 @@
   - [Other Operators](#other-operators)
   - [Core SQLite Functions](#core-sqlite-functions)
   - [Aggregate SQLite Functions](#aggregate-sqlite-functions)
+  - [Date and Time Functions](#date-and-time-functions)
   - [Custom SQL Functions](#custom-sql-functions)
   - [Custom Collations](#custom-collations)
   - [Full-text Search](#full-text-search)
@@ -1430,6 +1431,18 @@ Many of SQLite’s [core functions](https://www.sqlite.org/lang_corefunc.html) h
 
 Most of SQLite’s [aggregate functions](https://www.sqlite.org/lang_aggfunc.html) have been surfaced in and type-audited for SQLite.swift.
 
+## Date and Time functions
+
+SQLite's [date and time](https://www.sqlite.org/lang_datefunc.html) are available:
+
+```swift
+DateFunctions.date("now")
+// date('now')
+Date().date
+// date('2007-01-09T09:41:00.000')
+Expression<Date>("date").date
+// date("date")
+```
 
 ## Custom SQL Functions
 
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 3093b11d..cb776608 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -46,17 +46,22 @@
 		03A65E951C6BB3030062603F /* TestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B161C3F127200AE3E12 /* TestHelpers.swift */; };
 		03A65E971C6BB3210062603F /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 03A65E961C6BB3210062603F /* libsqlite3.tbd */; };
 		19A1709C3E7A406E62293B2A /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; };
+		19A17152E32A9585831E3FE0 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
 		19A1717B10CC941ACB5533D6 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
 		19A171967CC511C4F6F773C9 /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */; };
 		19A171E6FA242F72A308C594 /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
 		19A171F12AB8B07F2FD7201A /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
 		19A1720B67ED13E6150C6A3D /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */; };
 		19A17254FBA7894891F7297B /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
+		19A172EB202970561E5C4245 /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */; };
+		19A173668D948AD4DF1F5352 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
+		19A1737286A74F3CF7412906 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
 		19A17408007B182F884E3A53 /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; };
 		19A17490543609FCED53CACC /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
 		19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
 		19A1750CEE9B05267995CF3D /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
 		19A175DFF47B84757E547C62 /* fixtures in Resources */ = {isa = PBXBuildFile; fileRef = 19A17E2695737FAB5D6086E3 /* fixtures */; };
+		19A1769C1F3A7542BECF50FF /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */; };
 		19A177CC33F2E6A24AF90B02 /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
 		19A178072B371489E6A1E839 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
 		19A17835FD5886FDC5A3228F /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
@@ -66,8 +71,10 @@
 		19A179CCF9671E345E5A9811 /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
 		19A179E76EA6207669B60C1B /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
 		19A17C4B951CB054EE48AB1C /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
+		19A17C80076860CF7751A056 /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */; };
 		19A17DC282E36C4F41AA440B /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
 		19A17E04C4C0956715C5676A /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
+		19A17E29278A12BC4F542506 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
 		19A17EC0D68BA8C03288ADF7 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
 		19A17F3E1F7ACA33BD43E138 /* fixtures in Resources */ = {isa = PBXBuildFile; fileRef = 19A17E2695737FAB5D6086E3 /* fixtures */; };
 		19A17F60B685636D1F83C2DD /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; };
@@ -209,12 +216,14 @@
 		03A65E961C6BB3210062603F /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
 		19A1710E73A46D5AC721CDA9 /* Errors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = "<group>"; };
 		19A1721B8984686B9963B45D /* FTS5Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5Tests.swift; sourceTree = "<group>"; };
+		19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAndTimeFunctionTests.swift; sourceTree = "<group>"; };
 		19A1730E4390C775C25677D1 /* FTS5.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5.swift; sourceTree = "<group>"; };
 		19A17399EA9E61235D5D77BF /* CipherTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CipherTests.swift; sourceTree = "<group>"; };
 		19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RowTests.swift; sourceTree = "<group>"; };
 		19A178A39ACA9667A62663CC /* Cipher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cipher.swift; sourceTree = "<group>"; };
 		19A1794CC4D7827E997E32A7 /* FoundationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationTests.swift; sourceTree = "<group>"; };
 		19A17B93B48B5560E6E51791 /* Fixtures.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Fixtures.swift; sourceTree = "<group>"; };
+		19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAndTimeFunctions.swift; sourceTree = "<group>"; };
 		19A17E2695737FAB5D6086E3 /* fixtures */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = folder; path = fixtures; sourceTree = "<group>"; };
 		3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.0.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
 		49EB68C31F7B3CB400D89D40 /* Coding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coding.swift; sourceTree = "<group>"; };
@@ -408,6 +417,7 @@
 				19A17399EA9E61235D5D77BF /* CipherTests.swift */,
 				19A17B93B48B5560E6E51791 /* Fixtures.swift */,
 				19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */,
+				19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */,
 			);
 			name = SQLiteTests;
 			path = Tests/SQLiteTests;
@@ -452,6 +462,7 @@
 				EE247B011C3F06E900AE3E12 /* Schema.swift */,
 				EE247B021C3F06E900AE3E12 /* Setter.swift */,
 				49EB68C31F7B3CB400D89D40 /* Coding.swift */,
+				19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */,
 			);
 			path = Typed;
 			sourceTree = "<group>";
@@ -806,6 +817,7 @@
 				19A17EC0D68BA8C03288ADF7 /* FTS5.swift in Sources */,
 				19A179E76EA6207669B60C1B /* Cipher.swift in Sources */,
 				19A17FF4A10B44D3937C8CAC /* Errors.swift in Sources */,
+				19A1737286A74F3CF7412906 /* DateAndTimeFunctions.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -833,6 +845,7 @@
 				19A179A0C45377CB09BB358C /* CipherTests.swift in Sources */,
 				19A17F60B685636D1F83C2DD /* Fixtures.swift in Sources */,
 				19A1785195182AF8731A8BDA /* RowTests.swift in Sources */,
+				19A1769C1F3A7542BECF50FF /* DateAndTimeFunctionTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -862,6 +875,7 @@
 				3D67B3E81DB246BA00A4F4C6 /* Connection.swift in Sources */,
 				19A179CCF9671E345E5A9811 /* Cipher.swift in Sources */,
 				19A17DC282E36C4F41AA440B /* Errors.swift in Sources */,
+				19A173668D948AD4DF1F5352 /* DateAndTimeFunctions.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -891,6 +905,7 @@
 				19A1717B10CC941ACB5533D6 /* FTS5.swift in Sources */,
 				19A171F12AB8B07F2FD7201A /* Cipher.swift in Sources */,
 				19A1792C0520D4E83C2EB075 /* Errors.swift in Sources */,
+				19A17E29278A12BC4F542506 /* DateAndTimeFunctions.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -918,6 +933,7 @@
 				19A177CC33F2E6A24AF90B02 /* CipherTests.swift in Sources */,
 				19A17408007B182F884E3A53 /* Fixtures.swift in Sources */,
 				19A1720B67ED13E6150C6A3D /* RowTests.swift in Sources */,
+				19A17C80076860CF7751A056 /* DateAndTimeFunctionTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -947,6 +963,7 @@
 				19A1750CEE9B05267995CF3D /* FTS5.swift in Sources */,
 				19A17835FD5886FDC5A3228F /* Cipher.swift in Sources */,
 				19A17490543609FCED53CACC /* Errors.swift in Sources */,
+				19A17152E32A9585831E3FE0 /* DateAndTimeFunctions.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -974,6 +991,7 @@
 				19A17C4B951CB054EE48AB1C /* CipherTests.swift in Sources */,
 				19A1709C3E7A406E62293B2A /* Fixtures.swift in Sources */,
 				19A171967CC511C4F6F773C9 /* RowTests.swift in Sources */,
+				19A172EB202970561E5C4245 /* DateAndTimeFunctionTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/Sources/SQLite/Typed/DateAndTimeFunctions.swift b/Sources/SQLite/Typed/DateAndTimeFunctions.swift
new file mode 100644
index 00000000..0b9a497f
--- /dev/null
+++ b/Sources/SQLite/Typed/DateAndTimeFunctions.swift
@@ -0,0 +1,106 @@
+//
+// SQLite.swift
+// https://github.com/stephencelis/SQLite.swift
+// Copyright © 2014-2015 Stephen Celis.
+//
+// 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.
+//
+
+import Foundation
+
+/// All five date and time functions take a time string as an argument.
+/// The time string is followed by zero or more modifiers.
+/// The strftime() function also takes a format string as its first argument.
+///
+/// https://www.sqlite.org/lang_datefunc.html
+public class DateFunctions {
+    /// The date() function returns the date in this format: YYYY-MM-DD.
+    public static func date(_ timestring: String, _ modifiers: String...) -> Expression<Date?> {
+        return timefunction("date", timestring: timestring, modifiers: modifiers)
+    }
+
+    /// The time() function returns the time as HH:MM:SS.
+    public static func time(_ timestring: String, _ modifiers: String...) -> Expression<Date?> {
+        return timefunction("time", timestring: timestring, modifiers: modifiers)
+    }
+
+    /// The datetime() function returns "YYYY-MM-DD HH:MM:SS".
+    public static func datetime(_ timestring: String, _ modifiers: String...) -> Expression<Date?> {
+        return timefunction("datetime", timestring: timestring, modifiers: modifiers)
+    }
+
+    /// The julianday() function returns the Julian day -
+    /// the number of days since noon in Greenwich on November 24, 4714 B.C.
+    public static func julianday(_ timestring: String, _ modifiers: String...) -> Expression<Date?> {
+        return timefunction("julianday", timestring: timestring, modifiers: modifiers)
+    }
+
+    ///  The strftime() routine returns the date formatted according to the format string specified as the first argument.
+    public static func strftime(_ format: String, _ timestring: String, _ modifiers: String...) -> Expression<Date?> {
+        if !modifiers.isEmpty {
+            let templates = [String](repeating: "?", count: modifiers.count).joined(separator: ", ")
+            return Expression("strftime(?, ?, \(templates))", [format, timestring] + modifiers)
+        }
+        return Expression("strftime(?, ?)", [format, timestring])
+    }
+
+    private static func timefunction(_ name: String, timestring: String, modifiers: [String]) -> Expression<Date?> {
+        if !modifiers.isEmpty {
+            let templates = [String](repeating: "?", count: modifiers.count).joined(separator: ", ")
+            return Expression("\(name)(?, \(templates))", [timestring] + modifiers)
+        }
+        return Expression("\(name)(?)", [timestring])
+    }
+}
+
+extension Date {
+    public var date: Expression<Date?> {
+        return DateFunctions.date(dateFormatter.string(from: self))
+    }
+
+    public var time: Expression<Date?> {
+        return DateFunctions.time(dateFormatter.string(from: self))
+    }
+
+    public var datetime: Expression<Date?> {
+        return DateFunctions.datetime(dateFormatter.string(from: self))
+    }
+
+    public var julianday: Expression<Date?> {
+        return DateFunctions.julianday(dateFormatter.string(from: self))
+    }
+}
+
+extension Expression where UnderlyingType == Date {
+    public var date: Expression<Date> {
+        return Expression<Date>("date(\(template))", bindings)
+    }
+
+    public var time: Expression<Date> {
+        return Expression<Date>("time(\(template))", bindings)
+    }
+
+    public var datetime: Expression<Date> {
+        return Expression<Date>("datetime(\(template))", bindings)
+    }
+
+    public var julianday: Expression<Date> {
+        return Expression<Date>("julianday(\(template))", bindings)
+    }
+}
diff --git a/Sources/SQLite/Typed/Operators.swift b/Sources/SQLite/Typed/Operators.swift
index 01381bb8..5f95993f 100644
--- a/Sources/SQLite/Typed/Operators.swift
+++ b/Sources/SQLite/Typed/Operators.swift
@@ -474,11 +474,20 @@ public func <=<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> wher
     return infix(lhs, rhs)
 }
 
-public func ~=<V : Value>(lhs: ClosedRange<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return Expression("\(rhs.template) BETWEEN ? AND ?", rhs.bindings + [lhs.lowerBound as? Binding, lhs.upperBound as? Binding])
+public func ~=<V : Value>(lhs: ClosedRange<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable & Value {
+    return Expression("\(rhs.template) BETWEEN ? AND ?", rhs.bindings + [lhs.lowerBound.datatypeValue, lhs.upperBound.datatypeValue])
 }
-public func ~=<V : Value>(lhs: ClosedRange<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return Expression("\(rhs.template) BETWEEN ? AND ?", rhs.bindings + [lhs.lowerBound as? Binding, lhs.upperBound as? Binding])
+
+public func ~=<V : Value>(lhs: ClosedRange<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable & Value {
+    return Expression("\(rhs.template) BETWEEN ? AND ?", rhs.bindings + [lhs.lowerBound.datatypeValue, lhs.upperBound.datatypeValue])
+}
+
+public func ~=<V : Value>(lhs: Range<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable & Value {
+    return Expression("\(rhs.template) >= ? AND \(rhs.template) < ?", rhs.bindings + [lhs.lowerBound.datatypeValue] + rhs.bindings + [lhs.upperBound.datatypeValue])
+}
+
+public func ~=<V : Value>(lhs: Range<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable & Value {
+    return Expression("\(rhs.template) >= ? AND \(rhs.template) < ?", rhs.bindings + [lhs.lowerBound.datatypeValue] + rhs.bindings + [lhs.upperBound.datatypeValue])
 }
 
 // MARK: -
diff --git a/Tests/SQLiteTests/DateAndTimeFunctionTests.swift b/Tests/SQLiteTests/DateAndTimeFunctionTests.swift
new file mode 100644
index 00000000..628b5910
--- /dev/null
+++ b/Tests/SQLiteTests/DateAndTimeFunctionTests.swift
@@ -0,0 +1,66 @@
+import XCTest
+@testable import SQLite
+
+class DateAndTimeFunctionsTests : XCTestCase {
+
+    func test_date() {
+        AssertSQL("date('now')", DateFunctions.date("now"))
+        AssertSQL("date('now', 'localtime')", DateFunctions.date("now", "localtime"))
+    }
+
+    func test_time() {
+        AssertSQL("time('now')", DateFunctions.time("now"))
+        AssertSQL("time('now', 'localtime')", DateFunctions.time("now", "localtime"))
+    }
+
+    func test_datetime() {
+        AssertSQL("datetime('now')", DateFunctions.datetime("now"))
+        AssertSQL("datetime('now', 'localtime')", DateFunctions.datetime("now", "localtime"))
+    }
+
+    func test_julianday() {
+        AssertSQL("julianday('now')", DateFunctions.julianday("now"))
+        AssertSQL("julianday('now', 'localtime')", DateFunctions.julianday("now", "localtime"))
+    }
+
+    func test_strftime() {
+        AssertSQL("strftime('%Y-%m-%d', 'now')", DateFunctions.strftime("%Y-%m-%d", "now"))
+        AssertSQL("strftime('%Y-%m-%d', 'now', 'localtime')", DateFunctions.strftime("%Y-%m-%d", "now", "localtime"))
+    }
+}
+
+class DateExtensionTests : XCTestCase {
+    func test_time() {
+        AssertSQL("time('1970-01-01T00:00:00.000')", Date(timeIntervalSince1970: 0).time)
+    }
+
+    func test_date() {
+        AssertSQL("date('1970-01-01T00:00:00.000')", Date(timeIntervalSince1970: 0).date)
+    }
+
+    func test_datetime() {
+        AssertSQL("datetime('1970-01-01T00:00:00.000')", Date(timeIntervalSince1970: 0).datetime)
+    }
+
+    func test_julianday() {
+        AssertSQL("julianday('1970-01-01T00:00:00.000')", Date(timeIntervalSince1970: 0).julianday)
+    }
+}
+
+class DateExpressionTests : XCTestCase {
+    func test_date() {
+        AssertSQL("date(\"date\")", date.date)
+    }
+
+    func test_time() {
+        AssertSQL("time(\"date\")", date.time)
+    }
+
+    func test_datetime() {
+        AssertSQL("datetime(\"date\")", date.datetime)
+    }
+
+    func test_julianday() {
+        AssertSQL("julianday(\"date\")", date.julianday)
+    }
+}
diff --git a/Tests/SQLiteTests/OperatorsTests.swift b/Tests/SQLiteTests/OperatorsTests.swift
index f0e585cd..08e679c1 100644
--- a/Tests/SQLiteTests/OperatorsTests.swift
+++ b/Tests/SQLiteTests/OperatorsTests.swift
@@ -255,6 +255,11 @@ class OperatorsTests : XCTestCase {
         AssertSQL("\"doubleOptional\" BETWEEN 1.2 AND 4.5", 1.2...4.5 ~= doubleOptional)
     }
 
+    func test_patternMatchingOperator_withComparableRange_buildsBooleanExpression() {
+        AssertSQL("\"double\" >= 1.2 AND \"double\" < 4.5", 1.2..<4.5 ~= double)
+        AssertSQL("\"doubleOptional\" >= 1.2 AND \"doubleOptional\" < 4.5", 1.2..<4.5 ~= doubleOptional)
+    }
+
     func test_patternMatchingOperator_withomparableClosedRangeString_buildsBetweenBooleanExpression() {
         AssertSQL("\"string\" BETWEEN 'a' AND 'b'", "a"..."b" ~= string)
         AssertSQL("\"stringOptional\" BETWEEN 'a' AND 'b'", "a"..."b" ~= stringOptional)
@@ -293,4 +298,30 @@ class OperatorsTests : XCTestCase {
         AssertSQL("((1 = 1) AND ((1 = 1) OR (1 = 1)))", n == n && (n == n || n == n))
     }
 
+    func test_dateExpressionLessGreater() {
+        let begin = Date(timeIntervalSince1970: 0)
+        AssertSQL("(\"date\" < '1970-01-01T00:00:00.000')", date < begin)
+        AssertSQL("(\"date\" > '1970-01-01T00:00:00.000')", date > begin)
+        AssertSQL("(\"date\" >= '1970-01-01T00:00:00.000')", date >= begin)
+        AssertSQL("(\"date\" <= '1970-01-01T00:00:00.000')", date <= begin)
+    }
+
+    func test_dateExpressionRange() {
+        let begin = Date(timeIntervalSince1970: 0)
+        let end = Date(timeIntervalSince1970: 5000)
+        AssertSQL(
+            "\"date\" >= '1970-01-01T00:00:00.000' AND \"date\" < '1970-01-01T01:23:20.000'",
+            (begin..<end) ~= date
+        )
+    }
+
+    func test_dateExpressionClosedRange() {
+        let begin = Date(timeIntervalSince1970: 0)
+        let end = Date(timeIntervalSince1970: 5000)
+        AssertSQL(
+            "\"date\" BETWEEN '1970-01-01T00:00:00.000' AND '1970-01-01T01:23:20.000'",
+            (begin...end) ~= date
+        )
+    }
+
 }

From 5c9f6609b97a156b7a82c910ac8f69661fb22c22 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 28 Sep 2017 08:36:31 +0200
Subject: [PATCH 261/685] Reflow documentation

---
 Documentation/Index.md | 849 +++++++++++++++++++++++++++--------------
 README.md              |  47 ++-
 2 files changed, 590 insertions(+), 306 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 9a6d07ad..9657a94a 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -67,7 +67,8 @@
 
 ## Installation
 
-> _Note:_ SQLite.swift requires Swift 3 (and [Xcode 8](https://developer.apple.com/xcode/downloads/)) or greater.
+> _Note:_ SQLite.swift requires Swift 4 (and
+> [Xcode 9](https://developer.apple.com/xcode/downloads/)) or greater.
 
 
 ### Carthage
@@ -78,7 +79,7 @@ install SQLite.swift with Carthage:
 
  2. Update your Cartfile to include the following:
 
-    ```
+    ```ruby
     github "stephencelis/SQLite.swift" ~> 0.11.4
     ```
 
@@ -94,9 +95,10 @@ install SQLite.swift with Carthage:
 
 [CocoaPods][] is a dependency manager for Cocoa projects. To install SQLite.swift with CocoaPods:
 
- 1. Make sure CocoaPods is [installed][CocoaPods Installation] (SQLite.swift requires version 1.0.0 or greater).
+ 1. Make sure CocoaPods is [installed][CocoaPods Installation] (SQLite.swift
+    requires version 1.0.0 or greater).
 
-    ``` sh
+    ```sh
     # Using the default Ruby install will require you to use sudo when
     # installing and updating gems.
     [sudo] gem install cocoapods
@@ -104,7 +106,7 @@ install SQLite.swift with Carthage:
 
  2. Update your Podfile to include the following:
 
-    ``` ruby
+    ```ruby
     use_frameworks!
 
     target 'YourAppTargetName' do
@@ -117,17 +119,20 @@ install SQLite.swift with Carthage:
 
 #### Requiring a specific version of SQLite
 
- If you want to use a more recent version of SQLite than what is provided with the OS you can require the `standalone` subspec:
+If you want to use a more recent version of SQLite than what is provided
+with the OS you can require the `standalone` subspec:
 
-``` ruby
+```ruby
 target 'YourAppTargetName' do
   pod 'SQLite.swift/standalone', '~> 0.11.4'
 end
 ```
 
-By default this will use the most recent version of SQLite without any extras. If you want you can further customize this by adding another dependency to sqlite3 or one of its subspecs:
+By default this will use the most recent version of SQLite without any
+extras. If you want you can further customize this by adding another
+dependency to sqlite3 or one of its subspecs:
 
-``` ruby
+```ruby
 target 'YourAppTargetName' do
   pod 'SQLite.swift/standalone', '~> 0.11.4'
   pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
@@ -138,19 +143,19 @@ See the [sqlite3 podspec][sqlite3pod] for more details.
 
 #### Using SQLite.swift with SQLCipher
 
-If you want to use [SQLCipher][] with SQLite.swift you can require the `SQLCipher`
-subspec in your Podfile:
+If you want to use [SQLCipher][] with SQLite.swift you can require the
+`SQLCipher` subspec in your Podfile:
 
-``` ruby
+```ruby
 target 'YourAppTargetName' do
   pod 'SQLite.swift/SQLCipher', '~> 0.11.4'
 end
 ```
 
-This will automatically add a dependency to the SQLCipher pod as well as extend
-`Connection` with methods to change the database key:
+This will automatically add a dependency to the SQLCipher pod as well as
+extend `Connection` with methods to change the database key:
 
-``` swift
+```swift
 import SQLite
 
 let db = try Connection("path/to/db.sqlite3")
@@ -165,11 +170,12 @@ try db.rekey("another secret")
 
 ### Swift Package Manager
 
-The [Swift Package Manager][] is a tool for managing the distribution of Swift code.
-It’s integrated with the Swift build system to automate the process of
-downloading, compiling, and linking dependencies.
+The [Swift Package Manager][] is a tool for managing the distribution of
+Swift code. It’s integrated with the Swift build system to automate the
+process of downloading, compiling, and linking dependencies.
 
-It is the recommended approach for using SQLite.swift in OSX CLI applications.
+It is the recommended approach for using SQLite.swift in OSX CLI
+applications.
 
  1. Add the following to your `Package.swift` file:
 
@@ -181,7 +187,7 @@ It is the recommended approach for using SQLite.swift in OSX CLI applications.
 
  2. Build your project:
 
-  ``` sh
+  ```sh
   $ swift build
   ```
 
@@ -191,21 +197,28 @@ It is the recommended approach for using SQLite.swift in OSX CLI applications.
 
 To install SQLite.swift as an Xcode sub-project:
 
- 1. Drag the **SQLite.xcodeproj** file into your own project. ([Submodule](http://git-scm.com/book/en/Git-Tools-Submodules), clone, or [download](https://github.com/stephencelis/SQLite.swift/archive/master.zip) the project first.)
+ 1. Drag the **SQLite.xcodeproj** file into your own project.
+    ([Submodule](http://git-scm.com/book/en/Git-Tools-Submodules), clone, or
+    [download](https://github.com/stephencelis/SQLite.swift/archive/master.zip)
+    the project first.)
 
     ![Installation Screen Shot](Resources/installation@2x.png)
 
- 2. In your target’s **General** tab, click the **+** button under **Linked Frameworks and Libraries**.
+ 2. In your target’s **General** tab, click the **+** button under **Linked
+    Frameworks and Libraries**.
 
  3. Select the appropriate **SQLite.framework** for your platform.
 
  4. **Add**.
 
-You should now be able to `import SQLite` from any of your target’s source files and begin using SQLite.swift.
+You should now be able to `import SQLite` from any of your target’s source
+files and begin using SQLite.swift.
 
-Some additional steps are required to install the application on an actual device:
+Some additional steps are required to install the application on an actual
+device:
 
- 5. In the **General** tab, click the **+** button under **Embedded Binaries**.
+ 5. In the **General** tab, click the **+** button under **Embedded
+    Binaries**.
 
  6. Select the appropriate **SQLite.framework** for your platform.
 
@@ -213,27 +226,31 @@ Some additional steps are required to install the application on an actual devic
 
 ## Getting Started
 
-To use SQLite.swift classes or structures in your target’s source file, first import the `SQLite` module.
+To use SQLite.swift classes or structures in your target’s source file, first
+import the `SQLite` module.
 
-``` swift
+```swift
 import SQLite
 ```
 
 
 ### Connecting to a Database
 
-Database connections are established using the `Connection` class. A connection is initialized with a path to a database. SQLite will attempt to create the database file if it does not already exist.
+Database connections are established using the `Connection` class. A
+connection is initialized with a path to a database. SQLite will attempt to
+create the database file if it does not already exist.
 
-``` swift
+```swift
 let db = try Connection("path/to/db.sqlite3")
 ```
 
 
 #### Read-Write Databases
 
-On iOS, you can create a writable database in your app’s **Documents** directory.
+On iOS, you can create a writable database in your app’s **Documents**
+directory.
 
-``` swift
+```swift
 let path = NSSearchPathForDirectoriesInDomains(
     .documentDirectory, .userDomainMask, true
 ).first!
@@ -243,7 +260,7 @@ let db = try Connection("\(path)/db.sqlite3")
 
 On OS X, you can use your app’s **Application Support** directory:
 
-``` swift
+```swift
 var path = NSSearchPathForDirectoriesInDomains(
     .applicationSupportDirectory, .userDomainMask, true
 ).first! + "/" + Bundle.main.bundleIdentifier!
@@ -259,38 +276,53 @@ let db = try Connection("\(path)/db.sqlite3")
 
 #### Read-Only Databases
 
-If you bundle a database with your app (_i.e._, you’ve copied a database file into your Xcode project and added it to your application target), you can establish a _read-only_ connection to it.
+If you bundle a database with your app (_i.e._, you’ve copied a database file
+into your Xcode project and added it to your application target), you can
+establish a _read-only_ connection to it.
 
-``` swift
+```swift
 let path = Bundle.main.pathForResource("db", ofType: "sqlite3")!
 
 let db = try Connection(path, readonly: true)
 ```
 
-> _Note:_ Signed applications cannot modify their bundle resources. If you bundle a database file with your app for the purpose of bootstrapping, copy it to a writable location _before_ establishing a connection (see [Read-Write Databases](#read-write-databases), above, for typical, writable locations).
+> _Note:_ Signed applications cannot modify their bundle resources. If you
+> bundle a database file with your app for the purpose of bootstrapping, copy
+> it to a writable location _before_ establishing a connection (see [Read-
+> Write Databases](#read-write-databases), above, for typical, writable
+> locations).
 >
-> See these two Stack Overflow questions for more information about iOS apps with SQLite databases: [1](https://stackoverflow.com/questions/34609746/what-different-between-store-database-in-different-locations-in-ios), [2](https://stackoverflow.com/questions/34614968/ios-how-to-copy-pre-seeded-database-at-the-first-running-app-with-sqlite-swift). We welcome sample code to show how to successfully copy and use a bundled "seed" database for writing in an app.
+> See these two Stack Overflow questions for more information about iOS apps
+> with SQLite databases: [1](https://stackoverflow.com/questions/34609746/what-different-between-store-database-in-different-locations-in-ios),
+> [2](https://stackoverflow.com/questions/34614968/ios-how-to-copy-pre-seeded-database-at-the-first-running-app-with-sqlite-swift).
+> We welcome sample code to show how to successfully copy and use a bundled "seed"
+> database for writing in an app.
 
 #### In-Memory Databases
 
-If you omit the path, SQLite.swift will provision an [in-memory database](https://www.sqlite.org/inmemorydb.html).
+If you omit the path, SQLite.swift will provision an [in-memory
+database](https://www.sqlite.org/inmemorydb.html).
 
-``` swift
+```swift
 let db = try Connection() // equivalent to `Connection(.inMemory)`
 ```
 
 To create a temporary, disk-backed database, pass an empty file name.
 
-``` swift
+```swift
 let db = try Connection(.temporary)
 ```
 
-In-memory databases are automatically deleted when the database connection is closed.
+In-memory databases are automatically deleted when the database connection is
+closed.
 
 
 #### Thread-Safety
 
-Every Connection comes equipped with its own serial queue for statement execution and can be safely accessed across threads. Threads that open transactions and savepoints will block other threads from executing statements while the transaction is open.
+Every Connection comes equipped with its own serial queue for statement
+execution and can be safely accessed across threads. Threads that open
+transactions and savepoints will block other threads from executing
+statements while the transaction is open.
 
 If you maintain multiple connections for a single database, consider setting a timeout (in seconds) and/or a busy handler:
 
@@ -305,12 +337,16 @@ db.busyHandler({ tries in
 })
 ```
 
-> _Note:_ The default timeout is 0, so if you see `database is locked` errors, you may be trying to access the same database simultaneously from multiple connections.
+> _Note:_ The default timeout is 0, so if you see `database is locked`
+> errors, you may be trying to access the same database simultaneously from
+> multiple connections.
 
 
 ## Building Type-Safe SQL
 
-SQLite.swift comes with a typed expression layer that directly maps [Swift types](https://developer.apple.com/library/prerelease/ios/documentation/General/Reference/SwiftStandardLibraryReference/) to their [SQLite counterparts](https://www.sqlite.org/datatype3.html).
+SQLite.swift comes with a typed expression layer that directly maps
+[Swift types](https://developer.apple.com/library/prerelease/ios/documentation/General/Reference/SwiftStandardLibraryReference/)
+to their [SQLite counterparts](https://www.sqlite.org/datatype3.html).
 
 | Swift Type      | SQLite Type |
 | --------------- | ----------- |
@@ -320,22 +356,32 @@ SQLite.swift comes with a typed expression layer that directly maps [Swift types
 | `nil`           | `NULL`      |
 | `SQLite.Blob`†  | `BLOB`      |
 
-> *While `Int64` is the basic, raw type (to preserve 64-bit integers on 32-bit platforms), `Int` and `Bool` work transparently.
+> *While `Int64` is the basic, raw type (to preserve 64-bit integers on
+> 32-bit platforms), `Int` and `Bool` work transparently.
 >
-> †SQLite.swift defines its own `Blob` structure, which safely wraps the underlying bytes.
+> †SQLite.swift defines its own `Blob` structure, which safely wraps the
+> underlying bytes.
 >
-> See [Custom Types](#custom-types) for more information about extending other classes and structures to work with SQLite.swift.
+> See [Custom Types](#custom-types) for more information about extending
+> other classes and structures to work with SQLite.swift.
 >
-> See [Executing Arbitrary SQL](#executing-arbitrary-sql) to forego the typed layer and execute raw SQL, instead.
+> See [Executing Arbitrary SQL](#executing-arbitrary-sql) to forego the typed
+> layer and execute raw SQL, instead.
 
-These expressions (in the form of the structure, [`Expression`](#expressions)) build on one another and, with a query ([`QueryType`](#queries)), can create and execute SQL statements.
+These expressions (in the form of the structure,
+[`Expression`](#expressions)) build on one another and, with a query
+([`QueryType`](#queries)), can create and execute SQL statements.
 
 
 ### Expressions
 
-Expressions are generic structures associated with a type ([built-in](#building-type-safe-sql) or [custom](#custom-types)), raw SQL, and (optionally) values to bind to that SQL. Typically, you will only explicitly create expressions to describe your columns, and typically only once per column.
+Expressions are generic structures associated with a type ([built-in
+](#building-type-safe-sql) or [custom](#custom-types)), raw SQL, and
+(optionally) values to bind to that SQL. Typically, you will only explicitly
+create expressions to describe your columns, and typically only once per
+column.
 
-``` swift
+```swift
 let id = Expression<Int64>("id")
 let email = Expression<String>("email")
 let balance = Expression<Double>("balance")
@@ -344,34 +390,48 @@ let verified = Expression<Bool>("verified")
 
 Use optional generics for expressions that can evaluate to `NULL`.
 
-``` swift
+```swift
 let name = Expression<String?>("name")
 ```
 
-> _Note:_ The default `Expression` initializer is for [quoted identifiers](https://www.sqlite.org/lang_keywords.html) (_i.e._, column names). To build a literal SQL expression, use `init(literal:)`. <!-- FIXME -->
+> _Note:_ The default `Expression` initializer is for [quoted
+> identifiers](https://www.sqlite.org/lang_keywords.html) (_i.e._, column
+> names). To build a literal SQL expression, use `init(literal:)`.
+> <!-- FIXME -->
 
 
 ### Compound Expressions
 
-Expressions can be combined with other expressions and types using [filter operators and functions](#filter-operators-and-functions) (as well as other [non-filter operators](#other-operators) and [functions](#core-sqlite-functions)). These building blocks can create complex SQLite statements.
+Expressions can be combined with other expressions and types using
+[filter operators and functions](#filter-operators-and-functions)
+(as well as other [non-filter operators](#other-operators) and
+[functions](#core-sqlite-functions)). These building blocks can create complex SQLite statements.
 
 
 ### Queries
 
-Queries are structures that reference a database and table name, and can be used to build a variety of statements using expressions. We can create a query by initializing a `Table`, `View`, or `VirtualTable`.
+Queries are structures that reference a database and table name, and can be
+used to build a variety of statements using expressions. We can create a
+query by initializing a `Table`, `View`, or `VirtualTable`.
 
-``` swift
+```swift
 let users = Table("users")
 ```
 
-Assuming [the table exists](#creating-a-table), we can immediately [insert](#inserting-rows), [select](#selecting-rows), [update](#updating-rows), and [delete](#deleting-rows) rows.
+Assuming [the table exists](#creating-a-table), we can immediately [insert
+](#inserting-rows), [select](#selecting-rows), [update](#updating-rows), and
+[delete](#deleting-rows) rows.
 
 
 ## Creating a Table
 
-We can build [`CREATE TABLE` statements](https://www.sqlite.org/lang_createtable.html) by calling the `create` function on a `Table`. The following is a basic example of SQLite.swift code (using the [expressions](#expressions) and [query](#queries) above) and the corresponding SQL it generates.
+We can build [`CREATE TABLE`
+statements](https://www.sqlite.org/lang_createtable.html) by calling the
+`create` function on a `Table`. The following is a basic example of
+SQLite.swift code (using the [expressions](#expressions) and
+[query](#queries) above) and the corresponding SQL it generates.
 
-``` swift
+```swift
 try db.run(users.create { t in     // CREATE TABLE "users" (
     t.column(id, primaryKey: true) //     "id" INTEGER PRIMARY KEY NOT NULL,
     t.column(email, unique: true)  //     "email" TEXT UNIQUE NOT NULL,
@@ -379,34 +439,42 @@ try db.run(users.create { t in     // CREATE TABLE "users" (
 })                                 // )
 ```
 
-> _Note:_ `Expression<T>` structures (in this case, the `id` and `email` columns), generate `NOT NULL` constraints automatically, while `Expression<T?>` structures (`name`) do not.
+> _Note:_ `Expression<T>` structures (in this case, the `id` and `email`
+> columns), generate `NOT NULL` constraints automatically, while
+> `Expression<T?>` structures (`name`) do not.
 
 
 ### Create Table Options
 
 The `Table.create` function has several default parameters we can override.
 
-  - `temporary` adds a `TEMPORARY` clause to the `CREATE TABLE` statement (to create a temporary table that will automatically drop when the database connection closes). Default: `false`.
+  - `temporary` adds a `TEMPORARY` clause to the `CREATE TABLE` statement (to
+    create a temporary table that will automatically drop when the database
+    connection closes). Default: `false`.
 
-    ``` swift
+    ```swift
     try db.run(users.create(temporary: true) { t in /* ... */ })
     // CREATE TEMPORARY TABLE "users" -- ...
     ```
 
-  - `ifNotExists` adds an `IF NOT EXISTS` clause to the `CREATE TABLE` statement (which will bail out gracefully if the table already exists). Default: `false`.
+  - `ifNotExists` adds an `IF NOT EXISTS` clause to the `CREATE TABLE`
+    statement (which will bail out gracefully if the table already exists).
+    Default: `false`.
 
-    ``` swift
+    ```swift
     try db.run(users.create(ifNotExists: true) { t in /* ... */ })
     // CREATE TABLE "users" IF NOT EXISTS -- ...
     ```
 
 ### Column Constraints
 
-The `column` function is used for a single column definition. It takes an [expression](#expressions) describing the column name and type, and accepts several parameters that map to various column constraints and clauses.
+The `column` function is used for a single column definition. It takes an
+[expression](#expressions) describing the column name and type, and accepts
+several parameters that map to various column constraints and clauses.
 
   - `primaryKey` adds a `PRIMARY KEY` constraint to a single column.
 
-    ``` swift
+    ```swift
     t.column(id, primaryKey: true)
     // "id" INTEGER PRIMARY KEY NOT NULL
 
@@ -414,38 +482,59 @@ The `column` function is used for a single column definition. It takes an [expre
     // "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL
     ```
 
-    > _Note:_ The `primaryKey` parameter cannot be used alongside `references`. If you need to create a column that has a default value and is also a primary and/or foreign key, use the `primaryKey` and `foreignKey` functions mentioned under [Table Constraints](#table-constraints).
+    > _Note:_ The `primaryKey` parameter cannot be used alongside
+    > `references`. If you need to create a column that has a default value
+    > and is also a primary and/or foreign key, use the `primaryKey` and
+    > `foreignKey` functions mentioned under
+    > [Table Constraints](#table-constraints).
     >
     > Primary keys cannot be optional (_e.g._, `Expression<Int64?>`).
     >
     > Only an `INTEGER PRIMARY KEY` can take `.autoincrement`.
 
-  - `unique` adds a `UNIQUE` constraint to the column. (See the `unique` function under [Table Constraints](#table-constraints) for uniqueness over multiple columns).
+  - `unique` adds a `UNIQUE` constraint to the column. (See the `unique`
+    function under [Table Constraints](#table-constraints) for uniqueness
+    over multiple columns).
 
-    ``` swift
+    ```swift
     t.column(email, unique: true)
     // "email" TEXT UNIQUE NOT NULL
     ```
 
-  - `check` attaches a `CHECK` constraint to a column definition in the form of a boolean expression (`Expression<Bool>`). Boolean expressions can be easily built using [filter operators and functions](#filter-operators-and-functions). (See also the `check` function under [Table Constraints](#table-constraints).)
+  - `check` attaches a `CHECK` constraint to a column definition in the form
+    of a boolean expression (`Expression<Bool>`). Boolean expressions can be
+    easily built using
+    [filter operators and functions](#filter-operators-and-functions).
+    (See also the `check` function under
+    [Table Constraints](#table-constraints).)
 
-    ``` swift
+    ```swift
     t.column(email, check: email.like("%@%"))
     // "email" TEXT NOT NULL CHECK ("email" LIKE '%@%')
     ```
 
-  - `defaultValue` adds a `DEFAULT` clause to a column definition and _only_ accepts a value (or expression) matching the column’s type. This value is used if none is explicitly provided during [an `INSERT`](#inserting-rows).
+  - `defaultValue` adds a `DEFAULT` clause to a column definition and _only_
+    accepts a value (or expression) matching the column’s type. This value is
+    used if none is explicitly provided during [an `INSERT`](#inserting-
+    rows).
 
-    ``` swift
+    ```swift
     t.column(name, defaultValue: "Anonymous")
     // "name" TEXT DEFAULT 'Anonymous'
     ```
 
-    > _Note:_ The `defaultValue` parameter cannot be used alongside `primaryKey` and `references`. If you need to create a column that has a default value and is also a primary and/or foreign key, use the `primaryKey` and `foreignKey` functions mentioned under [Table Constraints](#table-constraints).
+    > _Note:_ The `defaultValue` parameter cannot be used alongside
+    > `primaryKey` and `references`. If you need to create a column that has
+    > a default value and is also a primary and/or foreign key, use the
+    > `primaryKey` and `foreignKey` functions mentioned under
+    > [Table Constraints](#table-constraints).
 
-  - `collate` adds a `COLLATE` clause to `Expression<String>` (and `Expression<String?>`) column definitions with [a collating sequence](https://www.sqlite.org/datatype3.html#collation) defined in the `Collation` enumeration.
+  - `collate` adds a `COLLATE` clause to `Expression<String>` (and
+    `Expression<String?>`) column definitions with
+    [a collating sequence](https://www.sqlite.org/datatype3.html#collation)
+    defined in the `Collation` enumeration.
 
-    ``` swift
+    ```swift
     t.column(email, collate: .nocase)
     // "email" TEXT NOT NULL COLLATE "NOCASE"
 
@@ -453,50 +542,66 @@ The `column` function is used for a single column definition. It takes an [expre
     // "name" TEXT COLLATE "RTRIM"
     ```
 
-  - `references` adds a `REFERENCES` clause to `Expression<Int64>` (and `Expression<Int64?>`) column definitions and accepts a table (`SchemaType`) or namespaced column expression. (See the `foreignKey` function under [Table Constraints](#table-constraints) for non-integer foreign key support.)
+  - `references` adds a `REFERENCES` clause to `Expression<Int64>` (and
+    `Expression<Int64?>`) column definitions and accepts a table
+    (`SchemaType`) or namespaced column expression. (See the `foreignKey`
+    function under [Table Constraints](#table-constraints) for non-integer
+    foreign key support.)
 
-    ``` swift
+    ```swift
     t.column(user_id, references: users, id)
     // "user_id" INTEGER REFERENCES "users" ("id")
-
-<!-- TODO: restore functionality?
-    t.column(user_id, references: users)
-    // "user_id" INTEGER REFERENCES "users"
-    // -- assumes "users" has a PRIMARY KEY
     ```
--->
 
-    > _Note:_ The `references` parameter cannot be used alongside `primaryKey` and `defaultValue`. If you need to create a column that has a default value and is also a primary and/or foreign key, use the `primaryKey` and `foreignKey` functions mentioned under [Table Constraints](#table-constraints).
+    > _Note:_ The `references` parameter cannot be used alongside
+    > `primaryKey` and `defaultValue`. If you need to create a column that
+    > has a default value and is also a primary and/or foreign key, use the
+    > `primaryKey` and `foreignKey` functions mentioned under
+    > [Table Constraints](#table-constraints).
 
 
 ### Table Constraints
 
-Additional constraints may be provided outside the scope of a single column using the following functions.
+Additional constraints may be provided outside the scope of a single column
+using the following functions.
 
-  - `primaryKey` adds a `PRIMARY KEY` constraint to the table. Unlike [the column constraint, above](#column-constraints), it supports all SQLite types, [ascending and descending orders](#sorting-rows), and composite (multiple column) keys.
+  - `primaryKey` adds a `PRIMARY KEY` constraint to the table. Unlike [the
+    column constraint, above](#column-constraints), it supports all SQLite
+    types, [ascending and descending orders](#sorting-rows), and composite
+    (multiple column) keys.
 
-    ``` swift
+    ```swift
     t.primaryKey(email.asc, name)
     // PRIMARY KEY("email" ASC, "name")
     ```
 
-  - `unique` adds a `UNIQUE` constraint to the table. Unlike [the column constraint, above](#column-constraints), it supports composite (multiple column) constraints.
+  - `unique` adds a `UNIQUE` constraint to the table. Unlike
+    [the column constraint, above](#column-constraints), it
+    supports composite (multiplecolumn) constraints.
 
-    ``` swift
+    ```swift
     t.unique(local, domain)
     // UNIQUE("local", "domain")
     ```
 
-  - `check` adds a `CHECK` constraint to the table in the form of a boolean expression (`Expression<Bool>`). Boolean expressions can be easily built using [filter operators and functions](#filter-operators-and-functions). (See also the `check` parameter under [Column Constraints](#column-constraints).)
+  - `check` adds a `CHECK` constraint to the table in the form of a boolean
+    expression (`Expression<Bool>`). Boolean expressions can be easily built
+    using [filter operators and functions](#filter-operators-and-functions).
+    (See also the `check` parameter under [Column Constraints](#column-
+    constraints).)
 
-    ``` swift
+    ```swift
     t.check(balance >= 0)
     // CHECK ("balance" >= 0.0)
     ```
 
-  - `foreignKey` adds a `FOREIGN KEY` constraint to the table. Unlike [the `references` constraint, above](#column-constraints), it supports all SQLite types, both [`ON UPDATE` and `ON DELETE` actions](https://www.sqlite.org/foreignkeys.html#fk_actions), and composite (multiple column) keys.
+  - `foreignKey` adds a `FOREIGN KEY` constraint to the table. Unlike [the
+    `references` constraint, above](#column-constraints), it supports all
+    SQLite types, both [`ON UPDATE` and `ON DELETE`
+    actions](https://www.sqlite.org/foreignkeys.html#fk_actions), and
+    composite (multiple column) keys.
 
-    ``` swift
+    ```swift
     t.foreignKey(user_id, references: users, id, delete: .setNull)
     // FOREIGN KEY("user_id") REFERENCES "users"("id") ON DELETE SET NULL
     ```
@@ -508,9 +613,12 @@ Additional constraints may be provided outside the scope of a single column usin
 
 ## Inserting Rows
 
-We can insert rows into a table by calling a [query’s](#queries) `insert` function with a list of [setters](#setters)—typically [typed column expressions](#expressions) and values (which can also be expressions)—each joined by the `<-` operator.
+We can insert rows into a table by calling a [query’s](#queries) `insert`
+function with a list of [setters](#setters)—typically [typed column
+expressions](#expressions) and values (which can also be expressions)—each
+joined by the `<-` operator.
 
-``` swift
+```swift
 try db.run(users.insert(email <- "alice@mac.com", name <- "Alice"))
 // INSERT INTO "users" ("email", "name") VALUES ('alice@mac.com', 'Alice')
 
@@ -518,9 +626,10 @@ try db.run(users.insert(or: .replace, email <- "alice@mac.com", name <- "Alice B
 // INSERT OR REPLACE INTO "users" ("email", "name") VALUES ('alice@mac.com', 'Alice B.')
 ```
 
-The `insert` function, when run successfully, returns an `Int64` representing the inserted row’s [`ROWID`][ROWID].
+The `insert` function, when run successfully, returns an `Int64` representing
+the inserted row’s [`ROWID`][ROWID].
 
-``` swift
+```swift
 do {
     let rowid = try db.run(users.insert(email <- "alice@mac.com"))
     print("inserted id: \(rowid)")
@@ -529,11 +638,14 @@ do {
 }
 ```
 
-The [`update`](#updating-rows) and [`delete`](#deleting-rows) functions follow similar patterns.
+The [`update`](#updating-rows) and [`delete`](#deleting-rows) functions
+follow similar patterns.
 
-> _Note:_ If `insert` is called without any arguments, the statement will run with a `DEFAULT VALUES` clause. The table must not have any constraints that aren’t fulfilled by default values.
+> _Note:_ If `insert` is called without any arguments, the statement will run
+> with a `DEFAULT VALUES` clause. The table must not have any constraints
+> that aren’t fulfilled by default values.
 >
-> ``` swift
+> ```swift
 > try db.run(timestamps.insert())
 > // INSERT INTO "timestamps" DEFAULT VALUES
 > ```
@@ -541,25 +653,27 @@ The [`update`](#updating-rows) and [`delete`](#deleting-rows) functions follow s
 
 ### Setters
 
-SQLite.swift typically uses the `<-` operator to set values during [inserts](#inserting-rows) and [updates](#updating-rows).
+SQLite.swift typically uses the `<-` operator to set values during [inserts
+](#inserting-rows) and [updates](#updating-rows).
 
-``` swift
+```swift
 try db.run(counter.update(count <- 0))
 // UPDATE "counters" SET "count" = 0 WHERE ("id" = 1)
 ```
 
-There are also a number of convenience setters that take the existing value into account using native Swift operators.
+There are also a number of convenience setters that take the existing value
+into account using native Swift operators.
 
 For example, to atomically increment a column, we can use `++`:
 
-``` swift
+```swift
 try db.run(counter.update(count++)) // equivalent to `counter.update(count -> count + 1)`
 // UPDATE "counters" SET "count" = "count" + 1 WHERE ("id" = 1)
 ```
 
 To take an amount and “move” it via transaction, we can use `-=` and `+=`:
 
-``` swift
+```swift
 let amount = 100.0
 try db.transaction {
     try db.run(alice.update(balance -= amount))
@@ -600,14 +714,18 @@ try db.transaction {
 
 ## Selecting Rows
 
-[Query structures](#queries) are `SELECT` statements waiting to happen. They execute via [iteration](#iterating-and-accessing-values) and [other means](#plucking-values) of sequence access.
+[Query structures](#queries) are `SELECT` statements waiting to happen. They
+execute via [iteration](#iterating-and-accessing-values) and [other means
+](#plucking-values) of sequence access.
 
 
 ### Iterating and Accessing Values
 
-Prepared [queries](#queries) execute lazily upon iteration. Each row is returned as a `Row` object, which can be subscripted with a [column expression](#expressions) matching one of the columns returned.
+Prepared [queries](#queries) execute lazily upon iteration. Each row is
+returned as a `Row` object, which can be subscripted with a [column
+expression](#expressions) matching one of the columns returned.
 
-``` swift
+```swift
 for user in try db.prepare(users) {
     print("id: \(user[id]), email: \(user[email]), name: \(user[name])")
     // id: 1, email: alice@mac.com, name: Optional("Alice")
@@ -615,21 +733,25 @@ for user in try db.prepare(users) {
 // SELECT * FROM "users"
 ```
 
-`Expression<T>` column values are _automatically unwrapped_ (we’ve made a promise to the compiler that they’ll never be `NULL`), while `Expression<T?>` values remain wrapped.
+`Expression<T>` column values are _automatically unwrapped_ (we’ve made a
+promise to the compiler that they’ll never be `NULL`), while `Expression<T?>`
+values remain wrapped.
 
 
 ### Plucking Rows
 
-We can pluck the first row by passing a query to the `pluck` function on a database connection.
+We can pluck the first row by passing a query to the `pluck` function on a
+database connection.
 
-``` swift
+```swift
 if let user = try db.pluck(users) { /* ... */ } // Row
 // SELECT * FROM "users" LIMIT 1
 ```
 
-To collect all rows into an array, we can simply wrap the sequence (though this is not always the most memory-efficient idea).
+To collect all rows into an array, we can simply wrap the sequence (though
+this is not always the most memory-efficient idea).
 
-``` swift
+```swift
 let all = Array(try db.prepare(users))
 // SELECT * FROM "users"
 ```
@@ -637,9 +759,12 @@ let all = Array(try db.prepare(users))
 
 ### Building Complex Queries
 
-[Queries](#queries) have a number of chainable functions that can be used (with [expressions](#expressions)) to add and modify [a number of clauses](https://www.sqlite.org/lang_select.html) to the underlying statement.
+[Queries](#queries) have a number of chainable functions that can be used
+(with [expressions](#expressions)) to add and modify [a number of
+clauses](https://www.sqlite.org/lang_select.html) to the underlying
+statement.
 
-``` swift
+```swift
 let query = users.select(email)           // SELECT "email" FROM "users"
                  .filter(name != nil)     // WHERE "name" IS NOT NULL
                  .order(email.desc, name) // ORDER BY "email" DESC, "name"
@@ -649,9 +774,11 @@ let query = users.select(email)           // SELECT "email" FROM "users"
 
 #### Selecting Columns
 
-By default, [queries](#queries) select every column of the result set (using `SELECT *`). We can use the `select` function with a list of [expressions](#expressions) to return specific columns instead.
+By default, [queries](#queries) select every column of the result set (using
+`SELECT *`). We can use the `select` function with a list of
+[expressions](#expressions) to return specific columns instead.
 
-``` swift
+```swift
 for user in try db.prepare(users.select(id, email)) {
     print("id: \(user[id]), email: \(user[email])")
     // id: 1, email: alice@mac.com
@@ -659,9 +786,10 @@ for user in try db.prepare(users.select(id, email)) {
 // SELECT "id", "email" FROM "users"
 ```
 
-We can access the results of more complex expressions by holding onto a reference of the expression itself.
+We can access the results of more complex expressions by holding onto a
+reference of the expression itself.
 
-``` swift
+```swift
 let sentence = name + " is " + cast(age) as Expression<String?> + " years old!"
 for user in users.select(sentence) {
     print(user[sentence])
@@ -675,35 +803,42 @@ for user in users.select(sentence) {
 
 We can join tables using a [query’s](#queries) `join` function.
 
-``` swift
+```swift
 users.join(posts, on: user_id == users[id])
 // SELECT * FROM "users" INNER JOIN "posts" ON ("user_id" = "users"."id")
 ```
 
-The `join` function takes a [query](#queries) object (for the table being joined on), a join condition (`on`), and is prefixed with an optional join type (default: `.inner`). Join conditions can be built using [filter operators and functions](#filter-operators-and-functions), generally require [namespacing](#column-namespacing), and sometimes require [aliasing](#table-aliasing).
+The `join` function takes a [query](#queries) object (for the table being
+joined on), a join condition (`on`), and is prefixed with an optional join
+type (default: `.inner`). Join conditions can be built using [filter
+operators and functions](#filter-operators-and-functions), generally require
+[namespacing](#column-namespacing), and sometimes require [aliasing](#table-
+aliasing).
 
 
 ##### Column Namespacing
 
-When joining tables, column names can become ambiguous. _E.g._, both tables may have an `id` column.
+When joining tables, column names can become ambiguous. _E.g._, both tables
+may have an `id` column.
 
-``` swift
+```swift
 let query = users.join(posts, on: user_id == id)
 // assertion failure: ambiguous column 'id'
 ```
 
 We can disambiguate by namespacing `id`.
 
-``` swift
+```swift
 let query = users.join(posts, on: user_id == users[id])
 // SELECT * FROM "users" INNER JOIN "posts" ON ("user_id" = "users"."id")
 ```
 
-Namespacing is achieved by subscripting a [query](#queries) with a [column expression](#expressions) (_e.g._, `users[id]` above becomes `users.id`).
+Namespacing is achieved by subscripting a [query](#queries) with a [column
+expression](#expressions) (_e.g._, `users[id]` above becomes `users.id`).
 
 > _Note:_ We can namespace all of a table’s columns using `*`.
 >
-> ``` swift
+> ```swift
 > let query = users.select(users[*])
 > // SELECT "users".* FROM "users"
 > ```
@@ -711,9 +846,11 @@ Namespacing is achieved by subscripting a [query](#queries) with a [column expre
 
 ##### Table Aliasing
 
-Occasionally, we need to join a table to itself, in which case we must alias the table with another name. We can achieve this using the [query’s](#queries) `alias` function.
+Occasionally, we need to join a table to itself, in which case we must alias
+the table with another name. We can achieve this using the
+[query’s](#queries) `alias` function.
 
-``` swift
+```swift
 let managers = users.alias("managers")
 
 let query = users.join(managers, on: managers[id] == users[managerId])
@@ -721,9 +858,11 @@ let query = users.join(managers, on: managers[id] == users[managerId])
 // INNER JOIN ("users") AS "managers" ON ("managers"."id" = "users"."manager_id")
 ```
 
-If query results can have ambiguous column names, row values should be accessed with namespaced [column expressions](#expressions). In the above case, `SELECT *` immediately namespaces all columns of the result set.
+If query results can have ambiguous column names, row values should be
+accessed with namespaced [column expressions](#expressions). In the above
+case, `SELECT *` immediately namespaces all columns of the result set.
 
-``` swift
+```swift
 let user = try db.pluck(query)
 user[id]           // fatal error: ambiguous column 'id'
                    // (please disambiguate: ["users"."id", "managers"."id"])
@@ -735,9 +874,10 @@ user[managers[id]] // returns "managers"."id"
 
 #### Filtering Rows
 
-SQLite.swift filters rows using a [query’s](#queries) `filter` function with a boolean [expression](#expressions) (`Expression<Bool>`).
+SQLite.swift filters rows using a [query’s](#queries) `filter` function with
+a boolean [expression](#expressions) (`Expression<Bool>`).
 
-``` swift
+```swift
 users.filter(id == 1)
 // SELECT * FROM "users" WHERE ("id" = 1)
 
@@ -754,18 +894,21 @@ users.filter(verified || balance >= 10_000)
 // SELECT * FROM "users" WHERE ("verified" OR ("balance" >= 10000.0))
 ```
 
-We can build our own boolean expressions by using one of the many [filter operators and functions](#filter-operators-and-functions).
+We can build our own boolean expressions by using one of the many [filter
+operators and functions](#filter-operators-and-functions).
 
 Instead of `filter` we can also use the `where` function which is an alias:
 
-``` swift
+```swift
 users.where(id == 1)
 // SELECT * FROM "users" WHERE ("id" = 1)
 ```
 
 ##### Filter Operators and Functions
 
-SQLite.swift defines a number of operators for building filtering predicates. Operators and functions work together in a type-safe manner, so attempting to equate or compare different types will prevent compilation.
+SQLite.swift defines a number of operators for building filtering predicates.
+Operators and functions work together in a type-safe manner, so attempting to
+equate or compare different types will prevent compilation.
 
 
 ###### Infix Filter Operators
@@ -782,7 +925,8 @@ SQLite.swift defines a number of operators for building filtering predicates. Op
 | `&&`  | `Bool -> Bool`                   | `AND`          |
 | `||`  | `Bool -> Bool`                   | `OR`           |
 
-> *When comparing against `nil`, SQLite.swift will use `IS` and `IS NOT` accordingly.
+> *When comparing against `nil`, SQLite.swift will use `IS` and `IS NOT`
+> accordingly.
 
 
 ###### Prefix Filter Operators
@@ -813,16 +957,18 @@ We can pre-sort returned rows using the [query’s](#queries) `order` function.
 
 _E.g._, to return users sorted by `email`, then `name`, in ascending order:
 
-``` swift
+```swift
 users.order(email, name)
 // SELECT * FROM "users" ORDER BY "email", "name"
 ```
 
 The `order` function takes a list of [column expressions](#expressions).
 
-`Expression` objects have two computed properties to assist sorting: `asc` and `desc`. These properties append the expression with `ASC` and `DESC` to mark ascending and descending order respectively.
+`Expression` objects have two computed properties to assist sorting: `asc`
+and `desc`. These properties append the expression with `ASC` and `DESC` to
+mark ascending and descending order respectively.
 
-``` swift
+```swift
 users.order(email.desc, name.asc)
 // SELECT * FROM "users" ORDER BY "email" DESC, "name" ASC
 ```
@@ -830,9 +976,10 @@ users.order(email.desc, name.asc)
 
 #### Limiting and Paging Results
 
-We can limit and skip returned rows using a [query’s](#queries) `limit` function (and its optional `offset` parameter).
+We can limit and skip returned rows using a [query’s](#queries) `limit`
+function (and its optional `offset` parameter).
 
-``` swift
+```swift
 users.limit(5)
 // SELECT * FROM "users" LIMIT 5
 
@@ -843,67 +990,79 @@ users.limit(5, offset: 5)
 
 #### Aggregation
 
-[Queries](#queries) come with a number of functions that quickly return aggregate scalar values from the table. These mirror the [core aggregate functions](#aggregate-sqlite-functions) and are executed immediately against the query.
+[Queries](#queries) come with a number of functions that quickly return
+aggregate scalar values from the table. These mirror the [core aggregate
+functions](#aggregate-sqlite-functions) and are executed immediately against
+the query.
 
-``` swift
+```swift
 let count = try db.scalar(users.count)
 // SELECT count(*) FROM "users"
 ```
 
 Filtered queries will appropriately filter aggregate values.
 
-``` swift
+```swift
 let count = try db.scalar(users.filter(name != nil).count)
 // SELECT count(*) FROM "users" WHERE "name" IS NOT NULL
 ```
 
-  - `count` as a computed property on a query (see examples above) returns the total number of rows matching the query.
+  - `count` as a computed property on a query (see examples above) returns
+    the total number of rows matching the query.
 
-    `count` as a computed property on a column expression returns the total number of rows where that column is not `NULL`.
+    `count` as a computed property on a column expression returns the total
+    number of rows where that column is not `NULL`.
 
-    ``` swift
+    ```swift
     let count = try db.scalar(users.select(name.count)) // -> Int
     // SELECT count("name") FROM "users"
     ```
 
-  - `max` takes a comparable column expression and returns the largest value if any exists.
+  - `max` takes a comparable column expression and returns the largest value
+    if any exists.
 
-    ``` swift
+    ```swift
     let max = try db.scalar(users.select(id.max)) // -> Int64?
     // SELECT max("id") FROM "users"
     ```
 
-  - `min` takes a comparable column expression and returns the smallest value if any exists.
+  - `min` takes a comparable column expression and returns the smallest value
+    if any exists.
 
-    ``` swift
+    ```swift
     let min = try db.scalar(users.select(id.min)) // -> Int64?
     // SELECT min("id") FROM "users"
     ```
 
-  - `average` takes a numeric column expression and returns the average row value (as a `Double`) if any exists.
+  - `average` takes a numeric column expression and returns the average row
+    value (as a `Double`) if any exists.
 
-    ``` swift
+    ```swift
     let average = try db.scalar(users.select(balance.average)) // -> Double?
     // SELECT avg("balance") FROM "users"
     ```
 
-  - `sum` takes a numeric column expression and returns the sum total of all rows if any exist.
+  - `sum` takes a numeric column expression and returns the sum total of all
+    rows if any exist.
 
-    ``` swift
+    ```swift
     let sum = try db.scalar(users.select(balance.sum)) // -> Double?
     // SELECT sum("balance") FROM "users"
     ```
 
-  - `total`, like `sum`, takes a numeric column expression and returns the sum total of all rows, but in this case always returns a `Double`, and returns `0.0` for an empty query.
+  - `total`, like `sum`, takes a numeric column expression and returns the
+    sum total of all rows, but in this case always returns a `Double`, and
+    returns `0.0` for an empty query.
 
-    ``` swift
+    ```swift
     let total = try db.scalar(users.select(balance.total)) // -> Double
     // SELECT total("balance") FROM "users"
     ```
 
-> _Note:_ Expressions can be prefixed with a `DISTINCT` clause by calling the `distinct` computed property.
+> _Note:_ Expressions can be prefixed with a `DISTINCT` clause by calling the
+> `distinct` computed property.
 >
-> ``` swift
+> ```swift
 > let count = try db.scalar(users.select(name.distinct.count) // -> Int
 > // SELECT count(DISTINCT "name") FROM "users"
 > ```
@@ -911,26 +1070,32 @@ let count = try db.scalar(users.filter(name != nil).count)
 
 ## Updating Rows
 
-We can update a table’s rows by calling a [query’s](#queries) `update` function with a list of [setters](#setters)—typically [typed column expressions](#expressions) and values (which can also be expressions)—each joined by the `<-` operator.
+We can update a table’s rows by calling a [query’s](#queries) `update`
+function with a list of [setters](#setters)—typically [typed column
+expressions](#expressions) and values (which can also be expressions)—each
+joined by the `<-` operator.
 
-When an unscoped query calls `update`, it will update _every_ row in the table.
+When an unscoped query calls `update`, it will update _every_ row in the
+table.
 
-``` swift
+```swift
 try db.run(users.update(email <- "alice@me.com"))
 // UPDATE "users" SET "email" = 'alice@me.com'
 ```
 
-Be sure to scope `UPDATE` statements beforehand using [the `filter` function](#filtering-rows).
+Be sure to scope `UPDATE` statements beforehand using [the `filter` function
+](#filtering-rows).
 
-``` swift
+```swift
 let alice = users.filter(id == 1)
 try db.run(alice.update(email <- "alice@me.com"))
 // UPDATE "users" SET "email" = 'alice@me.com' WHERE ("id" = 1)
 ```
 
-The `update` function returns an `Int` representing the number of updated rows.
+The `update` function returns an `Int` representing the number of updated
+rows.
 
-``` swift
+```swift
 do {
     if try db.run(alice.update(email <- "alice@me.com")) > 0 {
         print("updated alice")
@@ -945,26 +1110,30 @@ do {
 
 ## Deleting Rows
 
-We can delete rows from a table by calling a [query’s](#queries) `delete` function.
+We can delete rows from a table by calling a [query’s](#queries) `delete`
+function.
 
-When an unscoped query calls `delete`, it will delete _every_ row in the table.
+When an unscoped query calls `delete`, it will delete _every_ row in the
+table.
 
-``` swift
+```swift
 try db.run(users.delete())
 // DELETE FROM "users"
 ```
 
-Be sure to scope `DELETE` statements beforehand using [the `filter` function](#filtering-rows).
+Be sure to scope `DELETE` statements beforehand using
+[the `filter` function](#filtering-rows).
 
-``` swift
+```swift
 let alice = users.filter(id == 1)
 try db.run(alice.delete())
 // DELETE FROM "users" WHERE ("id" = 1)
 ```
 
-The `delete` function returns an `Int` representing the number of deleted rows.
+The `delete` function returns an `Int` representing the number of deleted
+rows.
 
-``` swift
+```swift
 do {
     if try db.run(alice.delete()) > 0 {
         print("deleted alice")
@@ -979,9 +1148,11 @@ do {
 
 ## Transactions and Savepoints
 
-Using the `transaction` and `savepoint` functions, we can run a series of statements in a transaction. If a single statement fails or the block throws an error, the changes will be rolled back.
+Using the `transaction` and `savepoint` functions, we can run a series of
+statements in a transaction. If a single statement fails or the block throws
+an error, the changes will be rolled back.
 
-``` swift
+```swift
 try db.transaction {
     let rowid = try db.run(users.insert(email <- "betty@icloud.com"))
     try db.run(users.insert(email <- "cathy@icloud.com", managerId <- rowid))
@@ -997,14 +1168,16 @@ try db.transaction {
 
 ## Altering the Schema
 
-SQLite.swift comes with several functions (in addition to `Table.create`) for altering a database schema in a type-safe manner.
+SQLite.swift comes with several functions (in addition to `Table.create`) for
+altering a database schema in a type-safe manner.
 
 
 ### Renaming Tables
 
-We can build an `ALTER TABLE … RENAME TO` statement by calling the `rename` function on a `Table` or `VirtualTable`.
+We can build an `ALTER TABLE … RENAME TO` statement by calling the `rename`
+function on a `Table` or `VirtualTable`.
 
-``` swift
+```swift
 try db.run(users.rename(Table("users_old"))
 // ALTER TABLE "users" RENAME TO "users_old"
 ```
@@ -1012,9 +1185,12 @@ try db.run(users.rename(Table("users_old"))
 
 ### Adding Columns
 
-We can add columns to a table by calling `addColumn` function on a `Table`. SQLite.swift enforces [the same limited subset](https://www.sqlite.org/lang_altertable.html) of `ALTER TABLE` that SQLite supports.
+We can add columns to a table by calling `addColumn` function on a `Table`.
+SQLite.swift enforces
+[the same limited subset](https://www.sqlite.org/lang_altertable.html) of
+`ALTER TABLE` that SQLite supports.
 
-``` swift
+```swift
 try db.run(users.addColumn(suffix))
 // ALTER TABLE "users" ADD COLUMN "suffix" TEXT
 ```
@@ -1022,27 +1198,38 @@ try db.run(users.addColumn(suffix))
 
 #### Added Column Constraints
 
-The `addColumn` function shares several of the same [`column` function parameters](#column-constraints) used when [creating tables](#creating-a-table).
+The `addColumn` function shares several of the same [`column` function
+parameters](#column-constraints) used when [creating
+tables](#creating-a-table).
 
-  - `check` attaches a `CHECK` constraint to a column definition in the form of a boolean expression (`Expression<Bool>`). (See also the `check` function under [Table Constraints](#table-constraints).)
+  - `check` attaches a `CHECK` constraint to a column definition in the form
+    of a boolean expression (`Expression<Bool>`). (See also the `check`
+    function under [Table Constraints](#table-constraints).)
 
-    ``` swift
+    ```swift
     try db.run(users.addColumn(suffix, check: ["JR", "SR"].contains(suffix)))
     // ALTER TABLE "users" ADD COLUMN "suffix" TEXT CHECK ("suffix" IN ('JR', 'SR'))
     ```
 
-  - `defaultValue` adds a `DEFAULT` clause to a column definition and _only_ accepts a value matching the column’s type. This value is used if none is explicitly provided during [an `INSERT`](#inserting-rows).
+  - `defaultValue` adds a `DEFAULT` clause to a column definition and _only_
+    accepts a value matching the column’s type. This value is used if none is
+    explicitly provided during [an `INSERT`](#inserting-rows).
 
-    ``` swift
+    ```swift
     try db.run(users.addColumn(suffix, defaultValue: "SR"))
     // ALTER TABLE "users" ADD COLUMN "suffix" TEXT DEFAULT 'SR'
     ```
 
-    > _Note:_ Unlike the [`CREATE TABLE` constraint](#table-constraints), default values may not be expression structures (including `CURRENT_TIME`, `CURRENT_DATE`, or `CURRENT_TIMESTAMP`).
+    > _Note:_ Unlike the [`CREATE TABLE` constraint](#table-constraints),
+    > default values may not be expression structures (including
+    > `CURRENT_TIME`, `CURRENT_DATE`, or `CURRENT_TIMESTAMP`).
 
-  - `collate` adds a `COLLATE` clause to `Expression<String>` (and `Expression<String?>`) column definitions with [a collating sequence](https://www.sqlite.org/datatype3.html#collation) defined in the `Collation` enumeration.
+  - `collate` adds a `COLLATE` clause to `Expression<String>` (and
+    `Expression<String?>`) column definitions with [a collating
+    sequence](https://www.sqlite.org/datatype3.html#collation) defined in the
+    `Collation` enumeration.
 
-    ``` swift
+    ```swift
     try db.run(users.addColumn(email, collate: .nocase))
     // ALTER TABLE "users" ADD COLUMN "email" TEXT NOT NULL COLLATE "NOCASE"
 
@@ -1050,9 +1237,12 @@ The `addColumn` function shares several of the same [`column` function parameter
     // ALTER TABLE "users" ADD COLUMN "name" TEXT COLLATE "RTRIM"
     ```
 
-  - `references` adds a `REFERENCES` clause to `Int64` (and `Int64?`) column definitions and accepts a table or namespaced column expression. (See the `foreignKey` function under [Table Constraints](#table-constraints) for non-integer foreign key support.)
+  - `references` adds a `REFERENCES` clause to `Int64` (and `Int64?`) column
+    definitions and accepts a table or namespaced column expression. (See the
+    `foreignKey` function under [Table Constraints](#table-constraints) for
+    non-integer foreign key support.)
 
-    ``` swift
+    ```swift
     try db.run(posts.addColumn(userId, references: users, id)
     // ALTER TABLE "posts" ADD COLUMN "user_id" INTEGER REFERENCES "users" ("id")
     ```
@@ -1063,27 +1253,32 @@ The `addColumn` function shares several of the same [`column` function parameter
 
 #### Creating Indexes
 
-We can build [`CREATE INDEX` statements](https://www.sqlite.org/lang_createindex.html) by calling the `createIndex` function on a `SchemaType`.
+We can build
+[`CREATE INDEX` statements](https://www.sqlite.org/lang_createindex.html)
+by calling the `createIndex` function on a `SchemaType`.
 
-``` swift
+```swift
 try db.run(users.createIndex(email))
 // CREATE INDEX "index_users_on_email" ON "users" ("email")
 ```
 
-The index name is generated automatically based on the table and column names.
+The index name is generated automatically based on the table and column
+names.
 
 The `createIndex` function has a couple default parameters we can override.
 
   - `unique` adds a `UNIQUE` constraint to the index. Default: `false`.
 
-    ``` swift
+    ```swift
     try db.run(users.createIndex(email, unique: true))
     // CREATE UNIQUE INDEX "index_users_on_email" ON "users" ("email")
     ```
 
-  - `ifNotExists` adds an `IF NOT EXISTS` clause to the `CREATE TABLE` statement (which will bail out gracefully if the table already exists). Default: `false`.
+  - `ifNotExists` adds an `IF NOT EXISTS` clause to the `CREATE TABLE`
+    statement (which will bail out gracefully if the table already exists).
+    Default: `false`.
 
-    ``` swift
+    ```swift
     try db.run(users.createIndex(email, ifNotExists: true))
     // CREATE INDEX IF NOT EXISTS "index_users_on_email" ON "users" ("email")
     ```
@@ -1091,16 +1286,19 @@ The `createIndex` function has a couple default parameters we can override.
 
 #### Dropping Indexes
 
-We can build [`DROP INDEX` statements](https://www.sqlite.org/lang_dropindex.html) by calling the `dropIndex` function on a `SchemaType`.
+We can build
+[`DROP INDEX` statements](https://www.sqlite.org/lang_dropindex.html) by
+calling the `dropIndex` function on a `SchemaType`.
 
-``` swift
+```swift
 try db.run(users.dropIndex(email))
 // DROP INDEX "index_users_on_email"
 ```
 
-The `dropIndex` function has one additional parameter, `ifExists`, which (when `true`) adds an `IF EXISTS` clause to the statement.
+The `dropIndex` function has one additional parameter, `ifExists`, which
+(when `true`) adds an `IF EXISTS` clause to the statement.
 
-``` swift
+```swift
 try db.run(users.dropIndex(email, ifExists: true))
 // DROP INDEX IF EXISTS "index_users_on_email"
 ```
@@ -1108,16 +1306,19 @@ try db.run(users.dropIndex(email, ifExists: true))
 
 ### Dropping Tables
 
-We can build [`DROP TABLE` statements](https://www.sqlite.org/lang_droptable.html) by calling the `dropTable` function on a `SchemaType`.
+We can build
+[`DROP TABLE` statements](https://www.sqlite.org/lang_droptable.html)
+by calling the `dropTable` function on a `SchemaType`.
 
-``` swift
+```swift
 try db.run(users.drop())
 // DROP TABLE "users"
 ```
 
-The `drop` function has one additional parameter, `ifExists`, which (when `true`) adds an `IF EXISTS` clause to the statement.
+The `drop` function has one additional parameter, `ifExists`, which (when
+`true`) adds an `IF EXISTS` clause to the statement.
 
-``` swift
+```swift
 try db.run(users.drop(ifExists: true))
 // DROP TABLE IF EXISTS "users"
 ```
@@ -1125,11 +1326,12 @@ try db.run(users.drop(ifExists: true))
 
 ### Migrations and Schema Versioning
 
-You can add a convenience property on `Connection` to query and set the [`PRAGMA user_version`](https://sqlite.org/pragma.html#pragma_user_version).
+You can add a convenience property on `Connection` to query and set the
+[`PRAGMA user_version`](https://sqlite.org/pragma.html#pragma_user_version).
 
 This is a great way to manage your schema’s version over migrations.
 
-``` swift
+```swift
 extension Connection {
     public var userVersion: Int32 {
         get { return Int32(try! scalar("PRAGMA user_version") as! Int64)}
@@ -1151,14 +1353,15 @@ if db.userVersion == 1 {
 }
 ```
 
-For more complex migration requirements check out the schema management system
-[SQLiteMigrationManager.swift][].
+For more complex migration requirements check out the schema management
+system [SQLiteMigrationManager.swift][].
 
 ## Custom Types
 
-SQLite.swift supports serializing and deserializing any custom type as long as it conforms to the `Value` protocol.
+SQLite.swift supports serializing and deserializing any custom type as long
+as it conforms to the `Value` protocol.
 
-> ``` swift
+> ```swift
 > protocol Value {
 >     typealias Datatype: Binding
 >     class var declaredDatatype: String { get }
@@ -1167,20 +1370,27 @@ SQLite.swift supports serializing and deserializing any custom type as long as i
 > }
 > ```
 
-The `Datatype` must be one of the basic Swift types that values are bridged through before serialization and deserialization (see [Building Type-Safe SQL](#building-type-safe-sql) for a list of types).
+The `Datatype` must be one of the basic Swift types that values are bridged
+through before serialization and deserialization (see [Building Type-Safe SQL
+](#building-type-safe-sql) for a list of types).
 
-> _Note:_ `Binding` is a protocol that SQLite.swift uses internally to directly map SQLite types to Swift types. **Do _not_** conform custom types to the `Binding` protocol.
+> _Note:_ `Binding` is a protocol that SQLite.swift uses internally to
+> directly map SQLite types to Swift types. **Do _not_** conform custom types
+> to the `Binding` protocol.
 
-Once extended, the type can be used [_almost_](#custom-type-caveats) wherever typed expressions can be.
+Once extended, the type can be used [_almost_](#custom-type-caveats) wherever
+typed expressions can be.
 
 
 ### Date-Time Values
 
-In SQLite, `DATETIME` columns can be treated as strings or numbers, so we can transparently bridge `Date` objects through Swift’s `String` or `Int` types.
+In SQLite, `DATETIME` columns can be treated as strings or numbers, so we can
+transparently bridge `Date` objects through Swift’s `String` or `Int` types.
 
-To serialize `Date` objects as `TEXT` values (in ISO 8601), we’ll use `String`.
+To serialize `Date` objects as `TEXT` values (in ISO 8601), we’ll use
+`String`.
 
-``` swift
+```swift
 extension Date: Value {
     class var declaredDatatype: String {
         return String.declaredDatatype
@@ -1204,7 +1414,7 @@ let SQLDateFormatter: DateFormatter = {
 
 We can also treat them as `INTEGER` values using `Int`.
 
-``` swift
+```swift
 extension Date: Value {
     class var declaredDatatype: String {
         return Int.declaredDatatype
@@ -1218,11 +1428,14 @@ extension Date: Value {
 }
 ```
 
-> _Note:_ SQLite’s `CURRENT_DATE`, `CURRENT_TIME`, and `CURRENT_TIMESTAMP` helpers return `TEXT` values. Because of this (and the fact that Unix time is far less human-readable when we’re faced with the raw data), we recommend using the `TEXT` extension.
+> _Note:_ SQLite’s `CURRENT_DATE`, `CURRENT_TIME`, and `CURRENT_TIMESTAMP`
+> helpers return `TEXT` values. Because of this (and the fact that Unix time
+> is far less human-readable when we’re faced with the raw data), we
+> recommend using the `TEXT` extension.
 
 Once defined, we can use these types directly in SQLite statements.
 
-``` swift
+```swift
 let published_at = Expression<Date>("published_at")
 
 let published = posts.filter(published_at <= Date())
@@ -1237,7 +1450,7 @@ let published = posts.filter(published_at <= Date())
 
 We can bridge any type that can be initialized from and encoded to `Data`.
 
-``` swift
+```swift
 extension UIImage: Value {
     public class var declaredDatatype: String {
         return Blob.declaredDatatype
@@ -1252,16 +1465,20 @@ extension UIImage: Value {
 }
 ```
 
-> _Note:_ See the [Archives and Serializations Programming Guide](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Archiving/Archiving.html#//apple_ref/doc/uid/10000047i) for more information on encoding and decoding custom types.
+> _Note:_ See the [Archives and Serializations Programming Guide][] for more
+> information on encoding and decoding custom types.
 
 
+[Archives and Serializations Programming Guide]: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Archiving/Archiving.html#//apple_ref/doc/uid/10000047i
+
 ### Custom Type Caveats
 
-Swift does _not_ currently support generic subscripting, which means we cannot, by default, subscript Expressions with custom types to:
+Swift does _not_ currently support generic subscripting, which means we
+cannot, by default, subscript Expressions with custom types to:
 
  1. **Namespace expressions**. Use the `namespace` function, instead:
 
-    ``` swift
+    ```swift
     let avatar = Expression<UIImage?>("avatar")
     users[avatar]           // fails to compile
     users.namespace(avatar) // "users"."avatar"
@@ -1269,7 +1486,7 @@ Swift does _not_ currently support generic subscripting, which means we cannot,
 
  2. **Access column data**. Use the `get` function, instead:
 
-    ``` swift
+    ```swift
     let user = users.first!
     user[avatar]            // fails to compile
     user.get(avatar)        // UIImage?
@@ -1277,7 +1494,7 @@ Swift does _not_ currently support generic subscripting, which means we cannot,
 
 We can, of course, write extensions, but they’re rather wordy.
 
-``` swift
+```swift
 extension Query {
     subscript(column: Expression<UIImage>) -> Expression<UIImage> {
         return namespace(column)
@@ -1299,53 +1516,63 @@ extension Row {
 
 ## Codable Types
 
-Codable types were introduced as a part of Swift 4 to allow serializing and deserializing types. SQLite.swift
-supports the insertion, updating, and retrieval of basic Codable types.
+Codable types were introduced as a part of Swift 4 to allow serializing and
+deserializing types. SQLite.swift supports the insertion, updating, and
+retrieval of basic Codable types.
 
 ### Inserting Codable Types
 
 Queries have a method to allow inserting an Encodable type.
 
-``` swift
+```swift
 try db.run(users.insert(user))
 
 ```
 
 There are two other parameters also available to this method:
 
-- `userInfo` is a dictionary that is passed to the encoder and made available to encodable types to allow customizing their behavior.
-- `otherSetters` allows you to specify additional setters on top of those that are generated from the encodable types themselves.
+- `userInfo` is a dictionary that is passed to the encoder and made available
+  to encodable types to allow customizing their behavior.
+
+- `otherSetters` allows you to specify additional setters on top of those
+  that are generated from the encodable types themselves.
 
 ### Updating Codable Types
 
 Queries have a method to allow updating an Encodable type.
 
-``` swift
+```swift
 try db.run(users.update(user))
 
 ```
 
 There are two other parameters also available to this method:
 
-- `userInfo` is a dictionary that is passed to the encoder and made available to encodable types to allow customizing their behavior.
-- `otherSetters` allows you to specify additional setters on top of those that are generated from the encodable types themselves.
+- `userInfo` is a dictionary that is passed to the encoder and made available
+  to encodable types to allow customizing their behavior.
+
+- `otherSetters` allows you to specify additional setters on top of those
+  that are generated from the encodable types themselves.
 
 ### Retrieving Codable Types
 
 Rows have a method to decode a Decodable type.
 
-``` swift
+```swift
 let loadedUsers: [User] = try db.prepare(users).map { row in
     return try row.decode()
 }
 ```
 
-You can also create a decoder to use manually yourself. This can be useful for example if you are using
-the [Facade pattern](https://en.wikipedia.org/wiki/Facade_pattern) to hide subclasses behind a super class.
-For example, you may want to encode an Image type that can be multiple different formats such as PNGImage, JPGImage,
-or HEIFIamge. You will need to determine the correct subclass before you know which type to decode.
+You can also create a decoder to use manually yourself. This can be useful
+for example if you are using the
+[Facade pattern](https://en.wikipedia.org/wiki/Facade_pattern) to hide
+subclasses behind a super class. For example, you may want to encode an Image
+type that can be multiple different formats such as PNGImage, JPGImage, or
+HEIFIamge. You will need to determine the correct subclass before you know
+which type to decode.
 
-``` swift
+```swift
 enum ImageCodingKeys: String, CodingKey {
     case kind
 }
@@ -1370,7 +1597,8 @@ let loadedImages: [Image] = try db.prepare(images).map { row in
 
 Both of the above methods also have the following optional parameter:
 
-- `userInfo` is a dictionary that is passed to the decoder and made available to decodable types to allow customizing their behavior.
+- `userInfo` is a dictionary that is passed to the decoder and made available
+  to decodable types to allow customizing their behavior.
 
 ### Restrictions
 
@@ -1379,15 +1607,19 @@ There are a few restrictions on using Codable types:
 - The encodable and decodable objects can only use the following types:
     - Int, Bool, Float, Double, String
     - Nested Codable types that will be encoded as JSON to a single column
-- These methods will not handle object relationships for you. You must write your own Codable and Decodable
-implementations if you wish to support this.
-- The Codable types may not try to access nested containers or nested unkeyed containers
-- The Codable types may not access single value containers or unkeyed containers
+- These methods will not handle object relationships for you. You must write
+  your own Codable and Decodable implementations if you wish to support this.
+- The Codable types may not try to access nested containers or nested unkeyed
+  containers
+- The Codable types may not access single value containers or unkeyed
+  containers
 - The Codable types may not access super decoders or encoders
 
 ## Other Operators
 
-In addition to [filter operators](#filtering-infix-operators), SQLite.swift defines a number of operators that can modify expression values with arithmetic, bitwise operations, and concatenation.
+In addition to [filter operators](#filtering-infix-operators), SQLite.swift
+defines a number of operators that can modify expression values with
+arithmetic, bitwise operations, and concatenation.
 
 
 ###### Other Infix Operators
@@ -1405,7 +1637,8 @@ In addition to [filter operators](#filtering-infix-operators), SQLite.swift defi
 | `|`   | `Int -> Int`                     | `|`      |
 | `+`   | `String -> String`               | `||`     |
 
-> _Note:_ SQLite.swift also defines a bitwise XOR operator, `^`, which expands the expression `lhs ^ rhs` to `~(lhs & rhs) & (lhs | rhs)`.
+> _Note:_ SQLite.swift also defines a bitwise XOR operator, `^`, which
+> expands the expression `lhs ^ rhs` to `~(lhs & rhs) & (lhs | rhs)`.
 
 
 ###### Other Prefix Operators
@@ -1418,22 +1651,26 @@ In addition to [filter operators](#filtering-infix-operators), SQLite.swift defi
 
 ## Core SQLite Functions
 
-Many of SQLite’s [core functions](https://www.sqlite.org/lang_corefunc.html) have been surfaced in and type-audited for SQLite.swift.
+Many of SQLite’s [core functions](https://www.sqlite.org/lang_corefunc.html)
+have been surfaced in and type-audited for SQLite.swift.
 
 > _Note:_ SQLite.swift aliases the `??` operator to the `ifnull` function.
 >
-> ``` swift
+> ```swift
 > name ?? email // ifnull("name", "email")
 > ```
 
 
 ## Aggregate SQLite Functions
 
-Most of SQLite’s [aggregate functions](https://www.sqlite.org/lang_aggfunc.html) have been surfaced in and type-audited for SQLite.swift.
+Most of SQLite’s
+[aggregate functions](https://www.sqlite.org/lang_aggfunc.html) have been
+surfaced in and type-audited for SQLite.swift.
 
 ## Date and Time functions
 
-SQLite's [date and time](https://www.sqlite.org/lang_datefunc.html) are available:
+SQLite's [date and time](https://www.sqlite.org/lang_datefunc.html)
+functions are available:
 
 ```swift
 DateFunctions.date("now")
@@ -1446,11 +1683,14 @@ Expression<Date>("date").date
 
 ## Custom SQL Functions
 
-We can create custom SQL functions by calling `createFunction` on a database connection.
+We can create custom SQL functions by calling `createFunction` on a database
+connection.
 
-For example, to give queries access to [`MobileCoreServices.UTTypeConformsTo`](https://developer.apple.com/library/ios/documentation/MobileCoreServices/Reference/UTTypeRef/index.html#//apple_ref/c/func/UTTypeConformsTo), we can write the following:
+For example, to give queries access to
+[`MobileCoreServices.UTTypeConformsTo`][UTTypeConformsTo], we can
+write the following:
 
-``` swift
+```swift
 import MobileCoreServices
 
 let typeConformsTo: (Expression<String>, Expression<String>) -> Expression<Bool> = (
@@ -1460,23 +1700,27 @@ let typeConformsTo: (Expression<String>, Expression<String>) -> Expression<Bool>
 )
 ```
 
-> _Note:_ The optional `deterministic` parameter is an optimization that causes the function to be created with [`SQLITE_DETERMINISTIC`](https://www.sqlite.org/c3ref/create_function.html).
+> _Note:_ The optional `deterministic` parameter is an optimization that
+> causes the function to be created with
+> [`SQLITE_DETERMINISTIC`](https://www.sqlite.org/c3ref/create_function.html).
 
 Note `typeConformsTo`’s signature:
 
-``` swift
+```swift
 (Expression<String>, Expression<String>) -> Expression<Bool>
 ```
 
-Because of this, `createFunction` expects a block with the following signature:
+Because of this, `createFunction` expects a block with the following
+signature:
 
-``` swift
+```swift
 (String, String) -> Bool
 ```
 
-Once assigned, the closure can be called wherever boolean expressions are accepted.
+Once assigned, the closure can be called wherever boolean expressions are
+accepted.
 
-``` swift
+```swift
 let attachments = Table("attachments")
 let UTI = Expression<String>("UTI")
 
@@ -1484,38 +1728,44 @@ let images = attachments.filter(typeConformsTo(UTI, kUTTypeImage))
 // SELECT * FROM "attachments" WHERE "typeConformsTo"("UTI", 'public.image')
 ```
 
-> _Note:_ The return type of a function must be [a core SQL type](#building-type-safe-sql) or [conform to `Value`](#custom-types).
+> _Note:_ The return type of a function must be [a core SQL type](#building-
+> type-safe-sql) or [conform to `Value`](#custom-types).
 
-We can create loosely-typed functions by handling an array of raw arguments, instead.
+We can create loosely-typed functions by handling an array of raw arguments,
+instead.
 
-``` swift
+```swift
 db.createFunction("typeConformsTo", deterministic: true) { args in
     guard let UTI = args[0] as? String, conformsToUTI = args[1] as? String else { return nil }
     return UTTypeConformsTo(UTI, conformsToUTI)
 }
 ```
 
-Creating a loosely-typed function cannot return a closure and instead must be wrapped manually or executed [using raw SQL](#executing-arbitrary-sql).
+Creating a loosely-typed function cannot return a closure and instead must be
+wrapped manually or executed [using raw SQL](#executing-arbitrary-sql).
 
-``` swift
+```swift
 let stmt = try db.prepare("SELECT * FROM attachments WHERE typeConformsTo(UTI, ?)")
 for row in stmt.bind(kUTTypeImage) { /* ... */ }
 ```
 
+[UTTypeConformsTo]: https://developer.apple.com/library/ios/documentation/MobileCoreServices/Reference/UTTypeRef/index.html#//apple_ref/c/func/UTTypeConformsTo
 
 ## Custom Collations
 
-We can create custom collating sequences by calling `createCollation` on a database connection.
+We can create custom collating sequences by calling `createCollation` on a
+database connection.
 
-``` swift
+```swift
 try db.createCollation("NODIACRITIC") { lhs, rhs in
     return lhs.compare(rhs, options: .diacriticInsensitiveSearch)
 }
 ```
 
-We can reference a custom collation using the `Custom` member of the `Collation` enumeration.
+We can reference a custom collation using the `Custom` member of the
+`Collation` enumeration.
 
-``` swift
+```swift
 restaurants.order(collate(.custom("NODIACRITIC"), name))
 // SELECT * FROM "restaurants" ORDER BY "name" COLLATE "NODIACRITIC"
 ```
@@ -1523,9 +1773,11 @@ restaurants.order(collate(.custom("NODIACRITIC"), name))
 
 ## Full-text Search
 
-We can create a virtual table using the [FTS4 module](http://www.sqlite.org/fts3.html) by calling `create` on a `VirtualTable`.
+We can create a virtual table using the [FTS4
+module](http://www.sqlite.org/fts3.html) by calling `create` on a
+`VirtualTable`.
 
-``` swift
+```swift
 let emails = VirtualTable("emails")
 let subject = Expression<String>("subject")
 let body = Expression<String>("body")
@@ -1536,14 +1788,14 @@ try db.run(emails.create(.FTS4(subject, body)))
 
 We can specify a [tokenizer](http://www.sqlite.org/fts3.html#tokenizer) using the `tokenize` parameter.
 
-``` swift
+```swift
 try db.run(emails.create(.FTS4([subject, body], tokenize: .Porter)))
 // CREATE VIRTUAL TABLE "emails" USING fts4("subject", "body", tokenize=porter)
 ```
 
 We can set the full range of parameters by creating a `FTS4Config` object.
 
-``` swift
+```swift
 let emails = VirtualTable("emails")
 let subject = Expression<String>("subject")
 let body = Expression<String>("body")
@@ -1557,9 +1809,11 @@ try db.run(emails.create(.FTS4(config))
 // CREATE VIRTUAL TABLE "emails" USING fts4("subject", "body", notindexed="body", languageid="lid", order="desc")
 ```
 
-Once we insert a few rows, we can search using the `match` function, which takes a table or column as its first argument and a query string as its second.
+Once we insert a few rows, we can search using the `match` function, which
+takes a table or column as its first argument and a query string as its
+second.
 
-``` swift
+```swift
 try db.run(emails.insert(
     subject <- "Just Checking In",
     body <- "Hey, I was just wondering...did you get my last email?"
@@ -1574,8 +1828,9 @@ let replies = emails.filter(subject.match("Re:*"))
 
 ### FTS5
 
-When linking against a version of SQLite with [FTS5](http://www.sqlite.org/fts5.html) enabled we can create the virtual table
-in a similar fashion.
+When linking against a version of SQLite with
+[FTS5](http://www.sqlite.org/fts5.html) enabled we can create the virtual
+table in a similar fashion.
 
 ```swift
 let emails = VirtualTable("emails")
@@ -1598,11 +1853,14 @@ let replies = emails.filter(emails.match("subject:\"Re:\"*))
 
 ## Executing Arbitrary SQL
 
-Though we recommend you stick with SQLite.swift’s [type-safe system](#building-type-safe-sql) whenever possible, it is possible to simply and safely prepare and execute raw SQL statements via a `Database` connection using the following functions.
+Though we recommend you stick with SQLite.swift’s [type-safe system
+](#building-type-safe-sql) whenever possible, it is possible to simply and
+safely prepare and execute raw SQL statements via a `Database` connection
+using the following functions.
 
   - `execute` runs an arbitrary number of SQL statements as a convenience.
 
-    ``` swift
+    ```swift
     try db.execute(
         "BEGIN TRANSACTION;" +
         "CREATE TABLE users (" +
@@ -1621,22 +1879,26 @@ Though we recommend you stick with SQLite.swift’s [type-safe system](#building
     )
     ```
 
-  - `prepare` prepares a single `Statement` object from a SQL string, optionally binds values to it (using the statement’s `bind` function), and returns the statement for deferred execution.
+  - `prepare` prepares a single `Statement` object from a SQL string,
+      optionally binds values to it (using the statement’s `bind` function),
+      and returns the statement for deferred execution.
 
-    ``` swift
+    ```swift
     let stmt = try db.prepare("INSERT INTO users (email) VALUES (?)")
     ```
 
-    Once prepared, statements may be executed using `run`, binding any unbound parameters.
+    Once prepared, statements may be executed using `run`, binding any
+    unbound parameters.
 
-    ``` swift
+    ```swift
     try stmt.run("alice@mac.com")
     db.changes // -> {Some 1}
     ```
 
-    Statements with results may be iterated over, using the columnNames if useful.
+    Statements with results may be iterated over, using the columnNames if
+    useful.
 
-    ``` swift
+    ```swift
     let stmt = try db.prepare("SELECT id, email FROM users")
     for row in stmt {
         for (index, name) in stmt.columnNames.enumerate() {
@@ -1646,21 +1908,26 @@ Though we recommend you stick with SQLite.swift’s [type-safe system](#building
     }
     ```
 
-  - `run` prepares a single `Statement` object from a SQL string, optionally binds values to it (using the statement’s `bind` function), executes, and returns the statement.
+  - `run` prepares a single `Statement` object from a SQL string, optionally
+    binds values to it (using the statement’s `bind` function), executes,
+    and returns the statement.
 
-    ``` swift
+    ```swift
     try db.run("INSERT INTO users (email) VALUES (?)", "alice@mac.com")
     ```
 
-  - `scalar` prepares a single `Statement` object from a SQL string, optionally binds values to it (using the statement’s `bind` function), executes, and returns the first value of the first row.
+  - `scalar` prepares a single `Statement` object from a SQL string,
+      optionally binds values to it (using the statement’s `bind` function),
+      executes, and returns the first value of the first row.
 
-    ``` swift
+    ```swift
     let count = try db.scalar("SELECT count(*) FROM users") as! Int64
     ```
 
-    Statements also have a `scalar` function, which can optionally re-bind values at execution.
+    Statements also have a `scalar` function, which can optionally re-bind
+    values at execution.
 
-    ``` swift
+    ```swift
     let stmt = try db.prepare("SELECT count (*) FROM users")
     let count = try stmt.scalar() as! Int64
     ```
@@ -1670,7 +1937,7 @@ Though we recommend you stick with SQLite.swift’s [type-safe system](#building
 
 We can log SQL using the database’s `trace` function.
 
-``` swift
+```swift
 #if DEBUG
     db.trace { print($0) }
 #endif
diff --git a/README.md b/README.md
index a10f2c09..07802fa8 100644
--- a/README.md
+++ b/README.md
@@ -26,7 +26,10 @@ syntax _and_ intent.
  - [Well-documented][See Documentation]
  - Extensively tested
  - SQLCipher support via CocoaPods
- - Active support at [StackOverflow](http://stackoverflow.com/questions/tagged/sqlite.swift), and [Gitter Chat Room](https://gitter.im/stephencelis/SQLite.swift) (_experimental_)
+ - Active support at
+   [StackOverflow](http://stackoverflow.com/questions/tagged/sqlite.swift),
+   and [Gitter Chat Room](https://gitter.im/stephencelis/SQLite.swift)
+   (_experimental_)
 
 [Full-text search]: Documentation/Index.md#full-text-search
 [See Documentation]: Documentation/Index.md#sqliteswift-documentation
@@ -34,7 +37,7 @@ syntax _and_ intent.
 
 ## Usage
 
-``` swift
+```swift
 import SQLite
 
 let db = try Connection("path/to/db.sqlite3")
@@ -81,7 +84,7 @@ try db.scalar(users.count) // 0
 SQLite.swift also works as a lightweight, Swift-friendly wrapper over the C
 API.
 
-``` swift
+```swift
 let stmt = try db.prepare("INSERT INTO users (email) VALUES (?)")
 for email in ["betty@icloud.com", "cathy@icloud.com"] {
     try stmt.run(email)
@@ -105,7 +108,13 @@ interactively, from the Xcode project’s playground.
 
 ![SQLite.playground Screen Shot](Documentation/Resources/playground@2x.png)
 
-For a more comprehensive example, see [this article](http://masteringswift.blogspot.com/2015/09/create-data-access-layer-with.html) and the [companion repository](https://github.com/hoffmanjon/SQLiteDataAccessLayer2/tree/master).
+For a more comprehensive example, see
+[this article][Create a Data Access Layer with SQLite.swift and Swift 2]
+and the [companion repository][SQLiteDataAccessLayer2].
+
+
+[Create a Data Access Layer with SQLite.swift and Swift 2]: http://masteringswift.blogspot.com/2015/09/create-data-access-layer-with.html
+[SQLiteDataAccessLayer2]: https://github.com/hoffmanjon/SQLiteDataAccessLayer2/tree/master
 
 ## Installation
 
@@ -120,11 +129,12 @@ install SQLite.swift with Carthage:
 
  2. Update your Cartfile to include the following:
 
-    ```
+    ```ruby
     github "stephencelis/SQLite.swift" ~> 0.11.4
     ```
 
- 3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
+ 3. Run `carthage update` and
+    [add the appropriate framework][Carthage Usage].
 
 
 [Carthage]: https://github.com/Carthage/Carthage
@@ -137,9 +147,10 @@ install SQLite.swift with Carthage:
 [CocoaPods][] is a dependency manager for Cocoa projects. To install
 SQLite.swift with CocoaPods:
 
- 1. Make sure CocoaPods is [installed][CocoaPods Installation]. (SQLite.swift requires version 1.0.0 or greater.)
+ 1. Make sure CocoaPods is [installed][CocoaPods Installation]. (SQLite.swift
+    requires version 1.0.0 or greater.)
 
-    ``` sh
+    ```sh
     # Using the default Ruby install will require you to use sudo when
     # installing and updating gems.
     [sudo] gem install cocoapods
@@ -147,7 +158,7 @@ SQLite.swift with CocoaPods:
 
  2. Update your Podfile to include the following:
 
-    ``` ruby
+    ```ruby
     use_frameworks!
 
     target 'YourAppTargetName' do
@@ -162,7 +173,8 @@ SQLite.swift with CocoaPods:
 
 ### Swift Package Manager
 
-The [Swift Package Manager][] is a tool for managing the distribution of Swift code.
+The [Swift Package Manager][] is a tool for managing the distribution of
+Swift code.
 
 1. Add the following to your `Package.swift` file:
 
@@ -174,7 +186,7 @@ The [Swift Package Manager][] is a tool for managing the distribution of Swift c
 
 2. Build your project:
 
-  ``` sh
+  ```sh
   $ swift build
   ```
 
@@ -196,9 +208,11 @@ To install SQLite.swift as an Xcode sub-project:
 
  4. **Add**.
 
-Some additional steps are required to install the application on an actual device:
+Some additional steps are required to install the application on an actual
+device:
 
- 5. In the **General** tab, click the **+** button under **Embedded Binaries**.
+ 5. In the **General** tab, click the **+** button under **Embedded
+    Binaries**.
 
  6. Select the appropriate **SQLite.framework** for your platform.
 
@@ -243,7 +257,8 @@ file](./LICENSE.txt) for more information.
 
 These projects enhance or use SQLite.swift:
 
- - [SQLiteMigrationManager.swift](https://github.com/garriguv/SQLiteMigrationManager.swift) (inspired by [FMDBMigrationManager](https://github.com/layerhq/FMDBMigrationManager))
+ - [SQLiteMigrationManager.swift][] (inspired by
+   [FMDBMigrationManager][])
 
 
 ## Alternatives
@@ -257,5 +272,7 @@ Looking for something else? Try another Swift wrapper (or [FMDB][]):
  - [SwiftData](https://github.com/ryanfowler/SwiftData)
  - [SwiftSQLite](https://github.com/chrismsimpson/SwiftSQLite)
 
-[FMDB]: https://github.com/ccgus/fmdb
 [swift-4]: https://github.com/stephencelis/SQLite.swift/tree/swift-4
+[SQLiteMigrationManager.swift]: https://github.com/garriguv/SQLiteMigrationManager.swift
+[FMDB]: https://github.com/ccgus/fmdb
+[FMDBMigrationManager]: https://github.com/layerhq/FMDBMigrationManager

From f7dfd88229c5e882dc84fa916b224f30dcab39cd Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 28 Sep 2017 08:56:29 +0200
Subject: [PATCH 262/685] Update changelog

---
 CHANGELOG.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e36e40d7..09c5c33f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
 ========================================
 
 * Added Date and Time functions ([#142][])
+* Add Swift4 Coding support ([#733][])
 * Preliminary Linux support ([#315][], [#681][])
 * Add `RowIterator` for more safety ([#647][], [#726][])
 * Make Row.get throw instead of crash ([#649][])
@@ -69,4 +70,5 @@
 [#681]: https://github.com/stephencelis/SQLite.swift/issues/681
 [#722]: https://github.com/stephencelis/SQLite.swift/pull/722
 [#723]: https://github.com/stephencelis/SQLite.swift/pull/723
+[#733]: https://github.com/stephencelis/SQLite.swift/pull/733
 [#726]: https://github.com/stephencelis/SQLite.swift/pull/726

From 25b2ae6e3eddfce2d0c18b69bb997316bfac4b25 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 28 Sep 2017 09:02:34 +0200
Subject: [PATCH 263/685] Add link

---
 Documentation/Index.md | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 9657a94a..74837148 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1516,9 +1516,11 @@ extension Row {
 
 ## Codable Types
 
-Codable types were introduced as a part of Swift 4 to allow serializing and
-deserializing types. SQLite.swift supports the insertion, updating, and
-retrieval of basic Codable types.
+[Codable types][Encoding and Decoding Custom Types] were introduced as a part
+of Swift 4 to  allow serializing and deserializing types. SQLite.swift supports
+the insertion, updating, and retrieval of basic Codable types.
+
+[Encoding and Decoding Custom Types]: https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types
 
 ### Inserting Codable Types
 

From 93f2f63f38f021583ac7a31c5c5b07a1e9fd7069 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 28 Sep 2017 09:06:46 +0200
Subject: [PATCH 264/685] clarify

---
 Documentation/Index.md | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 74837148..4b5c0025 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1527,7 +1527,10 @@ the insertion, updating, and retrieval of basic Codable types.
 Queries have a method to allow inserting an Encodable type.
 
 ```swift
-try db.run(users.insert(user))
+struct User: Codable {
+    let name: String
+}
+try db.run(users.insert(User(name: "test")))
 
 ```
 

From 865f4ad448b746b7ce82d55e0fee46478f87f38b Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 28 Sep 2017 09:27:42 +0200
Subject: [PATCH 265/685] Doc fixes

---
 Documentation/Index.md | 138 ++++++++++++++---------------------------
 README.md              |  32 +++++++---
 2 files changed, 70 insertions(+), 100 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 4b5c0025..f3569374 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -288,8 +288,8 @@ let db = try Connection(path, readonly: true)
 
 > _Note:_ Signed applications cannot modify their bundle resources. If you
 > bundle a database file with your app for the purpose of bootstrapping, copy
-> it to a writable location _before_ establishing a connection (see [Read-
-> Write Databases](#read-write-databases), above, for typical, writable
+> it to a writable location _before_ establishing a connection (see
+> [Read-Write Databases](#read-write-databases), above, for typical, writable
 > locations).
 >
 > See these two Stack Overflow questions for more information about iOS apps
@@ -515,8 +515,8 @@ several parameters that map to various column constraints and clauses.
 
   - `defaultValue` adds a `DEFAULT` clause to a column definition and _only_
     accepts a value (or expression) matching the column’s type. This value is
-    used if none is explicitly provided during [an `INSERT`](#inserting-
-    rows).
+    used if none is explicitly provided during
+    [an `INSERT`](#inserting-rows).
 
     ```swift
     t.column(name, defaultValue: "Anonymous")
@@ -587,8 +587,8 @@ using the following functions.
   - `check` adds a `CHECK` constraint to the table in the form of a boolean
     expression (`Expression<Bool>`). Boolean expressions can be easily built
     using [filter operators and functions](#filter-operators-and-functions).
-    (See also the `check` parameter under [Column Constraints](#column-
-    constraints).)
+    (See also the `check` parameter under
+    [Column Constraints](#column-constraints).)
 
     ```swift
     t.check(balance >= 0)
@@ -812,8 +812,8 @@ The `join` function takes a [query](#queries) object (for the table being
 joined on), a join condition (`on`), and is prefixed with an optional join
 type (default: `.inner`). Join conditions can be built using [filter
 operators and functions](#filter-operators-and-functions), generally require
-[namespacing](#column-namespacing), and sometimes require [aliasing](#table-
-aliasing).
+[namespacing](#column-namespacing), and sometimes require
+[aliasing](#table-aliasing).
 
 
 ##### Column Namespacing
@@ -1361,14 +1361,14 @@ system [SQLiteMigrationManager.swift][].
 SQLite.swift supports serializing and deserializing any custom type as long
 as it conforms to the `Value` protocol.
 
-> ```swift
-> protocol Value {
->     typealias Datatype: Binding
->     class var declaredDatatype: String { get }
->     class func fromDatatypeValue(datatypeValue: Datatype) -> Self
->     var datatypeValue: Datatype { get }
-> }
-> ```
+```swift
+protocol Value {
+    typealias Datatype: Binding
+    class var declaredDatatype: String { get }
+    class func fromDatatypeValue(datatypeValue: Datatype) -> Self
+    var datatypeValue: Datatype { get }
+}
+```
 
 The `Datatype` must be one of the basic Swift types that values are bridged
 through before serialization and deserialization (see [Building Type-Safe SQL
@@ -1385,64 +1385,19 @@ typed expressions can be.
 ### Date-Time Values
 
 In SQLite, `DATETIME` columns can be treated as strings or numbers, so we can
-transparently bridge `Date` objects through Swift’s `String` or `Int` types.
-
-To serialize `Date` objects as `TEXT` values (in ISO 8601), we’ll use
-`String`.
-
-```swift
-extension Date: Value {
-    class var declaredDatatype: String {
-        return String.declaredDatatype
-    }
-    class func fromDatatypeValue(stringValue: String) -> Date {
-        return SQLDateFormatter.dateFromString(stringValue)!
-    }
-    var datatypeValue: String {
-        return SQLDateFormatter.stringFromDate(self)
-    }
-}
+transparently bridge `Date` objects through Swift’s `String` types.
 
-let SQLDateFormatter: DateFormatter = {
-    let formatter = DateFormatter()
-    formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"
-    formatter.locale = Locale(localeIdentifier: "en_US_POSIX")
-    formatter.timeZone = TimeZone(forSecondsFromGMT: 0)
-    return formatter
-}()
-```
-
-We can also treat them as `INTEGER` values using `Int`.
-
-```swift
-extension Date: Value {
-    class var declaredDatatype: String {
-        return Int.declaredDatatype
-    }
-    class func fromDatatypeValue(intValue: Int) -> Self {
-        return self(timeIntervalSince1970: TimeInterval(intValue))
-    }
-    var datatypeValue: Int {
-        return Int(timeIntervalSince1970)
-    }
-}
-```
-
-> _Note:_ SQLite’s `CURRENT_DATE`, `CURRENT_TIME`, and `CURRENT_TIMESTAMP`
-> helpers return `TEXT` values. Because of this (and the fact that Unix time
-> is far less human-readable when we’re faced with the raw data), we
-> recommend using the `TEXT` extension.
-
-Once defined, we can use these types directly in SQLite statements.
+We can use these types directly in SQLite statements.
 
 ```swift
 let published_at = Expression<Date>("published_at")
 
 let published = posts.filter(published_at <= Date())
-// extension where Datatype == String:
-//     SELECT * FROM "posts" WHERE "published_at" <= '2014-11-18 12:45:30'
-// extension where Datatype == Int:
-//     SELECT * FROM "posts" WHERE "published_at" <= 1416314730
+// SELECT * FROM "posts" WHERE "published_at" <= '2014-11-18T12:45:30.000'
+
+let startDate = Date(timeIntervalSince1970: 0)
+let published = posts.filter(startDate...Date() ~= published_at)
+// SELECT * FROM "posts" WHERE "published_at" BETWEEN '1970-01-01T00:00:00.000' AND '2014-11-18T12:45:30.000'
 ```
 
 
@@ -1469,7 +1424,7 @@ extension UIImage: Value {
 > information on encoding and decoding custom types.
 
 
-[Archives and Serializations Programming Guide]: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Archiving/Archiving.html#//apple_ref/doc/uid/10000047i
+[Archives and Serializations Programming Guide]: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Archiving/Archiving.html
 
 ### Custom Type Caveats
 
@@ -1707,7 +1662,7 @@ let typeConformsTo: (Expression<String>, Expression<String>) -> Expression<Bool>
 
 > _Note:_ The optional `deterministic` parameter is an optimization that
 > causes the function to be created with
-> [`SQLITE_DETERMINISTIC`](https://www.sqlite.org/c3ref/create_function.html).
+> [`SQLITE_DETERMINISTIC`](https://www.sqlite.org/c3ref/c_deterministic.html).
 
 Note `typeConformsTo`’s signature:
 
@@ -1733,8 +1688,8 @@ let images = attachments.filter(typeConformsTo(UTI, kUTTypeImage))
 // SELECT * FROM "attachments" WHERE "typeConformsTo"("UTI", 'public.image')
 ```
 
-> _Note:_ The return type of a function must be [a core SQL type](#building-
-> type-safe-sql) or [conform to `Value`](#custom-types).
+> _Note:_ The return type of a function must be
+> [a core SQL type](#building-type-safe-sql) or [conform to `Value`](#custom-types).
 
 We can create loosely-typed functions by handling an array of raw arguments,
 instead.
@@ -1754,7 +1709,7 @@ let stmt = try db.prepare("SELECT * FROM attachments WHERE typeConformsTo(UTI, ?
 for row in stmt.bind(kUTTypeImage) { /* ... */ }
 ```
 
-[UTTypeConformsTo]: https://developer.apple.com/library/ios/documentation/MobileCoreServices/Reference/UTTypeRef/index.html#//apple_ref/c/func/UTTypeConformsTo
+[UTTypeConformsTo]: https://developer.apple.com/documentation/coreservices/1444079-uttypeconformsto
 
 ## Custom Collations
 
@@ -1858,29 +1813,30 @@ let replies = emails.filter(emails.match("subject:\"Re:\"*))
 
 ## Executing Arbitrary SQL
 
-Though we recommend you stick with SQLite.swift’s [type-safe system
-](#building-type-safe-sql) whenever possible, it is possible to simply and
-safely prepare and execute raw SQL statements via a `Database` connection
+Though we recommend you stick with SQLite.swift’s
+[type-safe system](#building-type-safe-sql) whenever possible, it is possible
+to simply and safely prepare and execute raw SQL statements via a `Database` connection
 using the following functions.
 
   - `execute` runs an arbitrary number of SQL statements as a convenience.
 
     ```swift
-    try db.execute(
-        "BEGIN TRANSACTION;" +
-        "CREATE TABLE users (" +
-            "id INTEGER PRIMARY KEY NOT NULL," +
-            "email TEXT UNIQUE NOT NULL," +
-            "name TEXT" +
-        ");" +
-        "CREATE TABLE posts (" +
-            "id INTEGER PRIMARY KEY NOT NULL," +
-            "title TEXT NOT NULL," +
-            "body TEXT NOT NULL," +
-            "published_at DATETIME" +
-        ");" +
-        "PRAGMA user_version = 1;" +
-        "COMMIT TRANSACTION;"
+    try db.execute("""
+        BEGIN TRANSACTION;
+        CREATE TABLE users (
+            id INTEGER PRIMARY KEY NOT NULL,
+            email TEXT UNIQUE NOT NULL,
+            name TEXT
+        );
+        CREATE TABLE posts (
+            id INTEGER PRIMARY KEY NOT NULL,
+            title TEXT NOT NULL,
+            body TEXT NOT NULL,
+            published_at DATETIME
+        );
+        PRAGMA user_version = 1;
+        COMMIT TRANSACTION;
+        """
     )
     ```
 
diff --git a/README.md b/README.md
index 07802fa8..3a9ceecb 100644
--- a/README.md
+++ b/README.md
@@ -1,19 +1,12 @@
 # SQLite.swift
 
-[![Build Status][Badge]][Travis] [![CocoaPods Version](https://cocoapod-badges.herokuapp.com/v/SQLite.swift/badge.png)](http://cocoadocs.org/docsets/SQLite.swift) [![Swift](https://img.shields.io/badge/swift-4-orange.svg?style=flat)](https://developer.apple.com/swift/) [![Platform](https://cocoapod-badges.herokuapp.com/p/SQLite.swift/badge.png)](http://cocoadocs.org/docsets/SQLite.swift) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![Join the chat at https://gitter.im/stephencelis/SQLite.swift](https://badges.gitter.im/stephencelis/SQLite.swift.svg)](https://gitter.im/stephencelis/SQLite.swift)
+[![Build Status][TravisBadge]][TravisLink] [![CocoaPods Version][CocoaPodsVersionBadge]][CocoaPodsVersionLink] [![Swift4 compatible][Swift4Badge]][Swift4Link] [![Platform][PlatformBadge]][PlatformLink] [![Carthage compatible][CartagheBadge]][CarthageLink] [![Join the chat at https://gitter.im/stephencelis/SQLite.swift][GitterBadge]][GitterLink]
 
 A type-safe, [Swift][]-language layer over [SQLite3][].
 
 [SQLite.swift][] provides compile-time confidence in SQL statement
 syntax _and_ intent.
 
-[Badge]: https://img.shields.io/travis/stephencelis/SQLite.swift/master.svg?style=flat
-[Travis]: https://travis-ci.org/stephencelis/SQLite.swift
-[Swift]: https://developer.apple.com/swift/
-[SQLite3]: http://www.sqlite.org
-[SQLite.swift]: https://github.com/stephencelis/SQLite.swift
-
-
 ## Features
 
  - A pure-Swift interface
@@ -272,7 +265,28 @@ Looking for something else? Try another Swift wrapper (or [FMDB][]):
  - [SwiftData](https://github.com/ryanfowler/SwiftData)
  - [SwiftSQLite](https://github.com/chrismsimpson/SwiftSQLite)
 
-[swift-4]: https://github.com/stephencelis/SQLite.swift/tree/swift-4
+[Swift]: https://swift.org/
+[SQLite3]: http://www.sqlite.org
+[SQLite.swift]: https://github.com/stephencelis/SQLite.swift
+
+[TravisBadge]: https://img.shields.io/travis/stephencelis/SQLite.swift/master.svg?style=flat
+[TravisLink]: https://travis-ci.org/stephencelis/SQLite.swift
+
+[CocoaPodsVersionBadge]: https://cocoapod-badges.herokuapp.com/v/SQLite.swift/badge.png
+[CocoaPodsVersionLink]: http://cocoadocs.org/docsets/SQLite.swift
+
+[PlatformBadge]: https://cocoapod-badges.herokuapp.com/p/SQLite.swift/badge.png
+[PlatformLink]: http://cocoadocs.org/docsets/SQLite.swift
+
+[CartagheBadge]: https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat
+[CarthageLink]: https://github.com/Carthage/Carthage
+
+[GitterBadge]: https://badges.gitter.im/stephencelis/SQLite.swift.svg
+[GitterLink]: https://gitter.im/stephencelis/SQLite.swift
+
+[Swift4Badge]: https://img.shields.io/badge/swift-4-orange.svg?style=flat
+[Swift4Link]: https://developer.apple.com/swift/
+
 [SQLiteMigrationManager.swift]: https://github.com/garriguv/SQLiteMigrationManager.swift
 [FMDB]: https://github.com/ccgus/fmdb
 [FMDBMigrationManager]: https://github.com/layerhq/FMDBMigrationManager

From 5df5620a218d560fe727648b579cd988da13537b Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 28 Sep 2017 10:17:12 +0200
Subject: [PATCH 266/685] Update changelog

---
 CHANGELOG.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 09c5c33f..3f0e9f0d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
 0.11.4 (xx-09-2017), [diff][diff-0.11.4]
 ========================================
 
+* Add possibility to have expression on right hand side of like ([#591][])
 * Added Date and Time functions ([#142][])
 * Add Swift4 Coding support ([#733][])
 * Preliminary Linux support ([#315][], [#681][])
@@ -61,6 +62,7 @@
 [#560]: https://github.com/stephencelis/SQLite.swift/pull/560
 [#561]: https://github.com/stephencelis/SQLite.swift/issues/561
 [#571]: https://github.com/stephencelis/SQLite.swift/issues/571
+[#591]: https://github.com/stephencelis/SQLite.swift/pull/591
 [#615]: https://github.com/stephencelis/SQLite.swift/pull/615
 [#647]: https://github.com/stephencelis/SQLite.swift/pull/647
 [#649]: https://github.com/stephencelis/SQLite.swift/pull/649

From bc60dcdec186040c77df5f164ec1909ba803955a Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 28 Sep 2017 10:24:14 +0200
Subject: [PATCH 267/685] Update changelog

---
 CHANGELOG.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3f0e9f0d..7f3db59e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
 0.11.4 (xx-09-2017), [diff][diff-0.11.4]
 ========================================
 
+* Fix transactions not being rolled back when committing fails ([#426][])
 * Add possibility to have expression on right hand side of like ([#591][])
 * Added Date and Time functions ([#142][])
 * Add Swift4 Coding support ([#733][])
@@ -52,6 +53,7 @@
 
 [#142]: https://github.com/stephencelis/SQLit1e.swift/issues/142
 [#315]: https://github.com/stephencelis/SQLit1e.swift/issues/315
+[#426]: https://github.com/stephencelis/SQLit1e.swift/pull/426
 [#481]: https://github.com/stephencelis/SQLit1e.swift/pull/481
 [#532]: https://github.com/stephencelis/SQLit1e.swift/issues/532
 [#541]: https://github.com/stephencelis/SQLit1e.swift/issues/541

From 0fa5e5e00a3e0456ba292b502013ed3708bab756 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 28 Sep 2017 11:09:38 +0200
Subject: [PATCH 268/685] Optional types should not enforce NOT NULL

Closes #697
---
 CHANGELOG.md                        |  2 ++
 Sources/SQLite/Typed/Schema.swift   | 12 ++++----
 Tests/SQLiteTests/SchemaTests.swift | 48 ++++++++++++++---------------
 3 files changed, 32 insertions(+), 30 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7f3db59e..f9a920d5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
 0.11.4 (xx-09-2017), [diff][diff-0.11.4]
 ========================================
 
+* Collate .nocase strictly enforces NOT NULL even when using Optional ([#697][])
 * Fix transactions not being rolled back when committing fails ([#426][])
 * Add possibility to have expression on right hand side of like ([#591][])
 * Added Date and Time functions ([#142][])
@@ -72,6 +73,7 @@
 [#666]: https://github.com/stephencelis/SQLite.swift/pull/666
 [#668]: https://github.com/stephencelis/SQLite.swift/pull/668
 [#681]: https://github.com/stephencelis/SQLite.swift/issues/681
+[#697]: https://github.com/stephencelis/SQLite.swift/issues/697
 [#722]: https://github.com/stephencelis/SQLite.swift/pull/722
 [#723]: https://github.com/stephencelis/SQLite.swift/pull/723
 [#733]: https://github.com/stephencelis/SQLite.swift/pull/733
diff --git a/Sources/SQLite/Typed/Schema.swift b/Sources/SQLite/Typed/Schema.swift
index 690a26a5..46a1f87a 100644
--- a/Sources/SQLite/Typed/Schema.swift
+++ b/Sources/SQLite/Typed/Schema.swift
@@ -300,27 +300,27 @@ public final class TableBuilder {
     }
 
     public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: Expression<V>? = nil, collate: Collation) where V.Datatype == String {
-        column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate)
+        column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, collate)
     }
 
     public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: Expression<V?>, collate: Collation) where V.Datatype == String {
-        column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate)
+        column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, collate)
     }
 
     public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: V, collate: Collation) where V.Datatype == String {
-        column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate)
+        column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, collate)
     }
 
     public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, defaultValue: Expression<V>? = nil, collate: Collation) where V.Datatype == String {
-        column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate)
+        column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, collate)
     }
 
     public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, defaultValue: Expression<V?>, collate: Collation) where V.Datatype == String {
-        column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate)
+        column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, collate)
     }
 
     public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, defaultValue: V, collate: Collation) where V.Datatype == String {
-        column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate)
+        column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, collate)
     }
 
     fileprivate func column(_ name: Expressible, _ datatype: String, _ primaryKey: PrimaryKey?, _ null: Bool, _ unique: Bool, _ check: Expressible?, _ defaultValue: Expressible?, _ references: (QueryType, Expressible)?, _ collate: Collation?) {
diff --git a/Tests/SQLiteTests/SchemaTests.swift b/Tests/SQLiteTests/SchemaTests.swift
index 34226b3c..b9a08881 100644
--- a/Tests/SQLiteTests/SchemaTests.swift
+++ b/Tests/SQLiteTests/SchemaTests.swift
@@ -435,99 +435,99 @@ class SchemaTests : XCTestCase {
         )
 
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, unique: true, collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL CHECK (\"string\" != '') COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"string\" != '') COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, check: string != "", collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL CHECK (\"stringOptional\" != '') COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"stringOptional\" != '') COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, check: stringOptional != "", collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL DEFAULT (\"string\") COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT DEFAULT (\"string\") COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, defaultValue: string, collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL DEFAULT (\"stringOptional\") COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT DEFAULT (\"stringOptional\") COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, defaultValue: stringOptional, collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL DEFAULT ('string') COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT DEFAULT ('string') COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, defaultValue: "string", collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE CHECK (\"string\" != '') COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"string\" != '') COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, unique: true, check: string != "", collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE CHECK (\"stringOptional\" != '') COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"stringOptional\" != '') COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, unique: true, check: stringOptional != "", collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE DEFAULT (\"string\") COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE DEFAULT (\"string\") COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, unique: true, defaultValue: string, collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE DEFAULT (\"stringOptional\") COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE DEFAULT (\"stringOptional\") COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, unique: true, defaultValue: stringOptional, collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE DEFAULT ('string') COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE DEFAULT ('string') COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, unique: true, defaultValue: "string", collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE CHECK (\"string\" != '') DEFAULT (\"string\") COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"string\" != '') DEFAULT (\"string\") COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, unique: true, check: string != "", defaultValue: string, collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE CHECK (\"string\" != '') DEFAULT (\"stringOptional\") COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"string\" != '') DEFAULT (\"stringOptional\") COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, unique: true, check: string != "", defaultValue: stringOptional, collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE CHECK (\"stringOptional\" != '') DEFAULT (\"string\") COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"stringOptional\" != '') DEFAULT (\"string\") COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, unique: true, check: stringOptional != "", defaultValue: string, collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE CHECK (\"stringOptional\" != '') DEFAULT (\"stringOptional\") COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"stringOptional\" != '') DEFAULT (\"stringOptional\") COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, unique: true, check: stringOptional != "", defaultValue: stringOptional, collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE CHECK (\"string\" != '') DEFAULT ('string') COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"string\" != '') DEFAULT ('string') COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, unique: true, check: string != "", defaultValue: "string", collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL UNIQUE CHECK (\"stringOptional\" != '') DEFAULT ('string') COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"stringOptional\" != '') DEFAULT ('string') COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, unique: true, check: stringOptional != "", defaultValue: "string", collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL CHECK (\"string\" != '') DEFAULT (\"string\") COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"string\" != '') DEFAULT (\"string\") COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, check: string != "", defaultValue: string, collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL CHECK (\"stringOptional\" != '') DEFAULT (\"string\") COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"stringOptional\" != '') DEFAULT (\"string\") COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, check: stringOptional != "", defaultValue: string, collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL CHECK (\"string\" != '') DEFAULT (\"stringOptional\") COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"string\" != '') DEFAULT (\"stringOptional\") COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, check: string != "", defaultValue: stringOptional, collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL CHECK (\"stringOptional\" != '') DEFAULT (\"stringOptional\") COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"stringOptional\" != '') DEFAULT (\"stringOptional\") COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, check: stringOptional != "", defaultValue: stringOptional, collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL CHECK (\"string\" != '') DEFAULT ('string') COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"string\" != '') DEFAULT ('string') COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, check: string != "", defaultValue: "string", collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT NOT NULL CHECK (\"stringOptional\" != '') DEFAULT ('string') COLLATE RTRIM)",
+            "CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"stringOptional\" != '') DEFAULT ('string') COLLATE RTRIM)",
             table.create { t in t.column(stringOptional, check: stringOptional != "", defaultValue: "string", collate: .rtrim) }
         )
     }

From 44452ad553e72e76d567ccefa1208317f60c8626 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 28 Sep 2017 12:09:04 +0200
Subject: [PATCH 269/685] Document error handling

Closes #700
---
 Documentation/Index.md             | 14 ++++++++++++++
 Tests/SQLiteTests/QueryTests.swift | 12 ++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index f3569374..aa219633 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -650,6 +650,20 @@ follow similar patterns.
 > // INSERT INTO "timestamps" DEFAULT VALUES
 > ```
 
+### Handling specific SQLite errors
+
+You can pattern match on the error to selectively catch SQLite errors:
+
+```swift
+do {
+    try db.run(users.insert(email <- "alice@mac.com"))
+    try db.run(users.insert(email <- "alice@mac.com"))
+} catch let Result.error(_, code, _) where code == SQLITE_CONSTRAINT {
+    print("constraint failed")
+} catch let error {
+    print("insertion failed: \(error)")
+}
+```
 
 ### Setters
 
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index bb99d016..cd609708 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -518,4 +518,16 @@ class QueryIntegrationTests : SQLiteTestCase {
             }
         }
     }
+
+    func test_catchConstraintError() {
+        try! db.run(users.insert(email <- "alice@example.com"))
+        do {
+            try db.run(users.insert(email <- "alice@example.com"))
+            XCTFail("expected error")
+        } catch let Result.error(_, code, _) where code == SQLITE_CONSTRAINT {
+            // expected
+        } catch let error {
+            XCTFail("unexpected error: \(error)")
+        }
+    }
 }

From 1602cc044ece758cd1a80b0c403aea9b21452bb7 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 28 Sep 2017 12:32:01 +0200
Subject: [PATCH 270/685] Link milestone

---
 Documentation/Planning.md | 30 ++++++++++++++++++++++--------
 1 file changed, 22 insertions(+), 8 deletions(-)

diff --git a/Documentation/Planning.md b/Documentation/Planning.md
index d814d26b..8a3d5a11 100644
--- a/Documentation/Planning.md
+++ b/Documentation/Planning.md
@@ -1,7 +1,13 @@
 # SQLite.swift Planning
 
-This document captures both near term steps (aka Roadmap) and feature requests.
-The goal is to add some visibility and guidance for future additions and Pull Requests, as well as to keep the Issues list clear of enhancement requests so that bugs are more visible.
+This document captures both near term steps (aka Roadmap) and feature
+requests. The goal is to add some visibility and guidance for future
+additions and Pull Requests, as well as to keep the Issues list clear of
+enhancement requests so that bugs are more visible.
+
+> ⚠ This document is currently not actively maintained. See
+> the [0.12.0 milestone](https://github.com/stephencelis/SQLite.swift/issues?q=is%3Aopen+is%3Aissue+milestone%3A0.12.0)
+> on Github for additional information about planned features for the next release.
 
 ## Roadmap
 
@@ -9,16 +15,24 @@ _Lists agreed upon next steps in approximate priority order._
 
 ## Feature Requests
 
-_A gathering point for ideas for new features. In general, the corresponding issue will be closed once it is added here, with the assumption that it will be referred to when it comes time to add the corresponding feature._
+_A gathering point for ideas for new features. In general, the corresponding
+issue will be closed once it is added here, with the assumption that it will
+be referred to when it comes time to add the corresponding feature._
 
 ### Features
 
- * encapsulate ATTACH DATABASE / DETACH DATABASE as methods, per [#30](https://github.com/stephencelis/SQLite.swift/issues/30)
- * provide separate threads for update vs read, so updates don't block reads, per [#236](https://github.com/stephencelis/SQLite.swift/issues/236)
- * expose triggers, per [#164](https://github.com/stephencelis/SQLite.swift/issues/164)
+ * encapsulate ATTACH DATABASE / DETACH DATABASE as methods, per
+   [#30](https://github.com/stephencelis/SQLite.swift/issues/30)
+ * provide separate threads for update vs read, so updates don't block reads,
+   per [#236](https://github.com/stephencelis/SQLite.swift/issues/236)
+ * expose triggers, per
+   [#164](https://github.com/stephencelis/SQLite.swift/issues/164)
 
 ## Suspended Feature Requests
 
-_Features that are not actively being considered, perhaps because of no clean type-safe way to implement them with the current Swift, or bugs, or just general uncertainty._
+_Features that are not actively being considered, perhaps because of no clean
+type-safe way to implement them with the current Swift, or bugs, or just
+general uncertainty._
 
- * provide a mechanism for INSERT INTO multiple values, per [#168](https://github.com/stephencelis/SQLite.swift/issues/168)
+ * provide a mechanism for INSERT INTO multiple values, per
+   [#168](https://github.com/stephencelis/SQLite.swift/issues/168)

From 1bdd7f3855a5e5f5afc41c5fa07e0126cf8f10dd Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 28 Sep 2017 12:54:08 +0200
Subject: [PATCH 271/685] Docs: how to get error message

Closes #366
---
 Documentation/Index.md               | 13 +++++++++----
 Sources/SQLite/Core/Connection.swift |  7 +++++++
 2 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index aa219633..8ac564a8 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -650,21 +650,26 @@ follow similar patterns.
 > // INSERT INTO "timestamps" DEFAULT VALUES
 > ```
 
-### Handling specific SQLite errors
+### Handling SQLite errors
 
-You can pattern match on the error to selectively catch SQLite errors:
+You can pattern match on the error to selectively catch SQLite errors. For example, to
+specifically handle constraint errors ([SQLITE_CONSTRAINT](https://sqlite.org/rescode.html#constraint)):
 
 ```swift
 do {
     try db.run(users.insert(email <- "alice@mac.com"))
     try db.run(users.insert(email <- "alice@mac.com"))
-} catch let Result.error(_, code, _) where code == SQLITE_CONSTRAINT {
-    print("constraint failed")
+} catch let Result.error(message, code, statement) where code == SQLITE_CONSTRAINT {
+    print("constraint failed: \(message), in \(statement)")
 } catch let error {
     print("insertion failed: \(error)")
 }
 ```
 
+The `Result.error` type contains the English-language text that describes the error (`message`),
+the error `code` (see [SQLite result code list](https://sqlite.org/rescode.html#primary_result_code_list)
+for details) and a optional reference to the `statement` which produced the error.
+
 ### Setters
 
 SQLite.swift typically uses the `<-` operator to set values during [inserts
diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index d2f5f523..f7513115 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -681,6 +681,13 @@ public enum Result : Error {
 
     fileprivate static let successCodes: Set = [SQLITE_OK, SQLITE_ROW, SQLITE_DONE]
 
+    /// Represents a SQLite specific [error code](https://sqlite.org/rescode.html)
+    ///
+    /// - message: English-language text that describes the error
+    ///
+    /// - code: SQLite [error code](https://sqlite.org/rescode.html#primary_result_code_list)
+    ///
+    /// - statement: the statement which produced the error
     case error(message: String, code: Int32, statement: Statement?)
 
     init?(errorCode: Int32, connection: Connection, statement: Statement? = nil) {

From e9d93b5913e3e1326daee7a6bb9acabb874956de Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 28 Sep 2017 14:02:48 +0200
Subject: [PATCH 272/685] Missing import

---
 Tests/SQLiteTests/QueryTests.swift | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index cd609708..2a9e4ecb 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -1,4 +1,13 @@
 import XCTest
+#if SQLITE_SWIFT_STANDALONE
+import sqlite3
+#elseif SQLITE_SWIFT_SQLCIPHER
+import SQLCipher
+#elseif os(Linux)
+import CSQLite
+#else
+import SQLite3
+#endif
 @testable import SQLite
 
 class QueryTests : XCTestCase {

From 56d3a65e99cba3af5ee07795822dff1dfb3436d6 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 28 Sep 2017 14:53:07 +0200
Subject: [PATCH 273/685] Clear out trace

---
 Tests/SQLiteTests/ConnectionTests.swift | 2 +-
 Tests/SQLiteTests/TestHelpers.swift     | 8 +++-----
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index ac738961..ad902ed3 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -157,7 +157,7 @@ class ConnectionTests : SQLiteTestCase {
 
     func test_transaction_rollsBackTransactionsIfCommitsFail() {
         // This test case needs to emulate an environment where the individual statements succeed, but committing the
-        // transactuin fails. Using deferred foreign keys is one option to achieve this.
+        // transaction fails. Using deferred foreign keys is one option to achieve this.
         try! db.execute("PRAGMA foreign_keys = ON;")
         try! db.execute("PRAGMA defer_foreign_keys = ON;")
         let stmt = try! db.prepare("INSERT INTO users (email, manager_id) VALUES (?, ?)", "alice@example.com", 100)
diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index dc32bb83..bec6f751 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -2,15 +2,13 @@ import XCTest
 @testable import SQLite
 
 class SQLiteTestCase : XCTestCase {
-
-    var trace = [String: Int]()
-
-    let db = try! Connection()
-
+    private var trace:[String: Int]!
     let users = Table("users")
+    let db = try! Connection()
 
     override func setUp() {
         super.setUp()
+        trace = [String:Int]()
 
         db.trace { SQL in
             print(SQL)

From 7cc98a8d006caa35475f744944ad2b30b97f8e4e Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 28 Sep 2017 16:10:36 +0200
Subject: [PATCH 274/685] Recreate connection

---
 Tests/SQLiteTests/ConnectionTests.swift | 4 ++--
 Tests/SQLiteTests/TestHelpers.swift     | 3 ++-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index ad902ed3..b0be9a72 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -200,7 +200,7 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_savepoint_beginsAndCommitsSavepoints() {
-        let db = self.db
+        let db:Connection = self.db
 
         try! db.savepoint("1") {
             try db.savepoint("2") {
@@ -218,7 +218,7 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_savepoint_beginsAndRollsSavepointsBack() {
-        let db = self.db
+        let db:Connection = self.db
         let stmt = try! db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com")
 
         do {
diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index bec6f751..7f790ef7 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -3,11 +3,12 @@ import XCTest
 
 class SQLiteTestCase : XCTestCase {
     private var trace:[String: Int]!
+    var db:Connection!
     let users = Table("users")
-    let db = try! Connection()
 
     override func setUp() {
         super.setUp()
+        db = try! Connection()
         trace = [String:Int]()
 
         db.trace { SQL in

From 616e5bde44191e40f4722eada2e924216861c5cd Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 28 Sep 2017 17:33:36 +0200
Subject: [PATCH 275/685] 
 https://sqlite.org/pragma.html#pragma_defer_foreign_keys
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

“The defer_foreign_keys pragma is automatically switched off at each COMMIT or ROLLBACK. Hence, the defer_foreign_keys pragma must be separately enabled for each transaction. This pragma is only meaningful if foreign key constraints are enabled, of course.”
---
 Tests/SQLiteTests/ConnectionTests.swift | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index b0be9a72..f1af1fd0 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -159,14 +159,18 @@ class ConnectionTests : SQLiteTestCase {
         // This test case needs to emulate an environment where the individual statements succeed, but committing the
         // transaction fails. Using deferred foreign keys is one option to achieve this.
         try! db.execute("PRAGMA foreign_keys = ON;")
-        try! db.execute("PRAGMA defer_foreign_keys = ON;")
         let stmt = try! db.prepare("INSERT INTO users (email, manager_id) VALUES (?, ?)", "alice@example.com", 100)
 
         do {
             try db.transaction {
+                try db.execute("PRAGMA defer_foreign_keys = ON;")
                 try stmt.run()
             }
-        } catch {
+            XCTFail("expected error")
+        } catch let Result.error(_, code, _) {
+            XCTAssertEqual(SQLITE_CONSTRAINT, code)
+        } catch let error {
+            XCTFail("unexpected error: \(error)")
         }
 
         AssertSQL("BEGIN DEFERRED TRANSACTION")

From 1d6167fe877c327a29bbf2c4b7343f99d36bedae Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 28 Sep 2017 22:31:33 +0200
Subject: [PATCH 276/685] Swift 4

---
 Tests/SQLiteTests/TestHelpers.swift | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index 7f790ef7..271f4166 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -13,21 +13,22 @@ class SQLiteTestCase : XCTestCase {
 
         db.trace { SQL in
             print(SQL)
-            self.trace[SQL] = (self.trace[SQL] ?? 0) + 1
+            self.trace[SQL, default: 0] += 1
         }
     }
 
     func CreateUsersTable() {
-        try! db.execute(
-            "CREATE TABLE \"users\" (" +
-                "id INTEGER PRIMARY KEY, " +
-                "email TEXT NOT NULL UNIQUE, " +
-                "age INTEGER, " +
-                "salary REAL, " +
-                "admin BOOLEAN NOT NULL DEFAULT 0 CHECK (admin IN (0, 1)), " +
-                "manager_id INTEGER, " +
-                "FOREIGN KEY(manager_id) REFERENCES users(id)" +
-            ")"
+        try! db.execute("""
+            CREATE TABLE users (
+                id INTEGER PRIMARY KEY, 
+                email TEXT NOT NULL UNIQUE, 
+                age INTEGER, 
+                salary REAL,
+                admin BOOLEAN NOT NULL DEFAULT 0 CHECK (admin IN (0, 1)),
+                manager_id INTEGER,
+                FOREIGN KEY(manager_id) REFERENCES users(id)
+            )
+            """
         )
     }
 

From 2e59493201d19cd6be0f53a080e26729b686d5c4 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 28 Sep 2017 22:32:41 +0200
Subject: [PATCH 277/685] Skip tests for older versions of SQLite

---
 Tests/SQLiteTests/ConnectionTests.swift | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index f1af1fd0..d74a50c1 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -156,14 +156,21 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_transaction_rollsBackTransactionsIfCommitsFail() {
+        let sqliteVersion = String(describing: try! db.scalar("SELECT sqlite_version()")!)
+                .split(separator: ".").flatMap { Int($0) }
+        // PRAGMA defer_foreign_keys only supported in SQLite >= 3.8.0
+        guard sqliteVersion[0] == 3 && sqliteVersion[1] >= 8 else {
+            NSLog("skipping test for SQLite version \(sqliteVersion)")
+            return
+        }
         // This test case needs to emulate an environment where the individual statements succeed, but committing the
         // transaction fails. Using deferred foreign keys is one option to achieve this.
         try! db.execute("PRAGMA foreign_keys = ON;")
+        try! db.execute("PRAGMA defer_foreign_keys = ON;")
         let stmt = try! db.prepare("INSERT INTO users (email, manager_id) VALUES (?, ?)", "alice@example.com", 100)
 
         do {
             try db.transaction {
-                try db.execute("PRAGMA defer_foreign_keys = ON;")
                 try stmt.run()
             }
             XCTFail("expected error")

From 42727c2a3d8024bc081db0f0d16d3d46b64afec2 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 29 Sep 2017 07:21:48 +0200
Subject: [PATCH 278/685] Add issue template

---
 .github/ISSUE_TEMPLATE.md | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
 create mode 100644 .github/ISSUE_TEMPLATE.md

diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 00000000..61152bad
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,20 @@
+> Issues are used to track bugs and feature requests. 
+> Need  help or have a general question? Ask on Stack Overflow (tag sqlite.swift).
+
+## Build Information
+
+- Include the SQLite.swift version, commit or branch experiencing the issue.
+- Mention Xcode and OS X versions affected.
+- How do do you integrate SQLite.swift in your project? 
+    - manual
+    - CocoaPods
+    - Carthage
+    - Swift Package manager
+
+## General guidelines
+
+- Be as descriptive as possible.
+- Provide as much information needed to _reliably reproduce_ the issue.
+- Attach screenshots if possible.
+- Better yet: attach GIFs or link to video.
+- Even better: link to a sample project exhibiting the issue.

From fd9b42e5d8657680bd2073c0c1cde139cb8120a9 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 29 Sep 2017 07:21:54 +0200
Subject: [PATCH 279/685] Bump ruby version

---
 .travis.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index 7ff85f9a..4f17b26f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,5 @@
 language: objective-c
-rvm: 2.2
+rvm: 2.3
 osx_image: xcode9
 env:
   global:

From 2e8611fe06f8125668e346dad8a51218d901083d Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 29 Sep 2017 07:21:58 +0200
Subject: [PATCH 280/685] changelog

---
 CHANGELOG.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f9a920d5..41006b82 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,4 @@
-0.11.4 (xx-09-2017), [diff][diff-0.11.4]
+0.11.4 (30-09-2017), [diff][diff-0.11.4]
 ========================================
 
 * Collate .nocase strictly enforces NOT NULL even when using Optional ([#697][])

From ddb8049a58822768b3c1208ea58c8ba18a99952a Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 29 Sep 2017 07:28:28 +0200
Subject: [PATCH 281/685] Warn about `update()`

(#733)
---
 Documentation/Index.md | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 8ac564a8..a20087ea 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1521,10 +1521,13 @@ There are two other parameters also available to this method:
 Queries have a method to allow updating an Encodable type.
 
 ```swift
-try db.run(users.update(user))
+try db.run(users.filter(id == userId).update(user))
 
 ```
 
+> ⚠ Unless filtered, using the update method on an instance of a Codable
+> type updates all table rows.
+
 There are two other parameters also available to this method:
 
 - `userInfo` is a dictionary that is passed to the encoder and made available

From ae406afd75e72a0122e76b44c9abb5f6a2432cb1 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 29 Sep 2017 07:28:54 +0200
Subject: [PATCH 282/685] WS

---
 .github/ISSUE_TEMPLATE.md           | 4 ++--
 Tests/SQLiteTests/TestHelpers.swift | 6 +++---
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 61152bad..9304a672 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -1,11 +1,11 @@
-> Issues are used to track bugs and feature requests. 
+> Issues are used to track bugs and feature requests.
 > Need  help or have a general question? Ask on Stack Overflow (tag sqlite.swift).
 
 ## Build Information
 
 - Include the SQLite.swift version, commit or branch experiencing the issue.
 - Mention Xcode and OS X versions affected.
-- How do do you integrate SQLite.swift in your project? 
+- How do do you integrate SQLite.swift in your project?
     - manual
     - CocoaPods
     - Carthage
diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index 271f4166..8d60362c 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -20,9 +20,9 @@ class SQLiteTestCase : XCTestCase {
     func CreateUsersTable() {
         try! db.execute("""
             CREATE TABLE users (
-                id INTEGER PRIMARY KEY, 
-                email TEXT NOT NULL UNIQUE, 
-                age INTEGER, 
+                id INTEGER PRIMARY KEY,
+                email TEXT NOT NULL UNIQUE,
+                age INTEGER,
                 salary REAL,
                 admin BOOLEAN NOT NULL DEFAULT 0 CHECK (admin IN (0, 1)),
                 manager_id INTEGER,

From e12bd38d6f1d6de67efa7ce7894c663e15a232c9 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 29 Sep 2017 12:27:57 +0200
Subject: [PATCH 283/685] Modernize

---
 Tests/SQLiteTests/ConnectionTests.swift | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index 05d2676b..03f00719 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -382,31 +382,28 @@ class ConnectionTests : SQLiteTestCase {
         _ = DispatchQueue(label: "queue", qos: .background).asyncAfter(deadline: deadline, execute: db.interrupt)
         AssertThrows(try stmt.run())
     }
-    
+
     func test_concurrent_access_single_connection() {
-        let conn = try! Connection("\(NSTemporaryDirectory())/SQLite.swift Connection Tests.sqlite")
+        let conn = try! Connection("\(NSTemporaryDirectory())/\(UUID().uuidString)")
         try! conn.execute("DROP TABLE IF EXISTS test; CREATE TABLE test(value);")
         try! conn.run("INSERT INTO test(value) VALUES(?)", 0)
-        
-        let q = dispatch_queue_create("Readers", DISPATCH_QUEUE_CONCURRENT);
-        
-        var reads = [0, 0, 0, 0, 0]
+        let queue = DispatchQueue(label: "Readers", attributes: [.concurrent])
+        let nReaders = 5
+        var reads = Array(repeating: 0, count: nReaders)
         var finished = false
-        for index in 0..<5 {
-            dispatch_async(q) {
+        for index in 0..<nReaders {
+            queue.async {
                 while !finished {
-                    _ = try! conn.prepare("SELECT value FROM test")
+                    _ = try! conn.scalar("SELECT value FROM test")
                     reads[index] += 1
                 }
             }
         }
-        
         while !finished {
             sleep(1)
             finished = reads.reduce(true) { $0 && ($1 > 500) }
         }
-    } 
-
+    }
 }
 
 

From 73f4472097a1acdbba42d5ab8805d50a181589e3 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 29 Sep 2017 16:49:22 +0200
Subject: [PATCH 284/685] Changelog

---
 CHANGELOG.md | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 41006b82..514de7be 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,25 +1,25 @@
 0.11.4 (30-09-2017), [diff][diff-0.11.4]
 ========================================
 
-* Collate .nocase strictly enforces NOT NULL even when using Optional ([#697][])
+* Collate `.nocase` strictly enforces `NOT NULL` even when using Optional ([#697][])
 * Fix transactions not being rolled back when committing fails ([#426][])
 * Add possibility to have expression on right hand side of like ([#591][])
 * Added Date and Time functions ([#142][])
 * Add Swift4 Coding support ([#733][])
 * Preliminary Linux support ([#315][], [#681][])
 * Add `RowIterator` for more safety ([#647][], [#726][])
-* Make Row.get throw instead of crash ([#649][])
+* Make `Row.get` throw instead of crash ([#649][])
 * Fix create/drop index functions ([#666][])
-* Set deployment target to 8.0 (#624, #671, #717)
+* Revert deployment target to 8.0 ([#625][], [#671][], [#717][])
 * Added support for the union query clause ([#723][])
-* Add support for ORDER and LIMIT on UPDATE and DELETE ([#657][], [#722][])
+* Add support for `ORDER` and `LIMIT` on `UPDATE` and `DELETE` ([#657][], [#722][])
 * Swift 4 support ([#668][])
 
 0.11.3 (30-03-2017), [diff][diff-0.11.3]
 ========================================
 
 * Fix compilation problems when using Carthage ([#615][])
-* Add "WITHOUT ROWID" table option ([#541][])
+* Add `WITHOUT ROWID` table option ([#541][])
 * Argument count fixed for binary custom functions ([#481][])
 * Documentation updates
 * Tested with Xcode 8.3 / iOS 10.3
@@ -37,7 +37,7 @@
 
 * Integrate SQLCipher via CocoaPods ([#546][], [#553][])
 * Made lastInsertRowid consistent with other SQLite wrappers ([#532][])
-* Fix for ~= operator used with Double ranges
+* Fix for `~=` operator used with Double ranges
 * Various documentation updates
 
 0.11.0 (19-10-2016)
@@ -67,13 +67,16 @@
 [#571]: https://github.com/stephencelis/SQLite.swift/issues/571
 [#591]: https://github.com/stephencelis/SQLite.swift/pull/591
 [#615]: https://github.com/stephencelis/SQLite.swift/pull/615
+[#625]: https://github.com/stephencelis/SQLite.swift/issues/625
 [#647]: https://github.com/stephencelis/SQLite.swift/pull/647
 [#649]: https://github.com/stephencelis/SQLite.swift/pull/649
 [#657]: https://github.com/stephencelis/SQLite.swift/issues/657
 [#666]: https://github.com/stephencelis/SQLite.swift/pull/666
 [#668]: https://github.com/stephencelis/SQLite.swift/pull/668
+[#671]: https://github.com/stephencelis/SQLite.swift/issues/671
 [#681]: https://github.com/stephencelis/SQLite.swift/issues/681
 [#697]: https://github.com/stephencelis/SQLite.swift/issues/697
+[#717]: https://github.com/stephencelis/SQLite.swift/issues/717
 [#722]: https://github.com/stephencelis/SQLite.swift/pull/722
 [#723]: https://github.com/stephencelis/SQLite.swift/pull/723
 [#733]: https://github.com/stephencelis/SQLite.swift/pull/733

From 1c929b9e8071a6e144cc928c8077f765a6c7424c Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 29 Sep 2017 16:51:41 +0200
Subject: [PATCH 285/685] Link

---
 README.md | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 3a9ceecb..3900c0a3 100644
--- a/README.md
+++ b/README.md
@@ -18,12 +18,13 @@ syntax _and_ intent.
  - [Full-text search][] support
  - [Well-documented][See Documentation]
  - Extensively tested
- - SQLCipher support via CocoaPods
+ - [SQLCipher][] support via CocoaPods
  - Active support at
    [StackOverflow](http://stackoverflow.com/questions/tagged/sqlite.swift),
    and [Gitter Chat Room](https://gitter.im/stephencelis/SQLite.swift)
    (_experimental_)
 
+[SQLCipher]: https://www.zetetic.net/sqlcipher/
 [Full-text search]: Documentation/Index.md#full-text-search
 [See Documentation]: Documentation/Index.md#sqliteswift-documentation
 

From 172b3e55284de4f05c13b8d0e45702b3a2c270ca Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 29 Sep 2017 16:53:53 +0200
Subject: [PATCH 286/685] TOC

---
 Documentation/Index.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index a20087ea..3ccc6e21 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -20,6 +20,7 @@
     - [Column Constraints](#column-constraints)
     - [Table Constraints](#table-constraints)
   - [Inserting Rows](#inserting-rows)
+    - [Handling SQLite errors](#handling-sqlite-errors)
     - [Setters](#setters)
   - [Selecting Rows](#selecting-rows)
     - [Iterating and Accessing Values](#iterating-and-accessing-values)

From d68e0a761e6fafd40030887c24f54ee08f3f03a8 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 29 Sep 2017 17:05:51 +0200
Subject: [PATCH 287/685] Document throwing `Row.get()`

---
 Documentation/Index.md | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 3ccc6e21..be3d32a9 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -757,6 +757,18 @@ for user in try db.prepare(users) {
 promise to the compiler that they’ll never be `NULL`), while `Expression<T?>`
 values remain wrapped.
 
+⚠ Column subscripts on `Row` will force try and abort execution in error cases
+If you want to handle this yourself, use `Row.get(_ column: Expression<V>)`:
+
+```swift
+for user in try db.prepare(users) {
+    do {
+        print("name: \(try user.get(name))")
+    } catch {
+        // handle
+    }
+}
+```
 
 ### Plucking Rows
 

From e0eb663c114c579226422ccb41324c32d2841381 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 29 Sep 2017 17:16:56 +0200
Subject: [PATCH 288/685] Doc

---
 Documentation/Index.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index be3d32a9..88ed24a4 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1406,7 +1406,7 @@ The `Datatype` must be one of the basic Swift types that values are bridged
 through before serialization and deserialization (see [Building Type-Safe SQL
 ](#building-type-safe-sql) for a list of types).
 
-> _Note:_ `Binding` is a protocol that SQLite.swift uses internally to
+> ⚠ _Note:_ `Binding` is a protocol that SQLite.swift uses internally to
 > directly map SQLite types to Swift types. **Do _not_** conform custom types
 > to the `Binding` protocol.
 

From d80a5ef128338a1bfea2ed809c4ed5623a01bb44 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 29 Sep 2017 17:17:27 +0200
Subject: [PATCH 289/685] Support partial ranges for completeness

---
 Sources/SQLite/Typed/Operators.swift   | 24 ++++++++++++++++++++++++
 Tests/SQLiteTests/OperatorsTests.swift | 15 +++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/Sources/SQLite/Typed/Operators.swift b/Sources/SQLite/Typed/Operators.swift
index 5f95993f..d97e52b9 100644
--- a/Sources/SQLite/Typed/Operators.swift
+++ b/Sources/SQLite/Typed/Operators.swift
@@ -490,6 +490,30 @@ public func ~=<V : Value>(lhs: Range<V>, rhs: Expression<V?>) -> Expression<Bool
     return Expression("\(rhs.template) >= ? AND \(rhs.template) < ?", rhs.bindings + [lhs.lowerBound.datatypeValue] + rhs.bindings + [lhs.upperBound.datatypeValue])
 }
 
+public func ~=<V : Value>(lhs: PartialRangeThrough<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable & Value {
+    return Expression("\(rhs.template) <= ?", rhs.bindings + [lhs.upperBound.datatypeValue])
+}
+
+public func ~=<V : Value>(lhs: PartialRangeThrough<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable & Value {
+    return Expression("\(rhs.template) <= ?", rhs.bindings + [lhs.upperBound.datatypeValue])
+}
+
+public func ~=<V : Value>(lhs: PartialRangeUpTo<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable & Value {
+    return Expression("\(rhs.template) < ?", rhs.bindings + [lhs.upperBound.datatypeValue])
+}
+
+public func ~=<V : Value>(lhs: PartialRangeUpTo<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable & Value {
+    return Expression("\(rhs.template) < ?", rhs.bindings + [lhs.upperBound.datatypeValue])
+}
+
+public func ~=<V : Value>(lhs: PartialRangeFrom<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable & Value {
+    return Expression("\(rhs.template) >= ?", rhs.bindings + [lhs.lowerBound.datatypeValue])
+}
+
+public func ~=<V : Value>(lhs: PartialRangeFrom<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable & Value {
+    return Expression("\(rhs.template) >= ?", rhs.bindings + [lhs.lowerBound.datatypeValue])
+}
+
 // MARK: -
 
 public func &&(lhs: Expression<Bool>, rhs: Expression<Bool>) -> Expression<Bool> {
diff --git a/Tests/SQLiteTests/OperatorsTests.swift b/Tests/SQLiteTests/OperatorsTests.swift
index 08e679c1..4dcb6717 100644
--- a/Tests/SQLiteTests/OperatorsTests.swift
+++ b/Tests/SQLiteTests/OperatorsTests.swift
@@ -260,6 +260,21 @@ class OperatorsTests : XCTestCase {
         AssertSQL("\"doubleOptional\" >= 1.2 AND \"doubleOptional\" < 4.5", 1.2..<4.5 ~= doubleOptional)
     }
 
+    func test_patternMatchingOperator_withComparablePartialRangeThrough_buildsBooleanExpression() {
+        AssertSQL("\"double\" <= 4.5", ...4.5 ~= double)
+        AssertSQL("\"doubleOptional\" <= 4.5", ...4.5 ~= doubleOptional)
+    }
+
+    func test_patternMatchingOperator_withComparablePartialRangeUpTo_buildsBooleanExpression() {
+        AssertSQL("\"double\" < 4.5", ..<4.5 ~= double)
+        AssertSQL("\"doubleOptional\" < 4.5", ..<4.5 ~= doubleOptional)
+    }
+
+    func test_patternMatchingOperator_withComparablePartialRangeFrom_buildsBooleanExpression() {
+        AssertSQL("\"double\" >= 4.5", 4.5... ~= double)
+        AssertSQL("\"doubleOptional\" >= 4.5", 4.5... ~= doubleOptional)
+    }
+
     func test_patternMatchingOperator_withomparableClosedRangeString_buildsBetweenBooleanExpression() {
         AssertSQL("\"string\" BETWEEN 'a' AND 'b'", "a"..."b" ~= string)
         AssertSQL("\"stringOptional\" BETWEEN 'a' AND 'b'", "a"..."b" ~= stringOptional)

From 07df3355f45c443704fc973899fabc6a37f9e506 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 29 Sep 2017 17:21:33 +0200
Subject: [PATCH 290/685] No longer applies

---
 Documentation/Index.md | 47 ------------------------------------------
 1 file changed, 47 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 88ed24a4..476bc816 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -50,7 +50,6 @@
   - [Custom Types](#custom-types)
     - [Date-Time Values](#date-time-values)
     - [Binary Data](#binary-data)
-    - [Custom Type Caveats](#custom-type-caveats)
   - [Codable Types](#codable-types)
   - [Other Operators](#other-operators)
   - [Core SQLite Functions](#core-sqlite-functions)
@@ -1410,9 +1409,6 @@ through before serialization and deserialization (see [Building Type-Safe SQL
 > directly map SQLite types to Swift types. **Do _not_** conform custom types
 > to the `Binding` protocol.
 
-Once extended, the type can be used [_almost_](#custom-type-caveats) wherever
-typed expressions can be.
-
 
 ### Date-Time Values
 
@@ -1458,49 +1454,6 @@ extension UIImage: Value {
 
 [Archives and Serializations Programming Guide]: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Archiving/Archiving.html
 
-### Custom Type Caveats
-
-Swift does _not_ currently support generic subscripting, which means we
-cannot, by default, subscript Expressions with custom types to:
-
- 1. **Namespace expressions**. Use the `namespace` function, instead:
-
-    ```swift
-    let avatar = Expression<UIImage?>("avatar")
-    users[avatar]           // fails to compile
-    users.namespace(avatar) // "users"."avatar"
-    ```
-
- 2. **Access column data**. Use the `get` function, instead:
-
-    ```swift
-    let user = users.first!
-    user[avatar]            // fails to compile
-    user.get(avatar)        // UIImage?
-    ```
-
-We can, of course, write extensions, but they’re rather wordy.
-
-```swift
-extension Query {
-    subscript(column: Expression<UIImage>) -> Expression<UIImage> {
-        return namespace(column)
-    }
-    subscript(column: Expression<UIImage?>) -> Expression<UIImage?> {
-        return namespace(column)
-    }
-}
-
-extension Row {
-    subscript(column: Expression<UIImage>) -> UIImage {
-        return get(column)
-    }
-    subscript(column: Expression<UIImage?>) -> UIImage? {
-        return get(column)
-    }
-}
-```
-
 ## Codable Types
 
 [Codable types][Encoding and Decoding Custom Types] were introduced as a part

From fa041f8f0b5949ca110e049949d0c470f92b811a Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 29 Sep 2017 17:25:28 +0200
Subject: [PATCH 291/685] Docs

---
 Documentation/Index.md | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 476bc816..c97fe8ca 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -756,7 +756,7 @@ for user in try db.prepare(users) {
 promise to the compiler that they’ll never be `NULL`), while `Expression<T?>`
 values remain wrapped.
 
-⚠ Column subscripts on `Row` will force try and abort execution in error cases
+⚠ Column subscripts on `Row` will force try and abort execution in error cases.
 If you want to handle this yourself, use `Row.get(_ column: Expression<V>)`:
 
 ```swift
@@ -1464,10 +1464,10 @@ the insertion, updating, and retrieval of basic Codable types.
 
 ### Inserting Codable Types
 
-Queries have a method to allow inserting an Encodable type.
+Queries have a method to allow inserting an [Encodable][] type.
 
 ```swift
-struct User: Codable {
+struct User: Encodable {
     let name: String
 }
 try db.run(users.insert(User(name: "test")))
@@ -1482,6 +1482,8 @@ There are two other parameters also available to this method:
 - `otherSetters` allows you to specify additional setters on top of those
   that are generated from the encodable types themselves.
 
+[Encodable]: https://developer.apple.com/documentation/swift/encodable
+
 ### Updating Codable Types
 
 Queries have a method to allow updating an Encodable type.
@@ -1504,7 +1506,7 @@ There are two other parameters also available to this method:
 
 ### Retrieving Codable Types
 
-Rows have a method to decode a Decodable type.
+Rows have a method to decode a [Decodable][] type.
 
 ```swift
 let loadedUsers: [User] = try db.prepare(users).map { row in
@@ -1548,6 +1550,8 @@ Both of the above methods also have the following optional parameter:
 - `userInfo` is a dictionary that is passed to the decoder and made available
   to decodable types to allow customizing their behavior.
 
+[Decodable]: https://developer.apple.com/documentation/swift/decodable
+
 ### Restrictions
 
 There are a few restrictions on using Codable types:

From 4ea2f62c453a7a82a1d9ddbd85d28a321d767ec4 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 29 Sep 2017 17:32:21 +0200
Subject: [PATCH 292/685] Typos

---
 CHANGELOG.md | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 514de7be..578b59c2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -52,12 +52,12 @@
 [diff-0.11.3]: https://github.com/stephencelis/SQLite.swift/compare/0.11.2...0.11.3
 [diff-0.11.4]: https://github.com/stephencelis/SQLite.swift/compare/0.11.3...0.11.4
 
-[#142]: https://github.com/stephencelis/SQLit1e.swift/issues/142
-[#315]: https://github.com/stephencelis/SQLit1e.swift/issues/315
-[#426]: https://github.com/stephencelis/SQLit1e.swift/pull/426
-[#481]: https://github.com/stephencelis/SQLit1e.swift/pull/481
-[#532]: https://github.com/stephencelis/SQLit1e.swift/issues/532
-[#541]: https://github.com/stephencelis/SQLit1e.swift/issues/541
+[#142]: https://github.com/stephencelis/SQLite.swift/issues/142
+[#315]: https://github.com/stephencelis/SQLite.swift/issues/315
+[#426]: https://github.com/stephencelis/SQLite.swift/pull/426
+[#481]: https://github.com/stephencelis/SQLite.swift/pull/481
+[#532]: https://github.com/stephencelis/SQLite.swift/issues/532
+[#541]: https://github.com/stephencelis/SQLite.swift/issues/541
 [#546]: https://github.com/stephencelis/SQLite.swift/issues/546
 [#548]: https://github.com/stephencelis/SQLite.swift/pull/548
 [#553]: https://github.com/stephencelis/SQLite.swift/pull/553

From 9d8a8e5a7fff77486726f47f0dfc2c6994a57a31 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 29 Sep 2017 17:43:31 +0200
Subject: [PATCH 293/685] Typo

---
 Tests/SQLiteTests/OperatorsTests.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Tests/SQLiteTests/OperatorsTests.swift b/Tests/SQLiteTests/OperatorsTests.swift
index 4dcb6717..948eb0a4 100644
--- a/Tests/SQLiteTests/OperatorsTests.swift
+++ b/Tests/SQLiteTests/OperatorsTests.swift
@@ -275,7 +275,7 @@ class OperatorsTests : XCTestCase {
         AssertSQL("\"doubleOptional\" >= 4.5", 4.5... ~= doubleOptional)
     }
 
-    func test_patternMatchingOperator_withomparableClosedRangeString_buildsBetweenBooleanExpression() {
+    func test_patternMatchingOperator_withComparableClosedRangeString_buildsBetweenBooleanExpression() {
         AssertSQL("\"string\" BETWEEN 'a' AND 'b'", "a"..."b" ~= string)
         AssertSQL("\"stringOptional\" BETWEEN 'a' AND 'b'", "a"..."b" ~= stringOptional)
     }

From f0e3442e98862c16a129d1ab00ccd3a82555b6c1 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 2 Oct 2017 16:25:40 +0200
Subject: [PATCH 294/685] No longer needed

---
 SQLite.xcodeproj/project.pbxproj | 22 ----------------------
 1 file changed, 22 deletions(-)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index cb776608..df603862 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1032,8 +1032,6 @@
 				PRODUCT_NAME = SQLite;
 				SDKROOT = appletvos;
 				SKIP_INSTALL = YES;
-				"SWIFT_INCLUDE_PATHS[sdk=appletvos*]" = "$(SRCROOT)/CocoaPods/appletvos";
-				"SWIFT_INCLUDE_PATHS[sdk=appletvsimulator*]" = "$(SRCROOT)/CocoaPods/appletvsimulator";
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
@@ -1056,8 +1054,6 @@
 				PRODUCT_NAME = SQLite;
 				SDKROOT = appletvos;
 				SKIP_INSTALL = YES;
-				"SWIFT_INCLUDE_PATHS[sdk=appletvos*]" = "$(SRCROOT)/CocoaPods/appletvos";
-				"SWIFT_INCLUDE_PATHS[sdk=appletvsimulator*]" = "$(SRCROOT)/CocoaPods/appletvsimulator";
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
@@ -1109,8 +1105,6 @@
 				PRODUCT_NAME = SQLite;
 				SDKROOT = watchos;
 				SKIP_INSTALL = YES;
-				"SWIFT_INCLUDE_PATHS[sdk=watchos*]" = "$(SRCROOT)/CocoaPods/watchos";
-				"SWIFT_INCLUDE_PATHS[sdk=watchsimulator*]" = "$(SRCROOT)/CocoaPods/watchsimulator";
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
 				TARGETED_DEVICE_FAMILY = 4;
@@ -1135,8 +1129,6 @@
 				PRODUCT_NAME = SQLite;
 				SDKROOT = watchos;
 				SKIP_INSTALL = YES;
-				"SWIFT_INCLUDE_PATHS[sdk=watchos*]" = "$(SRCROOT)/CocoaPods/watchos";
-				"SWIFT_INCLUDE_PATHS[sdk=watchsimulator*]" = "$(SRCROOT)/CocoaPods/watchsimulator";
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
 				TARGETED_DEVICE_FAMILY = 4;
@@ -1271,10 +1263,6 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
-				"SWIFT_INCLUDE_PATHS[sdk=iphoneos*]" = "$(SRCROOT)/CocoaPods/iphoneos";
-				"SWIFT_INCLUDE_PATHS[sdk=iphoneos10.0]" = "$(SRCROOT)/CocoaPods/iphoneos-10.0";
-				"SWIFT_INCLUDE_PATHS[sdk=iphonesimulator*]" = "$(SRCROOT)/CocoaPods/iphonesimulator";
-				"SWIFT_INCLUDE_PATHS[sdk=iphonesimulator10.0]" = "$(SRCROOT)/CocoaPods/iphonesimulator-10.0";
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
@@ -1298,10 +1286,6 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
-				"SWIFT_INCLUDE_PATHS[sdk=iphoneos*]" = "$(SRCROOT)/CocoaPods/iphoneos";
-				"SWIFT_INCLUDE_PATHS[sdk=iphoneos10.0]" = "$(SRCROOT)/CocoaPods/iphoneos-10.0";
-				"SWIFT_INCLUDE_PATHS[sdk=iphonesimulator*]" = "$(SRCROOT)/CocoaPods/iphonesimulator";
-				"SWIFT_INCLUDE_PATHS[sdk=iphonesimulator10.0]" = "$(SRCROOT)/CocoaPods/iphonesimulator-10.0";
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
 			};
@@ -1353,9 +1337,6 @@
 				SDKROOT = macosx;
 				SKIP_INSTALL = YES;
 				SWIFT_INCLUDE_PATHS = "";
-				"SWIFT_INCLUDE_PATHS[sdk=macosx*]" = "$(SRCROOT)/CocoaPods/macosx";
-				"SWIFT_INCLUDE_PATHS[sdk=macosx10.11]" = "$(SRCROOT)/CocoaPods/macosx-10.11";
-				"SWIFT_INCLUDE_PATHS[sdk=macosx10.12]" = "$(SRCROOT)/CocoaPods/macosx-10.12";
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
 			};
@@ -1381,9 +1362,6 @@
 				SDKROOT = macosx;
 				SKIP_INSTALL = YES;
 				SWIFT_INCLUDE_PATHS = "";
-				"SWIFT_INCLUDE_PATHS[sdk=macosx*]" = "$(SRCROOT)/CocoaPods/macosx";
-				"SWIFT_INCLUDE_PATHS[sdk=macosx10.11]" = "$(SRCROOT)/CocoaPods/macosx-10.11";
-				"SWIFT_INCLUDE_PATHS[sdk=macosx10.12]" = "$(SRCROOT)/CocoaPods/macosx-10.12";
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
 			};

From dde0af2e26f6f50ca9119f43f3b87c9aeea938fe Mon Sep 17 00:00:00 2001
From: Camilleri Alexandre <alexcamill@gmail.com>
Date: Mon, 2 Oct 2017 16:56:57 +0200
Subject: [PATCH 295/685] Corected HEIFIamge to HEIFImage

Typo
---
 Documentation/Index.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index c97fe8ca..efb90ae6 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1519,7 +1519,7 @@ for example if you are using the
 [Facade pattern](https://en.wikipedia.org/wiki/Facade_pattern) to hide
 subclasses behind a super class. For example, you may want to encode an Image
 type that can be multiple different formats such as PNGImage, JPGImage, or
-HEIFIamge. You will need to determine the correct subclass before you know
+HEIFImage. You will need to determine the correct subclass before you know
 which type to decode.
 
 ```swift

From 35bb87c04c0152c7ac857da277742661f9d6c55b Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 9 Oct 2017 16:55:06 +0200
Subject: [PATCH 296/685] See #742

---
 SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme  | 5 +++--
 SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme  | 3 +--
 SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme | 5 +++--
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme
index 2c3c431f..f1fa216c 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme	
@@ -26,8 +26,8 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      shouldUseLaunchSchemeArgsEnv = "YES"
-      codeCoverageEnabled = "YES">
+      language = ""
+      shouldUseLaunchSchemeArgsEnv = "YES">
       <Testables>
          <TestableReference
             skipped = "NO">
@@ -56,6 +56,7 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      language = ""
       launchStyle = "0"
       useCustomWorkingDirectory = "NO"
       ignoresPersistentStateOnLaunch = "NO"
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme
index fb00f5bb..dca3ccea 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme	
@@ -27,8 +27,7 @@
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
       language = ""
-      shouldUseLaunchSchemeArgsEnv = "YES"
-      codeCoverageEnabled = "YES">
+      shouldUseLaunchSchemeArgsEnv = "YES">
       <Testables>
          <TestableReference
             skipped = "NO">
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme
index cfa4e0fa..be753151 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme	
@@ -26,8 +26,8 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      shouldUseLaunchSchemeArgsEnv = "YES"
-      codeCoverageEnabled = "YES">
+      language = ""
+      shouldUseLaunchSchemeArgsEnv = "YES">
       <Testables>
          <TestableReference
             skipped = "NO">
@@ -56,6 +56,7 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      language = ""
       launchStyle = "0"
       useCustomWorkingDirectory = "NO"
       ignoresPersistentStateOnLaunch = "NO"

From 83e0ad85c5b100a06467edd68e71fe3fe7dc1e37 Mon Sep 17 00:00:00 2001
From: Dan Federman <dan.federman@airbnb.com>
Date: Tue, 17 Oct 2017 10:57:52 -0700
Subject: [PATCH 297/685] Do not use .characters on Strings. Prevents warnings
 in Xcode 9.1 by adopting proper Swift 4 syntax

---
 Sources/SQLite/Core/Connection.swift    | 2 +-
 Sources/SQLite/Typed/Expression.swift   | 2 +-
 Sources/SQLite/Typed/Query.swift        | 2 +-
 Sources/SQLite/Typed/Schema.swift       | 2 +-
 Tests/SQLiteTests/ConnectionTests.swift | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index f7513115..1bbf7f73 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -577,7 +577,7 @@ public final class Connection {
             } else if let result = result as? Int64 {
                 sqlite3_result_int64(context, result)
             } else if let result = result as? String {
-                sqlite3_result_text(context, result, Int32(result.characters.count), SQLITE_TRANSIENT)
+                sqlite3_result_text(context, result, Int32(result.count), SQLITE_TRANSIENT)
             } else if result == nil {
                 sqlite3_result_null(context)
             } else {
diff --git a/Sources/SQLite/Typed/Expression.swift b/Sources/SQLite/Typed/Expression.swift
index 33329b73..d89ee6cc 100644
--- a/Sources/SQLite/Typed/Expression.swift
+++ b/Sources/SQLite/Typed/Expression.swift
@@ -77,7 +77,7 @@ extension Expressible {
     public func asSQL() -> String {
         let expressed = expression
         var idx = 0
-        return expressed.template.characters.reduce("") { template, character in
+        return expressed.template.reduce("") { template, character in
             let transcoded: String
             
             if character == "?" {
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index 17ec715a..1d04b797 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -938,7 +938,7 @@ extension Connection {
     private func columnNamesForQuery(_ query: QueryType) throws -> [String: Int] {
         var (columnNames, idx) = ([String: Int](), 0)
         column: for each in query.clauses.select.columns {
-            var names = each.expression.template.characters.split { $0 == "." }.map(String.init)
+            var names = each.expression.template.split { $0 == "." }.map(String.init)
             let column = names.removeLast()
             let namespace = names.joined(separator: ".")
             
diff --git a/Sources/SQLite/Typed/Schema.swift b/Sources/SQLite/Typed/Schema.swift
index 46a1f87a..60b7be8a 100644
--- a/Sources/SQLite/Typed/Schema.swift
+++ b/Sources/SQLite/Typed/Schema.swift
@@ -148,7 +148,7 @@ extension Table {
     fileprivate func indexName(_ columns: [Expressible]) -> Expressible {
         let string = (["index", clauses.from.name, "on"] + columns.map { $0.expression.template }).joined(separator: " ").lowercased()
 
-        let index = string.characters.reduce("") { underscored, character in
+        let index = string.reduce("") { underscored, character in
             guard character != "\"" else {
                 return underscored
             }
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index 03f00719..7bb86e41 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -369,7 +369,7 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_interrupt_interruptsLongRunningQuery() {
-        try! InsertUsers("abcdefghijklmnopqrstuvwxyz".characters.map { String($0) })
+        try! InsertUsers("abcdefghijklmnopqrstuvwxyz".map { String($0) })
         db.createFunction("sleep") { args in
             usleep(UInt32((args[0] as? Double ?? Double(args[0] as? Int64 ?? 1)) * 1_000_000))
             return nil

From 5dceef2028991e7984ec35630dae802335381085 Mon Sep 17 00:00:00 2001
From: Vinay Ganesh <vganesh@hearsaycorp.com>
Date: Mon, 6 Nov 2017 22:10:46 -0800
Subject: [PATCH 298/685] Resolved the warning that was raised because
 "characters" of a "String" has been deprecated.

---
 Sources/SQLite/Helpers.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Sources/SQLite/Helpers.swift b/Sources/SQLite/Helpers.swift
index 64e5eca8..ac831667 100644
--- a/Sources/SQLite/Helpers.swift
+++ b/Sources/SQLite/Helpers.swift
@@ -56,7 +56,7 @@ let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self)
 extension String {
 
     func quote(_ mark: Character = "\"") -> String {
-        let escaped = characters.reduce("") { string, character in
+        let escaped = reduce("") { string, character in
             string + (character == mark ? "\(mark)\(mark)" : "\(character)")
         }
         return "\(mark)\(escaped)\(mark)"

From f40ca4da2f02204fdc5e3d317014062fac55326a Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 12 Apr 2018 18:04:41 +0200
Subject: [PATCH 299/685] Fix Swift 4.1 warnings

---
 .travis.yml                                    |  2 +-
 SQLite.xcodeproj/project.pbxproj               |  6 +++++-
 .../xcshareddata/xcschemes/SQLite Mac.xcscheme |  4 +---
 .../xcshareddata/xcschemes/SQLite iOS.xcscheme |  4 +---
 .../xcschemes/SQLite tvOS.xcscheme             |  4 +---
 .../xcschemes/SQLite watchOS.xcscheme          |  2 +-
 Sources/SQLite/Typed/Coding.swift              |  2 +-
 Sources/SQLite/Typed/CoreFunctions.swift       |  2 +-
 Sources/SQLite/Typed/Query.swift               |  8 ++++----
 Sources/SQLite/Typed/Schema.swift              | 18 +++++++++---------
 Tests/SQLiteTests/BlobTests.swift              |  2 +-
 Tests/SQLiteTests/ConnectionTests.swift        |  2 +-
 Tests/SQLiteTests/FTS4Tests.swift              |  2 +-
 13 files changed, 28 insertions(+), 30 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 4f17b26f..41389849 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,6 @@
 language: objective-c
 rvm: 2.3
-osx_image: xcode9
+osx_image: xcode9.3
 env:
   global:
     - IOS_SIMULATOR="iPhone 6s"
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index df603862..2015b8ff 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -680,7 +680,7 @@
 			isa = PBXProject;
 			attributes = {
 				LastSwiftUpdateCheck = 0720;
-				LastUpgradeCheck = 0900;
+				LastUpgradeCheck = 0930;
 				TargetAttributes = {
 					03A65E591C6BB0F50062603F = {
 						CreatedOnToolsVersion = 7.2;
@@ -1148,12 +1148,14 @@
 				CLANG_WARN_BOOL_CONVERSION = YES;
 				CLANG_WARN_COMMA = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
 				CLANG_WARN_EMPTY_BODY = YES;
 				CLANG_WARN_ENUM_CONVERSION = YES;
 				CLANG_WARN_INFINITE_RECURSION = YES;
 				CLANG_WARN_INT_CONVERSION = YES;
 				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
 				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
 				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
 				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -1206,12 +1208,14 @@
 				CLANG_WARN_BOOL_CONVERSION = YES;
 				CLANG_WARN_COMMA = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
 				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
 				CLANG_WARN_EMPTY_BODY = YES;
 				CLANG_WARN_ENUM_CONVERSION = YES;
 				CLANG_WARN_INFINITE_RECURSION = YES;
 				CLANG_WARN_INT_CONVERSION = YES;
 				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
 				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
 				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
 				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme
index f1fa216c..2691862e 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme	
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0900"
+   LastUpgradeVersion = "0930"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -26,7 +26,6 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
       shouldUseLaunchSchemeArgsEnv = "YES">
       <Testables>
          <TestableReference
@@ -56,7 +55,6 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
       launchStyle = "0"
       useCustomWorkingDirectory = "NO"
       ignoresPersistentStateOnLaunch = "NO"
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme
index dca3ccea..8b3cd73b 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme	
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0900"
+   LastUpgradeVersion = "0930"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -26,7 +26,6 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
       shouldUseLaunchSchemeArgsEnv = "YES">
       <Testables>
          <TestableReference
@@ -56,7 +55,6 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
       launchStyle = "0"
       useCustomWorkingDirectory = "NO"
       ignoresPersistentStateOnLaunch = "NO"
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme
index be753151..9b444924 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme	
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0900"
+   LastUpgradeVersion = "0930"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -26,7 +26,6 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
       shouldUseLaunchSchemeArgsEnv = "YES">
       <Testables>
          <TestableReference
@@ -56,7 +55,6 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
       launchStyle = "0"
       useCustomWorkingDirectory = "NO"
       ignoresPersistentStateOnLaunch = "NO"
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite watchOS.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite watchOS.xcscheme
index 92cc9126..e45dbe7d 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite watchOS.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite watchOS.xcscheme	
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0900"
+   LastUpgradeVersion = "0930"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index dd6a4ec2..7c70db33 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -217,7 +217,7 @@ fileprivate class SQLiteDecoder : Decoder {
         }
 
         var allKeys: [Key] {
-            return self.row.columnNames.keys.flatMap({Key(stringValue: $0)})
+            return self.row.columnNames.keys.compactMap({Key(stringValue: $0)})
         }
 
         func contains(_ key: Key) -> Bool {
diff --git a/Sources/SQLite/Typed/CoreFunctions.swift b/Sources/SQLite/Typed/CoreFunctions.swift
index 1afe4e87..d7995b95 100644
--- a/Sources/SQLite/Typed/CoreFunctions.swift
+++ b/Sources/SQLite/Typed/CoreFunctions.swift
@@ -637,7 +637,7 @@ extension ExpressionType where UnderlyingType == String? {
 
 }
 
-extension Collection where Iterator.Element : Value, IndexDistance == Int {
+extension Collection where Iterator.Element : Value {
 
     /// Builds a copy of the expression prepended with an `IN` check against the
     /// collection.
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index 1d04b797..f6ef6df8 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -647,7 +647,7 @@ extension QueryType {
             whereClause
         ]
 
-        return Insert(" ".join(clauses.flatMap { $0 }).expression)
+        return Insert(" ".join(clauses.compactMap { $0 }).expression)
     }
 
     /// Runs an `INSERT` statement against the query with `DEFAULT VALUES`.
@@ -690,7 +690,7 @@ extension QueryType {
             limitOffsetClause
         ]
 
-        return Update(" ".join(clauses.flatMap { $0 }).expression)
+        return Update(" ".join(clauses.compactMap { $0 }).expression)
     }
 
     // MARK: DELETE
@@ -704,7 +704,7 @@ extension QueryType {
             limitOffsetClause
         ]
 
-        return Delete(" ".join(clauses.flatMap { $0 }).expression)
+        return Delete(" ".join(clauses.compactMap { $0 }).expression)
     }
 
     // MARK: EXISTS
@@ -789,7 +789,7 @@ extension QueryType {
             limitOffsetClause
         ]
 
-        return " ".join(clauses.flatMap { $0 }).expression
+        return " ".join(clauses.compactMap { $0 }).expression
     }
 
 }
diff --git a/Sources/SQLite/Typed/Schema.swift b/Sources/SQLite/Typed/Schema.swift
index 60b7be8a..62c90702 100644
--- a/Sources/SQLite/Typed/Schema.swift
+++ b/Sources/SQLite/Typed/Schema.swift
@@ -47,7 +47,7 @@ extension Table {
             withoutRowid ? Expression<Void>(literal: "WITHOUT ROWID") : nil
         ]
 
-        return " ".join(clauses.flatMap { $0 }).asSQL()
+        return " ".join(clauses.compactMap { $0 }).asSQL()
     }
 
     public func create(_ query: QueryType, temporary: Bool = false, ifNotExists: Bool = false) -> String {
@@ -57,7 +57,7 @@ extension Table {
             query
         ]
 
-        return " ".join(clauses.flatMap { $0 }).asSQL()
+        return " ".join(clauses.compactMap { $0 }).asSQL()
     }
 
     // MARK: - ALTER TABLE … ADD COLUMN
@@ -135,7 +135,7 @@ extension Table {
             "".wrap(columns) as Expression<Void>
         ]
 
-        return " ".join(clauses.flatMap { $0 }).asSQL()
+        return " ".join(clauses.compactMap { $0 }).asSQL()
     }
 
     // MARK: - DROP INDEX
@@ -174,7 +174,7 @@ extension View {
             query
         ]
 
-        return " ".join(clauses.flatMap { $0 }).asSQL()
+        return " ".join(clauses.compactMap { $0 }).asSQL()
     }
 
     // MARK: - DROP VIEW
@@ -196,7 +196,7 @@ extension VirtualTable {
             using
         ]
 
-        return " ".join(clauses.flatMap { $0 }).asSQL()
+        return " ".join(clauses.compactMap { $0 }).asSQL()
     }
 
     // MARK: - ALTER TABLE … RENAME TO
@@ -405,7 +405,7 @@ public final class TableBuilder {
             delete.map { Expression<Void>(literal: "ON DELETE \($0.rawValue)") }
         ]
 
-        definitions.append(" ".join(clauses.flatMap { $0 }))
+        definitions.append(" ".join(clauses.compactMap { $0 }))
     }
 
 }
@@ -456,7 +456,7 @@ private extension QueryType {
             name
         ]
 
-        return " ".join(clauses.flatMap { $0 })
+        return " ".join(clauses.compactMap { $0 })
     }
 
     func rename(to: Self) -> String {
@@ -475,7 +475,7 @@ private extension QueryType {
             name
         ]
 
-        return " ".join(clauses.flatMap { $0 }).asSQL()
+        return " ".join(clauses.compactMap { $0 }).asSQL()
     }
 
 }
@@ -493,7 +493,7 @@ private func definition(_ column: Expressible, _ datatype: String, _ primaryKey:
         collate.map { " ".join([Expression<Void>(literal: "COLLATE"), $0]) }
     ]
 
-    return " ".join(clauses.flatMap { $0 })
+    return " ".join(clauses.compactMap { $0 })
 }
 
 private func reference(_ primary: (QueryType, Expressible)) -> Expressible {
diff --git a/Tests/SQLiteTests/BlobTests.swift b/Tests/SQLiteTests/BlobTests.swift
index fbcca9bc..817205d6 100644
--- a/Tests/SQLiteTests/BlobTests.swift
+++ b/Tests/SQLiteTests/BlobTests.swift
@@ -16,7 +16,7 @@ class BlobTests : XCTestCase {
 
     func test_init_unsafeRawPointer() {
         let pointer = UnsafeMutablePointer<UInt8>.allocate(capacity: 3)
-        pointer.initialize(to: 42, count: 3)
+        pointer.initialize(repeating: 42, count: 3)
         let blob = Blob(bytes: pointer, length: 3)
         XCTAssertEqual(blob.bytes, [42, 42, 42])
     }
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index 7bb86e41..7fc26110 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -157,7 +157,7 @@ class ConnectionTests : SQLiteTestCase {
 
     func test_transaction_rollsBackTransactionsIfCommitsFail() {
         let sqliteVersion = String(describing: try! db.scalar("SELECT sqlite_version()")!)
-                .split(separator: ".").flatMap { Int($0) }
+            .split(separator: ".").compactMap { Int($0) }
         // PRAGMA defer_foreign_keys only supported in SQLite >= 3.8.0
         guard sqliteVersion[0] == 3 && sqliteVersion[1] >= 8 else {
             NSLog("skipping test for SQLite version \(sqliteVersion)")
diff --git a/Tests/SQLiteTests/FTS4Tests.swift b/Tests/SQLiteTests/FTS4Tests.swift
index 4373bf8b..79f0a8e2 100644
--- a/Tests/SQLiteTests/FTS4Tests.swift
+++ b/Tests/SQLiteTests/FTS4Tests.swift
@@ -184,7 +184,7 @@ class FTS4IntegrationTests : SQLiteTestCase {
 
         let locale = CFLocaleCopyCurrent()
         let tokenizerName = "tokenizer"
-        let tokenizer = CFStringTokenizerCreate(nil, "" as CFString!, CFRangeMake(0, 0), UInt(kCFStringTokenizerUnitWord), locale)
+        let tokenizer = CFStringTokenizerCreate(nil, "" as CFString, CFRangeMake(0, 0), UInt(kCFStringTokenizerUnitWord), locale)
         try! db.registerTokenizer(tokenizerName) { string in
             CFStringTokenizerSetString(tokenizer, string as CFString, CFRangeMake(0, CFStringGetLength(string as CFString)))
             if CFStringTokenizerAdvanceToNextToken(tokenizer).isEmpty {

From 1ed747ec930889de2b6e79451a8c37eea3109326 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 12 Apr 2018 18:43:32 +0200
Subject: [PATCH 300/685] Fix iOS version

---
 .travis.yml | 2 +-
 Makefile    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 41389849..f278301d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,7 +4,7 @@ osx_image: xcode9.3
 env:
   global:
     - IOS_SIMULATOR="iPhone 6s"
-    - IOS_VERSION="11.0"
+    - IOS_VERSION="11.3"
 matrix:
   include:
     - env: BUILD_SCHEME="SQLite iOS"
diff --git a/Makefile b/Makefile
index ebd38494..cd4afb8d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 BUILD_TOOL = xcodebuild
 BUILD_SCHEME = SQLite Mac
 IOS_SIMULATOR = iPhone 6s
-IOS_VERSION = 11.0
+IOS_VERSION = 11.3
 ifeq ($(BUILD_SCHEME),SQLite iOS)
 	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -destination "platform=iOS Simulator,name=$(IOS_SIMULATOR),OS=$(IOS_VERSION)"
 else

From be9fc789c3772edaef83000deda20ab777f607f7 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 12 Apr 2018 23:10:41 +0200
Subject: [PATCH 301/685] Update bundle

---
 Tests/CocoaPods/Gemfile      |  2 +-
 Tests/CocoaPods/Gemfile.lock | 54 +++++++++++++++++++-----------------
 2 files changed, 30 insertions(+), 26 deletions(-)

diff --git a/Tests/CocoaPods/Gemfile b/Tests/CocoaPods/Gemfile
index 04f0155a..3b9d6ba5 100644
--- a/Tests/CocoaPods/Gemfile
+++ b/Tests/CocoaPods/Gemfile
@@ -1,4 +1,4 @@
 source 'https://rubygems.org'
 
-gem 'cocoapods', '~> 1.3.1'
+gem 'cocoapods', '~> 1.5.0'
 gem 'minitest'
diff --git a/Tests/CocoaPods/Gemfile.lock b/Tests/CocoaPods/Gemfile.lock
index 47a2db58..de03030a 100644
--- a/Tests/CocoaPods/Gemfile.lock
+++ b/Tests/CocoaPods/Gemfile.lock
@@ -1,73 +1,77 @@
 GEM
   remote: https://rubygems.org/
   specs:
-    CFPropertyList (2.3.5)
-    activesupport (4.2.9)
+    CFPropertyList (3.0.0)
+    activesupport (4.2.10)
       i18n (~> 0.7)
       minitest (~> 5.1)
       thread_safe (~> 0.3, >= 0.3.4)
       tzinfo (~> 1.1)
+    atomos (0.1.2)
     claide (1.0.2)
-    cocoapods (1.3.1)
+    cocoapods (1.5.0)
       activesupport (>= 4.0.2, < 5)
       claide (>= 1.0.2, < 2.0)
-      cocoapods-core (= 1.3.1)
-      cocoapods-deintegrate (>= 1.0.1, < 2.0)
-      cocoapods-downloader (>= 1.1.3, < 2.0)
+      cocoapods-core (= 1.5.0)
+      cocoapods-deintegrate (>= 1.0.2, < 2.0)
+      cocoapods-downloader (>= 1.2.0, < 2.0)
       cocoapods-plugins (>= 1.0.0, < 2.0)
       cocoapods-search (>= 1.0.0, < 2.0)
       cocoapods-stats (>= 1.0.0, < 2.0)
-      cocoapods-trunk (>= 1.2.0, < 2.0)
+      cocoapods-trunk (>= 1.3.0, < 2.0)
       cocoapods-try (>= 1.1.0, < 2.0)
       colored2 (~> 3.1)
       escape (~> 0.0.4)
       fourflusher (~> 2.0.1)
       gh_inspector (~> 1.0)
-      molinillo (~> 0.5.7)
+      molinillo (~> 0.6.5)
       nap (~> 1.0)
       ruby-macho (~> 1.1)
-      xcodeproj (>= 1.5.1, < 2.0)
-    cocoapods-core (1.3.1)
+      xcodeproj (>= 1.5.7, < 2.0)
+    cocoapods-core (1.5.0)
       activesupport (>= 4.0.2, < 6)
       fuzzy_match (~> 2.0.4)
       nap (~> 1.0)
-    cocoapods-deintegrate (1.0.1)
-    cocoapods-downloader (1.1.3)
+    cocoapods-deintegrate (1.0.2)
+    cocoapods-downloader (1.2.0)
     cocoapods-plugins (1.0.0)
       nap
     cocoapods-search (1.0.0)
     cocoapods-stats (1.0.0)
-    cocoapods-trunk (1.2.0)
+    cocoapods-trunk (1.3.0)
       nap (>= 0.8, < 2.0)
-      netrc (= 0.7.8)
+      netrc (~> 0.11)
     cocoapods-try (1.1.0)
     colored2 (3.1.2)
+    concurrent-ruby (1.0.5)
     escape (0.0.4)
     fourflusher (2.0.1)
     fuzzy_match (2.0.4)
-    gh_inspector (1.0.3)
-    i18n (0.8.6)
+    gh_inspector (1.1.3)
+    i18n (0.9.5)
+      concurrent-ruby (~> 1.0)
     minitest (5.10.1)
-    molinillo (0.5.7)
-    nanaimo (0.2.3)
+    molinillo (0.6.5)
+    nanaimo (0.2.5)
     nap (1.1.0)
-    netrc (0.7.8)
+    netrc (0.11.0)
     ruby-macho (1.1.0)
     thread_safe (0.3.6)
-    tzinfo (1.2.3)
+    tzinfo (1.2.5)
       thread_safe (~> 0.1)
-    xcodeproj (1.5.1)
-      CFPropertyList (~> 2.3.3)
+    xcodeproj (1.5.7)
+      CFPropertyList (>= 2.3.3, < 4.0)
+      atomos (~> 0.1.2)
       claide (>= 1.0.2, < 2.0)
       colored2 (~> 3.1)
-      nanaimo (~> 0.2.3)
+      nanaimo (~> 0.2.4)
 
 PLATFORMS
   ruby
 
 DEPENDENCIES
-  cocoapods (~> 1.3.1)
+  cocoapods (~> 1.5.0)
   minitest
 
 BUNDLED WITH
-   1.13.6
+   1.16.1

From afd58d3ba205c4b0065528f5c1180e0685ee1388 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 13 Apr 2018 01:21:48 +0200
Subject: [PATCH 302/685] =?UTF-8?q?Don=E2=80=99t=20run=20iOS=20tests=20on?=
 =?UTF-8?q?=20oldest=20sim?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

“Early unexpected exit, operation never finished bootstrapping”
---
 Tests/CocoaPods/integration_test.rb | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/Tests/CocoaPods/integration_test.rb b/Tests/CocoaPods/integration_test.rb
index 9792b570..4bec8d40 100755
--- a/Tests/CocoaPods/integration_test.rb
+++ b/Tests/CocoaPods/integration_test.rb
@@ -39,5 +39,32 @@ def test_pod
       # https://github.com/CocoaPods/CocoaPods/issues/7009
       super unless consumer.platform_name == :watchos
     end
+
+    def xcodebuild(action, scheme, configuration)
+      require 'fourflusher'
+      command = %W(clean #{action} -workspace #{File.join(validation_dir, 'App.xcworkspace')} -scheme #{scheme} -configuration #{configuration})
+      case consumer.platform_name
+      when :osx, :macos
+        command += %w(CODE_SIGN_IDENTITY=)
+      when :ios
+        command += %w(CODE_SIGN_IDENTITY=- -sdk iphonesimulator)
+        command += Fourflusher::SimControl.new.destination(nil, 'iOS', deployment_target)
+      when :watchos
+        command += %w(CODE_SIGN_IDENTITY=- -sdk watchsimulator)
+        command += Fourflusher::SimControl.new.destination(:oldest, 'watchOS', deployment_target)
+      when :tvos
+        command += %w(CODE_SIGN_IDENTITY=- -sdk appletvsimulator)
+        command += Fourflusher::SimControl.new.destination(:oldest, 'tvOS', deployment_target)
+      end
+
+      begin
+        _xcodebuild(command, true)
+      rescue => e
+        message = 'Returned an unsuccessful exit code.'
+        message += ' You can use `--verbose` for more information.' unless config.verbose?
+        error('xcodebuild', message)
+        e.message
+      end
+    end
   end
 end

From a1d478eb4325a8c980b99afdfc8e4a29dab0c3e0 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 13 Apr 2018 23:05:19 +0200
Subject: [PATCH 303/685] Exclude test on iOS/tvOS 9.x

---
 SQLite.xcodeproj/project.pbxproj        | 4 ++--
 Tests/SQLiteTests/ConnectionTests.swift | 3 +++
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 2015b8ff..75b38526 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1063,7 +1063,7 @@
 		03A65E6D1C6BB0F60062603F /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				INFOPLIST_FILE = Tests/SQLite/Info.plist;
+				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1077,7 +1077,7 @@
 		03A65E6E1C6BB0F60062603F /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				INFOPLIST_FILE = Tests/SQLite/Info.plist;
+				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index 7fc26110..9480e3bb 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -384,6 +384,9 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_concurrent_access_single_connection() {
+        // test can fail on iOS/tvOS 9.x: SQLite compile-time differences?
+        guard #available(iOS 10.0, OSX 10.10, tvOS 10.0, watchOS 2.2, *) else  { return }
+
         let conn = try! Connection("\(NSTemporaryDirectory())/\(UUID().uuidString)")
         try! conn.execute("DROP TABLE IF EXISTS test; CREATE TABLE test(value);")
         try! conn.run("INSERT INTO test(value) VALUES(?)", 0)

From d732db052d98d3ac2ef577c0331e6fb93a3a170f Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 14 Apr 2018 00:43:48 +0200
Subject: [PATCH 304/685] Docs

---
 .gitmodules            |  0
 .swift-version         |  2 +-
 CHANGELOG.md           |  7 +++++++
 Documentation/Index.md | 16 ++++++++--------
 README.md              | 10 +++++-----
 SQLite.swift.podspec   |  4 ++--
 6 files changed, 23 insertions(+), 16 deletions(-)
 delete mode 100644 .gitmodules

diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index e69de29b..00000000
diff --git a/.swift-version b/.swift-version
index 5186d070..7d5c902e 100644
--- a/.swift-version
+++ b/.swift-version
@@ -1 +1 @@
-4.0
+4.1
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 578b59c2..648cdc07 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+0.11.5 (04-14-2018), [diff][diff-0.11.5]
+========================================
+
+* Swift 4.1 ([#797][])
+
 0.11.4 (30-09-2017), [diff][diff-0.11.4]
 ========================================
 
@@ -51,6 +56,7 @@
 [diff-0.11.2]: https://github.com/stephencelis/SQLite.swift/compare/0.11.1...0.11.2
 [diff-0.11.3]: https://github.com/stephencelis/SQLite.swift/compare/0.11.2...0.11.3
 [diff-0.11.4]: https://github.com/stephencelis/SQLite.swift/compare/0.11.3...0.11.4
+[diff-0.11.5]: https://github.com/stephencelis/SQLite.swift/compare/0.11.4...0.11.5
 
 [#142]: https://github.com/stephencelis/SQLite.swift/issues/142
 [#315]: https://github.com/stephencelis/SQLite.swift/issues/315
@@ -81,3 +87,4 @@
 [#723]: https://github.com/stephencelis/SQLite.swift/pull/723
 [#733]: https://github.com/stephencelis/SQLite.swift/pull/733
 [#726]: https://github.com/stephencelis/SQLite.swift/pull/726
+[#797]: https://github.com/stephencelis/SQLite.swift/pull/797
diff --git a/Documentation/Index.md b/Documentation/Index.md
index efb90ae6..56c8c429 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -67,8 +67,8 @@
 
 ## Installation
 
-> _Note:_ SQLite.swift requires Swift 4 (and
-> [Xcode 9](https://developer.apple.com/xcode/downloads/)) or greater.
+> _Note:_ SQLite.swift requires Swift 4.1 (and
+> [Xcode 9.3](https://developer.apple.com/xcode/downloads/)) or greater.
 
 
 ### Carthage
@@ -80,7 +80,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.11.4
+    github "stephencelis/SQLite.swift" ~> 0.11.5
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -110,7 +110,7 @@ install SQLite.swift with Carthage:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.11.4'
+        pod 'SQLite.swift', '~> 0.11.5'
     end
     ```
 
@@ -124,7 +124,7 @@ with the OS you can require the `standalone` subspec:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.11.4'
+  pod 'SQLite.swift/standalone', '~> 0.11.5'
 end
 ```
 
@@ -134,7 +134,7 @@ dependency to sqlite3 or one of its subspecs:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.11.4'
+  pod 'SQLite.swift/standalone', '~> 0.11.5'
   pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
 end
 ```
@@ -148,7 +148,7 @@ If you want to use [SQLCipher][] with SQLite.swift you can require the
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/SQLCipher', '~> 0.11.4'
+  pod 'SQLite.swift/SQLCipher', '~> 0.11.5'
 end
 ```
 
@@ -181,7 +181,7 @@ applications.
 
   ```swift
   dependencies: [
-    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.11.4")
+    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.11.5")
   ]
   ```
 
diff --git a/README.md b/README.md
index 3900c0a3..bc43b6ec 100644
--- a/README.md
+++ b/README.md
@@ -112,7 +112,7 @@ and the [companion repository][SQLiteDataAccessLayer2].
 
 ## Installation
 
-> _Note:_ SQLite.swift requires Swift 4 (and [Xcode][] 9).
+> _Note:_ SQLite.swift requires Swift 4.1 (and [Xcode][] 9.3).
 
 ### Carthage
 
@@ -124,7 +124,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.11.4
+    github "stephencelis/SQLite.swift" ~> 0.11.5
     ```
 
  3. Run `carthage update` and
@@ -156,7 +156,7 @@ SQLite.swift with CocoaPods:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.11.4'
+        pod 'SQLite.swift', '~> 0.11.5'
     end
     ```
 
@@ -174,7 +174,7 @@ Swift code.
 
   ```swift
   dependencies: [
-      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.11.4")
+      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.11.5")
   ]
   ```
 
@@ -285,7 +285,7 @@ Looking for something else? Try another Swift wrapper (or [FMDB][]):
 [GitterBadge]: https://badges.gitter.im/stephencelis/SQLite.swift.svg
 [GitterLink]: https://gitter.im/stephencelis/SQLite.swift
 
-[Swift4Badge]: https://img.shields.io/badge/swift-4-orange.svg?style=flat
+[Swift4Badge]: https://img.shields.io/badge/swift-4.1-orange.svg?style=flat
 [Swift4Link]: https://developer.apple.com/swift/
 
 [SQLiteMigrationManager.swift]: https://github.com/garriguv/SQLiteMigrationManager.swift
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 4a329338..b03a9ce4 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.11.4"
+  s.version          = "0.11.5"
   s.summary          = "A type-safe, Swift-language layer over SQLite3 for iOS and OS X."
 
   s.description      = <<-DESC
@@ -21,7 +21,7 @@ Pod::Spec.new do |s|
   s.watchos.deployment_target = "2.2"
   s.default_subspec  = 'standard'
   s.pod_target_xcconfig = {
-    'SWIFT_VERSION' => '4.0',
+    'SWIFT_VERSION' => '4.1',
   }
 
   s.subspec 'standard' do |ss|

From 44097d32651d093e826e16ce5d2fa13d4c774c3a Mon Sep 17 00:00:00 2001
From: Dave DeLong <davedelong@me.com>
Date: Mon, 16 Apr 2018 16:13:04 +0200
Subject: [PATCH 305/685] Add `and` and `or` functions

When you're programmatically building a query to execute, you have times where you build a variable number of clauses by which you filter a table. There isn't a great way to turn an `Array<Expression<Bool>>` into an `Expression<Bool>`, short of making a large `(a AND (b AND (c AND (d AND e))))` expression.

`and` and `or` fix this by allowing you to turn an `Array<Expression<Bool>>` directly into a lower-complexity clause: `(a AND b AND c AND d AND e)`
---
 Sources/SQLite/Helpers.swift           |  6 +++++-
 Sources/SQLite/Typed/Operators.swift   | 12 ++++++++++++
 Tests/SQLiteTests/OperatorsTests.swift | 20 ++++++++++++++++++++
 3 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/Sources/SQLite/Helpers.swift b/Sources/SQLite/Helpers.swift
index ac831667..b4ff360e 100644
--- a/Sources/SQLite/Helpers.swift
+++ b/Sources/SQLite/Helpers.swift
@@ -73,7 +73,11 @@ extension String {
     }
 
     func infix<T>(_ lhs: Expressible, _ rhs: Expressible, wrap: Bool = true) -> Expression<T> {
-        let expression = Expression<T>(" \(self) ".join([lhs, rhs]).expression)
+        return infix([lhs, rhs])
+    }
+    
+    func infix<T>(_ terms: [Expressible], wrap: Bool = true) -> Expression<T> {
+        let expression = Expression<T>(" \(self) ".join(terms).expression)
         guard wrap else {
             return expression
         }
diff --git a/Sources/SQLite/Typed/Operators.swift b/Sources/SQLite/Typed/Operators.swift
index d97e52b9..a6df717f 100644
--- a/Sources/SQLite/Typed/Operators.swift
+++ b/Sources/SQLite/Typed/Operators.swift
@@ -516,6 +516,12 @@ public func ~=<V : Value>(lhs: PartialRangeFrom<V>, rhs: Expression<V?>) -> Expr
 
 // MARK: -
 
+public func and(_ terms: Expression<Bool>...) -> Expression<Bool> {
+    return "AND".infix(terms)
+}
+public func and(_ terms: [Expression<Bool>]) -> Expression<Bool> {
+    return "AND".infix(terms)
+}
 public func &&(lhs: Expression<Bool>, rhs: Expression<Bool>) -> Expression<Bool> {
     return "AND".infix(lhs, rhs)
 }
@@ -541,6 +547,12 @@ public func &&(lhs: Bool, rhs: Expression<Bool?>) -> Expression<Bool?> {
     return "AND".infix(lhs, rhs)
 }
 
+public func or(_ terms: Expression<Bool>...) -> Expression<Bool> {
+    return "OR".infix(terms)
+}
+public func or(_ terms: [Expression<Bool>]) -> Expression<Bool> {
+    return "OR".infix(terms)
+}
 public func ||(lhs: Expression<Bool>, rhs: Expression<Bool>) -> Expression<Bool> {
     return "OR".infix(lhs, rhs)
 }
diff --git a/Tests/SQLiteTests/OperatorsTests.swift b/Tests/SQLiteTests/OperatorsTests.swift
index 948eb0a4..050b1e39 100644
--- a/Tests/SQLiteTests/OperatorsTests.swift
+++ b/Tests/SQLiteTests/OperatorsTests.swift
@@ -290,6 +290,16 @@ class OperatorsTests : XCTestCase {
         AssertSQL("(1 AND \"bool\")", true && bool)
         AssertSQL("(1 AND \"boolOptional\")", true && boolOptional)
     }
+    
+    func test_andFunction_withBooleanExpressions_buildsCompoundExpression() {
+        AssertSQL("(\"bool\" AND \"bool\" AND \"bool\")", and([bool, bool, bool]))
+        AssertSQL("(\"bool\" AND \"bool\")", and([bool, bool]))
+        AssertSQL("(\"bool\")", and([bool]))
+        
+        AssertSQL("(\"bool\" AND \"bool\" AND \"bool\")", and(bool, bool, bool))
+        AssertSQL("(\"bool\" AND \"bool\")", and(bool, bool))
+        AssertSQL("(\"bool\")", and(bool))
+    }
 
     func test_doubleOrOperator_withBooleanExpressions_buildsCompoundExpression() {
         AssertSQL("(\"bool\" OR \"bool\")", bool || bool)
@@ -301,6 +311,16 @@ class OperatorsTests : XCTestCase {
         AssertSQL("(1 OR \"bool\")", true || bool)
         AssertSQL("(1 OR \"boolOptional\")", true || boolOptional)
     }
+    
+    func test_orFunction_withBooleanExpressions_buildsCompoundExpression() {
+        AssertSQL("(\"bool\" OR \"bool\" OR \"bool\")", or([bool, bool, bool]))
+        AssertSQL("(\"bool\" OR \"bool\")", or([bool, bool]))
+        AssertSQL("(\"bool\")", or([bool]))
+        
+        AssertSQL("(\"bool\" OR \"bool\" OR \"bool\")", or(bool, bool, bool))
+        AssertSQL("(\"bool\" OR \"bool\")", or(bool, bool))
+        AssertSQL("(\"bool\")", or(bool))
+    }
 
     func test_unaryNotOperator_withBooleanExpressions_buildsNotExpression() {
         AssertSQL("NOT (\"bool\")", !bool)

From e080a3ac0d2dc8fea15dde5681939bbbc0848b3e Mon Sep 17 00:00:00 2001
From: Dave DeLong <davedelong@me.com>
Date: Mon, 16 Apr 2018 16:15:09 +0200
Subject: [PATCH 306/685] Forgot to pass on a parameter

---
 Sources/SQLite/Helpers.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Sources/SQLite/Helpers.swift b/Sources/SQLite/Helpers.swift
index b4ff360e..4b755078 100644
--- a/Sources/SQLite/Helpers.swift
+++ b/Sources/SQLite/Helpers.swift
@@ -73,7 +73,7 @@ extension String {
     }
 
     func infix<T>(_ lhs: Expressible, _ rhs: Expressible, wrap: Bool = true) -> Expression<T> {
-        return infix([lhs, rhs])
+        return infix([lhs, rhs], wrap: wrap)
     }
     
     func infix<T>(_ terms: [Expressible], wrap: Bool = true) -> Expression<T> {

From 10d5e85a99e7f0daedccd5a5099bc457f58ea4e4 Mon Sep 17 00:00:00 2001
From: Madalin Mamuleanu <mamuleanu.madalin@gmail.com>
Date: Tue, 19 Jun 2018 17:12:28 +0300
Subject: [PATCH 307/685] Fixed one of Executing Arbitrary SQL examples: -
 corrected method name - added : instead of =

---
 Documentation/Index.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 56c8c429..9aa84f4a 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1854,8 +1854,8 @@ using the following functions.
     ```swift
     let stmt = try db.prepare("SELECT id, email FROM users")
     for row in stmt {
-        for (index, name) in stmt.columnNames.enumerate() {
-            print ("\(name)=\(row[index]!)")
+        for (index, name) in stmt.columnNames.enumerated() {
+            print ("\(name):\(row[index]!)")
             // id: Optional(1), email: Optional("alice@mac.com")
         }
     }

From 1f84745513aa56bbd38e428e0a5db5d55de3381e Mon Sep 17 00:00:00 2001
From: Serg <redetection@gmail.com>
Date: Sun, 15 Jul 2018 23:36:52 +0700
Subject: [PATCH 308/685] Support Int64 coding

---
 Sources/SQLite/Typed/Coding.swift | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index 7c70db33..3e4b5226 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -152,7 +152,7 @@ fileprivate class SQLiteEncoder: Encoder {
         }
 
         func encode(_ value: Int64, forKey key: Key) throws {
-            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an Int64 is not supported"))
+            self.encoder.setters.append(Expression(key.stringValue) <- value)
         }
 
         func encode(_ value: UInt, forKey key: Key) throws {
@@ -249,7 +249,7 @@ fileprivate class SQLiteDecoder : Decoder {
         }
 
         func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
-            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an UInt64 is not supported"))
+            return try self.row.get(Expression(key.stringValue))
         }
 
         func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {

From 01e152a0672f3934867b86017c290e1f0a62e24a Mon Sep 17 00:00:00 2001
From: Victor Kononov <v.kononov@itos.eu.org>
Date: Mon, 6 Aug 2018 17:09:57 +0300
Subject: [PATCH 309/685] non_framewrok_fix: fixed a mistype that prevented
 building SQLite.swift as non-framework sources.

---
 Sources/SQLite/Typed/Coding.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index 7c70db33..c3fb931b 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -184,7 +184,7 @@ fileprivate class SQLiteEncoder: Encoder {
         }
     }
 
-    fileprivate var setters: [SQLite.Setter] = []
+    fileprivate var setters: [Setter] = []
     let codingPath: [CodingKey] = []
     let userInfo: [CodingUserInfoKey: Any]
 

From 0aaddb3b97d8d62d46567e16c305beb34312bad2 Mon Sep 17 00:00:00 2001
From: Otto Suess <37940680+ottosuess@users.noreply.github.com>
Date: Thu, 13 Sep 2018 18:33:51 +0200
Subject: [PATCH 310/685] fix markdown table formatting

tables containing `|` are breaking github markdown formatter when they are not escaped.
---
 Documentation/Index.md | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 9aa84f4a..628e7464 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -718,7 +718,7 @@ try db.transaction {
 | `<<=`    | `Int -> Int`       |
 | `>>=`    | `Int -> Int`       |
 | `&=`     | `Int -> Int`       |
-| `||=`    | `Int -> Int`       |
+| `\|\|=`  | `Int -> Int`       |
 | `^=`     | `Int -> Int`       |
 | `+=`     | `String -> String` |
 
@@ -954,7 +954,7 @@ equate or compare different types will prevent compilation.
 | `<=`  | `Comparable -> Bool`             | `<=`           |
 | `~=`  | `(Interval, Comparable) -> Bool` | `BETWEEN`      |
 | `&&`  | `Bool -> Bool`                   | `AND`          |
-| `||`  | `Bool -> Bool`                   | `OR`           |
+| `\|\|`| `Bool -> Bool`                   | `OR`           |
 
 > *When comparing against `nil`, SQLite.swift will use `IS` and `IS NOT`
 > accordingly.
@@ -1586,8 +1586,8 @@ arithmetic, bitwise operations, and concatenation.
 | `<<`  | `Int -> Int`                     | `<<`     |
 | `>>`  | `Int -> Int`                     | `>>`     |
 | `&`   | `Int -> Int`                     | `&`      |
-| `|`   | `Int -> Int`                     | `|`      |
-| `+`   | `String -> String`               | `||`     |
+| `\|`  | `Int -> Int`                     | `\|`     |
+| `+`   | `String -> String`               | `\|\|`   |
 
 > _Note:_ SQLite.swift also defines a bitwise XOR operator, `^`, which
 > expands the expression `lhs ^ rhs` to `~(lhs & rhs) & (lhs | rhs)`.

From 304c39d42f45c07eece380f1d64e4ba40f3fadb1 Mon Sep 17 00:00:00 2001
From: Jason Peterson <jasonwpeterson@icloud.com>
Date: Sat, 29 Sep 2018 21:27:34 -0500
Subject: [PATCH 311/685] added sample code for copying a 'seed' database

---
 Documentation/Index.md | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 628e7464..12810f94 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -258,6 +258,28 @@ let path = NSSearchPathForDirectoriesInDomains(
 let db = try Connection("\(path)/db.sqlite3")
 ```
 
+If you have bundled it your application, you can use FileManager to copy it to the Documents directory:
+
+```swift
+func copyDatabaseIfNeeded(sourcePath : String) -> Bool {
+    var destinationPath = NSSearchPathForDirectoriesInDomains(
+        .documentDirectory, .userDomainMask, true
+    ).first!
+    destinationPath = destinationPath + "/db.sqlite3"
+    let databaseExistsWhereNeeded = FileManager.default.fileExists(atPath: destinationPath)
+    if (!databaseExistsWhereNeeded) {
+        do {
+            try FileManager.default.copyItem(atPath: sourcePath, toPath: destinationPath)
+            print("db copied")
+        }
+        catch {
+            print("error during file copy: \(error)")
+        }
+    }
+    return true
+}
+```
+
 On OS X, you can use your app’s **Application Support** directory:
 
 ```swift
@@ -295,7 +317,7 @@ let db = try Connection(path, readonly: true)
 > See these two Stack Overflow questions for more information about iOS apps
 > with SQLite databases: [1](https://stackoverflow.com/questions/34609746/what-different-between-store-database-in-different-locations-in-ios),
 > [2](https://stackoverflow.com/questions/34614968/ios-how-to-copy-pre-seeded-database-at-the-first-running-app-with-sqlite-swift).
-> We welcome sample code to show how to successfully copy and use a bundled "seed"
+> We welcome changes to the above sample code to show how to successfully copy and use a bundled "seed"
 > database for writing in an app.
 
 #### In-Memory Databases

From ad63c37cc044af3d4bc1588faa6c41c5600b71b0 Mon Sep 17 00:00:00 2001
From: Madalin Mamuleanu <mamuleanu.madalin@gmail.com>
Date: Tue, 2 Oct 2018 00:21:03 +0300
Subject: [PATCH 312/685] Documentation update. Fixes #841

---
 Documentation/Index.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 628e7464..f214b50a 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -266,8 +266,8 @@ var path = NSSearchPathForDirectoriesInDomains(
 ).first! + "/" + Bundle.main.bundleIdentifier!
 
 // create parent directory iff it doesn’t exist
-try FileManager.default.createDirectoryAtPath(
-    path, withIntermediateDirectories: true, attributes: nil
+try FileManager.default.createDirectory(
+atPath: path, withIntermediateDirectories: true, attributes: nil
 )
 
 let db = try Connection("\(path)/db.sqlite3")

From ab53696ce1aca28a292ecb1b20967a1f687cf7a1 Mon Sep 17 00:00:00 2001
From: Huan Lin <huan.lin@airbnb.com>
Date: Mon, 15 Oct 2018 21:52:10 -0700
Subject: [PATCH 313/685] add primary key with 4 columns.

---
 Sources/SQLite/Typed/Schema.swift   | 4 ++++
 Tests/SQLiteTests/SchemaTests.swift | 4 ++++
 2 files changed, 8 insertions(+)

diff --git a/Sources/SQLite/Typed/Schema.swift b/Sources/SQLite/Typed/Schema.swift
index 62c90702..febfe68c 100644
--- a/Sources/SQLite/Typed/Schema.swift
+++ b/Sources/SQLite/Typed/Schema.swift
@@ -341,6 +341,10 @@ public final class TableBuilder {
         primaryKey([compositeA, b, c])
     }
 
+    public func primaryKey<T : Value, U : Value, V : Value, W : Value>(_ compositeA: Expression<T>, _ b: Expression<U>, _ c: Expression<V>, _ d: Expression<W>) {
+        primaryKey([compositeA, b, c, d])
+    }
+
     fileprivate func primaryKey(_ composite: [Expressible]) {
         definitions.append("PRIMARY KEY".prefix(composite))
     }
diff --git a/Tests/SQLiteTests/SchemaTests.swift b/Tests/SQLiteTests/SchemaTests.swift
index b9a08881..30646b98 100644
--- a/Tests/SQLiteTests/SchemaTests.swift
+++ b/Tests/SQLiteTests/SchemaTests.swift
@@ -545,6 +545,10 @@ class SchemaTests : XCTestCase {
             "CREATE TABLE \"table\" (PRIMARY KEY (\"int64\", \"string\", \"double\"))",
             table.create { t in t.primaryKey(int64, string, double) }
         )
+        XCTAssertEqual(
+            "CREATE TABLE \"table\" (PRIMARY KEY (\"int64\", \"string\", \"double\", \"date\"))",
+            table.create { t in t.primaryKey(int64, string, double, date) }
+        )
     }
 
     func test_unique_compilesUniqueExpression() {

From cf4183f4ef54c5c9e82176cc46451934c8fdec2a Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 19 Dec 2018 12:35:50 +0100
Subject: [PATCH 314/685] Swift 4.2, Xcode 10.1

- fix tests running agains SQLCipher 4.x
---
 .swift-version                                |   2 +-
 .travis.yml                                   |   5 +-
 CHANGELOG.md                                  |   7 +++
 Makefile                                      |   2 +-
 SQLite.swift.podspec                          |   2 +-
 SQLite.xcodeproj/project.pbxproj              |  28 +++++------
 Sources/SQLite/Extensions/Cipher.swift        |   5 ++
 Sources/SQLiteObjc/include/SQLite-Bridging.h  |   3 +-
 Tests/CocoaPods/Gemfile                       |   2 +-
 Tests/CocoaPods/Gemfile.lock                  |  44 +++++++++---------
 Tests/CocoaPods/integration_test.rb           |   2 +-
 Tests/SQLiteTests/CipherTests.swift           |  10 +++-
 Tests/SQLiteTests/ConnectionTests.swift       |  35 +++++++-------
 Tests/SQLiteTests/TestHelpers.swift           |   9 ----
 ...{encrypted.sqlite => encrypted-3.x.sqlite} | Bin
 .../SQLiteTests/fixtures/encrypted-4.x.sqlite | Bin 0 -> 8192 bytes
 16 files changed, 83 insertions(+), 73 deletions(-)
 rename Tests/SQLiteTests/fixtures/{encrypted.sqlite => encrypted-3.x.sqlite} (100%)
 create mode 100644 Tests/SQLiteTests/fixtures/encrypted-4.x.sqlite

diff --git a/.swift-version b/.swift-version
index 7d5c902e..bf77d549 100644
--- a/.swift-version
+++ b/.swift-version
@@ -1 +1 @@
-4.1
+4.2
diff --git a/.travis.yml b/.travis.yml
index f278301d..909e5672 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,10 +1,11 @@
 language: objective-c
 rvm: 2.3
-osx_image: xcode9.3
+# https://docs.travis-ci.com/user/reference/osx
+osx_image: xcode10.1
 env:
   global:
     - IOS_SIMULATOR="iPhone 6s"
-    - IOS_VERSION="11.3"
+    - IOS_VERSION="12.1"
 matrix:
   include:
     - env: BUILD_SCHEME="SQLite iOS"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 648cdc07..027611ee 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+0.11.6 (xxx), [diff][diff-0.11.6]
+========================================
+
+* Swift 4.2, SQLCipher 4.x ([#866][])
+
 0.11.5 (04-14-2018), [diff][diff-0.11.5]
 ========================================
 
@@ -57,6 +62,7 @@
 [diff-0.11.3]: https://github.com/stephencelis/SQLite.swift/compare/0.11.2...0.11.3
 [diff-0.11.4]: https://github.com/stephencelis/SQLite.swift/compare/0.11.3...0.11.4
 [diff-0.11.5]: https://github.com/stephencelis/SQLite.swift/compare/0.11.4...0.11.5
+[diff-0.11.6]: https://github.com/stephencelis/SQLite.swift/compare/0.11.5...0.11.6
 
 [#142]: https://github.com/stephencelis/SQLite.swift/issues/142
 [#315]: https://github.com/stephencelis/SQLite.swift/issues/315
@@ -88,3 +94,4 @@
 [#733]: https://github.com/stephencelis/SQLite.swift/pull/733
 [#726]: https://github.com/stephencelis/SQLite.swift/pull/726
 [#797]: https://github.com/stephencelis/SQLite.swift/pull/797
+[#866]: https://github.com/stephencelis/SQLite.swift/pull/866
diff --git a/Makefile b/Makefile
index cd4afb8d..d98c8deb 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 BUILD_TOOL = xcodebuild
 BUILD_SCHEME = SQLite Mac
 IOS_SIMULATOR = iPhone 6s
-IOS_VERSION = 11.3
+IOS_VERSION = 12.1
 ifeq ($(BUILD_SCHEME),SQLite iOS)
 	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -destination "platform=iOS Simulator,name=$(IOS_SIMULATOR),OS=$(IOS_VERSION)"
 else
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index b03a9ce4..c2235aca 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -21,7 +21,7 @@ Pod::Spec.new do |s|
   s.watchos.deployment_target = "2.2"
   s.default_subspec  = 'standard'
   s.pod_target_xcconfig = {
-    'SWIFT_VERSION' => '4.1',
+    'SWIFT_VERSION' => '4.2',
   }
 
   s.subspec 'standard' do |ss|
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 75b38526..a155a115 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1033,7 +1033,7 @@
 				SDKROOT = appletvos;
 				SKIP_INSTALL = YES;
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.0;
+				SWIFT_VERSION = 4.2;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
 			name = Debug;
@@ -1055,7 +1055,7 @@
 				SDKROOT = appletvos;
 				SKIP_INSTALL = YES;
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.0;
+				SWIFT_VERSION = 4.2;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
 			name = Release;
@@ -1069,7 +1069,7 @@
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = appletvos;
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.0;
+				SWIFT_VERSION = 4.2;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
 			name = Debug;
@@ -1083,7 +1083,7 @@
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = appletvos;
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.0;
+				SWIFT_VERSION = 4.2;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
 			name = Release;
@@ -1106,7 +1106,7 @@
 				SDKROOT = watchos;
 				SKIP_INSTALL = YES;
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.0;
+				SWIFT_VERSION = 4.2;
 				TARGETED_DEVICE_FAMILY = 4;
 				WATCHOS_DEPLOYMENT_TARGET = 2.2;
 			};
@@ -1130,7 +1130,7 @@
 				SDKROOT = watchos;
 				SKIP_INSTALL = YES;
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.0;
+				SWIFT_VERSION = 4.2;
 				TARGETED_DEVICE_FAMILY = 4;
 				WATCHOS_DEPLOYMENT_TARGET = 2.2;
 			};
@@ -1269,7 +1269,7 @@
 				SKIP_INSTALL = YES;
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.0;
+				SWIFT_VERSION = 4.2;
 			};
 			name = Debug;
 		};
@@ -1291,7 +1291,7 @@
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.0;
+				SWIFT_VERSION = 4.2;
 			};
 			name = Release;
 		};
@@ -1304,7 +1304,7 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.0;
+				SWIFT_VERSION = 4.2;
 			};
 			name = Debug;
 		};
@@ -1317,7 +1317,7 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.0;
+				SWIFT_VERSION = 4.2;
 			};
 			name = Release;
 		};
@@ -1342,7 +1342,7 @@
 				SKIP_INSTALL = YES;
 				SWIFT_INCLUDE_PATHS = "";
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.0;
+				SWIFT_VERSION = 4.2;
 			};
 			name = Debug;
 		};
@@ -1367,7 +1367,7 @@
 				SKIP_INSTALL = YES;
 				SWIFT_INCLUDE_PATHS = "";
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.0;
+				SWIFT_VERSION = 4.2;
 			};
 			name = Release;
 		};
@@ -1383,7 +1383,7 @@
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = macosx;
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.0;
+				SWIFT_VERSION = 4.2;
 			};
 			name = Debug;
 		};
@@ -1399,7 +1399,7 @@
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = macosx;
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.0;
+				SWIFT_VERSION = 4.2;
 			};
 			name = Release;
 		};
diff --git a/Sources/SQLite/Extensions/Cipher.swift b/Sources/SQLite/Extensions/Cipher.swift
index 6c0d4657..71ef1765 100644
--- a/Sources/SQLite/Extensions/Cipher.swift
+++ b/Sources/SQLite/Extensions/Cipher.swift
@@ -6,6 +6,11 @@ import SQLCipher
 /// @see [sqlcipher api](https://www.zetetic.net/sqlcipher/sqlcipher-api/)
 extension Connection {
 
+    /// - Returns: the SQLCipher version
+    public var cipherVersion: String? {
+        return (try? scalar("PRAGMA cipher_version")) as? String
+    }
+
     /// Specify the key for an encrypted database.  This routine should be
     /// called right after sqlite3_open().
     ///
diff --git a/Sources/SQLiteObjc/include/SQLite-Bridging.h b/Sources/SQLiteObjc/include/SQLite-Bridging.h
index 5b356593..f8c2a3b3 100644
--- a/Sources/SQLiteObjc/include/SQLite-Bridging.h
+++ b/Sources/SQLiteObjc/include/SQLite-Bridging.h
@@ -23,8 +23,7 @@
 //
 
 @import Foundation;
-
-#import "sqlite3.h"
+@import SQLite3;
 
 NS_ASSUME_NONNULL_BEGIN
 typedef NSString * _Nullable (^_SQLiteTokenizerNextCallback)(const char *input, int *inputOffset, int *inputLength);
diff --git a/Tests/CocoaPods/Gemfile b/Tests/CocoaPods/Gemfile
index 3b9d6ba5..fd1c8c2e 100644
--- a/Tests/CocoaPods/Gemfile
+++ b/Tests/CocoaPods/Gemfile
@@ -1,4 +1,4 @@
 source 'https://rubygems.org'
 
-gem 'cocoapods', '~> 1.5.0'
+gem 'cocoapods', '~> 1.6.0beta2'
 gem 'minitest'
diff --git a/Tests/CocoaPods/Gemfile.lock b/Tests/CocoaPods/Gemfile.lock
index de03030a..b5172144 100644
--- a/Tests/CocoaPods/Gemfile.lock
+++ b/Tests/CocoaPods/Gemfile.lock
@@ -2,76 +2,76 @@ GEM
   remote: https://rubygems.org/
   specs:
     CFPropertyList (3.0.0)
-    activesupport (4.2.10)
+    activesupport (4.2.11)
       i18n (~> 0.7)
       minitest (~> 5.1)
       thread_safe (~> 0.3, >= 0.3.4)
       tzinfo (~> 1.1)
-    atomos (0.1.2)
+    atomos (0.1.3)
     claide (1.0.2)
-    cocoapods (1.5.0)
+    cocoapods (1.6.0.beta.2)
       activesupport (>= 4.0.2, < 5)
       claide (>= 1.0.2, < 2.0)
-      cocoapods-core (= 1.5.0)
+      cocoapods-core (= 1.6.0.beta.2)
       cocoapods-deintegrate (>= 1.0.2, < 2.0)
-      cocoapods-downloader (>= 1.2.0, < 2.0)
+      cocoapods-downloader (>= 1.2.2, < 2.0)
       cocoapods-plugins (>= 1.0.0, < 2.0)
       cocoapods-search (>= 1.0.0, < 2.0)
       cocoapods-stats (>= 1.0.0, < 2.0)
-      cocoapods-trunk (>= 1.3.0, < 2.0)
+      cocoapods-trunk (>= 1.3.1, < 2.0)
       cocoapods-try (>= 1.1.0, < 2.0)
       colored2 (~> 3.1)
       escape (~> 0.0.4)
       fourflusher (~> 2.0.1)
       gh_inspector (~> 1.0)
-      molinillo (~> 0.6.5)
+      molinillo (~> 0.6.6)
       nap (~> 1.0)
-      ruby-macho (~> 1.1)
-      xcodeproj (>= 1.5.7, < 2.0)
-    cocoapods-core (1.5.0)
+      ruby-macho (~> 1.3, >= 1.3.1)
+      xcodeproj (>= 1.7.0, < 2.0)
+    cocoapods-core (1.6.0.beta.2)
       activesupport (>= 4.0.2, < 6)
       fuzzy_match (~> 2.0.4)
       nap (~> 1.0)
     cocoapods-deintegrate (1.0.2)
-    cocoapods-downloader (1.2.0)
+    cocoapods-downloader (1.2.2)
     cocoapods-plugins (1.0.0)
       nap
     cocoapods-search (1.0.0)
     cocoapods-stats (1.0.0)
-    cocoapods-trunk (1.3.0)
+    cocoapods-trunk (1.3.1)
       nap (>= 0.8, < 2.0)
       netrc (~> 0.11)
     cocoapods-try (1.1.0)
     colored2 (3.1.2)
-    concurrent-ruby (1.0.5)
+    concurrent-ruby (1.1.4)
     escape (0.0.4)
     fourflusher (2.0.1)
     fuzzy_match (2.0.4)
     gh_inspector (1.1.3)
     i18n (0.9.5)
       concurrent-ruby (~> 1.0)
-    minitest (5.10.1)
-    molinillo (0.6.5)
-    nanaimo (0.2.5)
+    minitest (5.11.3)
+    molinillo (0.6.6)
+    nanaimo (0.2.6)
     nap (1.1.0)
     netrc (0.11.0)
-    ruby-macho (1.1.0)
+    ruby-macho (1.3.1)
     thread_safe (0.3.6)
     tzinfo (1.2.5)
       thread_safe (~> 0.1)
-    xcodeproj (1.5.7)
+    xcodeproj (1.7.0)
       CFPropertyList (>= 2.3.3, < 4.0)
-      atomos (~> 0.1.2)
+      atomos (~> 0.1.3)
       claide (>= 1.0.2, < 2.0)
       colored2 (~> 3.1)
-      nanaimo (~> 0.2.4)
+      nanaimo (~> 0.2.6)
 
 PLATFORMS
   ruby
 
 DEPENDENCIES
-  cocoapods (~> 1.5.0)
+  cocoapods (~> 1.6.0beta2)
   minitest
 
 BUNDLED WITH
-   1.16.1
+   1.17.1
diff --git a/Tests/CocoaPods/integration_test.rb b/Tests/CocoaPods/integration_test.rb
index 4bec8d40..98a539b5 100755
--- a/Tests/CocoaPods/integration_test.rb
+++ b/Tests/CocoaPods/integration_test.rb
@@ -42,7 +42,7 @@ def test_pod
 
     def xcodebuild(action, scheme, configuration)
       require 'fourflusher'
-      command = %W(clean #{action} -workspace #{File.join(validation_dir, 'App.xcworkspace')} -scheme #{scheme} -configuration #{configuration})
+      command = %W(#{action} -workspace #{File.join(validation_dir, 'App.xcworkspace')} -scheme #{scheme} -configuration #{configuration})
       case consumer.platform_name
       when :osx, :macos
         command += %w(CODE_SIGN_IDENTITY=)
diff --git a/Tests/SQLiteTests/CipherTests.swift b/Tests/SQLiteTests/CipherTests.swift
index 3ee0b135..abecffba 100644
--- a/Tests/SQLiteTests/CipherTests.swift
+++ b/Tests/SQLiteTests/CipherTests.swift
@@ -73,11 +73,17 @@ class CipherTests: XCTestCase {
     }
 
     func test_open_db_encrypted_with_sqlcipher() {
-        // $ sqlcipher SQLiteTests/fixtures/encrypted.sqlite
+        // $ sqlcipher Tests/SQLiteTests/fixtures/encrypted-[version].x.sqlite
         // sqlite> pragma key = 'sqlcipher-test';
         // sqlite> CREATE TABLE foo (bar TEXT);
         // sqlite> INSERT INTO foo (bar) VALUES ('world');
-        let encryptedFile = fixture("encrypted", withExtension: "sqlite")
+        guard let cipherVersion:String = db1.cipherVersion,
+            cipherVersion.starts(with: "3.") || cipherVersion.starts(with: "4.")
+            else { return }
+
+        let encryptedFile = cipherVersion.starts(with: "3.") ?
+            fixture("encrypted-3.x", withExtension: "sqlite") :
+            fixture("encrypted-4.x", withExtension: "sqlite")
 
         try! FileManager.default.setAttributes([FileAttributeKey.immutable : 1], ofItemAtPath: encryptedFile)
         XCTAssertFalse(FileManager.default.isWritableFile(atPath: encryptedFile))
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index 9480e3bb..eab3cf00 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -369,18 +369,23 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_interrupt_interruptsLongRunningQuery() {
-        try! InsertUsers("abcdefghijklmnopqrstuvwxyz".map { String($0) })
+        let semaphore = DispatchSemaphore(value: 0)
         db.createFunction("sleep") { args in
-            usleep(UInt32((args[0] as? Double ?? Double(args[0] as? Int64 ?? 1)) * 1_000_000))
+            DispatchQueue.global(qos: .background).async {
+                self.db.interrupt()
+                semaphore.signal()
+            }
+            semaphore.wait()
             return nil
         }
-
-        let stmt = try! db.prepare("SELECT *, sleep(?) FROM users", 0.1)
-        try! stmt.run()
-
-        let deadline = DispatchTime.now() + 0.01
-        _ = DispatchQueue(label: "queue", qos: .background).asyncAfter(deadline: deadline, execute: db.interrupt)
-        AssertThrows(try stmt.run())
+        let stmt = try! db.prepare("SELECT sleep()")
+        XCTAssertThrowsError(try stmt.run()) { error in
+            if case Result.error(_, let code, _) = error {
+                XCTAssertEqual(code, SQLITE_INTERRUPT)
+            } else {
+                XCTFail("unexpected error: \(error)")
+            }
+        }
     }
 
     func test_concurrent_access_single_connection() {
@@ -391,21 +396,17 @@ class ConnectionTests : SQLiteTestCase {
         try! conn.execute("DROP TABLE IF EXISTS test; CREATE TABLE test(value);")
         try! conn.run("INSERT INTO test(value) VALUES(?)", 0)
         let queue = DispatchQueue(label: "Readers", attributes: [.concurrent])
+
         let nReaders = 5
-        var reads = Array(repeating: 0, count: nReaders)
-        var finished = false
+        let semaphores =  Array(repeating: DispatchSemaphore(value: 100), count: nReaders)
         for index in 0..<nReaders {
             queue.async {
-                while !finished {
+                while semaphores[index].signal() == 0 {
                     _ = try! conn.scalar("SELECT value FROM test")
-                    reads[index] += 1
                 }
             }
         }
-        while !finished {
-            sleep(1)
-            finished = reads.reduce(true) { $0 && ($1 > 500) }
-        }
+        semaphores.forEach { $0.wait() }
     }
 }
 
diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index 8d60362c..2e491b01 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -100,15 +100,6 @@ func AssertSQL(_ expression1: @autoclosure () -> String, _ expression2: @autoclo
     XCTAssertEqual(expression1(), expression2().asSQL(), file: file, line: line)
 }
 
-func AssertThrows<T>(_ expression: @autoclosure () throws -> T, file: StaticString = #file, line: UInt = #line) {
-    do {
-        _ = try expression()
-        XCTFail("expression expected to throw", file: file, line: line)
-    } catch {
-        XCTAssert(true, file: file, line: line)
-    }
-}
-
 let table = Table("table")
 let qualifiedTable = Table("table", database: "main")
 let virtualTable = VirtualTable("virtual_table")
diff --git a/Tests/SQLiteTests/fixtures/encrypted.sqlite b/Tests/SQLiteTests/fixtures/encrypted-3.x.sqlite
similarity index 100%
rename from Tests/SQLiteTests/fixtures/encrypted.sqlite
rename to Tests/SQLiteTests/fixtures/encrypted-3.x.sqlite
diff --git a/Tests/SQLiteTests/fixtures/encrypted-4.x.sqlite b/Tests/SQLiteTests/fixtures/encrypted-4.x.sqlite
new file mode 100644
index 0000000000000000000000000000000000000000..36890365583fc0fa1383f4377d7c9b844059872c
GIT binary patch

From 7c0bdfd01fd3461d273d24cb4f0205614567d4c9 Mon Sep 17 00:00:00 2001
From: Christian Roman <hello@christianroman.net>
Date: Fri, 11 Jan 2019 09:05:41 -0600
Subject: [PATCH 315/685] Codable - Add Date support

---
 Documentation/Index.md              |  2 +-
 Sources/SQLite/Typed/Coding.swift   |  7 +++++++
 Tests/SQLiteTests/QueryTests.swift  | 27 +++++++++++++++------------
 Tests/SQLiteTests/TestHelpers.swift |  5 ++++-
 4 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 628e7464..7fc74ea0 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1557,7 +1557,7 @@ Both of the above methods also have the following optional parameter:
 There are a few restrictions on using Codable types:
 
 - The encodable and decodable objects can only use the following types:
-    - Int, Bool, Float, Double, String
+    - Int, Bool, Float, Double, String, Date
     - Nested Codable types that will be encoded as JSON to a single column
 - These methods will not handle object relationships for you. You must write
   your own Codable and Decodable implementations if you wish to support this.
diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index c3fb931b..0eb02a55 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -132,6 +132,9 @@ fileprivate class SQLiteEncoder: Encoder {
             if let data = value as? Data {
                 self.encoder.setters.append(Expression(key.stringValue) <- data)
             }
+            else if let date = value as? Date {
+                self.encoder.setters.append(Expression(key.stringValue) <- date.datatypeValue)
+            }
             else {
                 let encoded = try JSONEncoder().encode(value)
                 let string = String(data: encoded, encoding: .utf8)
@@ -290,6 +293,10 @@ fileprivate class SQLiteDecoder : Decoder {
                 let data = try self.row.get(Expression<Data>(key.stringValue))
                 return data as! T
             }
+            else if type == Date.self {
+                let date = try self.row.get(Expression<Date>(key.stringValue))
+                return date as! T
+            }
             guard let JSONString = try self.row.get(Expression<String?>(key.stringValue)) else {
                 throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "an unsupported type was found"))
             }
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index 2a9e4ecb..8f48264f 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -249,23 +249,23 @@ class QueryTests : XCTestCase {
 
     func test_insert_encodable() throws {
         let emails = Table("emails")
-        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil)
+        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
         let insert = try emails.insert(value)
         AssertSQL(
-            "INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\") VALUES (1, '2', 1, 3.0, 4.0)",
+            "INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\") VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000')",
             insert
         )
     }
 
     func test_insert_encodable_with_nested_encodable() throws {
         let emails = Table("emails")
-        let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil)
-        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: "optional", sub: value1)
+        let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: "optional", sub: value1)
         let insert = try emails.insert(value)
         let encodedJSON = try JSONEncoder().encode(value1)
         let encodedJSONString = String(data: encodedJSON, encoding: .utf8)!
         AssertSQL(
-            "INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"optional\", \"sub\") VALUES (1, '2', 1, 3.0, 4.0, 'optional', '\(encodedJSONString)')",
+            "INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\", \"optional\", \"sub\") VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000', 'optional', '\(encodedJSONString)')",
             insert
         )
     }
@@ -286,23 +286,23 @@ class QueryTests : XCTestCase {
 
     func test_update_encodable() throws {
         let emails = Table("emails")
-        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil)
+        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
         let update = try emails.update(value)
         AssertSQL(
-            "UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0",
+            "UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0, \"date\" = '1970-01-01T00:00:00.000'",
             update
         )
     }
 
     func test_update_encodable_with_nested_encodable() throws {
         let emails = Table("emails")
-        let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil)
-        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: value1)
+        let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: nil, sub: value1)
         let update = try emails.update(value)
         let encodedJSON = try JSONEncoder().encode(value1)
         let encodedJSONString = String(data: encodedJSON, encoding: .utf8)!
         AssertSQL(
-            "UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0, \"sub\" = '\(encodedJSONString)'",
+            "UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0, \"date\" = '1970-01-01T00:00:00.000', \"sub\" = '\(encodedJSONString)'",
             update
         )
     }
@@ -438,12 +438,13 @@ class QueryIntegrationTests : SQLiteTestCase {
             builder.column(Expression<Bool>("bool"))
             builder.column(Expression<Double>("float"))
             builder.column(Expression<Double>("double"))
+            builder.column(Expression<Date>("date"))
             builder.column(Expression<String?>("optional"))
             builder.column(Expression<Data>("sub"))
         })
 
-        let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil)
-        let value = TestCodable(int: 5, string: "6", bool: true, float: 7, double: 8, optional: "optional", sub: value1)
+        let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+        let value = TestCodable(int: 5, string: "6", bool: true, float: 7, double: 8, date: Date(timeIntervalSince1970: 5000), optional: "optional", sub: value1)
 
         try db.run(table.insert(value))
 
@@ -455,12 +456,14 @@ class QueryIntegrationTests : SQLiteTestCase {
         XCTAssertEqual(values[0].bool, true)
         XCTAssertEqual(values[0].float, 7)
         XCTAssertEqual(values[0].double, 8)
+        XCTAssertEqual(values[0].date, Date(timeIntervalSince1970: 5000))
         XCTAssertEqual(values[0].optional, "optional")
         XCTAssertEqual(values[0].sub?.int, 1)
         XCTAssertEqual(values[0].sub?.string, "2")
         XCTAssertEqual(values[0].sub?.bool, true)
         XCTAssertEqual(values[0].sub?.float, 3)
         XCTAssertEqual(values[0].sub?.double, 4)
+        XCTAssertEqual(values[0].sub?.date, Date(timeIntervalSince1970: 0))
         XCTAssertNil(values[0].sub?.optional)
         XCTAssertNil(values[0].sub?.sub)
     }
diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index 2e491b01..247013b4 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -26,6 +26,7 @@ class SQLiteTestCase : XCTestCase {
                 salary REAL,
                 admin BOOLEAN NOT NULL DEFAULT 0 CHECK (admin IN (0, 1)),
                 manager_id INTEGER,
+                created_at DATETIME,
                 FOREIGN KEY(manager_id) REFERENCES users(id)
             )
             """
@@ -111,15 +112,17 @@ class TestCodable: Codable {
     let bool: Bool
     let float: Float
     let double: Double
+    let date: Date
     let optional: String?
     let sub: TestCodable?
 
-    init(int: Int, string: String, bool: Bool, float: Float, double: Double, optional: String?, sub: TestCodable?) {
+    init(int: Int, string: String, bool: Bool, float: Float, double: Double, date: Date, optional: String?, sub: TestCodable?) {
         self.int = int
         self.string = string
         self.bool = bool
         self.float = float
         self.double = double
+        self.date = date
         self.optional = optional
         self.sub = sub
     }

From 2b82d152e1870d353cedae0bcbfce0b31a511275 Mon Sep 17 00:00:00 2001
From: Gregory Todd Williams <greg@evilfunhouse.com>
Date: Thu, 21 Feb 2019 21:08:29 -0800
Subject: [PATCH 316/685] Add prototype implementation for
 Connection.createAggregation.

---
 SQLite.xcodeproj/project.pbxproj              |   8 ++
 Sources/SQLite/Core/Connection.swift          | 106 ++++++++++++++++++
 .../SQLiteTests/CustomAggregationTests.swift  |  73 ++++++++++++
 3 files changed, 187 insertions(+)
 create mode 100644 Tests/SQLiteTests/CustomAggregationTests.swift

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index a155a115..1635f651 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -81,6 +81,9 @@
 		19A17FB80B94E882050AA908 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
 		19A17FDA323BAFDEC627E76F /* fixtures in Resources */ = {isa = PBXBuildFile; fileRef = 19A17E2695737FAB5D6086E3 /* fixtures */; };
 		19A17FF4A10B44D3937C8CAC /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
+		3717F908221F5D8800B9BD3D /* CustomAggregationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */; };
+		3717F909221F5D8900B9BD3D /* CustomAggregationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */; };
+		3717F90A221F5D8900B9BD3D /* CustomAggregationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */; };
 		3D67B3E61DB2469200A4F4C6 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */; };
 		3D67B3E71DB246BA00A4F4C6 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
 		3D67B3E81DB246BA00A4F4C6 /* Connection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEF1C3F06E900AE3E12 /* Connection.swift */; };
@@ -225,6 +228,7 @@
 		19A17B93B48B5560E6E51791 /* Fixtures.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Fixtures.swift; sourceTree = "<group>"; };
 		19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAndTimeFunctions.swift; sourceTree = "<group>"; };
 		19A17E2695737FAB5D6086E3 /* fixtures */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = folder; path = fixtures; sourceTree = "<group>"; };
+		3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomAggregationTests.swift; sourceTree = "<group>"; };
 		3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.0.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
 		49EB68C31F7B3CB400D89D40 /* Coding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coding.swift; sourceTree = "<group>"; };
 		A121AC451CA35C79005A31D1 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -401,6 +405,7 @@
 				EE247B1D1C3F137700AE3E12 /* ConnectionTests.swift */,
 				EE247B1E1C3F137700AE3E12 /* CoreFunctionsTests.swift */,
 				EE247B1F1C3F137700AE3E12 /* CustomFunctionsTests.swift */,
+				3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */,
 				EE247B201C3F137700AE3E12 /* ExpressionTests.swift */,
 				EE247B211C3F137700AE3E12 /* FTS4Tests.swift */,
 				EE247B2A1C3F141E00AE3E12 /* OperatorsTests.swift */,
@@ -834,6 +839,7 @@
 				03A65E921C6BB3030062603F /* SetterTests.swift in Sources */,
 				03A65E891C6BB3030062603F /* ConnectionTests.swift in Sources */,
 				03A65E8A1C6BB3030062603F /* CoreFunctionsTests.swift in Sources */,
+				3717F90A221F5D8900B9BD3D /* CustomAggregationTests.swift in Sources */,
 				03A65E931C6BB3030062603F /* StatementTests.swift in Sources */,
 				03A65E911C6BB3030062603F /* SchemaTests.swift in Sources */,
 				03A65E8D1C6BB3030062603F /* FTS4Tests.swift in Sources */,
@@ -922,6 +928,7 @@
 				EE247B271C3F137700AE3E12 /* CustomFunctionsTests.swift in Sources */,
 				EE247B341C3F142E00AE3E12 /* StatementTests.swift in Sources */,
 				EE247B301C3F141E00AE3E12 /* RTreeTests.swift in Sources */,
+				3717F908221F5D8800B9BD3D /* CustomAggregationTests.swift in Sources */,
 				EE247B231C3F137700AE3E12 /* BlobTests.swift in Sources */,
 				EE247B351C3F142E00AE3E12 /* ValueTests.swift in Sources */,
 				EE247B2F1C3F141E00AE3E12 /* QueryTests.swift in Sources */,
@@ -980,6 +987,7 @@
 				EE247B5F1C3F3FC700AE3E12 /* StatementTests.swift in Sources */,
 				EE247B5C1C3F3FC700AE3E12 /* RTreeTests.swift in Sources */,
 				EE247B571C3F3FC700AE3E12 /* CustomFunctionsTests.swift in Sources */,
+				3717F909221F5D8900B9BD3D /* CustomAggregationTests.swift in Sources */,
 				EE247B601C3F3FC700AE3E12 /* ValueTests.swift in Sources */,
 				EE247B551C3F3FC700AE3E12 /* ConnectionTests.swift in Sources */,
 				EE247B611C3F3FC700AE3E12 /* TestHelpers.swift in Sources */,
diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 1bbf7f73..1fce790f 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -597,8 +597,114 @@ public final class Connection {
         if functions[function] == nil { self.functions[function] = [:] }
         functions[function]?[argc] = box
     }
+    
+    /// Creates or redefines a custom SQL aggregate.
+    ///
+    /// - Parameters:
+    ///
+    ///   - aggregate: The name of the aggregate to create or redefine.
+    ///
+    ///   - argumentCount: The number of arguments that the aggregate takes. If
+    ///     `nil`, the aggregate may take any number of arguments.
+    ///
+    ///     Default: `nil`
+    ///
+    ///   - deterministic: Whether or not the aggregate is deterministic (_i.e._
+    ///     the aggregate always returns the same result for a given input).
+    ///
+    ///     Default: `false`
+    ///
+    ///   - step: A block of code to run for each row of an aggregation group.
+    ///     The block is called with an array of raw SQL values mapped to the
+    ///     aggregate’s parameters, and an UnsafeMutablePointer to a state
+    ///     variable.
+    ///
+    ///   - final: A block of code to run after each row of an aggregation group
+    ///     is processed. The block is called with an UnsafeMutablePointer to a
+    ///     state variable, and should return a raw SQL value (or nil).
+    ///
+    ///   - state: A block of code to run to produce a fresh state variable for
+    ///     each aggregation group. The block should return an
+    ///     UnsafeMutablePointer to the fresh state variable.
+    public func createAggregation<T>(_ aggregate: String, argumentCount: UInt? = nil, deterministic: Bool = false, step: @escaping ([Binding?], UnsafeMutablePointer<T>) -> (), final: @escaping (UnsafeMutablePointer<T>) -> Binding?, state: @escaping () -> UnsafeMutablePointer<T>) {
+        let argc = argumentCount.map { Int($0) } ?? -1
+        let box : Aggregate = { (stepFlag: Int, context: OpaquePointer?, argc: Int32, argv: UnsafeMutablePointer<OpaquePointer?>?) in
+            let ptr = sqlite3_aggregate_context(context, 64)! // needs to be at least as large as uintptr_t; better way to do this?
+            let p = ptr.assumingMemoryBound(to: UnsafeMutableRawPointer.self)
+            if stepFlag > 0 {
+                let arguments: [Binding?] = (0..<Int(argc)).map { idx in
+                    let value = argv![idx]
+                    switch sqlite3_value_type(value) {
+                    case SQLITE_BLOB:
+                        return Blob(bytes: sqlite3_value_blob(value), length: Int(sqlite3_value_bytes(value)))
+                    case SQLITE_FLOAT:
+                        return sqlite3_value_double(value)
+                    case SQLITE_INTEGER:
+                        return sqlite3_value_int64(value)
+                    case SQLITE_NULL:
+                        return nil
+                    case SQLITE_TEXT:
+                        return String(cString: UnsafePointer(sqlite3_value_text(value)))
+                    case let type:
+                        fatalError("unsupported value type: \(type)")
+                    }
+                }
+                
+                if ptr.assumingMemoryBound(to: Int64.self).pointee == 0 {
+                    let v = state()
+                    p.pointee = UnsafeMutableRawPointer(mutating: v)
+                }
+                step(arguments, p.pointee.assumingMemoryBound(to: T.self))
+            } else {
+                let result = final(p.pointee.assumingMemoryBound(to: T.self))
+                if let result = result as? Blob {
+                    sqlite3_result_blob(context, result.bytes, Int32(result.bytes.count), nil)
+                } else if let result = result as? Double {
+                    sqlite3_result_double(context, result)
+                } else if let result = result as? Int64 {
+                    sqlite3_result_int64(context, result)
+                } else if let result = result as? String {
+                    sqlite3_result_text(context, result, Int32(result.count), SQLITE_TRANSIENT)
+                } else if result == nil {
+                    sqlite3_result_null(context)
+                } else {
+                    fatalError("unsupported result type: \(String(describing: result))")
+                }
+            }
+        }
+        
+        var flags = SQLITE_UTF8
+        #if !os(Linux)
+        if deterministic {
+            flags |= SQLITE_DETERMINISTIC
+        }
+        #endif
+        
+        sqlite3_create_function_v2(
+            handle,
+            aggregate,
+            Int32(argc),
+            flags,
+            unsafeBitCast(box, to: UnsafeMutableRawPointer.self),
+            nil,
+            { context, argc, value in
+                let function = unsafeBitCast(sqlite3_user_data(context), to: Aggregate.self)
+                function(1, context, argc, value)
+            },
+            { context in
+                let function = unsafeBitCast(sqlite3_user_data(context), to: Aggregate.self)
+                function(0, context, 0, nil)
+            },
+            nil
+        )
+        if aggregations[aggregate] == nil { self.aggregations[aggregate] = [:] }
+        aggregations[aggregate]?[argc] = box
+    }
+    
+    fileprivate typealias Aggregate = @convention(block) (Int, OpaquePointer?, Int32, UnsafeMutablePointer<OpaquePointer?>?) -> Void
     fileprivate typealias Function = @convention(block) (OpaquePointer?, Int32, UnsafeMutablePointer<OpaquePointer?>?) -> Void
     fileprivate var functions = [String: [Int: Function]]()
+    fileprivate var aggregations = [String: [Int: Aggregate]]()
 
     /// Defines a new collating sequence.
     ///
diff --git a/Tests/SQLiteTests/CustomAggregationTests.swift b/Tests/SQLiteTests/CustomAggregationTests.swift
new file mode 100644
index 00000000..56c3c011
--- /dev/null
+++ b/Tests/SQLiteTests/CustomAggregationTests.swift
@@ -0,0 +1,73 @@
+import XCTest
+import Foundation
+import Dispatch
+@testable import SQLite
+
+#if SQLITE_SWIFT_STANDALONE
+import sqlite3
+#elseif SQLITE_SWIFT_SQLCIPHER
+import SQLCipher
+#elseif os(Linux)
+import CSQLite
+#else
+import SQLite3
+#endif
+
+class CustomAggregationTests : SQLiteTestCase {
+    override func setUp() {
+        super.setUp()
+        CreateUsersTable()
+        try! InsertUser("Alice", age: 30, admin: true)
+        try! InsertUser("Bob", age: 25, admin: true)
+        try! InsertUser("Eve", age: 28, admin: false)
+    }
+    
+    func testCustomSum() {
+        let step = { (bindings: [Binding?], state: UnsafeMutablePointer<Int64>) in
+            if let v = bindings[0] as? Int64 {
+                state.pointee += v
+            }
+        }
+
+        let final = { (state: UnsafeMutablePointer<Int64>) -> Binding? in
+            let v = state.pointee
+            let p = UnsafeMutableBufferPointer(start: state, count: 1)
+            p.deallocate()
+            return v
+        }
+        let _ = db.createAggregation("mySUM", step: step, final: final) {
+            let v = UnsafeMutableBufferPointer<Int64>.allocate(capacity: 1)
+            v[0] = 0
+            return v.baseAddress!
+        }
+        let result = try! db.prepare("SELECT mySUM(age) AS s FROM users")
+        let i = result.columnNames.index(of: "s")!
+        for row in result {
+            let value = row[i] as? Int64
+            XCTAssertEqual(83, value)
+        }
+    }
+    
+    func testCustomSumGrouping() {
+        let step = { (bindings: [Binding?], state: UnsafeMutablePointer<Int64>) in
+            if let v = bindings[0] as? Int64 {
+                state.pointee += v
+            }
+        }
+        let final = { (state: UnsafeMutablePointer<Int64>) -> Binding? in
+            let v = state.pointee
+            let p = UnsafeMutableBufferPointer(start: state, count: 1)
+            p.deallocate()
+            return v
+        }
+        let _ = db.createAggregation("mySUM", step: step, final: final) {
+            let v = UnsafeMutableBufferPointer<Int64>.allocate(capacity: 1)
+            v[0] = 0
+            return v.baseAddress!
+        }
+        let result = try! db.prepare("SELECT mySUM(age) AS s FROM users GROUP BY admin ORDER BY s")
+        let i = result.columnNames.index(of: "s")!
+        let values = result.compactMap { $0[i] as? Int64 }
+        XCTAssertTrue(values.elementsEqual([28, 55]))
+    }
+}

From 1e6bfbf2c046606adc08c9ca2ee4d7bc17f7cb2a Mon Sep 17 00:00:00 2001
From: Gregory Todd Williams <greg@evilfunhouse.com>
Date: Thu, 21 Feb 2019 21:58:34 -0800
Subject: [PATCH 317/685] Added convenience overloads for
 Connection.createAggregation.

---
 Sources/SQLite/Core/Connection.swift          | 16 +++--
 Sources/SQLite/Typed/CustomFunctions.swift    | 65 +++++++++++++++++
 .../SQLiteTests/CustomAggregationTests.swift  | 71 +++++++++++++++++--
 3 files changed, 141 insertions(+), 11 deletions(-)

diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 1fce790f..349c18b6 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -626,7 +626,15 @@ public final class Connection {
     ///   - state: A block of code to run to produce a fresh state variable for
     ///     each aggregation group. The block should return an
     ///     UnsafeMutablePointer to the fresh state variable.
-    public func createAggregation<T>(_ aggregate: String, argumentCount: UInt? = nil, deterministic: Bool = false, step: @escaping ([Binding?], UnsafeMutablePointer<T>) -> (), final: @escaping (UnsafeMutablePointer<T>) -> Binding?, state: @escaping () -> UnsafeMutablePointer<T>) {
+    public func createAggregation<T>(
+        _ aggregate: String,
+        argumentCount: UInt? = nil,
+        deterministic: Bool = false,
+        step: @escaping ([Binding?], UnsafeMutablePointer<T>) -> (),
+        final: @escaping (UnsafeMutablePointer<T>) -> Binding?,
+        state: @escaping () -> UnsafeMutablePointer<T>) {
+        
+        
         let argc = argumentCount.map { Int($0) } ?? -1
         let box : Aggregate = { (stepFlag: Int, context: OpaquePointer?, argc: Int32, argv: UnsafeMutablePointer<OpaquePointer?>?) in
             let ptr = sqlite3_aggregate_context(context, 64)! // needs to be at least as large as uintptr_t; better way to do this?
@@ -690,17 +698,17 @@ public final class Connection {
             { context, argc, value in
                 let function = unsafeBitCast(sqlite3_user_data(context), to: Aggregate.self)
                 function(1, context, argc, value)
-            },
+        },
             { context in
                 let function = unsafeBitCast(sqlite3_user_data(context), to: Aggregate.self)
                 function(0, context, 0, nil)
-            },
+        },
             nil
         )
         if aggregations[aggregate] == nil { self.aggregations[aggregate] = [:] }
         aggregations[aggregate]?[argc] = box
     }
-    
+
     fileprivate typealias Aggregate = @convention(block) (Int, OpaquePointer?, Int32, UnsafeMutablePointer<OpaquePointer?>?) -> Void
     fileprivate typealias Function = @convention(block) (OpaquePointer?, Int32, UnsafeMutablePointer<OpaquePointer?>?) -> Void
     fileprivate var functions = [String: [Int: Function]]()
diff --git a/Sources/SQLite/Typed/CustomFunctions.swift b/Sources/SQLite/Typed/CustomFunctions.swift
index 2389901f..375a6b99 100644
--- a/Sources/SQLite/Typed/CustomFunctions.swift
+++ b/Sources/SQLite/Typed/CustomFunctions.swift
@@ -133,4 +133,69 @@ public extension Connection {
         }
     }
 
+    // MARK: -
+    
+    public func createAggregation<T: AnyObject>(
+        _ aggregate: String,
+        argumentCount: UInt? = nil,
+        deterministic: Bool = false,
+        initialValue: T,
+        reduce: @escaping (T, [Binding?]) -> T,
+        result: @escaping (T) -> Binding?
+        ) {
+        
+        let step: ([Binding?], UnsafeMutablePointer<UnsafeMutableRawPointer>) -> () = { (bindings, ptr) in
+            let p = ptr.pointee.assumingMemoryBound(to: T.self)
+            let current = Unmanaged<T>.fromOpaque(p).takeRetainedValue()
+            let next = reduce(current, bindings)
+            ptr.pointee = Unmanaged.passRetained(next).toOpaque()
+        }
+        
+        let final: (UnsafeMutablePointer<UnsafeMutableRawPointer>) -> Binding? = { (ptr) in
+            let p = ptr.pointee.assumingMemoryBound(to: T.self)
+            let obj = Unmanaged<T>.fromOpaque(p).takeRetainedValue()
+            let value = result(obj)
+            ptr.deallocate()
+            return value
+        }
+        
+        let state: () -> UnsafeMutablePointer<UnsafeMutableRawPointer> = {
+            let p = UnsafeMutablePointer<UnsafeMutableRawPointer>.allocate(capacity: 1)
+            p.pointee = Unmanaged.passRetained(initialValue).toOpaque()
+            return p
+        }
+        
+        createAggregation(aggregate, step: step, final: final, state: state)
+    }
+    
+    public func createAggregation<T>(
+        _ aggregate: String,
+        argumentCount: UInt? = nil,
+        deterministic: Bool = false,
+        initialValue: T,
+        reduce: @escaping (T, [Binding?]) -> T,
+        result: @escaping (T) -> Binding?
+        ) {
+        
+        let step: ([Binding?], UnsafeMutablePointer<T>) -> () = { (bindings, p) in
+            let current = p.pointee
+            let next = reduce(current, bindings)
+            p.pointee = next
+        }
+        
+        let final: (UnsafeMutablePointer<T>) -> Binding? = { (p) in
+            let v = result(p.pointee)
+            p.deallocate()
+            return v
+        }
+        
+        let state: () -> UnsafeMutablePointer<T> = {
+            let p = UnsafeMutablePointer<T>.allocate(capacity: 1)
+            p.pointee = initialValue
+            return p
+        }
+        
+        createAggregation(aggregate, step: step, final: final, state: state)
+    }
+
 }
diff --git a/Tests/SQLiteTests/CustomAggregationTests.swift b/Tests/SQLiteTests/CustomAggregationTests.swift
index 56c3c011..1035f67c 100644
--- a/Tests/SQLiteTests/CustomAggregationTests.swift
+++ b/Tests/SQLiteTests/CustomAggregationTests.swift
@@ -22,25 +22,25 @@ class CustomAggregationTests : SQLiteTestCase {
         try! InsertUser("Eve", age: 28, admin: false)
     }
     
-    func testCustomSum() {
+    func testUnsafeCustomSum() {
         let step = { (bindings: [Binding?], state: UnsafeMutablePointer<Int64>) in
             if let v = bindings[0] as? Int64 {
                 state.pointee += v
             }
         }
-
+        
         let final = { (state: UnsafeMutablePointer<Int64>) -> Binding? in
             let v = state.pointee
             let p = UnsafeMutableBufferPointer(start: state, count: 1)
             p.deallocate()
             return v
         }
-        let _ = db.createAggregation("mySUM", step: step, final: final) {
+        let _ = db.createAggregation("mySUM1", step: step, final: final) {
             let v = UnsafeMutableBufferPointer<Int64>.allocate(capacity: 1)
             v[0] = 0
             return v.baseAddress!
         }
-        let result = try! db.prepare("SELECT mySUM(age) AS s FROM users")
+        let result = try! db.prepare("SELECT mySUM1(age) AS s FROM users")
         let i = result.columnNames.index(of: "s")!
         for row in result {
             let value = row[i] as? Int64
@@ -48,7 +48,7 @@ class CustomAggregationTests : SQLiteTestCase {
         }
     }
     
-    func testCustomSumGrouping() {
+    func testUnsafeCustomSumGrouping() {
         let step = { (bindings: [Binding?], state: UnsafeMutablePointer<Int64>) in
             if let v = bindings[0] as? Int64 {
                 state.pointee += v
@@ -60,14 +60,71 @@ class CustomAggregationTests : SQLiteTestCase {
             p.deallocate()
             return v
         }
-        let _ = db.createAggregation("mySUM", step: step, final: final) {
+        let _ = db.createAggregation("mySUM2", step: step, final: final) {
             let v = UnsafeMutableBufferPointer<Int64>.allocate(capacity: 1)
             v[0] = 0
             return v.baseAddress!
         }
-        let result = try! db.prepare("SELECT mySUM(age) AS s FROM users GROUP BY admin ORDER BY s")
+        let result = try! db.prepare("SELECT mySUM2(age) AS s FROM users GROUP BY admin ORDER BY s")
         let i = result.columnNames.index(of: "s")!
         let values = result.compactMap { $0[i] as? Int64 }
         XCTAssertTrue(values.elementsEqual([28, 55]))
     }
+    
+    func testCustomSum() {
+        let reduce : (Int64, [Binding?]) -> Int64 = { (last, bindings) in
+            let v = (bindings[0] as? Int64) ?? 0
+            return last + v
+        }
+        let _ = db.createAggregation("myReduceSUM1", initialValue: Int64(2000), reduce: reduce, result: { $0 })
+        let result = try! db.prepare("SELECT myReduceSUM1(age) AS s FROM users")
+        let i = result.columnNames.index(of: "s")!
+        for row in result {
+            let value = row[i] as? Int64
+            XCTAssertEqual(2083, value)
+        }
+    }
+
+    func testCustomSumGrouping() {
+        let reduce : (Int64, [Binding?]) -> Int64 = { (last, bindings) in
+            let v = (bindings[0] as? Int64) ?? 0
+            return last + v
+        }
+        let _ = db.createAggregation("myReduceSUM2", initialValue: Int64(3000), reduce: reduce, result: { $0 })
+        let result = try! db.prepare("SELECT myReduceSUM2(age) AS s FROM users GROUP BY admin ORDER BY s")
+        let i = result.columnNames.index(of: "s")!
+        let values = result.compactMap { $0[i] as? Int64 }
+        XCTAssertTrue(values.elementsEqual([3028, 3055]))
+    }
+    
+    func testCustomObjectSum() {
+        {
+            let initial = TestObject(value: 1000)
+            let reduce : (TestObject, [Binding?]) -> TestObject = { (last, bindings) in
+                let v = (bindings[0] as? Int64) ?? 0
+                return TestObject(value: last.value + v)
+            }
+            let _ = db.createAggregation("myReduceSUMX", initialValue: initial, reduce: reduce, result: { $0.value })
+            // end this scope to ensure that the initial value is retained
+            // by the createAggregation call.
+        }()
+        let result = try! db.prepare("SELECT myReduceSUMX(age) AS s FROM users")
+        let i = result.columnNames.index(of: "s")!
+        for row in result {
+            let value = row[i] as? Int64
+            XCTAssertEqual(1083, value)
+        }
+    }
+}
+
+/// This class is used to test that aggregation state variables
+/// can be reference types and are properly memory managed when
+/// crossing the Swift<->C boundary multiple times.
+class TestObject {
+    var value: Int64
+    init(value: Int64) {
+        self.value = value
+    }
+    deinit {
+    }
 }

From b1d3a4036deddac396b46d725866192eb29df0ff Mon Sep 17 00:00:00 2001
From: Gregory Todd Williams <greg@evilfunhouse.com>
Date: Fri, 22 Feb 2019 08:25:08 -0800
Subject: [PATCH 318/685] Add extra test for custom aggregation.

---
 Tests/SQLiteTests/CustomAggregationTests.swift | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/Tests/SQLiteTests/CustomAggregationTests.swift b/Tests/SQLiteTests/CustomAggregationTests.swift
index 1035f67c..74a19df0 100644
--- a/Tests/SQLiteTests/CustomAggregationTests.swift
+++ b/Tests/SQLiteTests/CustomAggregationTests.swift
@@ -97,6 +97,21 @@ class CustomAggregationTests : SQLiteTestCase {
         XCTAssertTrue(values.elementsEqual([3028, 3055]))
     }
     
+    func testCustomStringAgg() {
+        let initial = String(repeating: " ", count: 64)
+        let reduce : (String, [Binding?]) -> String = { (last, bindings) in
+            let v = (bindings[0] as? String) ?? ""
+            return last + v
+        }
+        let _ = db.createAggregation("myReduceSUM3", initialValue: initial, reduce: reduce, result: { $0 })
+        let result = try! db.prepare("SELECT myReduceSUM3(email) AS s FROM users")
+        let i = result.columnNames.index(of: "s")!
+        for row in result {
+            let value = row[i] as? String
+            XCTAssertEqual("\(initial)Alice@example.comBob@example.comEve@example.com", value)
+        }
+    }
+    
     func testCustomObjectSum() {
         {
             let initial = TestObject(value: 1000)

From 4a28df38c187a428561c12ee9d0a3e3099ba336b Mon Sep 17 00:00:00 2001
From: Gregory Todd Williams <greg@evilfunhouse.com>
Date: Fri, 22 Feb 2019 09:05:24 -0800
Subject: [PATCH 319/685] Track retains/releases that occur during custom
 aggregation testing.

---
 .../SQLiteTests/CustomAggregationTests.swift  | 22 ++++++++++++++-----
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/Tests/SQLiteTests/CustomAggregationTests.swift b/Tests/SQLiteTests/CustomAggregationTests.swift
index 74a19df0..f8efc7e4 100644
--- a/Tests/SQLiteTests/CustomAggregationTests.swift
+++ b/Tests/SQLiteTests/CustomAggregationTests.swift
@@ -122,13 +122,18 @@ class CustomAggregationTests : SQLiteTestCase {
             let _ = db.createAggregation("myReduceSUMX", initialValue: initial, reduce: reduce, result: { $0.value })
             // end this scope to ensure that the initial value is retained
             // by the createAggregation call.
+        }();
+        {
+            XCTAssertEqual(TestObject.inits, 1)
+            let result = try! db.prepare("SELECT myReduceSUMX(age) AS s FROM users")
+            let i = result.columnNames.index(of: "s")!
+            for row in result {
+                let value = row[i] as? Int64
+                XCTAssertEqual(1083, value)
+            }
         }()
-        let result = try! db.prepare("SELECT myReduceSUMX(age) AS s FROM users")
-        let i = result.columnNames.index(of: "s")!
-        for row in result {
-            let value = row[i] as? Int64
-            XCTAssertEqual(1083, value)
-        }
+        XCTAssertEqual(TestObject.inits, 4)
+        XCTAssertEqual(TestObject.deinits, 3) // the initial value is still retained by the aggregate's state block, so deinits is one less than inits
     }
 }
 
@@ -136,10 +141,15 @@ class CustomAggregationTests : SQLiteTestCase {
 /// can be reference types and are properly memory managed when
 /// crossing the Swift<->C boundary multiple times.
 class TestObject {
+    static var inits = 0
+    static var deinits = 0
+    
     var value: Int64
     init(value: Int64) {
         self.value = value
+        TestObject.inits += 1
     }
     deinit {
+        TestObject.deinits += 1
     }
 }

From 0fa531d1118bf88e83ffb893d89b8898bfdd85b8 Mon Sep 17 00:00:00 2001
From: Andrew Finnell <andy@losingfight.com>
Date: Sun, 24 Feb 2019 13:54:35 -0500
Subject: [PATCH 320/685] Implement Upsert [#482]

# Problem

Apps need the ability to insert or, if the row already exists, update the existing row. This is commonly called "upsert" and is [documented for SQLite here](https://www.sqlite.org/lang_UPSERT.html). The existing "replace" on conflict clause for `insert()` often does not have the desired behavior. It will cascade (with deletes, if specified) along foreign keys if the value exists and has to be replaced ([see Issue 842](https://github.com/stephencelis/SQLite.swift/issues/842)).

# Solution

Create an `upsert()` method for queries. The basic form allows for the fallback setters to be manually specified. A slightly more ergonomic version will compute the setters from the inserted values by removing the "conflicting" column, and then using the inserted values via the "excluded" qualifier. Additionally, an `Encodable` version of `upsert` is provided.
---
 Documentation/Index.md             | 28 +++++++++++++++++++++
 Sources/SQLite/Typed/Coding.swift  | 23 ++++++++++++++++++
 Sources/SQLite/Typed/Query.swift   | 39 ++++++++++++++++++++++++++++++
 Sources/SQLite/Typed/Setter.swift  |  5 ++++
 Tests/SQLiteTests/QueryTests.swift | 35 ++++++++++++++++++++++++++-
 5 files changed, 129 insertions(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 628e7464..61c287d6 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -35,6 +35,7 @@
       - [Sorting Rows](#sorting-rows)
       - [Limiting and Paging Results](#limiting-and-paging-results)
       - [Aggregation](#aggregation)
+  - [Upserting Rows](#upserting-rows)
   - [Updating Rows](#updating-rows)
   - [Deleting Rows](#deleting-rows)
   - [Transactions and Savepoints](#transactions-and-savepoints)
@@ -1098,6 +1099,33 @@ let count = try db.scalar(users.filter(name != nil).count)
 > // SELECT count(DISTINCT "name") FROM "users"
 > ```
 
+## Upserting Rows
+
+We can upsert rows into a table by calling a [query’s](#queries) `upsert`
+function with a list of [setters](#setters)—typically [typed column
+expressions](#expressions) and values (which can also be expressions)—each
+joined by the `<-` operator. Upserting is like inserting, except if there is a 
+conflict on the specified column value, SQLite will perform an update on the row instead.
+
+```swift
+try db.run(users.upsert(email <- "alice@mac.com", name <- "Alice"), onConflictOf: email)
+// INSERT INTO "users" ("email", "name") VALUES ('alice@mac.com', 'Alice') ON CONFLICT (\"email\") DO UPDATE SET \"name\" = \"excluded\".\"name\"
+```
+
+The `upsert` function, when run successfully, returns an `Int64` representing
+the inserted row’s [`ROWID`][ROWID].
+
+```swift
+do {
+    let rowid = try db.run(users.upsert(email <- "alice@mac.com", name <- "Alice", onConflictOf: email))
+    print("inserted id: \(rowid)")
+} catch {
+    print("insertion failed: \(error)")
+}
+```
+
+The [`insert`](#inserting-rows), [`update`](#updating-rows), and [`delete`](#deleting-rows) functions
+follow similar patterns.
 
 ## Updating Rows
 
diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index c3fb931b..6ed8c987 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -45,6 +45,29 @@ extension QueryType {
         return self.insert(encoder.setters + otherSetters)
     }
 
+
+    /// Creates an `INSERT ON CONFLICT DO UPDATE` statement, aka upsert, by encoding the given object
+    /// This method converts any custom nested types to JSON data and does not handle any sort
+    /// of object relationships. If you want to support relationships between objects you will
+    /// have to provide your own Encodable implementations that encode the correct ids.
+    ///
+    /// - Parameters:
+    ///
+    ///   - encodable: An encodable object to insert
+    ///
+    ///   - userInfo: User info to be passed to encoder
+    ///
+    ///   - otherSetters: Any other setters to include in the insert
+    ///
+    ///   - onConflictOf: The column that if conflicts should trigger an update instead of insert.
+    ///
+    /// - Returns: An `INSERT` statement fort the encodable object
+    public func upsert(_ encodable: Encodable, userInfo: [CodingUserInfoKey:Any] = [:], otherSetters: [Setter] = [], onConflictOf conflicting: Expressible) throws -> Insert {
+        let encoder = SQLiteEncoder(userInfo: userInfo)
+        try encodable.encode(to: encoder)
+        return self.upsert(encoder.setters + otherSetters, onConflictOf: conflicting)
+    }
+
     /// Creates an `UPDATE` statement by encoding the given object
     /// This method converts any custom nested types to JSON data and does not handle any sort
     /// of object relationships. If you want to support relationships between objects you will
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index f6ef6df8..8793acae 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -672,6 +672,45 @@ extension QueryType {
             query.expression
         ]).expression)
     }
+    
+    // MARK: UPSERT
+    
+    public func upsert(_ insertValues: Setter..., onConflictOf conflicting: Expressible) -> Insert {
+        return upsert(insertValues, onConflictOf: conflicting)
+    }
+    
+    public func upsert(_ insertValues: [Setter], onConflictOf conflicting: Expressible) -> Insert {
+        let setValues = insertValues.filter { $0.column.asSQL() != conflicting.asSQL() }
+            .map { Setter(excluded: $0.column) }
+        return upsert(insertValues, onConflictOf: conflicting, set: setValues)
+    }
+    
+    public func upsert(_ insertValues: Setter..., onConflictOf conflicting: Expressible, set setValues: [Setter]) -> Insert {
+        return upsert(insertValues, onConflictOf: conflicting, set: setValues)
+    }
+    
+    public func upsert(_ insertValues: [Setter], onConflictOf conflicting: Expressible, set setValues: [Setter]) -> Insert {
+        let insert = insertValues.reduce((columns: [Expressible](), values: [Expressible]())) { insert, setter in
+            (insert.columns + [setter.column], insert.values + [setter.value])
+        }
+        
+        let clauses: [Expressible?] = [
+            Expression<Void>(literal: "INSERT"),
+            Expression<Void>(literal: "INTO"),
+            tableName(),
+            "".wrap(insert.columns) as Expression<Void>,
+            Expression<Void>(literal: "VALUES"),
+            "".wrap(insert.values) as Expression<Void>,
+            whereClause,
+            Expression<Void>(literal: "ON CONFLICT"),
+            "".wrap(conflicting) as Expression<Void>,
+            Expression<Void>(literal: "DO UPDATE SET"),
+            ", ".join(setValues.map { $0.expression })
+        ]
+        
+        return Insert(" ".join(clauses.compactMap { $0 }).expression)
+    }
+
 
     // MARK: UPDATE
 
diff --git a/Sources/SQLite/Typed/Setter.swift b/Sources/SQLite/Typed/Setter.swift
index 86f16fca..3d3170f6 100644
--- a/Sources/SQLite/Typed/Setter.swift
+++ b/Sources/SQLite/Typed/Setter.swift
@@ -60,6 +60,11 @@ public struct Setter {
         self.value = Expression<V?>(value: value)
     }
 
+    init(excluded column: Expressible) {
+        let excluded = Expression<Void>("excluded")
+        self.column = column
+        self.value = ".".join([excluded, column.expression])
+    }
 }
 
 extension Setter : Expressible {
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index 2a9e4ecb..694e7f26 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -270,6 +270,24 @@ class QueryTests : XCTestCase {
         )
     }
 
+    func test_upsert_withOnConflict_compilesInsertOrOnConflictExpression() {
+        AssertSQL(
+            "INSERT INTO \"users\" (\"email\", \"age\") VALUES ('alice@example.com', 30) ON CONFLICT (\"email\") DO UPDATE SET \"age\" = \"excluded\".\"age\"",
+            users.upsert(email <- "alice@example.com", age <- 30, onConflictOf: email)
+        )
+    }
+
+    func test_upsert_encodable() throws {
+        let emails = Table("emails")
+        let string = Expression<String>("string")
+        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil)
+        let insert = try emails.upsert(value, onConflictOf: string)
+        AssertSQL(
+            "INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\") VALUES (1, '2', 1, 3.0, 4.0) ON CONFLICT (\"string\") DO UPDATE SET \"int\" = \"excluded\".\"int\", \"bool\" = \"excluded\".\"bool\", \"float\" = \"excluded\".\"float\", \"double\" = \"excluded\".\"double\"",
+            insert
+        )
+    }
+
     func test_update_compilesUpdateExpression() {
         AssertSQL(
             "UPDATE \"users\" SET \"age\" = 30, \"admin\" = 1 WHERE (\"id\" = 1)",
@@ -378,7 +396,8 @@ class QueryIntegrationTests : SQLiteTestCase {
 
     let id = Expression<Int64>("id")
     let email = Expression<String>("email")
-
+    let age = Expression<Int>("age")
+    
     override func setUp() {
         super.setUp()
 
@@ -483,6 +502,20 @@ class QueryIntegrationTests : SQLiteTestCase {
         XCTAssertEqual(1, id)
     }
 
+    func test_upsert() throws {
+        let fetchAge = { () throws -> Int? in
+            return try self.db.pluck(self.users.filter(self.email == "alice@example.com")).flatMap { $0[self.age] }
+        }
+        
+        let id = try db.run(users.upsert(email <- "alice@example.com", age <- 30, onConflictOf: email))
+        XCTAssertEqual(1, id)
+        XCTAssertEqual(30, try fetchAge())
+        
+        let nextId = try db.run(users.upsert(email <- "alice@example.com", age <- 42, onConflictOf: email))
+        XCTAssertEqual(1, nextId)
+        XCTAssertEqual(42, try fetchAge())
+    }
+    
     func test_update() {
         let changes = try! db.run(users.update(email <- "alice@example.com"))
         XCTAssertEqual(0, changes)

From c96a5da4ef8c9ccec7bfac254b56ae17199097f3 Mon Sep 17 00:00:00 2001
From: Otto Suess <ottosuess@protonmail.com>
Date: Tue, 26 Mar 2019 12:53:22 +0100
Subject: [PATCH 321/685] fix xcode-10.2 issues

---
 Sources/SQLite/Helpers.swift                  |  12 -
 Sources/SQLite/Typed/AggregateFunctions.swift |  22 +-
 Sources/SQLite/Typed/CoreFunctions.swift      |  40 +--
 Sources/SQLite/Typed/Operators.swift          | 232 +++++++++---------
 4 files changed, 147 insertions(+), 159 deletions(-)

diff --git a/Sources/SQLite/Helpers.swift b/Sources/SQLite/Helpers.swift
index ac831667..115ea5c6 100644
--- a/Sources/SQLite/Helpers.swift
+++ b/Sources/SQLite/Helpers.swift
@@ -98,18 +98,6 @@ extension String {
 
 }
 
-func infix<T>(_ lhs: Expressible, _ rhs: Expressible, wrap: Bool = true, function: String = #function) -> Expression<T> {
-    return function.infix(lhs, rhs, wrap: wrap)
-}
-
-func wrap<T>(_ expression: Expressible, function: String = #function) -> Expression<T> {
-    return function.wrap(expression)
-}
-
-func wrap<T>(_ expressions: [Expressible], function: String = #function) -> Expression<T> {
-    return function.wrap(", ".join(expressions))
-}
-
 func transcode(_ literal: Binding?) -> String {
     guard let literal = literal else { return "NULL" }
 
diff --git a/Sources/SQLite/Typed/AggregateFunctions.swift b/Sources/SQLite/Typed/AggregateFunctions.swift
index 249bbe60..bb1157fe 100644
--- a/Sources/SQLite/Typed/AggregateFunctions.swift
+++ b/Sources/SQLite/Typed/AggregateFunctions.swift
@@ -48,7 +48,7 @@ extension ExpressionType where UnderlyingType : Value {
     /// - Returns: A copy of the expression wrapped with the `count` aggregate
     ///   function.
     public var count: Expression<Int> {
-        return wrap(self)
+        return "count".wrap(self)
     }
 
 }
@@ -79,7 +79,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
     /// - Returns: A copy of the expression wrapped with the `count` aggregate
     ///   function.
     public var count: Expression<Int> {
-        return wrap(self)
+        return "count".wrap(self)
     }
 
 }
@@ -96,7 +96,7 @@ extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype :
     /// - Returns: A copy of the expression wrapped with the `max` aggregate
     ///   function.
     public var max: Expression<UnderlyingType?> {
-        return wrap(self)
+        return "max".wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `min` aggregate
@@ -109,7 +109,7 @@ extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype :
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var min: Expression<UnderlyingType?> {
-        return wrap(self)
+        return "min".wrap(self)
     }
 
 }
@@ -126,7 +126,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
     /// - Returns: A copy of the expression wrapped with the `max` aggregate
     ///   function.
     public var max: Expression<UnderlyingType> {
-        return wrap(self)
+        return "max".wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `min` aggregate
@@ -139,7 +139,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var min: Expression<UnderlyingType> {
-        return wrap(self)
+        return "min".wrap(self)
     }
 
 }
@@ -169,7 +169,7 @@ extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype :
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var sum: Expression<UnderlyingType?> {
-        return wrap(self)
+        return "sum".wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `total` aggregate
@@ -182,7 +182,7 @@ extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype :
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var total: Expression<Double> {
-        return wrap(self)
+        return "total".wrap(self)
     }
 
 }
@@ -212,7 +212,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var sum: Expression<UnderlyingType> {
-        return wrap(self)
+        return "sum".wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `total` aggregate
@@ -225,7 +225,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var total: Expression<Double> {
-        return wrap(self)
+        return "total".wrap(self)
     }
 
 }
@@ -233,7 +233,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
 extension ExpressionType where UnderlyingType == Int {
 
     static func count(_ star: Star) -> Expression<UnderlyingType> {
-        return wrap(star(nil, nil))
+        return "count".wrap(star(nil, nil))
     }
 
 }
diff --git a/Sources/SQLite/Typed/CoreFunctions.swift b/Sources/SQLite/Typed/CoreFunctions.swift
index d7995b95..b7b53c71 100644
--- a/Sources/SQLite/Typed/CoreFunctions.swift
+++ b/Sources/SQLite/Typed/CoreFunctions.swift
@@ -68,9 +68,9 @@ extension ExpressionType where UnderlyingType == Double {
     /// - Returns: A copy of the expression wrapped with the `round` function.
     public func round(_ precision: Int? = nil) -> Expression<UnderlyingType> {
         guard let precision = precision else {
-            return wrap([self])
+            return "round".wrap([self])
         }
-        return wrap([self, Int(precision)])
+        return "round".wrap([self, Int(precision)])
     }
 
 }
@@ -88,9 +88,9 @@ extension ExpressionType where UnderlyingType == Double? {
     /// - Returns: A copy of the expression wrapped with the `round` function.
     public func round(_ precision: Int? = nil) -> Expression<UnderlyingType> {
         guard let precision = precision else {
-            return wrap(self)
+            return "round".wrap(self)
         }
-        return wrap([self, Int(precision)])
+        return "round".wrap([self, Int(precision)])
     }
 
 }
@@ -143,7 +143,7 @@ extension ExpressionType where UnderlyingType == Data {
     ///
     /// - Returns: A copy of the expression wrapped with the `length` function.
     public var length: Expression<Int> {
-        return wrap(self)
+        return "length".wrap(self)
     }
 
 }
@@ -158,7 +158,7 @@ extension ExpressionType where UnderlyingType == Data? {
     ///
     /// - Returns: A copy of the expression wrapped with the `length` function.
     public var length: Expression<Int?> {
-        return wrap(self)
+        return "length".wrap(self)
     }
 
 }
@@ -173,7 +173,7 @@ extension ExpressionType where UnderlyingType == String {
     ///
     /// - Returns: A copy of the expression wrapped with the `length` function.
     public var length: Expression<Int> {
-        return wrap(self)
+        return "length".wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `lower` function.
@@ -317,9 +317,9 @@ extension ExpressionType where UnderlyingType == String {
     /// - Returns: A copy of the expression wrapped with the `ltrim` function.
     public func ltrim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
-            return wrap(self)
+            return "ltrim".wrap(self)
         }
-        return wrap([self, String(characters)])
+        return "ltrim".wrap([self, String(characters)])
     }
 
     /// Builds a copy of the expression wrapped with the `rtrim` function.
@@ -335,9 +335,9 @@ extension ExpressionType where UnderlyingType == String {
     /// - Returns: A copy of the expression wrapped with the `rtrim` function.
     public func rtrim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
-            return wrap(self)
+            return "rtrim".wrap(self)
         }
-        return wrap([self, String(characters)])
+        return "rtrim".wrap([self, String(characters)])
     }
 
     /// Builds a copy of the expression wrapped with the `trim` function.
@@ -353,9 +353,9 @@ extension ExpressionType where UnderlyingType == String {
     /// - Returns: A copy of the expression wrapped with the `trim` function.
     public func trim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
-            return wrap([self])
+            return "trim".wrap([self])
         }
-        return wrap([self, String(characters)])
+        return "trim".wrap([self, String(characters)])
     }
 
     /// Builds a copy of the expression wrapped with the `replace` function.
@@ -398,7 +398,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression wrapped with the `length` function.
     public var length: Expression<Int?> {
-        return wrap(self)
+        return "length".wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `lower` function.
@@ -542,9 +542,9 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression wrapped with the `ltrim` function.
     public func ltrim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
-            return wrap(self)
+            return "ltrim".wrap(self)
         }
-        return wrap([self, String(characters)])
+        return "ltrim".wrap([self, String(characters)])
     }
 
     /// Builds a copy of the expression wrapped with the `rtrim` function.
@@ -560,9 +560,9 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression wrapped with the `rtrim` function.
     public func rtrim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
-            return wrap(self)
+            return "rtrim".wrap(self)
         }
-        return wrap([self, String(characters)])
+        return "rtrim".wrap([self, String(characters)])
     }
 
     /// Builds a copy of the expression wrapped with the `trim` function.
@@ -578,9 +578,9 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression wrapped with the `trim` function.
     public func trim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
-            return wrap(self)
+            return "trim".wrap(self)
         }
-        return wrap([self, String(characters)])
+        return "trim".wrap([self, String(characters)])
     }
 
     /// Builds a copy of the expression wrapped with the `replace` function.
diff --git a/Sources/SQLite/Typed/Operators.swift b/Sources/SQLite/Typed/Operators.swift
index d97e52b9..5f8be14b 100644
--- a/Sources/SQLite/Typed/Operators.swift
+++ b/Sources/SQLite/Typed/Operators.swift
@@ -53,237 +53,237 @@ public func +(lhs: String, rhs: Expression<String?>) -> Expression<String?> {
 // MARK: -
 
 public func +<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "+".infix(lhs, rhs)
 }
 public func +<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "+".infix(lhs, rhs)
 }
 public func +<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "+".infix(lhs, rhs)
 }
 public func +<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "+".infix(lhs, rhs)
 }
 public func +<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "+".infix(lhs, rhs)
 }
 public func +<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "+".infix(lhs, rhs)
 }
 public func +<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "+".infix(lhs, rhs)
 }
 public func +<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "+".infix(lhs, rhs)
 }
 
 public func -<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "-".infix(lhs, rhs)
 }
 public func -<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "-".infix(lhs, rhs)
 }
 public func -<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "-".infix(lhs, rhs)
 }
 public func -<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "-".infix(lhs, rhs)
 }
 public func -<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "-".infix(lhs, rhs)
 }
 public func -<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "-".infix(lhs, rhs)
 }
 public func -<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "-".infix(lhs, rhs)
 }
 public func -<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "-".infix(lhs, rhs)
 }
 
 public func *<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "*".infix(lhs, rhs)
 }
 public func *<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "*".infix(lhs, rhs)
 }
 public func *<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "*".infix(lhs, rhs)
 }
 public func *<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "*".infix(lhs, rhs)
 }
 public func *<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "*".infix(lhs, rhs)
 }
 public func *<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "*".infix(lhs, rhs)
 }
 public func *<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "*".infix(lhs, rhs)
 }
 public func *<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "*".infix(lhs, rhs)
 }
 
 public func /<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "/".infix(lhs, rhs)
 }
 public func /<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "/".infix(lhs, rhs)
 }
 public func /<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "/".infix(lhs, rhs)
 }
 public func /<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "/".infix(lhs, rhs)
 }
 public func /<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "/".infix(lhs, rhs)
 }
 public func /<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "/".infix(lhs, rhs)
 }
 public func /<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "/".infix(lhs, rhs)
 }
 public func /<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return infix(lhs, rhs)
+    return "/".infix(lhs, rhs)
 }
 
 public prefix func -<V : Value>(rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return wrap(rhs)
+    return "-".wrap(rhs)
 }
 public prefix func -<V : Value>(rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return wrap(rhs)
+    return "-".wrap(rhs)
 }
 
 // MARK: -
 
 public func %<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "%".infix(lhs, rhs)
 }
 public func %<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "%".infix(lhs, rhs)
 }
 public func %<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "%".infix(lhs, rhs)
 }
 public func %<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "%".infix(lhs, rhs)
 }
 public func %<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "%".infix(lhs, rhs)
 }
 public func %<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "%".infix(lhs, rhs)
 }
 public func %<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "%".infix(lhs, rhs)
 }
 public func %<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "%".infix(lhs, rhs)
 }
 
 public func <<<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "<<".infix(lhs, rhs)
 }
 public func <<<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "<<".infix(lhs, rhs)
 }
 public func <<<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "<<".infix(lhs, rhs)
 }
 public func <<<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "<<".infix(lhs, rhs)
 }
 public func <<<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "<<".infix(lhs, rhs)
 }
 public func <<<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "<<".infix(lhs, rhs)
 }
 public func <<<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "<<".infix(lhs, rhs)
 }
 public func <<<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "<<".infix(lhs, rhs)
 }
 
 public func >><V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return ">>".infix(lhs, rhs)
 }
 public func >><V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return ">>".infix(lhs, rhs)
 }
 public func >><V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return ">>".infix(lhs, rhs)
 }
 public func >><V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return ">>".infix(lhs, rhs)
 }
 public func >><V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return ">>".infix(lhs, rhs)
 }
 public func >><V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return ">>".infix(lhs, rhs)
 }
 public func >><V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return ">>".infix(lhs, rhs)
 }
 public func >><V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return ">>".infix(lhs, rhs)
 }
 
 public func &<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "&".infix(lhs, rhs)
 }
 public func &<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "&".infix(lhs, rhs)
 }
 public func &<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "&".infix(lhs, rhs)
 }
 public func &<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "&".infix(lhs, rhs)
 }
 public func &<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "&".infix(lhs, rhs)
 }
 public func &<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "&".infix(lhs, rhs)
 }
 public func &<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "&".infix(lhs, rhs)
 }
 public func &<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "&".infix(lhs, rhs)
 }
 
 public func |<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "|".infix(lhs, rhs)
 }
 public func |<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "|".infix(lhs, rhs)
 }
 public func |<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "|".infix(lhs, rhs)
 }
 public func |<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "|".infix(lhs, rhs)
 }
 public func |<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "|".infix(lhs, rhs)
 }
 public func |<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "|".infix(lhs, rhs)
 }
 public func |<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "|".infix(lhs, rhs)
 }
 public func |<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return infix(lhs, rhs)
+    return "|".infix(lhs, rhs)
 }
 
 public func ^<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
@@ -312,10 +312,10 @@ public func ^<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.
 }
 
 public prefix func ~<V : Value>(rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return wrap(rhs)
+    return "~".wrap(rhs)
 }
 public prefix func ~<V : Value>(rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return wrap(rhs)
+    return "~".wrap(rhs)
 }
 
 // MARK: -
@@ -348,130 +348,130 @@ public func ==<V : Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> whe
 }
 
 public func !=<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
-    return infix(lhs, rhs)
+    return "!=".infix(lhs, rhs)
 }
 public func !=<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
-    return infix(lhs, rhs)
+    return "!=".infix(lhs, rhs)
 }
 public func !=<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Equatable {
-    return infix(lhs, rhs)
+    return "!=".infix(lhs, rhs)
 }
 public func !=<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
-    return infix(lhs, rhs)
+    return "!=".infix(lhs, rhs)
 }
 public func !=<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Equatable {
-    return infix(lhs, rhs)
+    return "!=".infix(lhs, rhs)
 }
 public func !=<V : Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype : Equatable {
     guard let rhs = rhs else { return "IS NOT".infix(lhs, Expression<V?>(value: nil)) }
-    return infix(lhs, rhs)
+    return "!=".infix(lhs, rhs)
 }
 public func !=<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
-    return infix(lhs, rhs)
+    return "!=".infix(lhs, rhs)
 }
 public func !=<V : Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
     guard let lhs = lhs else { return "IS NOT".infix(Expression<V?>(value: nil), rhs) }
-    return infix(lhs, rhs)
+    return "!=".infix(lhs, rhs)
 }
 
 public func ><V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return ">".infix(lhs, rhs)
 }
 public func ><V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return ">".infix(lhs, rhs)
 }
 public func ><V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return ">".infix(lhs, rhs)
 }
 public func ><V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return ">".infix(lhs, rhs)
 }
 public func ><V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return ">".infix(lhs, rhs)
 }
 public func ><V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return ">".infix(lhs, rhs)
 }
 public func ><V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return ">".infix(lhs, rhs)
 }
 public func ><V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return ">".infix(lhs, rhs)
 }
 
 public func >=<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return ">=".infix(lhs, rhs)
 }
 public func >=<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return ">=".infix(lhs, rhs)
 }
 public func >=<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return ">=".infix(lhs, rhs)
 }
 public func >=<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return ">=".infix(lhs, rhs)
 }
 public func >=<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return ">=".infix(lhs, rhs)
 }
 public func >=<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return ">=".infix(lhs, rhs)
 }
 public func >=<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return ">=".infix(lhs, rhs)
 }
 public func >=<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return ">=".infix(lhs, rhs)
 }
 
 public func <<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return "<".infix(lhs, rhs)
 }
 public func <<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return "<".infix(lhs, rhs)
 }
 public func <<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return "<".infix(lhs, rhs)
 }
 public func <<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return "<".infix(lhs, rhs)
 }
 public func <<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return "<".infix(lhs, rhs)
 }
 public func <<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return "<".infix(lhs, rhs)
 }
 public func <<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return "<".infix(lhs, rhs)
 }
 public func <<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return "<".infix(lhs, rhs)
 }
 
 public func <=<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return "<=".infix(lhs, rhs)
 }
 public func <=<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return "<=".infix(lhs, rhs)
 }
 public func <=<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return "<=".infix(lhs, rhs)
 }
 public func <=<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return "<=".infix(lhs, rhs)
 }
 public func <=<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return "<=".infix(lhs, rhs)
 }
 public func <=<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return "<=".infix(lhs, rhs)
 }
 public func <=<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return "<=".infix(lhs, rhs)
 }
 public func <=<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return infix(lhs, rhs)
+    return "<=".infix(lhs, rhs)
 }
 
 public func ~=<V : Value>(lhs: ClosedRange<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable & Value {

From c5be72bac4a022448b92d75a8970e41c6254b21f Mon Sep 17 00:00:00 2001
From: Yehor Popovych <yehor@crossroad.io>
Date: Tue, 26 Mar 2019 17:54:28 +0200
Subject: [PATCH 322/685] Strings to enum constants

---
 Sources/SQLite/Typed/AggregateFunctions.swift |  39 ++-
 Sources/SQLite/Typed/CoreFunctions.swift      | 140 +++++---
 Sources/SQLite/Typed/Operators.swift          | 331 ++++++++++--------
 3 files changed, 294 insertions(+), 216 deletions(-)

diff --git a/Sources/SQLite/Typed/AggregateFunctions.swift b/Sources/SQLite/Typed/AggregateFunctions.swift
index bb1157fe..056d617e 100644
--- a/Sources/SQLite/Typed/AggregateFunctions.swift
+++ b/Sources/SQLite/Typed/AggregateFunctions.swift
@@ -22,6 +22,19 @@
 // THE SOFTWARE.
 //
 
+private enum Functions: String {
+    case count
+    case max
+    case min
+    case avg
+    case sum
+    case total
+    
+    func wrap<T>(_ expression: Expressible) -> Expression<T> {
+        return self.rawValue.wrap(expression)
+    }
+}
+
 extension ExpressionType where UnderlyingType : Value {
 
     /// Builds a copy of the expression prefixed with the `DISTINCT` keyword.
@@ -48,7 +61,7 @@ extension ExpressionType where UnderlyingType : Value {
     /// - Returns: A copy of the expression wrapped with the `count` aggregate
     ///   function.
     public var count: Expression<Int> {
-        return "count".wrap(self)
+        return Functions.count.wrap(self)
     }
 
 }
@@ -79,7 +92,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
     /// - Returns: A copy of the expression wrapped with the `count` aggregate
     ///   function.
     public var count: Expression<Int> {
-        return "count".wrap(self)
+        return Functions.count.wrap(self)
     }
 
 }
@@ -96,7 +109,7 @@ extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype :
     /// - Returns: A copy of the expression wrapped with the `max` aggregate
     ///   function.
     public var max: Expression<UnderlyingType?> {
-        return "max".wrap(self)
+        return Functions.max.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `min` aggregate
@@ -109,7 +122,7 @@ extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype :
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var min: Expression<UnderlyingType?> {
-        return "min".wrap(self)
+        return Functions.min.wrap(self)
     }
 
 }
@@ -126,7 +139,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
     /// - Returns: A copy of the expression wrapped with the `max` aggregate
     ///   function.
     public var max: Expression<UnderlyingType> {
-        return "max".wrap(self)
+        return Functions.max.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `min` aggregate
@@ -139,7 +152,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var min: Expression<UnderlyingType> {
-        return "min".wrap(self)
+        return Functions.min.wrap(self)
     }
 
 }
@@ -156,7 +169,7 @@ extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype :
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var average: Expression<Double?> {
-        return "avg".wrap(self)
+        return Functions.avg.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `sum` aggregate
@@ -169,7 +182,7 @@ extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype :
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var sum: Expression<UnderlyingType?> {
-        return "sum".wrap(self)
+        return Functions.sum.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `total` aggregate
@@ -182,7 +195,7 @@ extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype :
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var total: Expression<Double> {
-        return "total".wrap(self)
+        return Functions.total.wrap(self)
     }
 
 }
@@ -199,7 +212,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var average: Expression<Double?> {
-        return "avg".wrap(self)
+        return Functions.avg.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `sum` aggregate
@@ -212,7 +225,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var sum: Expression<UnderlyingType> {
-        return "sum".wrap(self)
+        return Functions.sum.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `total` aggregate
@@ -225,7 +238,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var total: Expression<Double> {
-        return "total".wrap(self)
+        return Functions.total.wrap(self)
     }
 
 }
@@ -233,7 +246,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
 extension ExpressionType where UnderlyingType == Int {
 
     static func count(_ star: Star) -> Expression<UnderlyingType> {
-        return "count".wrap(star(nil, nil))
+        return Functions.count.wrap(star(nil, nil))
     }
 
 }
diff --git a/Sources/SQLite/Typed/CoreFunctions.swift b/Sources/SQLite/Typed/CoreFunctions.swift
index b7b53c71..420110ae 100644
--- a/Sources/SQLite/Typed/CoreFunctions.swift
+++ b/Sources/SQLite/Typed/CoreFunctions.swift
@@ -24,6 +24,40 @@
 
 import Foundation
 
+private enum Functions: String {
+    case abs
+    case round
+    case random
+    case randomblob
+    case zeroblob
+    case length
+    case lower
+    case upper
+    case ltrim
+    case rtrim
+    case trim
+    case replace
+    case substr
+    case LIKE
+    case IN
+    case GLOB
+    case MATCH
+    case REGEXP
+    case COLLATE
+    case ifnull
+    
+    func infix<T>(_ lhs: Expressible, _ rhs: Expressible, wrap: Bool = true) -> Expression<T> {
+        return self.rawValue.infix(lhs, rhs, wrap: wrap)
+    }
+    
+    func wrap<T>(_ expression: Expressible) -> Expression<T> {
+        return self.rawValue.wrap(expression)
+    }
+    
+    func wrap<T>(_ expressions: [Expressible]) -> Expression<T> {
+        return self.rawValue.wrap(", ".join(expressions))
+    }
+}
 
 extension ExpressionType where UnderlyingType : Number {
 
@@ -35,7 +69,7 @@ extension ExpressionType where UnderlyingType : Number {
     ///
     /// - Returns: A copy of the expression wrapped with the `abs` function.
     public var absoluteValue : Expression<UnderlyingType> {
-        return "abs".wrap(self)
+        return Functions.abs.wrap(self)
     }
 
 }
@@ -50,7 +84,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
     ///
     /// - Returns: A copy of the expression wrapped with the `abs` function.
     public var absoluteValue : Expression<UnderlyingType> {
-        return "abs".wrap(self)
+        return Functions.abs.wrap(self)
     }
 
 }
@@ -68,9 +102,9 @@ extension ExpressionType where UnderlyingType == Double {
     /// - Returns: A copy of the expression wrapped with the `round` function.
     public func round(_ precision: Int? = nil) -> Expression<UnderlyingType> {
         guard let precision = precision else {
-            return "round".wrap([self])
+            return Functions.round.wrap([self])
         }
-        return "round".wrap([self, Int(precision)])
+        return Functions.round.wrap([self, Int(precision)])
     }
 
 }
@@ -88,9 +122,9 @@ extension ExpressionType where UnderlyingType == Double? {
     /// - Returns: A copy of the expression wrapped with the `round` function.
     public func round(_ precision: Int? = nil) -> Expression<UnderlyingType> {
         guard let precision = precision else {
-            return "round".wrap(self)
+            return Functions.round.wrap(self)
         }
-        return "round".wrap([self, Int(precision)])
+        return Functions.round.wrap([self, Int(precision)])
     }
 
 }
@@ -104,7 +138,7 @@ extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype =
     ///
     /// - Returns: An expression calling the `random` function.
     public static func random() -> Expression<UnderlyingType> {
-        return "random".wrap([])
+        return Functions.random.wrap([])
     }
 
 }
@@ -120,7 +154,7 @@ extension ExpressionType where UnderlyingType == Data {
     ///
     /// - Returns: An expression calling the `randomblob` function.
     public static func random(_ length: Int) -> Expression<UnderlyingType> {
-        return "randomblob".wrap([])
+        return Functions.randomblob.wrap([])
     }
 
     /// Builds an expression representing the `zeroblob` function.
@@ -132,7 +166,7 @@ extension ExpressionType where UnderlyingType == Data {
     ///
     /// - Returns: An expression calling the `zeroblob` function.
     public static func allZeros(_ length: Int) -> Expression<UnderlyingType> {
-        return "zeroblob".wrap([])
+        return Functions.zeroblob.wrap([])
     }
 
     /// Builds a copy of the expression wrapped with the `length` function.
@@ -143,7 +177,7 @@ extension ExpressionType where UnderlyingType == Data {
     ///
     /// - Returns: A copy of the expression wrapped with the `length` function.
     public var length: Expression<Int> {
-        return "length".wrap(self)
+        return Functions.length.wrap(self)
     }
 
 }
@@ -158,7 +192,7 @@ extension ExpressionType where UnderlyingType == Data? {
     ///
     /// - Returns: A copy of the expression wrapped with the `length` function.
     public var length: Expression<Int?> {
-        return "length".wrap(self)
+        return Functions.length.wrap(self)
     }
 
 }
@@ -173,7 +207,7 @@ extension ExpressionType where UnderlyingType == String {
     ///
     /// - Returns: A copy of the expression wrapped with the `length` function.
     public var length: Expression<Int> {
-        return "length".wrap(self)
+        return Functions.length.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `lower` function.
@@ -184,7 +218,7 @@ extension ExpressionType where UnderlyingType == String {
     ///
     /// - Returns: A copy of the expression wrapped with the `lower` function.
     public var lowercaseString: Expression<UnderlyingType> {
-        return "lower".wrap(self)
+        return Functions.lower.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `upper` function.
@@ -195,7 +229,7 @@ extension ExpressionType where UnderlyingType == String {
     ///
     /// - Returns: A copy of the expression wrapped with the `upper` function.
     public var uppercaseString: Expression<UnderlyingType> {
-        return "upper".wrap(self)
+        return Functions.upper.wrap(self)
     }
 
     /// Builds a copy of the expression appended with a `LIKE` query against the
@@ -242,9 +276,9 @@ extension ExpressionType where UnderlyingType == String {
     ///   the given pattern.
     public func like(_ pattern: Expression<String>, escape character: Character? = nil) -> Expression<Bool> {
         guard let character = character else {
-            return "LIKE".infix(self, pattern)
+            return Functions.LIKE.infix(self, pattern)
         }
-        let like: Expression<Bool> = "LIKE".infix(self, pattern, wrap: false)
+        let like: Expression<Bool> =  Functions.LIKE.infix(self, pattern, wrap: false)
         return Expression("(\(like.template) ESCAPE ?)", like.bindings + [String(character)])
     }
 
@@ -260,7 +294,7 @@ extension ExpressionType where UnderlyingType == String {
     /// - Returns: A copy of the expression appended with a `GLOB` query against
     ///   the given pattern.
     public func glob(_ pattern: String) -> Expression<Bool> {
-        return "GLOB".infix(self, pattern)
+        return Functions.GLOB.infix(self, pattern)
     }
 
     /// Builds a copy of the expression appended with a `MATCH` query against
@@ -275,7 +309,7 @@ extension ExpressionType where UnderlyingType == String {
     /// - Returns: A copy of the expression appended with a `MATCH` query
     ///   against the given pattern.
     public func match(_ pattern: String) -> Expression<Bool> {
-        return "MATCH".infix(self, pattern)
+        return Functions.MATCH.infix(self, pattern)
     }
 
     /// Builds a copy of the expression appended with a `REGEXP` query against
@@ -286,7 +320,7 @@ extension ExpressionType where UnderlyingType == String {
     /// - Returns: A copy of the expression appended with a `REGEXP` query
     ///   against the given pattern.
     public func regexp(_ pattern: String) -> Expression<Bool> {
-        return "REGEXP".infix(self, pattern)
+        return Functions.REGEXP.infix(self, pattern)
     }
 
     /// Builds a copy of the expression appended with a `COLLATE` clause with
@@ -301,7 +335,7 @@ extension ExpressionType where UnderlyingType == String {
     /// - Returns: A copy of the expression appended with a `COLLATE` clause
     ///   with the given sequence.
     public func collate(_ collation: Collation) -> Expression<UnderlyingType> {
-        return "COLLATE".infix(self, collation)
+        return Functions.COLLATE.infix(self, collation)
     }
 
     /// Builds a copy of the expression wrapped with the `ltrim` function.
@@ -317,9 +351,9 @@ extension ExpressionType where UnderlyingType == String {
     /// - Returns: A copy of the expression wrapped with the `ltrim` function.
     public func ltrim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
-            return "ltrim".wrap(self)
+            return Functions.ltrim.wrap(self)
         }
-        return "ltrim".wrap([self, String(characters)])
+        return Functions.ltrim.wrap([self, String(characters)])
     }
 
     /// Builds a copy of the expression wrapped with the `rtrim` function.
@@ -335,9 +369,9 @@ extension ExpressionType where UnderlyingType == String {
     /// - Returns: A copy of the expression wrapped with the `rtrim` function.
     public func rtrim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
-            return "rtrim".wrap(self)
+            return Functions.rtrim.wrap(self)
         }
-        return "rtrim".wrap([self, String(characters)])
+        return Functions.rtrim.wrap([self, String(characters)])
     }
 
     /// Builds a copy of the expression wrapped with the `trim` function.
@@ -353,9 +387,9 @@ extension ExpressionType where UnderlyingType == String {
     /// - Returns: A copy of the expression wrapped with the `trim` function.
     public func trim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
-            return "trim".wrap([self])
+            return Functions.trim.wrap([self])
         }
-        return "trim".wrap([self, String(characters)])
+        return Functions.trim.wrap([self, String(characters)])
     }
 
     /// Builds a copy of the expression wrapped with the `replace` function.
@@ -372,14 +406,14 @@ extension ExpressionType where UnderlyingType == String {
     ///
     /// - Returns: A copy of the expression wrapped with the `replace` function.
     public func replace(_ pattern: String, with replacement: String) -> Expression<UnderlyingType> {
-        return "replace".wrap([self, pattern, replacement])
+        return Functions.replace.wrap([self, pattern, replacement])
     }
 
     public func substring(_ location: Int, length: Int? = nil) -> Expression<UnderlyingType> {
         guard let length = length else {
-            return "substr".wrap([self, location])
+            return Functions.substr.wrap([self, location])
         }
-        return "substr".wrap([self, location, length])
+        return Functions.substr.wrap([self, location, length])
     }
 
     public subscript(range: Range<Int>) -> Expression<UnderlyingType> {
@@ -398,7 +432,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression wrapped with the `length` function.
     public var length: Expression<Int?> {
-        return "length".wrap(self)
+        return Functions.length.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `lower` function.
@@ -409,7 +443,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression wrapped with the `lower` function.
     public var lowercaseString: Expression<UnderlyingType> {
-        return "lower".wrap(self)
+        return Functions.lower.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `upper` function.
@@ -420,7 +454,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression wrapped with the `upper` function.
     public var uppercaseString: Expression<UnderlyingType> {
-        return "upper".wrap(self)
+        return Functions.upper.wrap(self)
     }
 
     /// Builds a copy of the expression appended with a `LIKE` query against the
@@ -443,7 +477,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///   the given pattern.
     public func like(_ pattern: String, escape character: Character? = nil) -> Expression<Bool?> {
         guard let character = character else {
-            return "LIKE".infix(self, pattern)
+            return Functions.LIKE.infix(self, pattern)
         }
         return Expression("(\(template) LIKE ? ESCAPE ?)", bindings + [pattern, String(character)])
     }
@@ -467,7 +501,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///   the given pattern.
     public func like(_ pattern: Expression<String>, escape character: Character? = nil) -> Expression<Bool?> {
         guard let character = character else {
-            return "LIKE".infix(self, pattern)
+            return Functions.LIKE.infix(self, pattern)
         }
         let like: Expression<Bool> = "LIKE".infix(self, pattern, wrap: false)
         return Expression("(\(like.template) ESCAPE ?)", like.bindings + [String(character)])
@@ -485,7 +519,7 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression appended with a `GLOB` query against
     ///   the given pattern.
     public func glob(_ pattern: String) -> Expression<Bool?> {
-        return "GLOB".infix(self, pattern)
+        return Functions.GLOB.infix(self, pattern)
     }
 
     /// Builds a copy of the expression appended with a `MATCH` query against
@@ -500,7 +534,7 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression appended with a `MATCH` query
     ///   against the given pattern.
     public func match(_ pattern: String) -> Expression<Bool> {
-        return "MATCH".infix(self, pattern)
+        return Functions.MATCH.infix(self, pattern)
     }
 
     /// Builds a copy of the expression appended with a `REGEXP` query against
@@ -511,7 +545,7 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression appended with a `REGEXP` query
     ///   against the given pattern.
     public func regexp(_ pattern: String) -> Expression<Bool?> {
-        return "REGEXP".infix(self, pattern)
+        return Functions.REGEXP.infix(self, pattern)
     }
 
     /// Builds a copy of the expression appended with a `COLLATE` clause with
@@ -526,7 +560,7 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression appended with a `COLLATE` clause
     ///   with the given sequence.
     public func collate(_ collation: Collation) -> Expression<UnderlyingType> {
-        return "COLLATE".infix(self, collation)
+        return Functions.COLLATE.infix(self, collation)
     }
 
     /// Builds a copy of the expression wrapped with the `ltrim` function.
@@ -542,9 +576,9 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression wrapped with the `ltrim` function.
     public func ltrim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
-            return "ltrim".wrap(self)
+            return Functions.ltrim.wrap(self)
         }
-        return "ltrim".wrap([self, String(characters)])
+        return Functions.ltrim.wrap([self, String(characters)])
     }
 
     /// Builds a copy of the expression wrapped with the `rtrim` function.
@@ -560,9 +594,9 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression wrapped with the `rtrim` function.
     public func rtrim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
-            return "rtrim".wrap(self)
+            return Functions.rtrim.wrap(self)
         }
-        return "rtrim".wrap([self, String(characters)])
+        return Functions.rtrim.wrap([self, String(characters)])
     }
 
     /// Builds a copy of the expression wrapped with the `trim` function.
@@ -578,9 +612,9 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression wrapped with the `trim` function.
     public func trim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
-            return "trim".wrap(self)
+            return Functions.trim.wrap(self)
         }
-        return "trim".wrap([self, String(characters)])
+        return Functions.trim.wrap([self, String(characters)])
     }
 
     /// Builds a copy of the expression wrapped with the `replace` function.
@@ -597,7 +631,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression wrapped with the `replace` function.
     public func replace(_ pattern: String, with replacement: String) -> Expression<UnderlyingType> {
-        return "replace".wrap([self, pattern, replacement])
+        return Functions.replace.wrap([self, pattern, replacement])
     }
 
     /// Builds a copy of the expression wrapped with the `substr` function.
@@ -617,9 +651,9 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression wrapped with the `substr` function.
     public func substring(_ location: Int, length: Int? = nil) -> Expression<UnderlyingType> {
         guard let length = length else {
-            return "substr".wrap([self, location])
+            return Functions.substr.wrap([self, location])
         }
-        return "substr".wrap([self, location, length])
+        return Functions.substr.wrap([self, location, length])
     }
 
     /// Builds a copy of the expression wrapped with the `substr` function.
@@ -652,7 +686,7 @@ extension Collection where Iterator.Element : Value {
     ///   the collection.
     public func contains(_ expression: Expression<Iterator.Element>) -> Expression<Bool> {
         let templates = [String](repeating: "?", count: count).joined(separator: ", ")
-        return "IN".infix(expression, Expression<Void>("(\(templates))", map { $0.datatypeValue }))
+        return Functions.IN.infix(expression, Expression<Void>("(\(templates))", map { $0.datatypeValue }))
     }
 
     /// Builds a copy of the expression prepended with an `IN` check against the
@@ -668,7 +702,7 @@ extension Collection where Iterator.Element : Value {
     ///   the collection.
     public func contains(_ expression: Expression<Iterator.Element?>) -> Expression<Bool?> {
         let templates = [String](repeating: "?", count: count).joined(separator: ", ")
-        return "IN".infix(expression, Expression<Void>("(\(templates))", map { $0.datatypeValue }))
+        return Functions.IN.infix(expression, Expression<Void>("(\(templates))", map { $0.datatypeValue }))
     }
 
 }
@@ -694,7 +728,7 @@ extension String {
     ///   the given pattern.
     public func like(_ pattern: Expression<String>, escape character: Character? = nil) -> Expression<Bool> {
         guard let character = character else {
-            return "LIKE".infix(self, pattern)
+            return Functions.LIKE.infix(self, pattern)
         }
         let like: Expression<Bool> = "LIKE".infix(self, pattern, wrap: false)
         return Expression("(\(like.template) ESCAPE ?)", like.bindings + [String(character)])
@@ -718,7 +752,7 @@ extension String {
 /// - Returns: A copy of the given expressions wrapped with the `ifnull`
 ///   function.
 public func ??<V : Value>(optional: Expression<V?>, defaultValue: V) -> Expression<V> {
-    return "ifnull".wrap([optional, defaultValue])
+    return Functions.ifnull.wrap([optional, defaultValue])
 }
 
 /// Builds a copy of the given expressions wrapped with the `ifnull` function.
@@ -738,7 +772,7 @@ public func ??<V : Value>(optional: Expression<V?>, defaultValue: V) -> Expressi
 /// - Returns: A copy of the given expressions wrapped with the `ifnull`
 ///   function.
 public func ??<V : Value>(optional: Expression<V?>, defaultValue: Expression<V>) -> Expression<V> {
-    return "ifnull".wrap([optional, defaultValue])
+    return Functions.ifnull.wrap([optional, defaultValue])
 }
 
 /// Builds a copy of the given expressions wrapped with the `ifnull` function.
@@ -758,5 +792,5 @@ public func ??<V : Value>(optional: Expression<V?>, defaultValue: Expression<V>)
 /// - Returns: A copy of the given expressions wrapped with the `ifnull`
 ///   function.
 public func ??<V : Value>(optional: Expression<V?>, defaultValue: Expression<V?>) -> Expression<V> {
-    return "ifnull".wrap([optional, defaultValue])
+    return Functions.ifnull.wrap([optional, defaultValue])
 }
diff --git a/Sources/SQLite/Typed/Operators.swift b/Sources/SQLite/Typed/Operators.swift
index 5f8be14b..751215e3 100644
--- a/Sources/SQLite/Typed/Operators.swift
+++ b/Sources/SQLite/Typed/Operators.swift
@@ -24,266 +24,297 @@
 
 // TODO: use `@warn_unused_result` by the time operator functions support it
 
+private enum Operators: String {
+    case plus = "+"
+    case minus = "-"
+    case or = "OR"
+    case and = "AND"
+    case not = "NOT "
+    case mul = "*"
+    case div = "/"
+    case mod = "%"
+    case bitwiseLeft = "<<"
+    case bitwiseRight = ">>"
+    case bitwiseAnd = "&"
+    case bitwiseOr = "|"
+    case bitwiseXor = "~"
+    case eq = "="
+    case neq = "!="
+    case gt = ">"
+    case lt = "<"
+    case gte = ">="
+    case lte = "<="
+    case concatenate = "||"
+    
+    func infix<T>(_ lhs: Expressible, _ rhs: Expressible, wrap: Bool = true) -> Expression<T> {
+        return self.rawValue.infix(lhs, rhs, wrap: wrap)
+    }
+    
+    func wrap<T>(_ expression: Expressible) -> Expression<T> {
+        return self.rawValue.wrap(expression)
+    }
+}
+
 public func +(lhs: Expression<String>, rhs: Expression<String>) -> Expression<String> {
-    return "||".infix(lhs, rhs)
+    return Operators.concatenate.infix(lhs, rhs)
 }
 
 public func +(lhs: Expression<String>, rhs: Expression<String?>) -> Expression<String?> {
-    return "||".infix(lhs, rhs)
+    return Operators.concatenate.infix(lhs, rhs)
 }
 public func +(lhs: Expression<String?>, rhs: Expression<String>) -> Expression<String?> {
-    return "||".infix(lhs, rhs)
+    return Operators.concatenate.infix(lhs, rhs)
 }
 public func +(lhs: Expression<String?>, rhs: Expression<String?>) -> Expression<String?> {
-    return "||".infix(lhs, rhs)
+    return Operators.concatenate.infix(lhs, rhs)
 }
 public func +(lhs: Expression<String>, rhs: String) -> Expression<String> {
-    return "||".infix(lhs, rhs)
+    return Operators.concatenate.infix(lhs, rhs)
 }
 public func +(lhs: Expression<String?>, rhs: String) -> Expression<String?> {
-    return "||".infix(lhs, rhs)
+    return Operators.concatenate.infix(lhs, rhs)
 }
 public func +(lhs: String, rhs: Expression<String>) -> Expression<String> {
-    return "||".infix(lhs, rhs)
+    return Operators.concatenate.infix(lhs, rhs)
 }
 public func +(lhs: String, rhs: Expression<String?>) -> Expression<String?> {
-    return "||".infix(lhs, rhs)
+    return Operators.concatenate.infix(lhs, rhs)
 }
 
 // MARK: -
 
 public func +<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return "+".infix(lhs, rhs)
+    return Operators.plus.infix(lhs, rhs)
 }
 public func +<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return "+".infix(lhs, rhs)
+    return Operators.plus.infix(lhs, rhs)
 }
 public func +<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype : Number {
-    return "+".infix(lhs, rhs)
+    return Operators.plus.infix(lhs, rhs)
 }
 public func +<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return "+".infix(lhs, rhs)
+    return Operators.plus.infix(lhs, rhs)
 }
 public func +<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype : Number {
-    return "+".infix(lhs, rhs)
+    return Operators.plus.infix(lhs, rhs)
 }
 public func +<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype : Number {
-    return "+".infix(lhs, rhs)
+    return Operators.plus.infix(lhs, rhs)
 }
 public func +<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return "+".infix(lhs, rhs)
+    return Operators.plus.infix(lhs, rhs)
 }
 public func +<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return "+".infix(lhs, rhs)
+    return Operators.plus.infix(lhs, rhs)
 }
 
 public func -<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return "-".infix(lhs, rhs)
+    return Operators.minus.infix(lhs, rhs)
 }
 public func -<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return "-".infix(lhs, rhs)
+    return Operators.minus.infix(lhs, rhs)
 }
 public func -<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype : Number {
-    return "-".infix(lhs, rhs)
+    return Operators.minus.infix(lhs, rhs)
 }
 public func -<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return "-".infix(lhs, rhs)
+    return Operators.minus.infix(lhs, rhs)
 }
 public func -<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype : Number {
-    return "-".infix(lhs, rhs)
+    return Operators.minus.infix(lhs, rhs)
 }
 public func -<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype : Number {
-    return "-".infix(lhs, rhs)
+    return Operators.minus.infix(lhs, rhs)
 }
 public func -<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return "-".infix(lhs, rhs)
+    return Operators.minus.infix(lhs, rhs)
 }
 public func -<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return "-".infix(lhs, rhs)
+    return Operators.minus.infix(lhs, rhs)
 }
 
 public func *<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return "*".infix(lhs, rhs)
+    return Operators.mul.infix(lhs, rhs)
 }
 public func *<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return "*".infix(lhs, rhs)
+    return Operators.mul.infix(lhs, rhs)
 }
 public func *<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype : Number {
-    return "*".infix(lhs, rhs)
+    return Operators.mul.infix(lhs, rhs)
 }
 public func *<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return "*".infix(lhs, rhs)
+    return Operators.mul.infix(lhs, rhs)
 }
 public func *<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype : Number {
-    return "*".infix(lhs, rhs)
+    return Operators.mul.infix(lhs, rhs)
 }
 public func *<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype : Number {
-    return "*".infix(lhs, rhs)
+    return Operators.mul.infix(lhs, rhs)
 }
 public func *<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return "*".infix(lhs, rhs)
+    return Operators.mul.infix(lhs, rhs)
 }
 public func *<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return "*".infix(lhs, rhs)
+    return Operators.mul.infix(lhs, rhs)
 }
 
 public func /<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return "/".infix(lhs, rhs)
+    return Operators.div.infix(lhs, rhs)
 }
 public func /<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return "/".infix(lhs, rhs)
+    return Operators.div.infix(lhs, rhs)
 }
 public func /<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype : Number {
-    return "/".infix(lhs, rhs)
+    return Operators.div.infix(lhs, rhs)
 }
 public func /<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return "/".infix(lhs, rhs)
+    return Operators.div.infix(lhs, rhs)
 }
 public func /<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype : Number {
-    return "/".infix(lhs, rhs)
+    return Operators.div.infix(lhs, rhs)
 }
 public func /<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype : Number {
-    return "/".infix(lhs, rhs)
+    return Operators.div.infix(lhs, rhs)
 }
 public func /<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return "/".infix(lhs, rhs)
+    return Operators.div.infix(lhs, rhs)
 }
 public func /<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return "/".infix(lhs, rhs)
+    return Operators.div.infix(lhs, rhs)
 }
 
 public prefix func -<V : Value>(rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return "-".wrap(rhs)
+    return Operators.minus.wrap(rhs)
 }
 public prefix func -<V : Value>(rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return "-".wrap(rhs)
+    return Operators.minus.wrap(rhs)
 }
 
 // MARK: -
 
 public func %<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return "%".infix(lhs, rhs)
+    return Operators.mod.infix(lhs, rhs)
 }
 public func %<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return "%".infix(lhs, rhs)
+    return Operators.mod.infix(lhs, rhs)
 }
 public func %<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
-    return "%".infix(lhs, rhs)
+    return Operators.mod.infix(lhs, rhs)
 }
 public func %<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return "%".infix(lhs, rhs)
+    return Operators.mod.infix(lhs, rhs)
 }
 public func %<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
-    return "%".infix(lhs, rhs)
+    return Operators.mod.infix(lhs, rhs)
 }
 public func %<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
-    return "%".infix(lhs, rhs)
+    return Operators.mod.infix(lhs, rhs)
 }
 public func %<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return "%".infix(lhs, rhs)
+    return Operators.mod.infix(lhs, rhs)
 }
 public func %<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return "%".infix(lhs, rhs)
+    return Operators.mod.infix(lhs, rhs)
 }
 
 public func <<<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return "<<".infix(lhs, rhs)
+    return Operators.bitwiseLeft.infix(lhs, rhs)
 }
 public func <<<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return "<<".infix(lhs, rhs)
+    return Operators.bitwiseLeft.infix(lhs, rhs)
 }
 public func <<<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
-    return "<<".infix(lhs, rhs)
+    return Operators.bitwiseLeft.infix(lhs, rhs)
 }
 public func <<<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return "<<".infix(lhs, rhs)
+    return Operators.bitwiseLeft.infix(lhs, rhs)
 }
 public func <<<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
-    return "<<".infix(lhs, rhs)
+    return Operators.bitwiseLeft.infix(lhs, rhs)
 }
 public func <<<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
-    return "<<".infix(lhs, rhs)
+    return Operators.bitwiseLeft.infix(lhs, rhs)
 }
 public func <<<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return "<<".infix(lhs, rhs)
+    return Operators.bitwiseLeft.infix(lhs, rhs)
 }
 public func <<<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return "<<".infix(lhs, rhs)
+    return Operators.bitwiseLeft.infix(lhs, rhs)
 }
 
 public func >><V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return ">>".infix(lhs, rhs)
+    return Operators.bitwiseRight.infix(lhs, rhs)
 }
 public func >><V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return ">>".infix(lhs, rhs)
+    return Operators.bitwiseRight.infix(lhs, rhs)
 }
 public func >><V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
-    return ">>".infix(lhs, rhs)
+    return Operators.bitwiseRight.infix(lhs, rhs)
 }
 public func >><V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return ">>".infix(lhs, rhs)
+    return Operators.bitwiseRight.infix(lhs, rhs)
 }
 public func >><V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
-    return ">>".infix(lhs, rhs)
+    return Operators.bitwiseRight.infix(lhs, rhs)
 }
 public func >><V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
-    return ">>".infix(lhs, rhs)
+    return Operators.bitwiseRight.infix(lhs, rhs)
 }
 public func >><V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return ">>".infix(lhs, rhs)
+    return Operators.bitwiseRight.infix(lhs, rhs)
 }
 public func >><V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return ">>".infix(lhs, rhs)
+    return Operators.bitwiseRight.infix(lhs, rhs)
 }
 
 public func &<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return "&".infix(lhs, rhs)
+    return Operators.bitwiseAnd.infix(lhs, rhs)
 }
 public func &<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return "&".infix(lhs, rhs)
+    return Operators.bitwiseAnd.infix(lhs, rhs)
 }
 public func &<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
-    return "&".infix(lhs, rhs)
+    return Operators.bitwiseAnd.infix(lhs, rhs)
 }
 public func &<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return "&".infix(lhs, rhs)
+    return Operators.bitwiseAnd.infix(lhs, rhs)
 }
 public func &<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
-    return "&".infix(lhs, rhs)
+    return Operators.bitwiseAnd.infix(lhs, rhs)
 }
 public func &<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
-    return "&".infix(lhs, rhs)
+    return Operators.bitwiseAnd.infix(lhs, rhs)
 }
 public func &<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return "&".infix(lhs, rhs)
+    return Operators.bitwiseAnd.infix(lhs, rhs)
 }
 public func &<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return "&".infix(lhs, rhs)
+    return Operators.bitwiseAnd.infix(lhs, rhs)
 }
 
 public func |<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return "|".infix(lhs, rhs)
+    return Operators.bitwiseOr.infix(lhs, rhs)
 }
 public func |<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return "|".infix(lhs, rhs)
+    return Operators.bitwiseOr.infix(lhs, rhs)
 }
 public func |<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
-    return "|".infix(lhs, rhs)
+    return Operators.bitwiseOr.infix(lhs, rhs)
 }
 public func |<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return "|".infix(lhs, rhs)
+    return Operators.bitwiseOr.infix(lhs, rhs)
 }
 public func |<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
-    return "|".infix(lhs, rhs)
+    return Operators.bitwiseOr.infix(lhs, rhs)
 }
 public func |<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
-    return "|".infix(lhs, rhs)
+    return Operators.bitwiseOr.infix(lhs, rhs)
 }
 public func |<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return "|".infix(lhs, rhs)
+    return Operators.bitwiseOr.infix(lhs, rhs)
 }
 public func |<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return "|".infix(lhs, rhs)
+    return Operators.bitwiseOr.infix(lhs, rhs)
 }
 
 public func ^<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
@@ -312,166 +343,166 @@ public func ^<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.
 }
 
 public prefix func ~<V : Value>(rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return "~".wrap(rhs)
+    return Operators.bitwiseXor.wrap(rhs)
 }
 public prefix func ~<V : Value>(rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return "~".wrap(rhs)
+    return Operators.bitwiseXor.wrap(rhs)
 }
 
 // MARK: -
 
 public func ==<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
-    return "=".infix(lhs, rhs)
+    return Operators.eq.infix(lhs, rhs)
 }
 public func ==<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
-    return "=".infix(lhs, rhs)
+    return Operators.eq.infix(lhs, rhs)
 }
 public func ==<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Equatable {
-    return "=".infix(lhs, rhs)
+    return Operators.eq.infix(lhs, rhs)
 }
 public func ==<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
-    return "=".infix(lhs, rhs)
+    return Operators.eq.infix(lhs, rhs)
 }
 public func ==<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Equatable {
-    return "=".infix(lhs, rhs)
+    return Operators.eq.infix(lhs, rhs)
 }
 public func ==<V : Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype : Equatable {
     guard let rhs = rhs else { return "IS".infix(lhs, Expression<V?>(value: nil)) }
-    return "=".infix(lhs, rhs)
+    return Operators.eq.infix(lhs, rhs)
 }
 public func ==<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
-    return "=".infix(lhs, rhs)
+    return Operators.eq.infix(lhs, rhs)
 }
 public func ==<V : Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
     guard let lhs = lhs else { return "IS".infix(Expression<V?>(value: nil), rhs) }
-    return "=".infix(lhs, rhs)
+    return Operators.eq.infix(lhs, rhs)
 }
 
 public func !=<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
-    return "!=".infix(lhs, rhs)
+    return Operators.neq.infix(lhs, rhs)
 }
 public func !=<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
-    return "!=".infix(lhs, rhs)
+    return Operators.neq.infix(lhs, rhs)
 }
 public func !=<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Equatable {
-    return "!=".infix(lhs, rhs)
+    return Operators.neq.infix(lhs, rhs)
 }
 public func !=<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
-    return "!=".infix(lhs, rhs)
+    return Operators.neq.infix(lhs, rhs)
 }
 public func !=<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Equatable {
-    return "!=".infix(lhs, rhs)
+    return Operators.neq.infix(lhs, rhs)
 }
 public func !=<V : Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype : Equatable {
     guard let rhs = rhs else { return "IS NOT".infix(lhs, Expression<V?>(value: nil)) }
-    return "!=".infix(lhs, rhs)
+    return Operators.neq.infix(lhs, rhs)
 }
 public func !=<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
-    return "!=".infix(lhs, rhs)
+    return Operators.neq.infix(lhs, rhs)
 }
 public func !=<V : Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
     guard let lhs = lhs else { return "IS NOT".infix(Expression<V?>(value: nil), rhs) }
-    return "!=".infix(lhs, rhs)
+    return Operators.neq.infix(lhs, rhs)
 }
 
 public func ><V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return ">".infix(lhs, rhs)
+    return Operators.gt.infix(lhs, rhs)
 }
 public func ><V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return ">".infix(lhs, rhs)
+    return Operators.gt.infix(lhs, rhs)
 }
 public func ><V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return ">".infix(lhs, rhs)
+    return Operators.gt.infix(lhs, rhs)
 }
 public func ><V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return ">".infix(lhs, rhs)
+    return Operators.gt.infix(lhs, rhs)
 }
 public func ><V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Comparable {
-    return ">".infix(lhs, rhs)
+    return Operators.gt.infix(lhs, rhs)
 }
 public func ><V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype : Comparable {
-    return ">".infix(lhs, rhs)
+    return Operators.gt.infix(lhs, rhs)
 }
 public func ><V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return ">".infix(lhs, rhs)
+    return Operators.gt.infix(lhs, rhs)
 }
 public func ><V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return ">".infix(lhs, rhs)
+    return Operators.gt.infix(lhs, rhs)
 }
 
 public func >=<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return ">=".infix(lhs, rhs)
+    return Operators.gte.infix(lhs, rhs)
 }
 public func >=<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return ">=".infix(lhs, rhs)
+    return Operators.gte.infix(lhs, rhs)
 }
 public func >=<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return ">=".infix(lhs, rhs)
+    return Operators.gte.infix(lhs, rhs)
 }
 public func >=<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return ">=".infix(lhs, rhs)
+    return Operators.gte.infix(lhs, rhs)
 }
 public func >=<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Comparable {
-    return ">=".infix(lhs, rhs)
+    return Operators.gte.infix(lhs, rhs)
 }
 public func >=<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype : Comparable {
-    return ">=".infix(lhs, rhs)
+    return Operators.gte.infix(lhs, rhs)
 }
 public func >=<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return ">=".infix(lhs, rhs)
+    return Operators.gte.infix(lhs, rhs)
 }
 public func >=<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return ">=".infix(lhs, rhs)
+    return Operators.gte.infix(lhs, rhs)
 }
 
 public func <<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return "<".infix(lhs, rhs)
+    return Operators.lt.infix(lhs, rhs)
 }
 public func <<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return "<".infix(lhs, rhs)
+    return Operators.lt.infix(lhs, rhs)
 }
 public func <<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return "<".infix(lhs, rhs)
+    return Operators.lt.infix(lhs, rhs)
 }
 public func <<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return "<".infix(lhs, rhs)
+    return Operators.lt.infix(lhs, rhs)
 }
 public func <<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Comparable {
-    return "<".infix(lhs, rhs)
+    return Operators.lt.infix(lhs, rhs)
 }
 public func <<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype : Comparable {
-    return "<".infix(lhs, rhs)
+    return Operators.lt.infix(lhs, rhs)
 }
 public func <<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return "<".infix(lhs, rhs)
+    return Operators.lt.infix(lhs, rhs)
 }
 public func <<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return "<".infix(lhs, rhs)
+    return Operators.lt.infix(lhs, rhs)
 }
 
 public func <=<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return "<=".infix(lhs, rhs)
+    return Operators.lte.infix(lhs, rhs)
 }
 public func <=<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return "<=".infix(lhs, rhs)
+    return Operators.lte.infix(lhs, rhs)
 }
 public func <=<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return "<=".infix(lhs, rhs)
+    return Operators.lte.infix(lhs, rhs)
 }
 public func <=<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return "<=".infix(lhs, rhs)
+    return Operators.lte.infix(lhs, rhs)
 }
 public func <=<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Comparable {
-    return "<=".infix(lhs, rhs)
+    return Operators.lte.infix(lhs, rhs)
 }
 public func <=<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype : Comparable {
-    return "<=".infix(lhs, rhs)
+    return Operators.lte.infix(lhs, rhs)
 }
 public func <=<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return "<=".infix(lhs, rhs)
+    return Operators.lte.infix(lhs, rhs)
 }
 public func <=<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return "<=".infix(lhs, rhs)
+    return Operators.lte.infix(lhs, rhs)
 }
 
 public func ~=<V : Value>(lhs: ClosedRange<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable & Value {
@@ -517,58 +548,58 @@ public func ~=<V : Value>(lhs: PartialRangeFrom<V>, rhs: Expression<V?>) -> Expr
 // MARK: -
 
 public func &&(lhs: Expression<Bool>, rhs: Expression<Bool>) -> Expression<Bool> {
-    return "AND".infix(lhs, rhs)
+    return Operators.and.infix(lhs, rhs)
 }
 public func &&(lhs: Expression<Bool>, rhs: Expression<Bool?>) -> Expression<Bool?> {
-    return "AND".infix(lhs, rhs)
+    return Operators.and.infix(lhs, rhs)
 }
 public func &&(lhs: Expression<Bool?>, rhs: Expression<Bool>) -> Expression<Bool?> {
-    return "AND".infix(lhs, rhs)
+    return Operators.and.infix(lhs, rhs)
 }
 public func &&(lhs: Expression<Bool?>, rhs: Expression<Bool?>) -> Expression<Bool?> {
-    return "AND".infix(lhs, rhs)
+    return Operators.and.infix(lhs, rhs)
 }
 public func &&(lhs: Expression<Bool>, rhs: Bool) -> Expression<Bool> {
-    return "AND".infix(lhs, rhs)
+    return Operators.and.infix(lhs, rhs)
 }
 public func &&(lhs: Expression<Bool?>, rhs: Bool) -> Expression<Bool?> {
-    return "AND".infix(lhs, rhs)
+    return Operators.and.infix(lhs, rhs)
 }
 public func &&(lhs: Bool, rhs: Expression<Bool>) -> Expression<Bool> {
-    return "AND".infix(lhs, rhs)
+    return Operators.and.infix(lhs, rhs)
 }
 public func &&(lhs: Bool, rhs: Expression<Bool?>) -> Expression<Bool?> {
-    return "AND".infix(lhs, rhs)
+    return Operators.and.infix(lhs, rhs)
 }
 
 public func ||(lhs: Expression<Bool>, rhs: Expression<Bool>) -> Expression<Bool> {
-    return "OR".infix(lhs, rhs)
+    return Operators.or.infix(lhs, rhs)
 }
 public func ||(lhs: Expression<Bool>, rhs: Expression<Bool?>) -> Expression<Bool?> {
-    return "OR".infix(lhs, rhs)
+    return Operators.or.infix(lhs, rhs)
 }
 public func ||(lhs: Expression<Bool?>, rhs: Expression<Bool>) -> Expression<Bool?> {
-    return "OR".infix(lhs, rhs)
+    return Operators.or.infix(lhs, rhs)
 }
 public func ||(lhs: Expression<Bool?>, rhs: Expression<Bool?>) -> Expression<Bool?> {
-    return "OR".infix(lhs, rhs)
+    return Operators.or.infix(lhs, rhs)
 }
 public func ||(lhs: Expression<Bool>, rhs: Bool) -> Expression<Bool> {
-    return "OR".infix(lhs, rhs)
+    return Operators.or.infix(lhs, rhs)
 }
 public func ||(lhs: Expression<Bool?>, rhs: Bool) -> Expression<Bool?> {
-    return "OR".infix(lhs, rhs)
+    return Operators.or.infix(lhs, rhs)
 }
 public func ||(lhs: Bool, rhs: Expression<Bool>) -> Expression<Bool> {
-    return "OR".infix(lhs, rhs)
+    return Operators.or.infix(lhs, rhs)
 }
 public func ||(lhs: Bool, rhs: Expression<Bool?>) -> Expression<Bool?> {
-    return "OR".infix(lhs, rhs)
+    return Operators.or.infix(lhs, rhs)
 }
 
 public prefix func !(rhs: Expression<Bool>) -> Expression<Bool> {
-    return "NOT ".wrap(rhs)
+    return Operators.not.wrap(rhs)
 }
 public prefix func !(rhs: Expression<Bool?>) -> Expression<Bool?> {
-    return "NOT ".wrap(rhs)
+    return Operators.not.wrap(rhs)
 }

From bc909add007da81916c8b9118df081d746aea4c4 Mon Sep 17 00:00:00 2001
From: Yehor Popovych <yehor@crossroad.io>
Date: Wed, 27 Mar 2019 13:48:58 +0200
Subject: [PATCH 323/685] Fixed enums naming

---
 Sources/SQLite/Typed/AggregateFunctions.swift |  28 +-
 Sources/SQLite/Typed/CoreFunctions.swift      | 124 +++----
 Sources/SQLite/Typed/Operators.swift          | 302 +++++++++---------
 3 files changed, 227 insertions(+), 227 deletions(-)

diff --git a/Sources/SQLite/Typed/AggregateFunctions.swift b/Sources/SQLite/Typed/AggregateFunctions.swift
index 056d617e..2ec28288 100644
--- a/Sources/SQLite/Typed/AggregateFunctions.swift
+++ b/Sources/SQLite/Typed/AggregateFunctions.swift
@@ -22,7 +22,7 @@
 // THE SOFTWARE.
 //
 
-private enum Functions: String {
+private enum Function: String {
     case count
     case max
     case min
@@ -61,7 +61,7 @@ extension ExpressionType where UnderlyingType : Value {
     /// - Returns: A copy of the expression wrapped with the `count` aggregate
     ///   function.
     public var count: Expression<Int> {
-        return Functions.count.wrap(self)
+        return Function.count.wrap(self)
     }
 
 }
@@ -92,7 +92,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
     /// - Returns: A copy of the expression wrapped with the `count` aggregate
     ///   function.
     public var count: Expression<Int> {
-        return Functions.count.wrap(self)
+        return Function.count.wrap(self)
     }
 
 }
@@ -109,7 +109,7 @@ extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype :
     /// - Returns: A copy of the expression wrapped with the `max` aggregate
     ///   function.
     public var max: Expression<UnderlyingType?> {
-        return Functions.max.wrap(self)
+        return Function.max.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `min` aggregate
@@ -122,7 +122,7 @@ extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype :
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var min: Expression<UnderlyingType?> {
-        return Functions.min.wrap(self)
+        return Function.min.wrap(self)
     }
 
 }
@@ -139,7 +139,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
     /// - Returns: A copy of the expression wrapped with the `max` aggregate
     ///   function.
     public var max: Expression<UnderlyingType> {
-        return Functions.max.wrap(self)
+        return Function.max.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `min` aggregate
@@ -152,7 +152,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var min: Expression<UnderlyingType> {
-        return Functions.min.wrap(self)
+        return Function.min.wrap(self)
     }
 
 }
@@ -169,7 +169,7 @@ extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype :
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var average: Expression<Double?> {
-        return Functions.avg.wrap(self)
+        return Function.avg.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `sum` aggregate
@@ -182,7 +182,7 @@ extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype :
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var sum: Expression<UnderlyingType?> {
-        return Functions.sum.wrap(self)
+        return Function.sum.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `total` aggregate
@@ -195,7 +195,7 @@ extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype :
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var total: Expression<Double> {
-        return Functions.total.wrap(self)
+        return Function.total.wrap(self)
     }
 
 }
@@ -212,7 +212,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var average: Expression<Double?> {
-        return Functions.avg.wrap(self)
+        return Function.avg.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `sum` aggregate
@@ -225,7 +225,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var sum: Expression<UnderlyingType> {
-        return Functions.sum.wrap(self)
+        return Function.sum.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `total` aggregate
@@ -238,7 +238,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var total: Expression<Double> {
-        return Functions.total.wrap(self)
+        return Function.total.wrap(self)
     }
 
 }
@@ -246,7 +246,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
 extension ExpressionType where UnderlyingType == Int {
 
     static func count(_ star: Star) -> Expression<UnderlyingType> {
-        return Functions.count.wrap(star(nil, nil))
+        return Function.count.wrap(star(nil, nil))
     }
 
 }
diff --git a/Sources/SQLite/Typed/CoreFunctions.swift b/Sources/SQLite/Typed/CoreFunctions.swift
index 420110ae..068dcf02 100644
--- a/Sources/SQLite/Typed/CoreFunctions.swift
+++ b/Sources/SQLite/Typed/CoreFunctions.swift
@@ -24,7 +24,7 @@
 
 import Foundation
 
-private enum Functions: String {
+private enum Function: String {
     case abs
     case round
     case random
@@ -38,12 +38,12 @@ private enum Functions: String {
     case trim
     case replace
     case substr
-    case LIKE
-    case IN
-    case GLOB
-    case MATCH
-    case REGEXP
-    case COLLATE
+    case like = "LIKE"
+    case `in` = "IN"
+    case glob = "GLOB"
+    case match = "MATCH"
+    case regexp = "REGEXP"
+    case collate = "COLLATE"
     case ifnull
     
     func infix<T>(_ lhs: Expressible, _ rhs: Expressible, wrap: Bool = true) -> Expression<T> {
@@ -69,7 +69,7 @@ extension ExpressionType where UnderlyingType : Number {
     ///
     /// - Returns: A copy of the expression wrapped with the `abs` function.
     public var absoluteValue : Expression<UnderlyingType> {
-        return Functions.abs.wrap(self)
+        return Function.abs.wrap(self)
     }
 
 }
@@ -84,7 +84,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
     ///
     /// - Returns: A copy of the expression wrapped with the `abs` function.
     public var absoluteValue : Expression<UnderlyingType> {
-        return Functions.abs.wrap(self)
+        return Function.abs.wrap(self)
     }
 
 }
@@ -102,9 +102,9 @@ extension ExpressionType where UnderlyingType == Double {
     /// - Returns: A copy of the expression wrapped with the `round` function.
     public func round(_ precision: Int? = nil) -> Expression<UnderlyingType> {
         guard let precision = precision else {
-            return Functions.round.wrap([self])
+            return Function.round.wrap([self])
         }
-        return Functions.round.wrap([self, Int(precision)])
+        return Function.round.wrap([self, Int(precision)])
     }
 
 }
@@ -122,9 +122,9 @@ extension ExpressionType where UnderlyingType == Double? {
     /// - Returns: A copy of the expression wrapped with the `round` function.
     public func round(_ precision: Int? = nil) -> Expression<UnderlyingType> {
         guard let precision = precision else {
-            return Functions.round.wrap(self)
+            return Function.round.wrap(self)
         }
-        return Functions.round.wrap([self, Int(precision)])
+        return Function.round.wrap([self, Int(precision)])
     }
 
 }
@@ -138,7 +138,7 @@ extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype =
     ///
     /// - Returns: An expression calling the `random` function.
     public static func random() -> Expression<UnderlyingType> {
-        return Functions.random.wrap([])
+        return Function.random.wrap([])
     }
 
 }
@@ -154,7 +154,7 @@ extension ExpressionType where UnderlyingType == Data {
     ///
     /// - Returns: An expression calling the `randomblob` function.
     public static func random(_ length: Int) -> Expression<UnderlyingType> {
-        return Functions.randomblob.wrap([])
+        return Function.randomblob.wrap([])
     }
 
     /// Builds an expression representing the `zeroblob` function.
@@ -166,7 +166,7 @@ extension ExpressionType where UnderlyingType == Data {
     ///
     /// - Returns: An expression calling the `zeroblob` function.
     public static func allZeros(_ length: Int) -> Expression<UnderlyingType> {
-        return Functions.zeroblob.wrap([])
+        return Function.zeroblob.wrap([])
     }
 
     /// Builds a copy of the expression wrapped with the `length` function.
@@ -177,7 +177,7 @@ extension ExpressionType where UnderlyingType == Data {
     ///
     /// - Returns: A copy of the expression wrapped with the `length` function.
     public var length: Expression<Int> {
-        return Functions.length.wrap(self)
+        return Function.length.wrap(self)
     }
 
 }
@@ -192,7 +192,7 @@ extension ExpressionType where UnderlyingType == Data? {
     ///
     /// - Returns: A copy of the expression wrapped with the `length` function.
     public var length: Expression<Int?> {
-        return Functions.length.wrap(self)
+        return Function.length.wrap(self)
     }
 
 }
@@ -207,7 +207,7 @@ extension ExpressionType where UnderlyingType == String {
     ///
     /// - Returns: A copy of the expression wrapped with the `length` function.
     public var length: Expression<Int> {
-        return Functions.length.wrap(self)
+        return Function.length.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `lower` function.
@@ -218,7 +218,7 @@ extension ExpressionType where UnderlyingType == String {
     ///
     /// - Returns: A copy of the expression wrapped with the `lower` function.
     public var lowercaseString: Expression<UnderlyingType> {
-        return Functions.lower.wrap(self)
+        return Function.lower.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `upper` function.
@@ -229,7 +229,7 @@ extension ExpressionType where UnderlyingType == String {
     ///
     /// - Returns: A copy of the expression wrapped with the `upper` function.
     public var uppercaseString: Expression<UnderlyingType> {
-        return Functions.upper.wrap(self)
+        return Function.upper.wrap(self)
     }
 
     /// Builds a copy of the expression appended with a `LIKE` query against the
@@ -276,9 +276,9 @@ extension ExpressionType where UnderlyingType == String {
     ///   the given pattern.
     public func like(_ pattern: Expression<String>, escape character: Character? = nil) -> Expression<Bool> {
         guard let character = character else {
-            return Functions.LIKE.infix(self, pattern)
+            return Function.like.infix(self, pattern)
         }
-        let like: Expression<Bool> =  Functions.LIKE.infix(self, pattern, wrap: false)
+        let like: Expression<Bool> =  Function.like.infix(self, pattern, wrap: false)
         return Expression("(\(like.template) ESCAPE ?)", like.bindings + [String(character)])
     }
 
@@ -294,7 +294,7 @@ extension ExpressionType where UnderlyingType == String {
     /// - Returns: A copy of the expression appended with a `GLOB` query against
     ///   the given pattern.
     public func glob(_ pattern: String) -> Expression<Bool> {
-        return Functions.GLOB.infix(self, pattern)
+        return Function.glob.infix(self, pattern)
     }
 
     /// Builds a copy of the expression appended with a `MATCH` query against
@@ -309,7 +309,7 @@ extension ExpressionType where UnderlyingType == String {
     /// - Returns: A copy of the expression appended with a `MATCH` query
     ///   against the given pattern.
     public func match(_ pattern: String) -> Expression<Bool> {
-        return Functions.MATCH.infix(self, pattern)
+        return Function.match.infix(self, pattern)
     }
 
     /// Builds a copy of the expression appended with a `REGEXP` query against
@@ -320,7 +320,7 @@ extension ExpressionType where UnderlyingType == String {
     /// - Returns: A copy of the expression appended with a `REGEXP` query
     ///   against the given pattern.
     public func regexp(_ pattern: String) -> Expression<Bool> {
-        return Functions.REGEXP.infix(self, pattern)
+        return Function.regexp.infix(self, pattern)
     }
 
     /// Builds a copy of the expression appended with a `COLLATE` clause with
@@ -335,7 +335,7 @@ extension ExpressionType where UnderlyingType == String {
     /// - Returns: A copy of the expression appended with a `COLLATE` clause
     ///   with the given sequence.
     public func collate(_ collation: Collation) -> Expression<UnderlyingType> {
-        return Functions.COLLATE.infix(self, collation)
+        return Function.collate.infix(self, collation)
     }
 
     /// Builds a copy of the expression wrapped with the `ltrim` function.
@@ -351,9 +351,9 @@ extension ExpressionType where UnderlyingType == String {
     /// - Returns: A copy of the expression wrapped with the `ltrim` function.
     public func ltrim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
-            return Functions.ltrim.wrap(self)
+            return Function.ltrim.wrap(self)
         }
-        return Functions.ltrim.wrap([self, String(characters)])
+        return Function.ltrim.wrap([self, String(characters)])
     }
 
     /// Builds a copy of the expression wrapped with the `rtrim` function.
@@ -369,9 +369,9 @@ extension ExpressionType where UnderlyingType == String {
     /// - Returns: A copy of the expression wrapped with the `rtrim` function.
     public func rtrim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
-            return Functions.rtrim.wrap(self)
+            return Function.rtrim.wrap(self)
         }
-        return Functions.rtrim.wrap([self, String(characters)])
+        return Function.rtrim.wrap([self, String(characters)])
     }
 
     /// Builds a copy of the expression wrapped with the `trim` function.
@@ -387,9 +387,9 @@ extension ExpressionType where UnderlyingType == String {
     /// - Returns: A copy of the expression wrapped with the `trim` function.
     public func trim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
-            return Functions.trim.wrap([self])
+            return Function.trim.wrap([self])
         }
-        return Functions.trim.wrap([self, String(characters)])
+        return Function.trim.wrap([self, String(characters)])
     }
 
     /// Builds a copy of the expression wrapped with the `replace` function.
@@ -406,14 +406,14 @@ extension ExpressionType where UnderlyingType == String {
     ///
     /// - Returns: A copy of the expression wrapped with the `replace` function.
     public func replace(_ pattern: String, with replacement: String) -> Expression<UnderlyingType> {
-        return Functions.replace.wrap([self, pattern, replacement])
+        return Function.replace.wrap([self, pattern, replacement])
     }
 
     public func substring(_ location: Int, length: Int? = nil) -> Expression<UnderlyingType> {
         guard let length = length else {
-            return Functions.substr.wrap([self, location])
+            return Function.substr.wrap([self, location])
         }
-        return Functions.substr.wrap([self, location, length])
+        return Function.substr.wrap([self, location, length])
     }
 
     public subscript(range: Range<Int>) -> Expression<UnderlyingType> {
@@ -432,7 +432,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression wrapped with the `length` function.
     public var length: Expression<Int?> {
-        return Functions.length.wrap(self)
+        return Function.length.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `lower` function.
@@ -443,7 +443,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression wrapped with the `lower` function.
     public var lowercaseString: Expression<UnderlyingType> {
-        return Functions.lower.wrap(self)
+        return Function.lower.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `upper` function.
@@ -454,7 +454,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression wrapped with the `upper` function.
     public var uppercaseString: Expression<UnderlyingType> {
-        return Functions.upper.wrap(self)
+        return Function.upper.wrap(self)
     }
 
     /// Builds a copy of the expression appended with a `LIKE` query against the
@@ -477,7 +477,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///   the given pattern.
     public func like(_ pattern: String, escape character: Character? = nil) -> Expression<Bool?> {
         guard let character = character else {
-            return Functions.LIKE.infix(self, pattern)
+            return Function.like.infix(self, pattern)
         }
         return Expression("(\(template) LIKE ? ESCAPE ?)", bindings + [pattern, String(character)])
     }
@@ -501,9 +501,9 @@ extension ExpressionType where UnderlyingType == String? {
     ///   the given pattern.
     public func like(_ pattern: Expression<String>, escape character: Character? = nil) -> Expression<Bool?> {
         guard let character = character else {
-            return Functions.LIKE.infix(self, pattern)
+            return Function.like.infix(self, pattern)
         }
-        let like: Expression<Bool> = "LIKE".infix(self, pattern, wrap: false)
+        let like: Expression<Bool> = Function.like.infix(self, pattern, wrap: false)
         return Expression("(\(like.template) ESCAPE ?)", like.bindings + [String(character)])
     }
 
@@ -519,7 +519,7 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression appended with a `GLOB` query against
     ///   the given pattern.
     public func glob(_ pattern: String) -> Expression<Bool?> {
-        return Functions.GLOB.infix(self, pattern)
+        return Function.glob.infix(self, pattern)
     }
 
     /// Builds a copy of the expression appended with a `MATCH` query against
@@ -534,7 +534,7 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression appended with a `MATCH` query
     ///   against the given pattern.
     public func match(_ pattern: String) -> Expression<Bool> {
-        return Functions.MATCH.infix(self, pattern)
+        return Function.match.infix(self, pattern)
     }
 
     /// Builds a copy of the expression appended with a `REGEXP` query against
@@ -545,7 +545,7 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression appended with a `REGEXP` query
     ///   against the given pattern.
     public func regexp(_ pattern: String) -> Expression<Bool?> {
-        return Functions.REGEXP.infix(self, pattern)
+        return Function.regexp.infix(self, pattern)
     }
 
     /// Builds a copy of the expression appended with a `COLLATE` clause with
@@ -560,7 +560,7 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression appended with a `COLLATE` clause
     ///   with the given sequence.
     public func collate(_ collation: Collation) -> Expression<UnderlyingType> {
-        return Functions.COLLATE.infix(self, collation)
+        return Function.collate.infix(self, collation)
     }
 
     /// Builds a copy of the expression wrapped with the `ltrim` function.
@@ -576,9 +576,9 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression wrapped with the `ltrim` function.
     public func ltrim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
-            return Functions.ltrim.wrap(self)
+            return Function.ltrim.wrap(self)
         }
-        return Functions.ltrim.wrap([self, String(characters)])
+        return Function.ltrim.wrap([self, String(characters)])
     }
 
     /// Builds a copy of the expression wrapped with the `rtrim` function.
@@ -594,9 +594,9 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression wrapped with the `rtrim` function.
     public func rtrim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
-            return Functions.rtrim.wrap(self)
+            return Function.rtrim.wrap(self)
         }
-        return Functions.rtrim.wrap([self, String(characters)])
+        return Function.rtrim.wrap([self, String(characters)])
     }
 
     /// Builds a copy of the expression wrapped with the `trim` function.
@@ -612,9 +612,9 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression wrapped with the `trim` function.
     public func trim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
         guard let characters = characters else {
-            return Functions.trim.wrap(self)
+            return Function.trim.wrap(self)
         }
-        return Functions.trim.wrap([self, String(characters)])
+        return Function.trim.wrap([self, String(characters)])
     }
 
     /// Builds a copy of the expression wrapped with the `replace` function.
@@ -631,7 +631,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression wrapped with the `replace` function.
     public func replace(_ pattern: String, with replacement: String) -> Expression<UnderlyingType> {
-        return Functions.replace.wrap([self, pattern, replacement])
+        return Function.replace.wrap([self, pattern, replacement])
     }
 
     /// Builds a copy of the expression wrapped with the `substr` function.
@@ -651,9 +651,9 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression wrapped with the `substr` function.
     public func substring(_ location: Int, length: Int? = nil) -> Expression<UnderlyingType> {
         guard let length = length else {
-            return Functions.substr.wrap([self, location])
+            return Function.substr.wrap([self, location])
         }
-        return Functions.substr.wrap([self, location, length])
+        return Function.substr.wrap([self, location, length])
     }
 
     /// Builds a copy of the expression wrapped with the `substr` function.
@@ -686,7 +686,7 @@ extension Collection where Iterator.Element : Value {
     ///   the collection.
     public func contains(_ expression: Expression<Iterator.Element>) -> Expression<Bool> {
         let templates = [String](repeating: "?", count: count).joined(separator: ", ")
-        return Functions.IN.infix(expression, Expression<Void>("(\(templates))", map { $0.datatypeValue }))
+        return Function.in.infix(expression, Expression<Void>("(\(templates))", map { $0.datatypeValue }))
     }
 
     /// Builds a copy of the expression prepended with an `IN` check against the
@@ -702,7 +702,7 @@ extension Collection where Iterator.Element : Value {
     ///   the collection.
     public func contains(_ expression: Expression<Iterator.Element?>) -> Expression<Bool?> {
         let templates = [String](repeating: "?", count: count).joined(separator: ", ")
-        return Functions.IN.infix(expression, Expression<Void>("(\(templates))", map { $0.datatypeValue }))
+        return Function.in.infix(expression, Expression<Void>("(\(templates))", map { $0.datatypeValue }))
     }
 
 }
@@ -728,9 +728,9 @@ extension String {
     ///   the given pattern.
     public func like(_ pattern: Expression<String>, escape character: Character? = nil) -> Expression<Bool> {
         guard let character = character else {
-            return Functions.LIKE.infix(self, pattern)
+            return Function.like.infix(self, pattern)
         }
-        let like: Expression<Bool> = "LIKE".infix(self, pattern, wrap: false)
+        let like: Expression<Bool> = Function.like.infix(self, pattern, wrap: false)
         return Expression("(\(like.template) ESCAPE ?)", like.bindings + [String(character)])
     }
 
@@ -752,7 +752,7 @@ extension String {
 /// - Returns: A copy of the given expressions wrapped with the `ifnull`
 ///   function.
 public func ??<V : Value>(optional: Expression<V?>, defaultValue: V) -> Expression<V> {
-    return Functions.ifnull.wrap([optional, defaultValue])
+    return Function.ifnull.wrap([optional, defaultValue])
 }
 
 /// Builds a copy of the given expressions wrapped with the `ifnull` function.
@@ -772,7 +772,7 @@ public func ??<V : Value>(optional: Expression<V?>, defaultValue: V) -> Expressi
 /// - Returns: A copy of the given expressions wrapped with the `ifnull`
 ///   function.
 public func ??<V : Value>(optional: Expression<V?>, defaultValue: Expression<V>) -> Expression<V> {
-    return Functions.ifnull.wrap([optional, defaultValue])
+    return Function.ifnull.wrap([optional, defaultValue])
 }
 
 /// Builds a copy of the given expressions wrapped with the `ifnull` function.
@@ -792,5 +792,5 @@ public func ??<V : Value>(optional: Expression<V?>, defaultValue: Expression<V>)
 /// - Returns: A copy of the given expressions wrapped with the `ifnull`
 ///   function.
 public func ??<V : Value>(optional: Expression<V?>, defaultValue: Expression<V?>) -> Expression<V> {
-    return Functions.ifnull.wrap([optional, defaultValue])
+    return Function.ifnull.wrap([optional, defaultValue])
 }
diff --git a/Sources/SQLite/Typed/Operators.swift b/Sources/SQLite/Typed/Operators.swift
index 751215e3..b5637ea3 100644
--- a/Sources/SQLite/Typed/Operators.swift
+++ b/Sources/SQLite/Typed/Operators.swift
@@ -24,7 +24,7 @@
 
 // TODO: use `@warn_unused_result` by the time operator functions support it
 
-private enum Operators: String {
+private enum Operator: String {
     case plus = "+"
     case minus = "-"
     case or = "OR"
@@ -56,265 +56,265 @@ private enum Operators: String {
 }
 
 public func +(lhs: Expression<String>, rhs: Expression<String>) -> Expression<String> {
-    return Operators.concatenate.infix(lhs, rhs)
+    return Operator.concatenate.infix(lhs, rhs)
 }
 
 public func +(lhs: Expression<String>, rhs: Expression<String?>) -> Expression<String?> {
-    return Operators.concatenate.infix(lhs, rhs)
+    return Operator.concatenate.infix(lhs, rhs)
 }
 public func +(lhs: Expression<String?>, rhs: Expression<String>) -> Expression<String?> {
-    return Operators.concatenate.infix(lhs, rhs)
+    return Operator.concatenate.infix(lhs, rhs)
 }
 public func +(lhs: Expression<String?>, rhs: Expression<String?>) -> Expression<String?> {
-    return Operators.concatenate.infix(lhs, rhs)
+    return Operator.concatenate.infix(lhs, rhs)
 }
 public func +(lhs: Expression<String>, rhs: String) -> Expression<String> {
-    return Operators.concatenate.infix(lhs, rhs)
+    return Operator.concatenate.infix(lhs, rhs)
 }
 public func +(lhs: Expression<String?>, rhs: String) -> Expression<String?> {
-    return Operators.concatenate.infix(lhs, rhs)
+    return Operator.concatenate.infix(lhs, rhs)
 }
 public func +(lhs: String, rhs: Expression<String>) -> Expression<String> {
-    return Operators.concatenate.infix(lhs, rhs)
+    return Operator.concatenate.infix(lhs, rhs)
 }
 public func +(lhs: String, rhs: Expression<String?>) -> Expression<String?> {
-    return Operators.concatenate.infix(lhs, rhs)
+    return Operator.concatenate.infix(lhs, rhs)
 }
 
 // MARK: -
 
 public func +<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return Operators.plus.infix(lhs, rhs)
+    return Operator.plus.infix(lhs, rhs)
 }
 public func +<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return Operators.plus.infix(lhs, rhs)
+    return Operator.plus.infix(lhs, rhs)
 }
 public func +<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype : Number {
-    return Operators.plus.infix(lhs, rhs)
+    return Operator.plus.infix(lhs, rhs)
 }
 public func +<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return Operators.plus.infix(lhs, rhs)
+    return Operator.plus.infix(lhs, rhs)
 }
 public func +<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype : Number {
-    return Operators.plus.infix(lhs, rhs)
+    return Operator.plus.infix(lhs, rhs)
 }
 public func +<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype : Number {
-    return Operators.plus.infix(lhs, rhs)
+    return Operator.plus.infix(lhs, rhs)
 }
 public func +<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return Operators.plus.infix(lhs, rhs)
+    return Operator.plus.infix(lhs, rhs)
 }
 public func +<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return Operators.plus.infix(lhs, rhs)
+    return Operator.plus.infix(lhs, rhs)
 }
 
 public func -<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return Operators.minus.infix(lhs, rhs)
+    return Operator.minus.infix(lhs, rhs)
 }
 public func -<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return Operators.minus.infix(lhs, rhs)
+    return Operator.minus.infix(lhs, rhs)
 }
 public func -<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype : Number {
-    return Operators.minus.infix(lhs, rhs)
+    return Operator.minus.infix(lhs, rhs)
 }
 public func -<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return Operators.minus.infix(lhs, rhs)
+    return Operator.minus.infix(lhs, rhs)
 }
 public func -<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype : Number {
-    return Operators.minus.infix(lhs, rhs)
+    return Operator.minus.infix(lhs, rhs)
 }
 public func -<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype : Number {
-    return Operators.minus.infix(lhs, rhs)
+    return Operator.minus.infix(lhs, rhs)
 }
 public func -<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return Operators.minus.infix(lhs, rhs)
+    return Operator.minus.infix(lhs, rhs)
 }
 public func -<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return Operators.minus.infix(lhs, rhs)
+    return Operator.minus.infix(lhs, rhs)
 }
 
 public func *<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return Operators.mul.infix(lhs, rhs)
+    return Operator.mul.infix(lhs, rhs)
 }
 public func *<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return Operators.mul.infix(lhs, rhs)
+    return Operator.mul.infix(lhs, rhs)
 }
 public func *<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype : Number {
-    return Operators.mul.infix(lhs, rhs)
+    return Operator.mul.infix(lhs, rhs)
 }
 public func *<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return Operators.mul.infix(lhs, rhs)
+    return Operator.mul.infix(lhs, rhs)
 }
 public func *<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype : Number {
-    return Operators.mul.infix(lhs, rhs)
+    return Operator.mul.infix(lhs, rhs)
 }
 public func *<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype : Number {
-    return Operators.mul.infix(lhs, rhs)
+    return Operator.mul.infix(lhs, rhs)
 }
 public func *<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return Operators.mul.infix(lhs, rhs)
+    return Operator.mul.infix(lhs, rhs)
 }
 public func *<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return Operators.mul.infix(lhs, rhs)
+    return Operator.mul.infix(lhs, rhs)
 }
 
 public func /<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return Operators.div.infix(lhs, rhs)
+    return Operator.div.infix(lhs, rhs)
 }
 public func /<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return Operators.div.infix(lhs, rhs)
+    return Operator.div.infix(lhs, rhs)
 }
 public func /<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype : Number {
-    return Operators.div.infix(lhs, rhs)
+    return Operator.div.infix(lhs, rhs)
 }
 public func /<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return Operators.div.infix(lhs, rhs)
+    return Operator.div.infix(lhs, rhs)
 }
 public func /<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype : Number {
-    return Operators.div.infix(lhs, rhs)
+    return Operator.div.infix(lhs, rhs)
 }
 public func /<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype : Number {
-    return Operators.div.infix(lhs, rhs)
+    return Operator.div.infix(lhs, rhs)
 }
 public func /<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return Operators.div.infix(lhs, rhs)
+    return Operator.div.infix(lhs, rhs)
 }
 public func /<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return Operators.div.infix(lhs, rhs)
+    return Operator.div.infix(lhs, rhs)
 }
 
 public prefix func -<V : Value>(rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
-    return Operators.minus.wrap(rhs)
+    return Operator.minus.wrap(rhs)
 }
 public prefix func -<V : Value>(rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
-    return Operators.minus.wrap(rhs)
+    return Operator.minus.wrap(rhs)
 }
 
 // MARK: -
 
 public func %<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return Operators.mod.infix(lhs, rhs)
+    return Operator.mod.infix(lhs, rhs)
 }
 public func %<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.mod.infix(lhs, rhs)
+    return Operator.mod.infix(lhs, rhs)
 }
 public func %<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.mod.infix(lhs, rhs)
+    return Operator.mod.infix(lhs, rhs)
 }
 public func %<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.mod.infix(lhs, rhs)
+    return Operator.mod.infix(lhs, rhs)
 }
 public func %<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
-    return Operators.mod.infix(lhs, rhs)
+    return Operator.mod.infix(lhs, rhs)
 }
 public func %<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.mod.infix(lhs, rhs)
+    return Operator.mod.infix(lhs, rhs)
 }
 public func %<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return Operators.mod.infix(lhs, rhs)
+    return Operator.mod.infix(lhs, rhs)
 }
 public func %<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.mod.infix(lhs, rhs)
+    return Operator.mod.infix(lhs, rhs)
 }
 
 public func <<<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return Operators.bitwiseLeft.infix(lhs, rhs)
+    return Operator.bitwiseLeft.infix(lhs, rhs)
 }
 public func <<<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.bitwiseLeft.infix(lhs, rhs)
+    return Operator.bitwiseLeft.infix(lhs, rhs)
 }
 public func <<<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.bitwiseLeft.infix(lhs, rhs)
+    return Operator.bitwiseLeft.infix(lhs, rhs)
 }
 public func <<<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.bitwiseLeft.infix(lhs, rhs)
+    return Operator.bitwiseLeft.infix(lhs, rhs)
 }
 public func <<<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
-    return Operators.bitwiseLeft.infix(lhs, rhs)
+    return Operator.bitwiseLeft.infix(lhs, rhs)
 }
 public func <<<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.bitwiseLeft.infix(lhs, rhs)
+    return Operator.bitwiseLeft.infix(lhs, rhs)
 }
 public func <<<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return Operators.bitwiseLeft.infix(lhs, rhs)
+    return Operator.bitwiseLeft.infix(lhs, rhs)
 }
 public func <<<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.bitwiseLeft.infix(lhs, rhs)
+    return Operator.bitwiseLeft.infix(lhs, rhs)
 }
 
 public func >><V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return Operators.bitwiseRight.infix(lhs, rhs)
+    return Operator.bitwiseRight.infix(lhs, rhs)
 }
 public func >><V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.bitwiseRight.infix(lhs, rhs)
+    return Operator.bitwiseRight.infix(lhs, rhs)
 }
 public func >><V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.bitwiseRight.infix(lhs, rhs)
+    return Operator.bitwiseRight.infix(lhs, rhs)
 }
 public func >><V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.bitwiseRight.infix(lhs, rhs)
+    return Operator.bitwiseRight.infix(lhs, rhs)
 }
 public func >><V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
-    return Operators.bitwiseRight.infix(lhs, rhs)
+    return Operator.bitwiseRight.infix(lhs, rhs)
 }
 public func >><V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.bitwiseRight.infix(lhs, rhs)
+    return Operator.bitwiseRight.infix(lhs, rhs)
 }
 public func >><V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return Operators.bitwiseRight.infix(lhs, rhs)
+    return Operator.bitwiseRight.infix(lhs, rhs)
 }
 public func >><V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.bitwiseRight.infix(lhs, rhs)
+    return Operator.bitwiseRight.infix(lhs, rhs)
 }
 
 public func &<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return Operators.bitwiseAnd.infix(lhs, rhs)
+    return Operator.bitwiseAnd.infix(lhs, rhs)
 }
 public func &<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.bitwiseAnd.infix(lhs, rhs)
+    return Operator.bitwiseAnd.infix(lhs, rhs)
 }
 public func &<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.bitwiseAnd.infix(lhs, rhs)
+    return Operator.bitwiseAnd.infix(lhs, rhs)
 }
 public func &<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.bitwiseAnd.infix(lhs, rhs)
+    return Operator.bitwiseAnd.infix(lhs, rhs)
 }
 public func &<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
-    return Operators.bitwiseAnd.infix(lhs, rhs)
+    return Operator.bitwiseAnd.infix(lhs, rhs)
 }
 public func &<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.bitwiseAnd.infix(lhs, rhs)
+    return Operator.bitwiseAnd.infix(lhs, rhs)
 }
 public func &<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return Operators.bitwiseAnd.infix(lhs, rhs)
+    return Operator.bitwiseAnd.infix(lhs, rhs)
 }
 public func &<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.bitwiseAnd.infix(lhs, rhs)
+    return Operator.bitwiseAnd.infix(lhs, rhs)
 }
 
 public func |<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return Operators.bitwiseOr.infix(lhs, rhs)
+    return Operator.bitwiseOr.infix(lhs, rhs)
 }
 public func |<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.bitwiseOr.infix(lhs, rhs)
+    return Operator.bitwiseOr.infix(lhs, rhs)
 }
 public func |<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.bitwiseOr.infix(lhs, rhs)
+    return Operator.bitwiseOr.infix(lhs, rhs)
 }
 public func |<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.bitwiseOr.infix(lhs, rhs)
+    return Operator.bitwiseOr.infix(lhs, rhs)
 }
 public func |<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
-    return Operators.bitwiseOr.infix(lhs, rhs)
+    return Operator.bitwiseOr.infix(lhs, rhs)
 }
 public func |<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.bitwiseOr.infix(lhs, rhs)
+    return Operator.bitwiseOr.infix(lhs, rhs)
 }
 public func |<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return Operators.bitwiseOr.infix(lhs, rhs)
+    return Operator.bitwiseOr.infix(lhs, rhs)
 }
 public func |<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.bitwiseOr.infix(lhs, rhs)
+    return Operator.bitwiseOr.infix(lhs, rhs)
 }
 
 public func ^<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
@@ -343,166 +343,166 @@ public func ^<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.
 }
 
 public prefix func ~<V : Value>(rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return Operators.bitwiseXor.wrap(rhs)
+    return Operator.bitwiseXor.wrap(rhs)
 }
 public prefix func ~<V : Value>(rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operators.bitwiseXor.wrap(rhs)
+    return Operator.bitwiseXor.wrap(rhs)
 }
 
 // MARK: -
 
 public func ==<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
-    return Operators.eq.infix(lhs, rhs)
+    return Operator.eq.infix(lhs, rhs)
 }
 public func ==<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
-    return Operators.eq.infix(lhs, rhs)
+    return Operator.eq.infix(lhs, rhs)
 }
 public func ==<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Equatable {
-    return Operators.eq.infix(lhs, rhs)
+    return Operator.eq.infix(lhs, rhs)
 }
 public func ==<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
-    return Operators.eq.infix(lhs, rhs)
+    return Operator.eq.infix(lhs, rhs)
 }
 public func ==<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Equatable {
-    return Operators.eq.infix(lhs, rhs)
+    return Operator.eq.infix(lhs, rhs)
 }
 public func ==<V : Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype : Equatable {
     guard let rhs = rhs else { return "IS".infix(lhs, Expression<V?>(value: nil)) }
-    return Operators.eq.infix(lhs, rhs)
+    return Operator.eq.infix(lhs, rhs)
 }
 public func ==<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
-    return Operators.eq.infix(lhs, rhs)
+    return Operator.eq.infix(lhs, rhs)
 }
 public func ==<V : Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
     guard let lhs = lhs else { return "IS".infix(Expression<V?>(value: nil), rhs) }
-    return Operators.eq.infix(lhs, rhs)
+    return Operator.eq.infix(lhs, rhs)
 }
 
 public func !=<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
-    return Operators.neq.infix(lhs, rhs)
+    return Operator.neq.infix(lhs, rhs)
 }
 public func !=<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
-    return Operators.neq.infix(lhs, rhs)
+    return Operator.neq.infix(lhs, rhs)
 }
 public func !=<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Equatable {
-    return Operators.neq.infix(lhs, rhs)
+    return Operator.neq.infix(lhs, rhs)
 }
 public func !=<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
-    return Operators.neq.infix(lhs, rhs)
+    return Operator.neq.infix(lhs, rhs)
 }
 public func !=<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Equatable {
-    return Operators.neq.infix(lhs, rhs)
+    return Operator.neq.infix(lhs, rhs)
 }
 public func !=<V : Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype : Equatable {
     guard let rhs = rhs else { return "IS NOT".infix(lhs, Expression<V?>(value: nil)) }
-    return Operators.neq.infix(lhs, rhs)
+    return Operator.neq.infix(lhs, rhs)
 }
 public func !=<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
-    return Operators.neq.infix(lhs, rhs)
+    return Operator.neq.infix(lhs, rhs)
 }
 public func !=<V : Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
     guard let lhs = lhs else { return "IS NOT".infix(Expression<V?>(value: nil), rhs) }
-    return Operators.neq.infix(lhs, rhs)
+    return Operator.neq.infix(lhs, rhs)
 }
 
 public func ><V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return Operators.gt.infix(lhs, rhs)
+    return Operator.gt.infix(lhs, rhs)
 }
 public func ><V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return Operators.gt.infix(lhs, rhs)
+    return Operator.gt.infix(lhs, rhs)
 }
 public func ><V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return Operators.gt.infix(lhs, rhs)
+    return Operator.gt.infix(lhs, rhs)
 }
 public func ><V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return Operators.gt.infix(lhs, rhs)
+    return Operator.gt.infix(lhs, rhs)
 }
 public func ><V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Comparable {
-    return Operators.gt.infix(lhs, rhs)
+    return Operator.gt.infix(lhs, rhs)
 }
 public func ><V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype : Comparable {
-    return Operators.gt.infix(lhs, rhs)
+    return Operator.gt.infix(lhs, rhs)
 }
 public func ><V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return Operators.gt.infix(lhs, rhs)
+    return Operator.gt.infix(lhs, rhs)
 }
 public func ><V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return Operators.gt.infix(lhs, rhs)
+    return Operator.gt.infix(lhs, rhs)
 }
 
 public func >=<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return Operators.gte.infix(lhs, rhs)
+    return Operator.gte.infix(lhs, rhs)
 }
 public func >=<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return Operators.gte.infix(lhs, rhs)
+    return Operator.gte.infix(lhs, rhs)
 }
 public func >=<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return Operators.gte.infix(lhs, rhs)
+    return Operator.gte.infix(lhs, rhs)
 }
 public func >=<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return Operators.gte.infix(lhs, rhs)
+    return Operator.gte.infix(lhs, rhs)
 }
 public func >=<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Comparable {
-    return Operators.gte.infix(lhs, rhs)
+    return Operator.gte.infix(lhs, rhs)
 }
 public func >=<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype : Comparable {
-    return Operators.gte.infix(lhs, rhs)
+    return Operator.gte.infix(lhs, rhs)
 }
 public func >=<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return Operators.gte.infix(lhs, rhs)
+    return Operator.gte.infix(lhs, rhs)
 }
 public func >=<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return Operators.gte.infix(lhs, rhs)
+    return Operator.gte.infix(lhs, rhs)
 }
 
 public func <<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return Operators.lt.infix(lhs, rhs)
+    return Operator.lt.infix(lhs, rhs)
 }
 public func <<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return Operators.lt.infix(lhs, rhs)
+    return Operator.lt.infix(lhs, rhs)
 }
 public func <<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return Operators.lt.infix(lhs, rhs)
+    return Operator.lt.infix(lhs, rhs)
 }
 public func <<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return Operators.lt.infix(lhs, rhs)
+    return Operator.lt.infix(lhs, rhs)
 }
 public func <<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Comparable {
-    return Operators.lt.infix(lhs, rhs)
+    return Operator.lt.infix(lhs, rhs)
 }
 public func <<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype : Comparable {
-    return Operators.lt.infix(lhs, rhs)
+    return Operator.lt.infix(lhs, rhs)
 }
 public func <<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return Operators.lt.infix(lhs, rhs)
+    return Operator.lt.infix(lhs, rhs)
 }
 public func <<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return Operators.lt.infix(lhs, rhs)
+    return Operator.lt.infix(lhs, rhs)
 }
 
 public func <=<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return Operators.lte.infix(lhs, rhs)
+    return Operator.lte.infix(lhs, rhs)
 }
 public func <=<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return Operators.lte.infix(lhs, rhs)
+    return Operator.lte.infix(lhs, rhs)
 }
 public func <=<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return Operators.lte.infix(lhs, rhs)
+    return Operator.lte.infix(lhs, rhs)
 }
 public func <=<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return Operators.lte.infix(lhs, rhs)
+    return Operator.lte.infix(lhs, rhs)
 }
 public func <=<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Comparable {
-    return Operators.lte.infix(lhs, rhs)
+    return Operator.lte.infix(lhs, rhs)
 }
 public func <=<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype : Comparable {
-    return Operators.lte.infix(lhs, rhs)
+    return Operator.lte.infix(lhs, rhs)
 }
 public func <=<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
-    return Operators.lte.infix(lhs, rhs)
+    return Operator.lte.infix(lhs, rhs)
 }
 public func <=<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
-    return Operators.lte.infix(lhs, rhs)
+    return Operator.lte.infix(lhs, rhs)
 }
 
 public func ~=<V : Value>(lhs: ClosedRange<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable & Value {
@@ -548,58 +548,58 @@ public func ~=<V : Value>(lhs: PartialRangeFrom<V>, rhs: Expression<V?>) -> Expr
 // MARK: -
 
 public func &&(lhs: Expression<Bool>, rhs: Expression<Bool>) -> Expression<Bool> {
-    return Operators.and.infix(lhs, rhs)
+    return Operator.and.infix(lhs, rhs)
 }
 public func &&(lhs: Expression<Bool>, rhs: Expression<Bool?>) -> Expression<Bool?> {
-    return Operators.and.infix(lhs, rhs)
+    return Operator.and.infix(lhs, rhs)
 }
 public func &&(lhs: Expression<Bool?>, rhs: Expression<Bool>) -> Expression<Bool?> {
-    return Operators.and.infix(lhs, rhs)
+    return Operator.and.infix(lhs, rhs)
 }
 public func &&(lhs: Expression<Bool?>, rhs: Expression<Bool?>) -> Expression<Bool?> {
-    return Operators.and.infix(lhs, rhs)
+    return Operator.and.infix(lhs, rhs)
 }
 public func &&(lhs: Expression<Bool>, rhs: Bool) -> Expression<Bool> {
-    return Operators.and.infix(lhs, rhs)
+    return Operator.and.infix(lhs, rhs)
 }
 public func &&(lhs: Expression<Bool?>, rhs: Bool) -> Expression<Bool?> {
-    return Operators.and.infix(lhs, rhs)
+    return Operator.and.infix(lhs, rhs)
 }
 public func &&(lhs: Bool, rhs: Expression<Bool>) -> Expression<Bool> {
-    return Operators.and.infix(lhs, rhs)
+    return Operator.and.infix(lhs, rhs)
 }
 public func &&(lhs: Bool, rhs: Expression<Bool?>) -> Expression<Bool?> {
-    return Operators.and.infix(lhs, rhs)
+    return Operator.and.infix(lhs, rhs)
 }
 
 public func ||(lhs: Expression<Bool>, rhs: Expression<Bool>) -> Expression<Bool> {
-    return Operators.or.infix(lhs, rhs)
+    return Operator.or.infix(lhs, rhs)
 }
 public func ||(lhs: Expression<Bool>, rhs: Expression<Bool?>) -> Expression<Bool?> {
-    return Operators.or.infix(lhs, rhs)
+    return Operator.or.infix(lhs, rhs)
 }
 public func ||(lhs: Expression<Bool?>, rhs: Expression<Bool>) -> Expression<Bool?> {
-    return Operators.or.infix(lhs, rhs)
+    return Operator.or.infix(lhs, rhs)
 }
 public func ||(lhs: Expression<Bool?>, rhs: Expression<Bool?>) -> Expression<Bool?> {
-    return Operators.or.infix(lhs, rhs)
+    return Operator.or.infix(lhs, rhs)
 }
 public func ||(lhs: Expression<Bool>, rhs: Bool) -> Expression<Bool> {
-    return Operators.or.infix(lhs, rhs)
+    return Operator.or.infix(lhs, rhs)
 }
 public func ||(lhs: Expression<Bool?>, rhs: Bool) -> Expression<Bool?> {
-    return Operators.or.infix(lhs, rhs)
+    return Operator.or.infix(lhs, rhs)
 }
 public func ||(lhs: Bool, rhs: Expression<Bool>) -> Expression<Bool> {
-    return Operators.or.infix(lhs, rhs)
+    return Operator.or.infix(lhs, rhs)
 }
 public func ||(lhs: Bool, rhs: Expression<Bool?>) -> Expression<Bool?> {
-    return Operators.or.infix(lhs, rhs)
+    return Operator.or.infix(lhs, rhs)
 }
 
 public prefix func !(rhs: Expression<Bool>) -> Expression<Bool> {
-    return Operators.not.wrap(rhs)
+    return Operator.not.wrap(rhs)
 }
 public prefix func !(rhs: Expression<Bool?>) -> Expression<Bool?> {
-    return Operators.not.wrap(rhs)
+    return Operator.not.wrap(rhs)
 }

From 93f55680604889fea660f191fb9b757d43d961b6 Mon Sep 17 00:00:00 2001
From: Shawn Burlew <shawn.burlew@apgdata.com>
Date: Sat, 30 Mar 2019 16:28:40 -0600
Subject: [PATCH 324/685] Updated project to Swift 5, fixed build warnings

---
 SQLite.xcodeproj/project.pbxproj              | 11 +++++---
 .../xcschemes/SQLite Mac.xcscheme             |  2 +-
 .../xcschemes/SQLite iOS.xcscheme             |  2 +-
 .../xcschemes/SQLite tvOS.xcscheme            |  2 +-
 .../xcschemes/SQLite watchOS.xcscheme         |  2 +-
 Sources/SQLite/Foundation.swift               |  6 ++--
 Sources/SQLite/Typed/CustomFunctions.swift    | 28 +++++++++----------
 7 files changed, 28 insertions(+), 25 deletions(-)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index a155a115..2294065f 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -680,7 +680,7 @@
 			isa = PBXProject;
 			attributes = {
 				LastSwiftUpdateCheck = 0720;
-				LastUpgradeCheck = 0930;
+				LastUpgradeCheck = 1020;
 				TargetAttributes = {
 					03A65E591C6BB0F50062603F = {
 						CreatedOnToolsVersion = 7.2;
@@ -714,10 +714,11 @@
 			};
 			buildConfigurationList = EE247ACD1C3F04ED00AE3E12 /* Build configuration list for PBXProject "SQLite" */;
 			compatibilityVersion = "Xcode 3.2";
-			developmentRegion = English;
+			developmentRegion = en;
 			hasScannedForEncodings = 0;
 			knownRegions = (
 				en,
+				Base,
 			);
 			mainGroup = EE247AC91C3F04ED00AE3E12;
 			productRefGroup = EE247AD41C3F04ED00AE3E12 /* Products */;
@@ -1140,6 +1141,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
 				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
 				CLANG_CXX_LIBRARY = "libc++";
 				CLANG_ENABLE_MODULES = YES;
@@ -1200,6 +1202,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
 				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
 				CLANG_CXX_LIBRARY = "libc++";
 				CLANG_ENABLE_MODULES = YES;
@@ -1269,7 +1272,7 @@
 				SKIP_INSTALL = YES;
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.2;
+				SWIFT_VERSION = 5.0;
 			};
 			name = Debug;
 		};
@@ -1291,7 +1294,7 @@
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.2;
+				SWIFT_VERSION = 5.0;
 			};
 			name = Release;
 		};
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme
index 2691862e..4e94e80a 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme	
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0930"
+   LastUpgradeVersion = "1020"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme
index 8b3cd73b..f4ba4231 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme	
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0930"
+   LastUpgradeVersion = "1020"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme
index 9b444924..7a3ddbfb 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme	
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0930"
+   LastUpgradeVersion = "1020"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite watchOS.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite watchOS.xcscheme
index e45dbe7d..ace02712 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite watchOS.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite watchOS.xcscheme	
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0930"
+   LastUpgradeVersion = "1020"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
diff --git a/Sources/SQLite/Foundation.swift b/Sources/SQLite/Foundation.swift
index 5638bc5b..cfb79bec 100644
--- a/Sources/SQLite/Foundation.swift
+++ b/Sources/SQLite/Foundation.swift
@@ -31,12 +31,12 @@ extension Data : Value {
     }
 
     public static func fromDatatypeValue(_ dataValue: Blob) -> Data {
-        return Data(bytes: dataValue.bytes)
+        return Data(dataValue.bytes)
     }
 
     public var datatypeValue: Blob {
-        return withUnsafeBytes { (pointer: UnsafePointer<UInt8>) -> Blob in
-            return Blob(bytes: pointer, length: count)
+        return withUnsafeBytes { (pointer: UnsafeRawBufferPointer) -> Blob in
+            return Blob(bytes: pointer.baseAddress!, length: count)
         }
     }
 
diff --git a/Sources/SQLite/Typed/CustomFunctions.swift b/Sources/SQLite/Typed/CustomFunctions.swift
index 2389901f..8910a24b 100644
--- a/Sources/SQLite/Typed/CustomFunctions.swift
+++ b/Sources/SQLite/Typed/CustomFunctions.swift
@@ -39,76 +39,76 @@ public extension Connection {
     ///     The assigned types must be explicit.
     ///
     /// - Returns: A closure returning an SQL expression to call the function.
-    public func createFunction<Z : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping () -> Z) throws -> (() -> Expression<Z>) {
+    func createFunction<Z : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping () -> Z) throws -> (() -> Expression<Z>) {
         let fn = try createFunction(function, 0, deterministic) { _ in block() }
         return { fn([]) }
     }
 
-    public func createFunction<Z : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping () -> Z?) throws -> (() -> Expression<Z?>) {
+    func createFunction<Z : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping () -> Z?) throws -> (() -> Expression<Z?>) {
         let fn = try createFunction(function, 0, deterministic) { _ in block() }
         return { fn([]) }
     }
 
     // MARK: -
 
-    public func createFunction<Z : Value, A : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A) -> Z) throws -> ((Expression<A>) -> Expression<Z>) {
+    func createFunction<Z : Value, A : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A) -> Z) throws -> ((Expression<A>) -> Expression<Z>) {
         let fn = try createFunction(function, 1, deterministic) { args in block(value(args[0])) }
         return { arg in fn([arg]) }
     }
 
-    public func createFunction<Z : Value, A : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?) -> Z) throws -> ((Expression<A?>) -> Expression<Z>) {
+    func createFunction<Z : Value, A : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?) -> Z) throws -> ((Expression<A?>) -> Expression<Z>) {
         let fn = try createFunction(function, 1, deterministic) { args in block(args[0].map(value)) }
         return { arg in fn([arg]) }
     }
 
-    public func createFunction<Z : Value, A : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A) -> Z?) throws -> ((Expression<A>) -> Expression<Z?>) {
+    func createFunction<Z : Value, A : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A) -> Z?) throws -> ((Expression<A>) -> Expression<Z?>) {
         let fn = try createFunction(function, 1, deterministic) { args in block(value(args[0])) }
         return { arg in fn([arg]) }
     }
 
-    public func createFunction<Z : Value, A : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?) -> Z?) throws -> ((Expression<A?>) -> Expression<Z?>) {
+    func createFunction<Z : Value, A : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?) -> Z?) throws -> ((Expression<A?>) -> Expression<Z?>) {
         let fn = try createFunction(function, 1, deterministic) { args in block(args[0].map(value)) }
         return { arg in fn([arg]) }
     }
 
     // MARK: -
 
-    public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B) -> Z) throws -> (Expression<A>, Expression<B>) -> Expression<Z> {
+    func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B) -> Z) throws -> (Expression<A>, Expression<B>) -> Expression<Z> {
         let fn = try createFunction(function, 2, deterministic) { args in block(value(args[0]), value(args[1])) }
         return { a, b in fn([a, b]) }
     }
 
-    public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B) -> Z) throws -> (Expression<A?>, Expression<B>) -> Expression<Z> {
+    func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B) -> Z) throws -> (Expression<A?>, Expression<B>) -> Expression<Z> {
         let fn = try createFunction(function, 2, deterministic) { args in block(args[0].map(value), value(args[1])) }
         return { a, b in fn([a, b]) }
     }
 
-    public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B?) -> Z) throws -> (Expression<A>, Expression<B?>) -> Expression<Z> {
+    func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B?) -> Z) throws -> (Expression<A>, Expression<B?>) -> Expression<Z> {
         let fn = try createFunction(function, 2, deterministic) { args in block(value(args[0]), args[1].map(value)) }
         return { a, b in fn([a, b]) }
     }
 
-    public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B) -> Z?) throws -> (Expression<A>, Expression<B>) -> Expression<Z?> {
+    func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B) -> Z?) throws -> (Expression<A>, Expression<B>) -> Expression<Z?> {
         let fn = try createFunction(function, 2, deterministic) { args in block(value(args[0]), value(args[1])) }
         return { a, b in fn([a, b]) }
     }
 
-    public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B?) -> Z) throws -> (Expression<A?>, Expression<B?>) -> Expression<Z> {
+    func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B?) -> Z) throws -> (Expression<A?>, Expression<B?>) -> Expression<Z> {
         let fn = try createFunction(function, 2, deterministic) { args in block(args[0].map(value), args[1].map(value)) }
         return { a, b in fn([a, b]) }
     }
 
-    public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B) -> Z?) throws -> (Expression<A?>, Expression<B>) -> Expression<Z?> {
+    func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B) -> Z?) throws -> (Expression<A?>, Expression<B>) -> Expression<Z?> {
         let fn = try createFunction(function, 2, deterministic) { args in block(args[0].map(value), value(args[1])) }
         return { a, b in fn([a, b]) }
     }
 
-    public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B?) -> Z?) throws -> (Expression<A>, Expression<B?>) -> Expression<Z?> {
+    func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B?) -> Z?) throws -> (Expression<A>, Expression<B?>) -> Expression<Z?> {
         let fn = try createFunction(function, 2, deterministic) { args in block(value(args[0]), args[1].map(value)) }
         return { a, b in fn([a, b]) }
     }
 
-    public func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B?) -> Z?) throws -> (Expression<A?>, Expression<B?>) -> Expression<Z?> {
+    func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B?) -> Z?) throws -> (Expression<A?>, Expression<B?>) -> Expression<Z?> {
         let fn = try createFunction(function, 2, deterministic) { args in block(args[0].map(value), args[1].map(value)) }
         return { a, b in fn([a, b]) }
     }

From e28f30c0f861b1e35eae17e9f04e1d0b8c1206d6 Mon Sep 17 00:00:00 2001
From: Shawn Burlew <shawn.burlew@apgdata.com>
Date: Wed, 3 Apr 2019 11:28:18 -0600
Subject: [PATCH 325/685] Swift 5 - Passed through project language version
 setting to framework & unit test targets - Bumped version to 0.11.6 in
 documentation & pod spec - Fixed build warnings in unit test code for Swift 5

---
 Documentation/Index.md                  | 16 ++++++-------
 README.md                               | 10 ++++----
 SQLite.swift.podspec                    |  4 ++--
 SQLite.xcodeproj/project.pbxproj        | 32 +++----------------------
 Tests/SQLiteTests/FoundationTests.swift |  4 ++--
 5 files changed, 20 insertions(+), 46 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 628e7464..9d40bfdd 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -67,8 +67,8 @@
 
 ## Installation
 
-> _Note:_ SQLite.swift requires Swift 4.1 (and
-> [Xcode 9.3](https://developer.apple.com/xcode/downloads/)) or greater.
+> _Note:_ SQLite.swift requires Swift 5 (and
+> [Xcode 10.2](https://developer.apple.com/xcode/downloads/)) or greater.
 
 
 ### Carthage
@@ -80,7 +80,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.11.5
+    github "stephencelis/SQLite.swift" ~> 0.11.6
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -110,7 +110,7 @@ install SQLite.swift with Carthage:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.11.5'
+        pod 'SQLite.swift', '~> 0.11.6'
     end
     ```
 
@@ -124,7 +124,7 @@ with the OS you can require the `standalone` subspec:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.11.5'
+  pod 'SQLite.swift/standalone', '~> 0.11.6'
 end
 ```
 
@@ -134,7 +134,7 @@ dependency to sqlite3 or one of its subspecs:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.11.5'
+  pod 'SQLite.swift/standalone', '~> 0.11.6'
   pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
 end
 ```
@@ -148,7 +148,7 @@ If you want to use [SQLCipher][] with SQLite.swift you can require the
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/SQLCipher', '~> 0.11.5'
+  pod 'SQLite.swift/SQLCipher', '~> 0.11.6'
 end
 ```
 
@@ -181,7 +181,7 @@ applications.
 
   ```swift
   dependencies: [
-    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.11.5")
+    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.11.6")
   ]
   ```
 
diff --git a/README.md b/README.md
index bc43b6ec..33598c69 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # SQLite.swift
 
-[![Build Status][TravisBadge]][TravisLink] [![CocoaPods Version][CocoaPodsVersionBadge]][CocoaPodsVersionLink] [![Swift4 compatible][Swift4Badge]][Swift4Link] [![Platform][PlatformBadge]][PlatformLink] [![Carthage compatible][CartagheBadge]][CarthageLink] [![Join the chat at https://gitter.im/stephencelis/SQLite.swift][GitterBadge]][GitterLink]
+[![Build Status][TravisBadge]][TravisLink] [![CocoaPods Version][CocoaPodsVersionBadge]][CocoaPodsVersionLink] [![Swift5 compatible][Swift5Badge]][Swift5Link] [![Platform][PlatformBadge]][PlatformLink] [![Carthage compatible][CartagheBadge]][CarthageLink] [![Join the chat at https://gitter.im/stephencelis/SQLite.swift][GitterBadge]][GitterLink]
 
 A type-safe, [Swift][]-language layer over [SQLite3][].
 
@@ -112,7 +112,7 @@ and the [companion repository][SQLiteDataAccessLayer2].
 
 ## Installation
 
-> _Note:_ SQLite.swift requires Swift 4.1 (and [Xcode][] 9.3).
+> _Note:_ SQLite.swift requires Swift 5 (and [Xcode][] 10.2).
 
 ### Carthage
 
@@ -124,7 +124,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.11.5
+    github "stephencelis/SQLite.swift" ~> 0.11.6
     ```
 
  3. Run `carthage update` and
@@ -156,7 +156,7 @@ SQLite.swift with CocoaPods:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.11.5'
+        pod 'SQLite.swift', '~> 0.11.6'
     end
     ```
 
@@ -174,7 +174,7 @@ Swift code.
 
   ```swift
   dependencies: [
-      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.11.5")
+      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.11.6")
   ]
   ```
 
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index c2235aca..63987b4b 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.11.5"
+  s.version          = "0.11.6"
   s.summary          = "A type-safe, Swift-language layer over SQLite3 for iOS and OS X."
 
   s.description      = <<-DESC
@@ -21,7 +21,7 @@ Pod::Spec.new do |s|
   s.watchos.deployment_target = "2.2"
   s.default_subspec  = 'standard'
   s.pod_target_xcconfig = {
-    'SWIFT_VERSION' => '4.2',
+    'SWIFT_VERSION' => '5',
   }
 
   s.subspec 'standard' do |ss|
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 2294065f..9d38dbc4 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -700,7 +700,7 @@
 					};
 					EE247ADC1C3F04ED00AE3E12 = {
 						CreatedOnToolsVersion = 7.2;
-						LastSwiftMigration = 0900;
+						LastSwiftMigration = 1020;
 					};
 					EE247B3B1C3F3ED000AE3E12 = {
 						CreatedOnToolsVersion = 7.2;
@@ -1033,8 +1033,6 @@
 				PRODUCT_NAME = SQLite;
 				SDKROOT = appletvos;
 				SKIP_INSTALL = YES;
-				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.2;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
 			name = Debug;
@@ -1055,8 +1053,6 @@
 				PRODUCT_NAME = SQLite;
 				SDKROOT = appletvos;
 				SKIP_INSTALL = YES;
-				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.2;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
 			name = Release;
@@ -1069,8 +1065,6 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = appletvos;
-				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.2;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
 			name = Debug;
@@ -1083,8 +1077,6 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = appletvos;
-				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.2;
 				TVOS_DEPLOYMENT_TARGET = 9.1;
 			};
 			name = Release;
@@ -1106,8 +1098,6 @@
 				PRODUCT_NAME = SQLite;
 				SDKROOT = watchos;
 				SKIP_INSTALL = YES;
-				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.2;
 				TARGETED_DEVICE_FAMILY = 4;
 				WATCHOS_DEPLOYMENT_TARGET = 2.2;
 			};
@@ -1130,8 +1120,6 @@
 				PRODUCT_NAME = SQLite;
 				SDKROOT = watchos;
 				SKIP_INSTALL = YES;
-				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.2;
 				TARGETED_DEVICE_FAMILY = 4;
 				WATCHOS_DEPLOYMENT_TARGET = 2.2;
 			};
@@ -1192,6 +1180,7 @@
 				PRODUCT_NAME = "";
 				SDKROOT = iphoneos;
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+				SWIFT_VERSION = 5.0;
 				TARGETED_DEVICE_FAMILY = "1,2,3";
 				VERSIONING_SYSTEM = "apple-generic";
 				VERSION_INFO_PREFIX = "";
@@ -1246,6 +1235,7 @@
 				PRODUCT_NAME = "";
 				SDKROOT = iphoneos;
 				SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+				SWIFT_VERSION = 5.0;
 				TARGETED_DEVICE_FAMILY = "1,2,3";
 				VALIDATE_PRODUCT = YES;
 				VERSIONING_SYSTEM = "apple-generic";
@@ -1271,8 +1261,6 @@
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
-				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 5.0;
 			};
 			name = Debug;
 		};
@@ -1293,8 +1281,6 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
-				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 5.0;
 			};
 			name = Release;
 		};
@@ -1306,8 +1292,6 @@
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
-				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.2;
 			};
 			name = Debug;
 		};
@@ -1319,8 +1303,6 @@
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
-				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.2;
 			};
 			name = Release;
 		};
@@ -1344,8 +1326,6 @@
 				SDKROOT = macosx;
 				SKIP_INSTALL = YES;
 				SWIFT_INCLUDE_PATHS = "";
-				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.2;
 			};
 			name = Debug;
 		};
@@ -1369,8 +1349,6 @@
 				SDKROOT = macosx;
 				SKIP_INSTALL = YES;
 				SWIFT_INCLUDE_PATHS = "";
-				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.2;
 			};
 			name = Release;
 		};
@@ -1385,8 +1363,6 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = macosx;
-				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.2;
 			};
 			name = Debug;
 		};
@@ -1401,8 +1377,6 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = macosx;
-				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
-				SWIFT_VERSION = 4.2;
 			};
 			name = Release;
 		};
diff --git a/Tests/SQLiteTests/FoundationTests.swift b/Tests/SQLiteTests/FoundationTests.swift
index 0df746d9..dd80afc1 100644
--- a/Tests/SQLiteTests/FoundationTests.swift
+++ b/Tests/SQLiteTests/FoundationTests.swift
@@ -3,7 +3,7 @@ import SQLite
 
 class FoundationTests : XCTestCase {
     func testDataFromBlob() {
-        let data = Data(bytes: [1, 2, 3])
+        let data = Data([1, 2, 3])
         let blob = data.datatypeValue
         XCTAssertEqual([1, 2, 3], blob.bytes)
     }
@@ -11,6 +11,6 @@ class FoundationTests : XCTestCase {
     func testBlobToData() {
         let blob = Blob(bytes: [1, 2, 3])
         let data = Data.fromDatatypeValue(blob)
-        XCTAssertEqual(Data(bytes: [1, 2, 3]), data)
+        XCTAssertEqual(Data([1, 2, 3]), data)
     }
 }

From 7a98a95ebc0a01729a490e6684e8221fd7adf5d8 Mon Sep 17 00:00:00 2001
From: Shawn Burlew <shawn.burlew@apgdata.com>
Date: Thu, 4 Apr 2019 09:16:01 -0600
Subject: [PATCH 326/685] - Reverted to swift 4.2, will go to 5 in another
 version update - Updated CI config

---
 .travis.yml                      | 4 ++--
 SQLite.xcodeproj/project.pbxproj | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 909e5672..f1212412 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,11 +1,11 @@
 language: objective-c
 rvm: 2.3
 # https://docs.travis-ci.com/user/reference/osx
-osx_image: xcode10.1
+osx_image: xcode10.2
 env:
   global:
     - IOS_SIMULATOR="iPhone 6s"
-    - IOS_VERSION="12.1"
+    - IOS_VERSION="12.2"
 matrix:
   include:
     - env: BUILD_SCHEME="SQLite iOS"
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 9d38dbc4..2eb11fd9 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1180,7 +1180,7 @@
 				PRODUCT_NAME = "";
 				SDKROOT = iphoneos;
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
-				SWIFT_VERSION = 5.0;
+				SWIFT_VERSION = 4.2;
 				TARGETED_DEVICE_FAMILY = "1,2,3";
 				VERSIONING_SYSTEM = "apple-generic";
 				VERSION_INFO_PREFIX = "";
@@ -1235,7 +1235,7 @@
 				PRODUCT_NAME = "";
 				SDKROOT = iphoneos;
 				SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
-				SWIFT_VERSION = 5.0;
+				SWIFT_VERSION = 4.2;
 				TARGETED_DEVICE_FAMILY = "1,2,3";
 				VALIDATE_PRODUCT = YES;
 				VERSIONING_SYSTEM = "apple-generic";

From 291f1842138b034d48b65df7a5b4972cbee920c3 Mon Sep 17 00:00:00 2001
From: Shawn Burlew <shawn.burlew@apgdata.com>
Date: Thu, 4 Apr 2019 09:24:15 -0600
Subject: [PATCH 327/685] Reverted other instances of swift 5 / Xcode 10.2 in
 documentation

---
 Documentation/Index.md | 4 ++--
 README.md              | 4 ++--
 SQLite.swift.podspec   | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 9d40bfdd..cf4815b9 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -67,8 +67,8 @@
 
 ## Installation
 
-> _Note:_ SQLite.swift requires Swift 5 (and
-> [Xcode 10.2](https://developer.apple.com/xcode/downloads/)) or greater.
+> _Note:_ SQLite.swift requires Swift 4.2 (and
+> [Xcode 9.3](https://developer.apple.com/xcode/downloads/)) or greater.
 
 
 ### Carthage
diff --git a/README.md b/README.md
index 33598c69..9192fe21 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # SQLite.swift
 
-[![Build Status][TravisBadge]][TravisLink] [![CocoaPods Version][CocoaPodsVersionBadge]][CocoaPodsVersionLink] [![Swift5 compatible][Swift5Badge]][Swift5Link] [![Platform][PlatformBadge]][PlatformLink] [![Carthage compatible][CartagheBadge]][CarthageLink] [![Join the chat at https://gitter.im/stephencelis/SQLite.swift][GitterBadge]][GitterLink]
+[![Build Status][TravisBadge]][TravisLink] [![CocoaPods Version][CocoaPodsVersionBadge]][CocoaPodsVersionLink] [![Swift4 compatible][Swift4Badge]][Swift4Link] [![Platform][PlatformBadge]][PlatformLink] [![Carthage compatible][CartagheBadge]][CarthageLink] [![Join the chat at https://gitter.im/stephencelis/SQLite.swift][GitterBadge]][GitterLink]
 
 A type-safe, [Swift][]-language layer over [SQLite3][].
 
@@ -112,7 +112,7 @@ and the [companion repository][SQLiteDataAccessLayer2].
 
 ## Installation
 
-> _Note:_ SQLite.swift requires Swift 5 (and [Xcode][] 10.2).
+> _Note:_ SQLite.swift requires Swift 4.2 (and [Xcode][] 9.3).
 
 ### Carthage
 
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 63987b4b..fcdf88c1 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -21,7 +21,7 @@ Pod::Spec.new do |s|
   s.watchos.deployment_target = "2.2"
   s.default_subspec  = 'standard'
   s.pod_target_xcconfig = {
-    'SWIFT_VERSION' => '5',
+    'SWIFT_VERSION' => '4.2',
   }
 
   s.subspec 'standard' do |ss|

From 7de9ee55694ae2b7df964c27724bb2811fb1ed9f Mon Sep 17 00:00:00 2001
From: Shawn Burlew <shawn.burlew@apgdata.com>
Date: Fri, 5 Apr 2019 08:53:37 -0600
Subject: [PATCH 328/685] Changed CI config back to Xcode 10.1, updated
 documents

---
 .travis.yml            | 4 ++--
 Documentation/Index.md | 2 +-
 README.md              | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index f1212412..909e5672 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,11 +1,11 @@
 language: objective-c
 rvm: 2.3
 # https://docs.travis-ci.com/user/reference/osx
-osx_image: xcode10.2
+osx_image: xcode10.1
 env:
   global:
     - IOS_SIMULATOR="iPhone 6s"
-    - IOS_VERSION="12.2"
+    - IOS_VERSION="12.1"
 matrix:
   include:
     - env: BUILD_SCHEME="SQLite iOS"
diff --git a/Documentation/Index.md b/Documentation/Index.md
index cf4815b9..4925ca77 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -68,7 +68,7 @@
 ## Installation
 
 > _Note:_ SQLite.swift requires Swift 4.2 (and
-> [Xcode 9.3](https://developer.apple.com/xcode/downloads/)) or greater.
+> [Xcode 10](https://developer.apple.com/xcode/downloads/)) or greater.
 
 
 ### Carthage
diff --git a/README.md b/README.md
index 9192fe21..bdb7aeaa 100644
--- a/README.md
+++ b/README.md
@@ -112,7 +112,7 @@ and the [companion repository][SQLiteDataAccessLayer2].
 
 ## Installation
 
-> _Note:_ SQLite.swift requires Swift 4.2 (and [Xcode][] 9.3).
+> _Note:_ SQLite.swift requires Swift 4.2 (and [Xcode][] 10).
 
 ### Carthage
 

From a3ad1f85a5fb8b31b026a73aa17e3925b618ac06 Mon Sep 17 00:00:00 2001
From: Shawn Burlew <shawn.burlew@apgdata.com>
Date: Fri, 5 Apr 2019 08:54:37 -0600
Subject: [PATCH 329/685] Updated Swift badge to 4.2

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index bdb7aeaa..d7c87acc 100644
--- a/README.md
+++ b/README.md
@@ -285,7 +285,7 @@ Looking for something else? Try another Swift wrapper (or [FMDB][]):
 [GitterBadge]: https://badges.gitter.im/stephencelis/SQLite.swift.svg
 [GitterLink]: https://gitter.im/stephencelis/SQLite.swift
 
-[Swift4Badge]: https://img.shields.io/badge/swift-4.1-orange.svg?style=flat
+[Swift4Badge]: https://img.shields.io/badge/swift-4.2-orange.svg?style=flat
 [Swift4Link]: https://developer.apple.com/swift/
 
 [SQLiteMigrationManager.swift]: https://github.com/garriguv/SQLiteMigrationManager.swift

From 3b4b93f17b90da96b99e636113eb68c71eabfb41 Mon Sep 17 00:00:00 2001
From: Shawn Burlew <shawn.burlew@apgdata.com>
Date: Fri, 5 Apr 2019 09:08:50 -0600
Subject: [PATCH 330/685] Changed Xcode back to 10.2 for CI config and
 documentation (apparently `withUnsafeBytes` doesn't use
 UnsafeRawBufferPointer prior to 10.2)

---
 .travis.yml            | 2 +-
 Documentation/Index.md | 2 +-
 README.md              | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 909e5672..2ce89b05 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,7 @@
 language: objective-c
 rvm: 2.3
 # https://docs.travis-ci.com/user/reference/osx
-osx_image: xcode10.1
+osx_image: xcode10.2
 env:
   global:
     - IOS_SIMULATOR="iPhone 6s"
diff --git a/Documentation/Index.md b/Documentation/Index.md
index 4925ca77..651aa991 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -68,7 +68,7 @@
 ## Installation
 
 > _Note:_ SQLite.swift requires Swift 4.2 (and
-> [Xcode 10](https://developer.apple.com/xcode/downloads/)) or greater.
+> [Xcode 10.2](https://developer.apple.com/xcode/downloads/)) or greater.
 
 
 ### Carthage
diff --git a/README.md b/README.md
index d7c87acc..a2f090e0 100644
--- a/README.md
+++ b/README.md
@@ -112,7 +112,7 @@ and the [companion repository][SQLiteDataAccessLayer2].
 
 ## Installation
 
-> _Note:_ SQLite.swift requires Swift 4.2 (and [Xcode][] 10).
+> _Note:_ SQLite.swift requires Swift 4.2 (and [Xcode][] 10.2).
 
 ### Carthage
 

From c31b43fee598eef452083bce3878d8f4bc328bd1 Mon Sep 17 00:00:00 2001
From: Shawn Burlew <shawn.burlew@apgdata.com>
Date: Tue, 9 Apr 2019 13:02:02 -0600
Subject: [PATCH 331/685] Changed travis CI device name to iPhone X

---
 .travis.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index 2ce89b05..2c474b79 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,7 +4,7 @@ rvm: 2.3
 osx_image: xcode10.2
 env:
   global:
-    - IOS_SIMULATOR="iPhone 6s"
+    - IOS_SIMULATOR="iPhone X"
     - IOS_VERSION="12.1"
 matrix:
   include:

From e926eb1120a8d4ac8cee0a5ee6f84bd664cc5376 Mon Sep 17 00:00:00 2001
From: Shawn Burlew <shawn.burlew@apgdata.com>
Date: Tue, 9 Apr 2019 14:24:08 -0600
Subject: [PATCH 332/685] - Updated makefile iOS simulator to iPhone X -
 Updated cocoapods version in gem file

---
 Makefile                | 2 +-
 Tests/CocoaPods/Gemfile | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile
index d98c8deb..7792ecdb 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 BUILD_TOOL = xcodebuild
 BUILD_SCHEME = SQLite Mac
-IOS_SIMULATOR = iPhone 6s
+IOS_SIMULATOR = iPhone X
 IOS_VERSION = 12.1
 ifeq ($(BUILD_SCHEME),SQLite iOS)
 	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -destination "platform=iOS Simulator,name=$(IOS_SIMULATOR),OS=$(IOS_VERSION)"
diff --git a/Tests/CocoaPods/Gemfile b/Tests/CocoaPods/Gemfile
index fd1c8c2e..77d90eec 100644
--- a/Tests/CocoaPods/Gemfile
+++ b/Tests/CocoaPods/Gemfile
@@ -1,4 +1,4 @@
 source 'https://rubygems.org'
 
-gem 'cocoapods', '~> 1.6.0beta2'
+gem 'cocoapods', '~> 1.6.1'
 gem 'minitest'

From c2487732f539fe2c0217a014206036a037a89c8d Mon Sep 17 00:00:00 2001
From: Shawn Burlew <shawn.burlew@apgdata.com>
Date: Fri, 19 Apr 2019 09:03:51 -0600
Subject: [PATCH 333/685] Implemented fixes provided by @timshadel

---
 .travis.yml               | 3 +++
 Sources/SQLite/Info.plist | 2 +-
 Tests/CocoaPods/Makefile  | 4 +++-
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 2c474b79..d54827b2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -25,4 +25,7 @@ before_install:
   - brew update
   - brew outdated carthage || brew upgrade carthage
 script:
+# Workaround for Xcode 10.2/tvOS 9.1 bug
+# See https://stackoverflow.com/questions/55389080/xcode-10-2-failed-to-run-app-on-simulator-with-ios-10
+  - sudo mkdir /Library/Developer/CoreSimulator/Profiles/Runtimes/tvOS\ 9.1.simruntime/Contents/Resources/RuntimeRoot/usr/lib/swift
   - ./run-tests.sh
diff --git a/Sources/SQLite/Info.plist b/Sources/SQLite/Info.plist
index 7347d842..c3f9414b 100644
--- a/Sources/SQLite/Info.plist
+++ b/Sources/SQLite/Info.plist
@@ -15,7 +15,7 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>0.11.4</string>
+	<string>0.11.6</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>
diff --git a/Tests/CocoaPods/Makefile b/Tests/CocoaPods/Makefile
index 26163fdb..fa87e245 100644
--- a/Tests/CocoaPods/Makefile
+++ b/Tests/CocoaPods/Makefile
@@ -1,7 +1,9 @@
+XCPRETTY := $(shell command -v xcpretty)
+
 test: install repo_update
 	@set -e; \
 	for test in *_test.rb; do \
-		bundle exec ./$$test; \
+		bundle exec ./$$test | $(XCPRETTY) -C; \
 	done
 
 repo_update:

From d89c0e895c3a1f956bb024a36a299719bf5f209e Mon Sep 17 00:00:00 2001
From: Shawn Burlew <shawn.burlew@apgdata.com>
Date: Fri, 19 Apr 2019 09:25:43 -0600
Subject: [PATCH 334/685] Fixed option typo

---
 Tests/CocoaPods/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Tests/CocoaPods/Makefile b/Tests/CocoaPods/Makefile
index fa87e245..532dcbff 100644
--- a/Tests/CocoaPods/Makefile
+++ b/Tests/CocoaPods/Makefile
@@ -3,7 +3,7 @@ XCPRETTY := $(shell command -v xcpretty)
 test: install repo_update
 	@set -e; \
 	for test in *_test.rb; do \
-		bundle exec ./$$test | $(XCPRETTY) -C; \
+		bundle exec ./$$test | $(XCPRETTY) -c; \
 	done
 
 repo_update:

From 9ae1a0bfe1f950099042964b0b4e6cb696681075 Mon Sep 17 00:00:00 2001
From: Shawn Burlew <shawn.burlew@apgdata.com>
Date: Fri, 19 Apr 2019 11:27:07 -0600
Subject: [PATCH 335/685] Updated to Swift 5

---
 .travis.yml                      |  4 ++--
 Documentation/Index.md           | 14 +++++++-------
 Makefile                         |  2 +-
 README.md                        | 10 +++++-----
 SQLite.swift.podspec             |  4 ++--
 SQLite.xcodeproj/project.pbxproj |  4 ++--
 Sources/SQLite/Info.plist        |  2 +-
 7 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index d54827b2..c8fc5feb 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,8 +4,8 @@ rvm: 2.3
 osx_image: xcode10.2
 env:
   global:
-    - IOS_SIMULATOR="iPhone X"
-    - IOS_VERSION="12.1"
+    - IOS_SIMULATOR="iPhone XS"
+    - IOS_VERSION="12.2"
 matrix:
   include:
     - env: BUILD_SCHEME="SQLite iOS"
diff --git a/Documentation/Index.md b/Documentation/Index.md
index 651aa991..cbb5d49a 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -67,7 +67,7 @@
 
 ## Installation
 
-> _Note:_ SQLite.swift requires Swift 4.2 (and
+> _Note:_ SQLite.swift requires Swift 5 (and
 > [Xcode 10.2](https://developer.apple.com/xcode/downloads/)) or greater.
 
 
@@ -80,7 +80,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.11.6
+    github "stephencelis/SQLite.swift" ~> 0.12
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -110,7 +110,7 @@ install SQLite.swift with Carthage:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.11.6'
+        pod 'SQLite.swift', '~> 0.12'
     end
     ```
 
@@ -124,7 +124,7 @@ with the OS you can require the `standalone` subspec:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.11.6'
+  pod 'SQLite.swift/standalone', '~> 0.12'
 end
 ```
 
@@ -134,7 +134,7 @@ dependency to sqlite3 or one of its subspecs:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.11.6'
+  pod 'SQLite.swift/standalone', '~> 0.12'
   pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
 end
 ```
@@ -148,7 +148,7 @@ If you want to use [SQLCipher][] with SQLite.swift you can require the
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/SQLCipher', '~> 0.11.6'
+  pod 'SQLite.swift/SQLCipher', '~> 0.12'
 end
 ```
 
@@ -181,7 +181,7 @@ applications.
 
   ```swift
   dependencies: [
-    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.11.6")
+    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.12")
   ]
   ```
 
diff --git a/Makefile b/Makefile
index 7792ecdb..5ea45d5d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 BUILD_TOOL = xcodebuild
 BUILD_SCHEME = SQLite Mac
 IOS_SIMULATOR = iPhone X
-IOS_VERSION = 12.1
+IOS_VERSION = 12.2
 ifeq ($(BUILD_SCHEME),SQLite iOS)
 	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -destination "platform=iOS Simulator,name=$(IOS_SIMULATOR),OS=$(IOS_VERSION)"
 else
diff --git a/README.md b/README.md
index a2f090e0..ce45ef4e 100644
--- a/README.md
+++ b/README.md
@@ -112,7 +112,7 @@ and the [companion repository][SQLiteDataAccessLayer2].
 
 ## Installation
 
-> _Note:_ SQLite.swift requires Swift 4.2 (and [Xcode][] 10.2).
+> _Note:_ SQLite.swift requires Swift 5 (and [Xcode][] 10.2).
 
 ### Carthage
 
@@ -124,7 +124,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.11.6
+    github "stephencelis/SQLite.swift" ~> 0.12
     ```
 
  3. Run `carthage update` and
@@ -156,7 +156,7 @@ SQLite.swift with CocoaPods:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.11.6'
+        pod 'SQLite.swift', '~> 0.12'
     end
     ```
 
@@ -174,7 +174,7 @@ Swift code.
 
   ```swift
   dependencies: [
-      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.11.6")
+      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.12")
   ]
   ```
 
@@ -285,7 +285,7 @@ Looking for something else? Try another Swift wrapper (or [FMDB][]):
 [GitterBadge]: https://badges.gitter.im/stephencelis/SQLite.swift.svg
 [GitterLink]: https://gitter.im/stephencelis/SQLite.swift
 
-[Swift4Badge]: https://img.shields.io/badge/swift-4.2-orange.svg?style=flat
+[Swift4Badge]: https://img.shields.io/badge/swift-5-orange.svg?style=flat
 [Swift4Link]: https://developer.apple.com/swift/
 
 [SQLiteMigrationManager.swift]: https://github.com/garriguv/SQLiteMigrationManager.swift
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index fcdf88c1..8b202745 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.11.6"
+  s.version          = "0.12"
   s.summary          = "A type-safe, Swift-language layer over SQLite3 for iOS and OS X."
 
   s.description      = <<-DESC
@@ -21,7 +21,7 @@ Pod::Spec.new do |s|
   s.watchos.deployment_target = "2.2"
   s.default_subspec  = 'standard'
   s.pod_target_xcconfig = {
-    'SWIFT_VERSION' => '4.2',
+    'SWIFT_VERSION' => '5',
   }
 
   s.subspec 'standard' do |ss|
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 2eb11fd9..9d38dbc4 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1180,7 +1180,7 @@
 				PRODUCT_NAME = "";
 				SDKROOT = iphoneos;
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
-				SWIFT_VERSION = 4.2;
+				SWIFT_VERSION = 5.0;
 				TARGETED_DEVICE_FAMILY = "1,2,3";
 				VERSIONING_SYSTEM = "apple-generic";
 				VERSION_INFO_PREFIX = "";
@@ -1235,7 +1235,7 @@
 				PRODUCT_NAME = "";
 				SDKROOT = iphoneos;
 				SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
-				SWIFT_VERSION = 4.2;
+				SWIFT_VERSION = 5.0;
 				TARGETED_DEVICE_FAMILY = "1,2,3";
 				VALIDATE_PRODUCT = YES;
 				VERSIONING_SYSTEM = "apple-generic";
diff --git a/Sources/SQLite/Info.plist b/Sources/SQLite/Info.plist
index c3f9414b..3a5fc4f6 100644
--- a/Sources/SQLite/Info.plist
+++ b/Sources/SQLite/Info.plist
@@ -15,7 +15,7 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>0.11.6</string>
+	<string>0.12</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>

From c0b9eb0dfd9faa6176a1ddbec87d98c076a4f62c Mon Sep 17 00:00:00 2001
From: Shawn Burlew <shawn.burlew@apgdata.com>
Date: Fri, 19 Apr 2019 11:29:40 -0600
Subject: [PATCH 336/685] Updated iOS simulator to iPhone XS

---
 Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index 5ea45d5d..50d07148 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 BUILD_TOOL = xcodebuild
 BUILD_SCHEME = SQLite Mac
-IOS_SIMULATOR = iPhone X
+IOS_SIMULATOR = iPhone XS
 IOS_VERSION = 12.2
 ifeq ($(BUILD_SCHEME),SQLite iOS)
 	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -destination "platform=iOS Simulator,name=$(IOS_SIMULATOR),OS=$(IOS_VERSION)"

From aa9821896a17878c0bca089d2e61415a2a806282 Mon Sep 17 00:00:00 2001
From: Shawn Burlew <shawn.burlew@apgdata.com>
Date: Sun, 21 Apr 2019 10:59:15 -0600
Subject: [PATCH 337/685] Documentation - Updated README to clarify Swift 5 vs
 Swift 4.2 supported versions - Updated minimum CocoaPods version - Updated
 SPM language versions

---
 Documentation/Index.md | 2 +-
 Package.swift          | 2 +-
 README.md              | 8 ++++----
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index cbb5d49a..94ad580b 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -96,7 +96,7 @@ install SQLite.swift with Carthage:
 [CocoaPods][] is a dependency manager for Cocoa projects. To install SQLite.swift with CocoaPods:
 
  1. Make sure CocoaPods is [installed][CocoaPods Installation] (SQLite.swift
-    requires version 1.0.0 or greater).
+    requires version 1.6.1 or greater).
 
     ```sh
     # Using the default Ruby install will require you to use sudo when
diff --git a/Package.swift b/Package.swift
index c008e482..2d4325f5 100644
--- a/Package.swift
+++ b/Package.swift
@@ -9,7 +9,7 @@ let package = Package(
         .target(name: "SQLiteObjc"),
         .testTarget(name: "SQLiteTests", dependencies: ["SQLite"], path: "Tests/SQLiteTests")
     ],
-    swiftLanguageVersions: [4]
+    swiftLanguageVersions: [5]
 )
 
 #if os(Linux)
diff --git a/README.md b/README.md
index ce45ef4e..6eaa69bb 100644
--- a/README.md
+++ b/README.md
@@ -112,7 +112,7 @@ and the [companion repository][SQLiteDataAccessLayer2].
 
 ## Installation
 
-> _Note:_ SQLite.swift requires Swift 5 (and [Xcode][] 10.2).
+> _Note:_ Version 0.12 requires Swift 5 (and [Xcode][] 10.2). \nVersion 0.11.6 requires Swift 4.2 (and [Xcode][] 10.1).
 
 ### Carthage
 
@@ -142,7 +142,7 @@ install SQLite.swift with Carthage:
 SQLite.swift with CocoaPods:
 
  1. Make sure CocoaPods is [installed][CocoaPods Installation]. (SQLite.swift
-    requires version 1.0.0 or greater.)
+    requires version 1.6.1 or greater.)
 
     ```sh
     # Using the default Ruby install will require you to use sudo when
@@ -285,8 +285,8 @@ Looking for something else? Try another Swift wrapper (or [FMDB][]):
 [GitterBadge]: https://badges.gitter.im/stephencelis/SQLite.swift.svg
 [GitterLink]: https://gitter.im/stephencelis/SQLite.swift
 
-[Swift4Badge]: https://img.shields.io/badge/swift-5-orange.svg?style=flat
-[Swift4Link]: https://developer.apple.com/swift/
+[Swift5Badge]: https://img.shields.io/badge/swift-5-orange.svg?style=flat
+[Swift5Link]: https://developer.apple.com/swift/
 
 [SQLiteMigrationManager.swift]: https://github.com/garriguv/SQLiteMigrationManager.swift
 [FMDB]: https://github.com/ccgus/fmdb

From 3afd756e04b90ca40f26c864f7168fd2335c591b Mon Sep 17 00:00:00 2001
From: Shawn Burlew <shawn.burlew@apgdata.com>
Date: Sun, 21 Apr 2019 11:04:11 -0600
Subject: [PATCH 338/685] Fixed Swift badges and installation note formatting

---
 README.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 6eaa69bb..8efc53d8 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # SQLite.swift
 
-[![Build Status][TravisBadge]][TravisLink] [![CocoaPods Version][CocoaPodsVersionBadge]][CocoaPodsVersionLink] [![Swift4 compatible][Swift4Badge]][Swift4Link] [![Platform][PlatformBadge]][PlatformLink] [![Carthage compatible][CartagheBadge]][CarthageLink] [![Join the chat at https://gitter.im/stephencelis/SQLite.swift][GitterBadge]][GitterLink]
+[![Build Status][TravisBadge]][TravisLink] [![CocoaPods Version][CocoaPodsVersionBadge]][CocoaPodsVersionLink] [![Swift5 compatible][Swift5Badge]][Swift5Link] [![Platform][PlatformBadge]][PlatformLink] [![Carthage compatible][CartagheBadge]][CarthageLink] [![Join the chat at https://gitter.im/stephencelis/SQLite.swift][GitterBadge]][GitterLink]
 
 A type-safe, [Swift][]-language layer over [SQLite3][].
 
@@ -112,7 +112,7 @@ and the [companion repository][SQLiteDataAccessLayer2].
 
 ## Installation
 
-> _Note:_ Version 0.12 requires Swift 5 (and [Xcode][] 10.2). \nVersion 0.11.6 requires Swift 4.2 (and [Xcode][] 10.1).
+> _Note:_ Version 0.12 requires Swift 5 (and [Xcode](https://developer.apple.com/xcode/downloads/)) 10.2) or greater. Version 0.11.6 requires Swift 4.2 (and [Xcode](https://developer.apple.com/xcode/downloads/) 10.1 or greater).
 
 ### Carthage
 

From 71dfa68f001c47046958001f4ec8b07ca3a7c7aa Mon Sep 17 00:00:00 2001
From: Shawn Burlew <shawn.burlew@apgdata.com>
Date: Sun, 21 Apr 2019 11:05:38 -0600
Subject: [PATCH 339/685] Fixed typo

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 8efc53d8..41c7ffdc 100644
--- a/README.md
+++ b/README.md
@@ -112,7 +112,7 @@ and the [companion repository][SQLiteDataAccessLayer2].
 
 ## Installation
 
-> _Note:_ Version 0.12 requires Swift 5 (and [Xcode](https://developer.apple.com/xcode/downloads/)) 10.2) or greater. Version 0.11.6 requires Swift 4.2 (and [Xcode](https://developer.apple.com/xcode/downloads/) 10.1 or greater).
+> _Note:_ Version 0.12 requires Swift 5 (and [Xcode](https://developer.apple.com/xcode/downloads/) 10.2) or greater. Version 0.11.6 requires Swift 4.2 (and [Xcode](https://developer.apple.com/xcode/downloads/) 10.1) or greater.
 
 ### Carthage
 

From f9cb6bdab2aeae1dc119d0177c90ac93ae710fc1 Mon Sep 17 00:00:00 2001
From: Shawn Burlew <shawn.burlew@apgdata.com>
Date: Mon, 22 Apr 2019 11:15:15 -0600
Subject: [PATCH 340/685] Documentation - Updated swift tools version in
 Package.swift - Updated "OS X" references to "macOS"

---
 CONTRIBUTING.md        | 2 +-
 Documentation/Index.md | 2 +-
 Package.swift          | 2 +-
 SQLite.swift.podspec   | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 60c18370..6c367b95 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -74,7 +74,7 @@ Made it through everything above and still having trouble? Sorry!
   - Even better: link to a sample project exhibiting the issue.
   - Include the SQLite.swift commit or branch experiencing the issue.
   - Include devices and operating systems affected.
-  - Include build information: the Xcode and OS X versions affected.
+  - Include build information: the Xcode and macOS versions affected.
 
 [installation instructions]: Documentation/Index.md#installation
 [See Documentation]: Documentation/Index.md#sqliteswift-documentation
diff --git a/Documentation/Index.md b/Documentation/Index.md
index 94ad580b..211c01a9 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -258,7 +258,7 @@ let path = NSSearchPathForDirectoriesInDomains(
 let db = try Connection("\(path)/db.sqlite3")
 ```
 
-On OS X, you can use your app’s **Application Support** directory:
+On macOS, you can use your app’s **Application Support** directory:
 
 ```swift
 var path = NSSearchPathForDirectoriesInDomains(
diff --git a/Package.swift b/Package.swift
index 2d4325f5..6644cd73 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,4 +1,4 @@
-// swift-tools-version:4.0
+// swift-tools-version:5.0
 import PackageDescription
 
 let package = Package(
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 8b202745..9405c903 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,7 +1,7 @@
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
   s.version          = "0.12"
-  s.summary          = "A type-safe, Swift-language layer over SQLite3 for iOS and OS X."
+  s.summary          = "A type-safe, Swift-language layer over SQLite3 for iOS and macOS."
 
   s.description      = <<-DESC
     SQLite.swift provides compile-time confidence in SQL statement syntax and

From 78089e2bdebbf1f634eaf85876d719981ed3c147 Mon Sep 17 00:00:00 2001
From: Stephan Heilner <stephanheilner@gmail.com>
Date: Thu, 31 May 2018 15:14:02 -0600
Subject: [PATCH 341/685] Fixed bug not allowing columns from multiple tables
 in the .select

---
 SQLite.xcodeproj/project.pbxproj    |  8 +++++
 Sources/SQLite/Typed/Query.swift    |  1 -
 Tests/SQLiteTests/SelectTests.swift | 45 +++++++++++++++++++++++++++++
 3 files changed, 53 insertions(+), 1 deletion(-)
 create mode 100644 Tests/SQLiteTests/SelectTests.swift

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 2eb11fd9..9143d1b2 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -108,6 +108,9 @@
 		49EB68C51F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
 		49EB68C61F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
 		49EB68C71F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
+		D4DB368C20C09CFB00D5A58E /* SelectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4DB368A20C09C9B00D5A58E /* SelectTests.swift */; };
+		D4DB368D20C09CFC00D5A58E /* SelectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4DB368A20C09C9B00D5A58E /* SelectTests.swift */; };
+		D4DB368E20C09CFD00D5A58E /* SelectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4DB368A20C09C9B00D5A58E /* SelectTests.swift */; };
 		EE247AD71C3F04ED00AE3E12 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		EE247ADE1C3F04ED00AE3E12 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE247AD31C3F04ED00AE3E12 /* SQLite.framework */; };
 		EE247B031C3F06E900AE3E12 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
@@ -228,6 +231,7 @@
 		3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.0.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
 		49EB68C31F7B3CB400D89D40 /* Coding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coding.swift; sourceTree = "<group>"; };
 		A121AC451CA35C79005A31D1 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		D4DB368A20C09C9B00D5A58E /* SelectTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectTests.swift; sourceTree = "<group>"; };
 		EE247AD31C3F04ED00AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AD61C3F04ED00AE3E12 /* SQLite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLite.h; sourceTree = "<group>"; };
 		EE247AD81C3F04ED00AE3E12 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -418,6 +422,7 @@
 				19A17B93B48B5560E6E51791 /* Fixtures.swift */,
 				19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */,
 				19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */,
+				D4DB368A20C09C9B00D5A58E /* SelectTests.swift */,
 			);
 			name = SQLiteTests;
 			path = Tests/SQLiteTests;
@@ -847,6 +852,7 @@
 				19A17F60B685636D1F83C2DD /* Fixtures.swift in Sources */,
 				19A1785195182AF8731A8BDA /* RowTests.swift in Sources */,
 				19A1769C1F3A7542BECF50FF /* DateAndTimeFunctionTests.swift in Sources */,
+				D4DB368E20C09CFD00D5A58E /* SelectTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -935,6 +941,7 @@
 				19A17408007B182F884E3A53 /* Fixtures.swift in Sources */,
 				19A1720B67ED13E6150C6A3D /* RowTests.swift in Sources */,
 				19A17C80076860CF7751A056 /* DateAndTimeFunctionTests.swift in Sources */,
+				D4DB368C20C09CFB00D5A58E /* SelectTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -993,6 +1000,7 @@
 				19A1709C3E7A406E62293B2A /* Fixtures.swift in Sources */,
 				19A171967CC511C4F6F773C9 /* RowTests.swift in Sources */,
 				19A172EB202970561E5C4245 /* DateAndTimeFunctionTests.swift in Sources */,
+				D4DB368D20C09CFC00D5A58E /* SelectTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index f6ef6df8..7ec5e581 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -963,7 +963,6 @@ extension Connection {
                             try expandGlob(true)(q)
                             continue column
                         }
-                        throw QueryError.noSuchTable(name: namespace)
                     }
                     throw QueryError.noSuchTable(name: namespace)
                 }
diff --git a/Tests/SQLiteTests/SelectTests.swift b/Tests/SQLiteTests/SelectTests.swift
new file mode 100644
index 00000000..bca01092
--- /dev/null
+++ b/Tests/SQLiteTests/SelectTests.swift
@@ -0,0 +1,45 @@
+import XCTest
+@testable import SQLite
+
+class SelectTests: SQLiteTestCase {
+    
+    override func setUp() {
+        super.setUp()
+        CreateUsersTable()
+        CreateUsersDataTable()
+    }
+    
+    func CreateUsersDataTable() {
+        try! db.execute("""
+            CREATE TABLE users_name (
+                id INTEGER,
+                user_id INTEGER REFERENCES users(id),
+                name TEXT
+            )
+            """
+        )
+    }
+    
+    func test_select_columns_from_multiple_tables() {
+        let usersData = Table("users_name")
+        let users = Table("users")
+        
+        let name = Expression<String>("name")
+        let id = Expression<Int64>("id")
+        let userID = Expression<Int64>("user_id")
+        let email = Expression<String>("email")
+        
+        try! InsertUser("Joey")
+        try! db.run(usersData.insert(
+            id <- 1,
+            userID <- 1,
+            name <- "Joey"
+        ))
+        
+        try! db.prepare(users.select(name, email).join(usersData, on: userID == users[id])).forEach {
+            XCTAssertEqual($0[name], "Joey")
+            XCTAssertEqual($0[email], "Joey@example.com")
+        }
+    }
+    
+}

From e8ca9c0d138dca152df122053a8a2e181e6c3c7d Mon Sep 17 00:00:00 2001
From: Stephen Celis <stephen.celis@gmail.com>
Date: Mon, 22 Apr 2019 12:29:15 -0600
Subject: [PATCH 342/685] Reverted swift tools version to 4.0 for backwards
 compatibility

Co-Authored-By: sburlewapg <49003548+sburlewapg@users.noreply.github.com>
---
 Package.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Package.swift b/Package.swift
index 6644cd73..2d4325f5 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,4 +1,4 @@
-// swift-tools-version:5.0
+// swift-tools-version:4.0
 import PackageDescription
 
 let package = Package(

From 3e27caa3d898ce366fc29c8a8af9ccb105bd21d1 Mon Sep 17 00:00:00 2001
From: Stephen Celis <stephen.celis@gmail.com>
Date: Mon, 22 Apr 2019 12:38:02 -0600
Subject: [PATCH 343/685] Added Swift 4 and 4.2 for CI compatibility

Co-Authored-By: sburlewapg <49003548+sburlewapg@users.noreply.github.com>
---
 Package.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Package.swift b/Package.swift
index 2d4325f5..96266a2c 100644
--- a/Package.swift
+++ b/Package.swift
@@ -9,7 +9,7 @@ let package = Package(
         .target(name: "SQLiteObjc"),
         .testTarget(name: "SQLiteTests", dependencies: ["SQLite"], path: "Tests/SQLiteTests")
     ],
-    swiftLanguageVersions: [5]
+    swiftLanguageVersions: [.version("5"), .v4_2, .v4]
 )
 
 #if os(Linux)

From a93b4956946f122a7f2202297f2f284da829e476 Mon Sep 17 00:00:00 2001
From: Shawn Burlew <shawn.burlew@apgdata.com>
Date: Mon, 22 Apr 2019 13:34:16 -0600
Subject: [PATCH 344/685] Changed language versions array to contain Ints to
 try and get CI working

---
 Package.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Package.swift b/Package.swift
index 96266a2c..430ae6f2 100644
--- a/Package.swift
+++ b/Package.swift
@@ -9,7 +9,7 @@ let package = Package(
         .target(name: "SQLiteObjc"),
         .testTarget(name: "SQLiteTests", dependencies: ["SQLite"], path: "Tests/SQLiteTests")
     ],
-    swiftLanguageVersions: [.version("5"), .v4_2, .v4]
+    swiftLanguageVersions: [4, 5]
 )
 
 #if os(Linux)

From 08a1696765940e4fdc6e7fd33ab76d92a87239c7 Mon Sep 17 00:00:00 2001
From: Yehor Popovych <yehor@crossroad.io>
Date: Wed, 24 Apr 2019 20:52:22 +0300
Subject: [PATCH 345/685] Fixed version

---
 SQLite.swift.podspec      | 2 +-
 Sources/SQLite/Info.plist | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 9405c903..57eda40a 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.12"
+  s.version          = "0.12.0"
   s.summary          = "A type-safe, Swift-language layer over SQLite3 for iOS and macOS."
 
   s.description      = <<-DESC
diff --git a/Sources/SQLite/Info.plist b/Sources/SQLite/Info.plist
index 3a5fc4f6..db84c711 100644
--- a/Sources/SQLite/Info.plist
+++ b/Sources/SQLite/Info.plist
@@ -15,7 +15,7 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>0.12</string>
+	<string>0.12.0</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>

From 9b2d3e231feeb25f960e36915656b42719435bea Mon Sep 17 00:00:00 2001
From: Yehor Popovych <yehor@crossroad.io>
Date: Wed, 24 Apr 2019 21:44:45 +0300
Subject: [PATCH 346/685] Updated version in README and Documentation

---
 Documentation/Index.md                | 12 ++++++------
 Documentation/Planning.md             |  2 +-
 README.md                             |  6 +++---
 Sources/SQLite/Typed/Expression.swift |  2 +-
 4 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 211c01a9..05967ff4 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -80,7 +80,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.12
+    github "stephencelis/SQLite.swift" ~> 0.12.0
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -110,7 +110,7 @@ install SQLite.swift with Carthage:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.12'
+        pod 'SQLite.swift', '~> 0.12.0'
     end
     ```
 
@@ -124,7 +124,7 @@ with the OS you can require the `standalone` subspec:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.12'
+  pod 'SQLite.swift/standalone', '~> 0.12.0'
 end
 ```
 
@@ -134,7 +134,7 @@ dependency to sqlite3 or one of its subspecs:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.12'
+  pod 'SQLite.swift/standalone', '~> 0.12.0'
   pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
 end
 ```
@@ -148,7 +148,7 @@ If you want to use [SQLCipher][] with SQLite.swift you can require the
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/SQLCipher', '~> 0.12'
+  pod 'SQLite.swift/SQLCipher', '~> 0.12.0'
 end
 ```
 
@@ -181,7 +181,7 @@ applications.
 
   ```swift
   dependencies: [
-    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.12")
+    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.12.0")
   ]
   ```
 
diff --git a/Documentation/Planning.md b/Documentation/Planning.md
index 8a3d5a11..5f885de8 100644
--- a/Documentation/Planning.md
+++ b/Documentation/Planning.md
@@ -6,7 +6,7 @@ additions and Pull Requests, as well as to keep the Issues list clear of
 enhancement requests so that bugs are more visible.
 
 > ⚠ This document is currently not actively maintained. See
-> the [0.12.0 milestone](https://github.com/stephencelis/SQLite.swift/issues?q=is%3Aopen+is%3Aissue+milestone%3A0.12.0)
+> the [0.13.0 milestone](https://github.com/stephencelis/SQLite.swift/issues?q=is%3Aopen+is%3Aissue+milestone%3A0.13.0)
 > on Github for additional information about planned features for the next release.
 
 ## Roadmap
diff --git a/README.md b/README.md
index 41c7ffdc..b7a18e0b 100644
--- a/README.md
+++ b/README.md
@@ -124,7 +124,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.12
+    github "stephencelis/SQLite.swift" ~> 0.12.0
     ```
 
  3. Run `carthage update` and
@@ -156,7 +156,7 @@ SQLite.swift with CocoaPods:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.12'
+        pod 'SQLite.swift', '~> 0.12.0'
     end
     ```
 
@@ -174,7 +174,7 @@ Swift code.
 
   ```swift
   dependencies: [
-      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.12")
+      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.12.0")
   ]
   ```
 
diff --git a/Sources/SQLite/Typed/Expression.swift b/Sources/SQLite/Typed/Expression.swift
index d89ee6cc..76ba04c4 100644
--- a/Sources/SQLite/Typed/Expression.swift
+++ b/Sources/SQLite/Typed/Expression.swift
@@ -73,7 +73,7 @@ public protocol Expressible {
 extension Expressible {
 
     // naïve compiler for statements that can’t be bound, e.g., CREATE TABLE
-    // FIXME: make internal (0.12.0)
+    // FIXME: make internal (0.13.0)
     public func asSQL() -> String {
         let expressed = expression
         var idx = 0

From 9a0170ed7a7a9b8a0bcb976783f849025e7f35e9 Mon Sep 17 00:00:00 2001
From: Yehor Popovych <yehor@crossroad.io>
Date: Thu, 25 Apr 2019 01:13:04 +0300
Subject: [PATCH 347/685] Removed warning in the Cipher extension

---
 Sources/SQLite/Extensions/Cipher.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Sources/SQLite/Extensions/Cipher.swift b/Sources/SQLite/Extensions/Cipher.swift
index 71ef1765..44919aab 100644
--- a/Sources/SQLite/Extensions/Cipher.swift
+++ b/Sources/SQLite/Extensions/Cipher.swift
@@ -60,7 +60,7 @@ extension Connection {
     // the key provided is incorrect. To test that the database can be successfully opened with the
     // provided key, it is necessary to perform some operation on the database (i.e. read from it).
     private func cipher_key_check() throws {
-        try scalar("SELECT count(*) FROM sqlite_master;")
+        let _ = try scalar("SELECT count(*) FROM sqlite_master;")
     }
 }
 #endif

From 026c5c264f925c0796d1cb72ee4927019c1dec4e Mon Sep 17 00:00:00 2001
From: Krzysztof <krzysztof.kapitan@gmail.com>
Date: Fri, 26 Apr 2019 22:27:16 +0200
Subject: [PATCH 348/685] Introduce support for backup

---
 SQLite.xcodeproj/project.pbxproj    |  18 +++
 Sources/SQLite/Core/Backup.swift    | 176 ++++++++++++++++++++++++++++
 Tests/SQLiteTests/BackupTests.swift |  36 ++++++
 3 files changed, 230 insertions(+)
 create mode 100644 Sources/SQLite/Core/Backup.swift
 create mode 100644 Tests/SQLiteTests/BackupTests.swift

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 9d38dbc4..aec22743 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -7,6 +7,13 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		02A43A9822738CF100FEC494 /* Backup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A43A9722738CF100FEC494 /* Backup.swift */; };
+		02A43A9922738CF100FEC494 /* Backup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A43A9722738CF100FEC494 /* Backup.swift */; };
+		02A43A9A22738CF100FEC494 /* Backup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A43A9722738CF100FEC494 /* Backup.swift */; };
+		02A43A9B22738CF100FEC494 /* Backup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A43A9722738CF100FEC494 /* Backup.swift */; };
+		02A43A9D22738E2900FEC494 /* BackupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A43A9C22738E2900FEC494 /* BackupTests.swift */; };
+		02A43A9E22738E2900FEC494 /* BackupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A43A9C22738E2900FEC494 /* BackupTests.swift */; };
+		02A43A9F22738E2900FEC494 /* BackupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A43A9C22738E2900FEC494 /* BackupTests.swift */; };
 		03A65E641C6BB0F60062603F /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03A65E5A1C6BB0F50062603F /* SQLite.framework */; };
 		03A65E721C6BB2D30062603F /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		03A65E731C6BB2D80062603F /* Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF71C3F06E900AE3E12 /* Foundation.swift */; };
@@ -211,6 +218,8 @@
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXFileReference section */
+		02A43A9722738CF100FEC494 /* Backup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Backup.swift; sourceTree = "<group>"; };
+		02A43A9C22738E2900FEC494 /* BackupTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupTests.swift; sourceTree = "<group>"; };
 		03A65E5A1C6BB0F50062603F /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		03A65E631C6BB0F60062603F /* SQLiteTests tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SQLiteTests tvOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
 		03A65E961C6BB3210062603F /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
@@ -398,6 +407,7 @@
 				19A17E2695737FAB5D6086E3 /* fixtures */,
 				EE247B1A1C3F137700AE3E12 /* AggregateFunctionsTests.swift */,
 				EE247B1B1C3F137700AE3E12 /* BlobTests.swift */,
+				02A43A9C22738E2900FEC494 /* BackupTests.swift */,
 				EE247B1D1C3F137700AE3E12 /* ConnectionTests.swift */,
 				EE247B1E1C3F137700AE3E12 /* CoreFunctionsTests.swift */,
 				EE247B1F1C3F137700AE3E12 /* CustomFunctionsTests.swift */,
@@ -434,6 +444,7 @@
 				EE247AF21C3F06E900AE3E12 /* Statement.swift */,
 				EE247AF31C3F06E900AE3E12 /* Value.swift */,
 				19A1710E73A46D5AC721CDA9 /* Errors.swift */,
+				02A43A9722738CF100FEC494 /* Backup.swift */,
 			);
 			path = Core;
 			sourceTree = "<group>";
@@ -817,6 +828,7 @@
 				03A65E7E1C6BB2FB0062603F /* AggregateFunctions.swift in Sources */,
 				19A17EC0D68BA8C03288ADF7 /* FTS5.swift in Sources */,
 				19A179E76EA6207669B60C1B /* Cipher.swift in Sources */,
+				02A43A9A22738CF100FEC494 /* Backup.swift in Sources */,
 				19A17FF4A10B44D3937C8CAC /* Errors.swift in Sources */,
 				19A1737286A74F3CF7412906 /* DateAndTimeFunctions.swift in Sources */,
 			);
@@ -839,6 +851,7 @@
 				03A65E911C6BB3030062603F /* SchemaTests.swift in Sources */,
 				03A65E8D1C6BB3030062603F /* FTS4Tests.swift in Sources */,
 				03A65E8C1C6BB3030062603F /* ExpressionTests.swift in Sources */,
+				02A43A9F22738E2900FEC494 /* BackupTests.swift in Sources */,
 				03A65E8E1C6BB3030062603F /* OperatorsTests.swift in Sources */,
 				03A65E951C6BB3030062603F /* TestHelpers.swift in Sources */,
 				19A17254FBA7894891F7297B /* FTS5Tests.swift in Sources */,
@@ -875,6 +888,7 @@
 				3D67B3E71DB246BA00A4F4C6 /* Blob.swift in Sources */,
 				3D67B3E81DB246BA00A4F4C6 /* Connection.swift in Sources */,
 				19A179CCF9671E345E5A9811 /* Cipher.swift in Sources */,
+				02A43A9B22738CF100FEC494 /* Backup.swift in Sources */,
 				19A17DC282E36C4F41AA440B /* Errors.swift in Sources */,
 				19A173668D948AD4DF1F5352 /* DateAndTimeFunctions.swift in Sources */,
 			);
@@ -905,6 +919,7 @@
 				EE247B0D1C3F06E900AE3E12 /* AggregateFunctions.swift in Sources */,
 				19A1717B10CC941ACB5533D6 /* FTS5.swift in Sources */,
 				19A171F12AB8B07F2FD7201A /* Cipher.swift in Sources */,
+				02A43A9822738CF100FEC494 /* Backup.swift in Sources */,
 				19A1792C0520D4E83C2EB075 /* Errors.swift in Sources */,
 				19A17E29278A12BC4F542506 /* DateAndTimeFunctions.swift in Sources */,
 			);
@@ -927,6 +942,7 @@
 				EE247B351C3F142E00AE3E12 /* ValueTests.swift in Sources */,
 				EE247B2F1C3F141E00AE3E12 /* QueryTests.swift in Sources */,
 				EE247B221C3F137700AE3E12 /* AggregateFunctionsTests.swift in Sources */,
+				02A43A9D22738E2900FEC494 /* BackupTests.swift in Sources */,
 				EE247B2E1C3F141E00AE3E12 /* OperatorsTests.swift in Sources */,
 				EE247B251C3F137700AE3E12 /* ConnectionTests.swift in Sources */,
 				19A171E6FA242F72A308C594 /* FTS5Tests.swift in Sources */,
@@ -963,6 +979,7 @@
 				EE247B6D1C3F3FEC00AE3E12 /* AggregateFunctions.swift in Sources */,
 				19A1750CEE9B05267995CF3D /* FTS5.swift in Sources */,
 				19A17835FD5886FDC5A3228F /* Cipher.swift in Sources */,
+				02A43A9922738CF100FEC494 /* Backup.swift in Sources */,
 				19A17490543609FCED53CACC /* Errors.swift in Sources */,
 				19A17152E32A9585831E3FE0 /* DateAndTimeFunctions.swift in Sources */,
 			);
@@ -985,6 +1002,7 @@
 				EE247B551C3F3FC700AE3E12 /* ConnectionTests.swift in Sources */,
 				EE247B611C3F3FC700AE3E12 /* TestHelpers.swift in Sources */,
 				EE247B581C3F3FC700AE3E12 /* ExpressionTests.swift in Sources */,
+				02A43A9E22738E2900FEC494 /* BackupTests.swift in Sources */,
 				EE247B5E1C3F3FC700AE3E12 /* SetterTests.swift in Sources */,
 				EE247B5B1C3F3FC700AE3E12 /* QueryTests.swift in Sources */,
 				19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */,
diff --git a/Sources/SQLite/Core/Backup.swift b/Sources/SQLite/Core/Backup.swift
new file mode 100644
index 00000000..d001ae7d
--- /dev/null
+++ b/Sources/SQLite/Core/Backup.swift
@@ -0,0 +1,176 @@
+//
+// SQLite.swift
+// https://github.com/stephencelis/SQLite.swift
+// Copyright © 2014-2015 Stephen Celis.
+//
+// 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.
+//
+
+import Foundation
+import Dispatch
+#if SQLITE_SWIFT_STANDALONE
+import sqlite3
+#elseif SQLITE_SWIFT_SQLCIPHER
+import SQLCipher
+#elseif os(Linux)
+import CSQLite
+#else
+import SQLite3
+#endif
+
+/// An object representing database backup.
+///
+/// See: <https://www.sqlite.org/backup.html>
+public final class Backup {
+    
+    /// The name of the database to backup
+    public enum DatabaseName {
+        
+        /// The main database
+        case main
+        
+        /// The temporary database
+        case temp
+        
+        /// A database added to the connection with ATTACH statement
+        case attached(name: String)
+        
+        var name: String {
+            switch self {
+            case .main:
+                return "main"
+            case .temp:
+                return "temp"
+            case .attached(let name):
+                return name
+            }
+        }
+    }
+    
+    /// Number of pages to copy while performing a backup step
+    public enum Pages {
+        
+        /// Indicates all remaining pages should be copied
+        case all
+        
+        /// Indicates the maximal number of pages to be copied in single step
+        case limited(number: Int32)
+        
+        var number: Int32 {
+            switch self {
+            case .all:
+                return -1
+            case .limited(let number):
+                return number
+            }
+        }
+    }
+    
+    /// Total number of pages to copy
+    ///
+    /// See: <https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backuppagecount>
+    public var pageCount: Int32 {
+        return handle.map { sqlite3_backup_pagecount($0) } ?? 0
+    }
+    
+    /// Number of remaining pages to copy.
+    ///
+    /// See: <https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupremaining>
+    public var remainingPages: Int32 {
+        return handle.map { sqlite3_backup_remaining($0) } ?? 0
+    }
+    
+    private let targetConnection: Connection
+    private let sourceConnection: Connection
+    
+    private var handle: OpaquePointer?
+    
+    /// Initializes a new SQLite backup.
+    ///
+    /// - Parameters:
+    ///
+    ///   - targetConnection: The connection to the database to save backup into.
+    ///
+    ///   - targetConnection: The name of the database to save backup into.
+    ///
+    ///     Default: `.main`.
+    ///
+    ///   - sourceConnection: The connection to the database to backup.
+    ///
+    ///   - targetConnection: The name of the database to backup.
+    /// 
+    ///     Default: `.main`.
+    ///
+    /// - Returns: A new database backup.
+    ///
+    /// See: <https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupinit>
+    public init(targetConnection: Connection,
+                targetName: DatabaseName = .main,
+                sourceConnection: Connection,
+                sourceName: DatabaseName = .main) throws {
+        
+        self.targetConnection = targetConnection
+        self.sourceConnection = sourceConnection
+        
+        self.handle = sqlite3_backup_init(targetConnection.handle,
+                                          targetName.name.withCString { $0 },
+                                          sourceConnection.handle,
+                                          sourceName.name.withCString { $0 })
+        
+        if self.handle == nil, let error = Result(errorCode: sqlite3_errcode(targetConnection.handle), connection: targetConnection) {
+            throw error
+        }
+    }
+    
+    /// Performs a backup step.
+    ///
+    /// - Parameter pagesToCopy: The maximal number of pages to copy in one step
+    ///
+    /// - Throws: `Result.Error` if step fails.
+    //
+    /// See: <https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupstep>
+    public func step(pagesToCopy pages: Pages = .all) throws {
+        let status = sqlite3_backup_step(handle, pages.number)
+        
+        guard status != SQLITE_DONE else {
+            finish()
+            return
+        }
+        
+        if let error = Result(errorCode: status, connection: targetConnection) {
+            throw error
+        }
+    }
+    
+    /// Finalizes backup.
+    ///
+    /// See: <https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupfinish>
+    public func finish() {
+        guard let handle = self.handle else {
+            return
+        }
+        
+        sqlite3_backup_finish(handle)
+        self.handle = nil
+    }
+    
+    deinit {
+        finish()
+    }
+}
diff --git a/Tests/SQLiteTests/BackupTests.swift b/Tests/SQLiteTests/BackupTests.swift
new file mode 100644
index 00000000..284ba610
--- /dev/null
+++ b/Tests/SQLiteTests/BackupTests.swift
@@ -0,0 +1,36 @@
+import XCTest
+import Foundation
+import Dispatch
+@testable import SQLite
+
+#if SQLITE_SWIFT_STANDALONE
+import sqlite3
+#elseif SQLITE_SWIFT_SQLCIPHER
+import SQLCipher
+#elseif os(Linux)
+import CSQLite
+#else
+import SQLite3
+#endif
+
+class BackupTests : SQLiteTestCase {
+    override func setUp() {
+        super.setUp()
+        
+        CreateUsersTable()
+    }
+    
+    func test_backup_copies_database() throws {
+        let source = db!
+        let target = try Connection()
+
+        try InsertUsers("alice", "betsy")
+        
+        let backup = try Backup(targetConnection: target, sourceConnection: source)
+        try backup.step()
+        
+        let users = try target.prepare("SELECT email FROM users ORDER BY email")
+        XCTAssertEqual(users.map { $0[0] as? String }, ["alice@example.com", "betsy@example.com"])
+    }
+}
+

From d10c9da458377c245a59f8a817196b1ca221414a Mon Sep 17 00:00:00 2001
From: Krzysztof <krzysztof.kapitan@gmail.com>
Date: Sat, 27 Apr 2019 00:21:17 +0200
Subject: [PATCH 349/685] Pass swift strings instead of UnsafePointers while
 initializing backup

---
 Sources/SQLite/Core/Backup.swift | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Sources/SQLite/Core/Backup.swift b/Sources/SQLite/Core/Backup.swift
index d001ae7d..e4fc6204 100644
--- a/Sources/SQLite/Core/Backup.swift
+++ b/Sources/SQLite/Core/Backup.swift
@@ -129,9 +129,9 @@ public final class Backup {
         self.sourceConnection = sourceConnection
         
         self.handle = sqlite3_backup_init(targetConnection.handle,
-                                          targetName.name.withCString { $0 },
+                                          targetName.name,
                                           sourceConnection.handle,
-                                          sourceName.name.withCString { $0 })
+                                          sourceName.name)
         
         if self.handle == nil, let error = Result(errorCode: sqlite3_errcode(targetConnection.handle), connection: targetConnection) {
             throw error

From 69ca8fed4574a8fac8f3074b4ca025ed5afdeac5 Mon Sep 17 00:00:00 2001
From: Krzysztof <krzysztof.kapitan@gmail.com>
Date: Mon, 29 Apr 2019 18:07:45 +0200
Subject: [PATCH 350/685] More convenient API for backup

---
 SQLite.xcodeproj/project.pbxproj        |  8 ------
 Sources/SQLite/Core/Backup.swift        |  4 +--
 Sources/SQLite/Core/Connection.swift    | 29 +++++++++++++++++++-
 Tests/SQLiteTests/BackupTests.swift     | 36 -------------------------
 Tests/SQLiteTests/ConnectionTests.swift | 12 +++++++++
 5 files changed, 42 insertions(+), 47 deletions(-)
 delete mode 100644 Tests/SQLiteTests/BackupTests.swift

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index aec22743..b0bf35e7 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -11,9 +11,6 @@
 		02A43A9922738CF100FEC494 /* Backup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A43A9722738CF100FEC494 /* Backup.swift */; };
 		02A43A9A22738CF100FEC494 /* Backup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A43A9722738CF100FEC494 /* Backup.swift */; };
 		02A43A9B22738CF100FEC494 /* Backup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A43A9722738CF100FEC494 /* Backup.swift */; };
-		02A43A9D22738E2900FEC494 /* BackupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A43A9C22738E2900FEC494 /* BackupTests.swift */; };
-		02A43A9E22738E2900FEC494 /* BackupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A43A9C22738E2900FEC494 /* BackupTests.swift */; };
-		02A43A9F22738E2900FEC494 /* BackupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A43A9C22738E2900FEC494 /* BackupTests.swift */; };
 		03A65E641C6BB0F60062603F /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03A65E5A1C6BB0F50062603F /* SQLite.framework */; };
 		03A65E721C6BB2D30062603F /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		03A65E731C6BB2D80062603F /* Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF71C3F06E900AE3E12 /* Foundation.swift */; };
@@ -219,7 +216,6 @@
 
 /* Begin PBXFileReference section */
 		02A43A9722738CF100FEC494 /* Backup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Backup.swift; sourceTree = "<group>"; };
-		02A43A9C22738E2900FEC494 /* BackupTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupTests.swift; sourceTree = "<group>"; };
 		03A65E5A1C6BB0F50062603F /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		03A65E631C6BB0F60062603F /* SQLiteTests tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SQLiteTests tvOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
 		03A65E961C6BB3210062603F /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
@@ -407,7 +403,6 @@
 				19A17E2695737FAB5D6086E3 /* fixtures */,
 				EE247B1A1C3F137700AE3E12 /* AggregateFunctionsTests.swift */,
 				EE247B1B1C3F137700AE3E12 /* BlobTests.swift */,
-				02A43A9C22738E2900FEC494 /* BackupTests.swift */,
 				EE247B1D1C3F137700AE3E12 /* ConnectionTests.swift */,
 				EE247B1E1C3F137700AE3E12 /* CoreFunctionsTests.swift */,
 				EE247B1F1C3F137700AE3E12 /* CustomFunctionsTests.swift */,
@@ -851,7 +846,6 @@
 				03A65E911C6BB3030062603F /* SchemaTests.swift in Sources */,
 				03A65E8D1C6BB3030062603F /* FTS4Tests.swift in Sources */,
 				03A65E8C1C6BB3030062603F /* ExpressionTests.swift in Sources */,
-				02A43A9F22738E2900FEC494 /* BackupTests.swift in Sources */,
 				03A65E8E1C6BB3030062603F /* OperatorsTests.swift in Sources */,
 				03A65E951C6BB3030062603F /* TestHelpers.swift in Sources */,
 				19A17254FBA7894891F7297B /* FTS5Tests.swift in Sources */,
@@ -942,7 +936,6 @@
 				EE247B351C3F142E00AE3E12 /* ValueTests.swift in Sources */,
 				EE247B2F1C3F141E00AE3E12 /* QueryTests.swift in Sources */,
 				EE247B221C3F137700AE3E12 /* AggregateFunctionsTests.swift in Sources */,
-				02A43A9D22738E2900FEC494 /* BackupTests.swift in Sources */,
 				EE247B2E1C3F141E00AE3E12 /* OperatorsTests.swift in Sources */,
 				EE247B251C3F137700AE3E12 /* ConnectionTests.swift in Sources */,
 				19A171E6FA242F72A308C594 /* FTS5Tests.swift in Sources */,
@@ -1002,7 +995,6 @@
 				EE247B551C3F3FC700AE3E12 /* ConnectionTests.swift in Sources */,
 				EE247B611C3F3FC700AE3E12 /* TestHelpers.swift in Sources */,
 				EE247B581C3F3FC700AE3E12 /* ExpressionTests.swift in Sources */,
-				02A43A9E22738E2900FEC494 /* BackupTests.swift in Sources */,
 				EE247B5E1C3F3FC700AE3E12 /* SetterTests.swift in Sources */,
 				EE247B5B1C3F3FC700AE3E12 /* QueryTests.swift in Sources */,
 				19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */,
diff --git a/Sources/SQLite/Core/Backup.swift b/Sources/SQLite/Core/Backup.swift
index e4fc6204..1ea9637d 100644
--- a/Sources/SQLite/Core/Backup.swift
+++ b/Sources/SQLite/Core/Backup.swift
@@ -107,13 +107,13 @@ public final class Backup {
     ///
     ///   - targetConnection: The connection to the database to save backup into.
     ///
-    ///   - targetConnection: The name of the database to save backup into.
+    ///   - targetName: The name of the database to save backup into.
     ///
     ///     Default: `.main`.
     ///
     ///   - sourceConnection: The connection to the database to backup.
     ///
-    ///   - targetConnection: The name of the database to backup.
+    ///   - sourceName: The name of the database to backup.
     /// 
     ///     Default: `.main`.
     ///
diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 1bbf7f73..c23076af 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -627,7 +627,34 @@ public final class Connection {
     }
     fileprivate typealias Collation = @convention(block) (UnsafeRawPointer, UnsafeRawPointer) -> Int32
     fileprivate var collations = [String: Collation]()
-
+    
+    // MARK: - Backup
+    
+    /// Prepares a new backup for current connection.
+    ///
+    /// - Parameters:
+    ///
+    ///   - databaseName: The name of the database to backup.
+    ///
+    ///     Default: `.main`
+    ///
+    ///   - targetConnection: The name of the database to save backup into.
+    ///
+    ///   - targetDatabaseName: The name of the database to save backup into.
+    ///
+    ///     Default: `.main`.
+    ///
+    /// - Returns: A new database backup.
+    
+    public func backup(databaseName: Backup.DatabaseName = .main,
+                       usingConnection targetConnection: Connection,
+                       andDatabaseName targetDatabaseName: Backup.DatabaseName = .main) throws -> Backup {
+        return try Backup(targetConnection: targetConnection,
+                          targetName: targetDatabaseName,
+                          sourceConnection: self,
+                          sourceName: databaseName)
+    }
+    
     // MARK: - Error Handling
 
     func sync<T>(_ block: () throws -> T) rethrows -> T {
diff --git a/Tests/SQLiteTests/BackupTests.swift b/Tests/SQLiteTests/BackupTests.swift
deleted file mode 100644
index 284ba610..00000000
--- a/Tests/SQLiteTests/BackupTests.swift
+++ /dev/null
@@ -1,36 +0,0 @@
-import XCTest
-import Foundation
-import Dispatch
-@testable import SQLite
-
-#if SQLITE_SWIFT_STANDALONE
-import sqlite3
-#elseif SQLITE_SWIFT_SQLCIPHER
-import SQLCipher
-#elseif os(Linux)
-import CSQLite
-#else
-import SQLite3
-#endif
-
-class BackupTests : SQLiteTestCase {
-    override func setUp() {
-        super.setUp()
-        
-        CreateUsersTable()
-    }
-    
-    func test_backup_copies_database() throws {
-        let source = db!
-        let target = try Connection()
-
-        try InsertUsers("alice", "betsy")
-        
-        let backup = try Backup(targetConnection: target, sourceConnection: source)
-        try backup.step()
-        
-        let users = try target.prepare("SELECT email FROM users ORDER BY email")
-        XCTAssertEqual(users.map { $0[0] as? String }, ["alice@example.com", "betsy@example.com"])
-    }
-}
-
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index eab3cf00..bae13971 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -141,6 +141,18 @@ class ConnectionTests : SQLiteTestCase {
 
         AssertSQL("BEGIN EXCLUSIVE TRANSACTION")
     }
+    
+    func test_backup_copiesDatabase() throws {
+        let target = try Connection()
+        
+        try InsertUsers("alice", "betsy")
+        
+        let backup = try db.backup(usingConnection: target)
+        try backup.step()
+        
+        let users = try target.prepare("SELECT email FROM users ORDER BY email")
+        XCTAssertEqual(users.map { $0[0] as? String }, ["alice@example.com", "betsy@example.com"])
+    }
 
     func test_transaction_beginsAndCommitsTransactions() {
         let stmt = try! db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com")

From 2509ee37b80b7633a8f6dc8e5c72f34ae60f08dc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?M=2EG=C3=B6kay=20Borulday?= <m.gokay@borulday.com>
Date: Wed, 22 May 2019 17:57:57 +0300
Subject: [PATCH 351/685] Add missing parenthesis

---
 Documentation/Index.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 05967ff4..70d67c2d 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1209,7 +1209,7 @@ We can build an `ALTER TABLE … RENAME TO` statement by calling the `rename`
 function on a `Table` or `VirtualTable`.
 
 ```swift
-try db.run(users.rename(Table("users_old"))
+try db.run(users.rename(Table("users_old")))
 // ALTER TABLE "users" RENAME TO "users_old"
 ```
 

From c27d53cab370631a21f089a19ac72a183693ab16 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simon=20K=C3=A5gedal=20Reimer?= <skagedal@gmail.com>
Date: Thu, 30 May 2019 11:15:11 +0200
Subject: [PATCH 352/685] Rename SQLite-Bridging.h -> SQLiteObjc.h

Fixes #925 and makes SwiftPM-generated Xcode projects that use SQLite.swift compile
out of the box.
---
 SQLite.xcodeproj/project.pbxproj              | 20 +++++++++----------
 .../xcshareddata/IDEWorkspaceChecks.plist     |  8 ++++++++
 Sources/SQLite/SQLite.h                       |  2 +-
 Sources/SQLiteObjc/SQLite-Bridging.m          |  2 +-
 .../{SQLite-Bridging.h => SQLiteObjc.h}       |  0
 5 files changed, 20 insertions(+), 12 deletions(-)
 create mode 100644 SQLite.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
 rename Sources/SQLiteObjc/include/{SQLite-Bridging.h => SQLiteObjc.h} (100%)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 9d38dbc4..2d7735db 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -11,7 +11,7 @@
 		03A65E721C6BB2D30062603F /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		03A65E731C6BB2D80062603F /* Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF71C3F06E900AE3E12 /* Foundation.swift */; };
 		03A65E741C6BB2DA0062603F /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF81C3F06E900AE3E12 /* Helpers.swift */; };
-		03A65E751C6BB2DF0062603F /* SQLite-Bridging.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808D1C46E5230038162A /* SQLite-Bridging.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		03A65E751C6BB2DF0062603F /* SQLiteObjc.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808D1C46E5230038162A /* SQLiteObjc.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		03A65E761C6BB2E60062603F /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
 		03A65E771C6BB2E60062603F /* Connection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEF1C3F06E900AE3E12 /* Connection.swift */; };
 		03A65E781C6BB2EA0062603F /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */; };
@@ -101,7 +101,7 @@
 		3D67B3F71DB246D700A4F4C6 /* Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF71C3F06E900AE3E12 /* Foundation.swift */; };
 		3D67B3F81DB246D700A4F4C6 /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF81C3F06E900AE3E12 /* Helpers.swift */; };
 		3D67B3F91DB246E700A4F4C6 /* SQLite-Bridging.m in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */; };
-		3D67B3FB1DB2470600A4F4C6 /* SQLite-Bridging.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808D1C46E5230038162A /* SQLite-Bridging.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3D67B3FB1DB2470600A4F4C6 /* SQLiteObjc.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808D1C46E5230038162A /* SQLiteObjc.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		3D67B3FC1DB2471B00A4F4C6 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		3D67B3FD1DB2472D00A4F4C6 /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */; };
 		49EB68C41F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
@@ -180,8 +180,8 @@
 		EE247B731C3F3FEC00AE3E12 /* Query.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B001C3F06E900AE3E12 /* Query.swift */; };
 		EE247B741C3F3FEC00AE3E12 /* Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B011C3F06E900AE3E12 /* Schema.swift */; };
 		EE247B751C3F3FEC00AE3E12 /* Setter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B021C3F06E900AE3E12 /* Setter.swift */; };
-		EE91808E1C46E5230038162A /* SQLite-Bridging.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808D1C46E5230038162A /* SQLite-Bridging.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		EE91808F1C46E76D0038162A /* SQLite-Bridging.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808D1C46E5230038162A /* SQLite-Bridging.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		EE91808E1C46E5230038162A /* SQLiteObjc.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808D1C46E5230038162A /* SQLiteObjc.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		EE91808F1C46E76D0038162A /* SQLiteObjc.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808D1C46E5230038162A /* SQLiteObjc.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		EE9180941C46EA210038162A /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = EE9180931C46EA210038162A /* libsqlite3.tbd */; };
 		EE9180951C46EBCC0038162A /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = EE9180911C46E9D30038162A /* libsqlite3.tbd */; };
 /* End PBXBuildFile section */
@@ -277,7 +277,7 @@
 		EE247B911C3F822500AE3E12 /* installation@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "installation@2x.png"; sourceTree = "<group>"; };
 		EE247B921C3F822600AE3E12 /* playground@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "playground@2x.png"; sourceTree = "<group>"; };
 		EE247B931C3F826100AE3E12 /* SQLite.swift.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; path = SQLite.swift.podspec; sourceTree = "<group>"; };
-		EE91808D1C46E5230038162A /* SQLite-Bridging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "SQLite-Bridging.h"; path = "../../SQLiteObjc/include/SQLite-Bridging.h"; sourceTree = "<group>"; };
+		EE91808D1C46E5230038162A /* SQLiteObjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SQLiteObjc.h; path = ../../SQLiteObjc/include/SQLiteObjc.h; sourceTree = "<group>"; };
 		EE9180911C46E9D30038162A /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
 		EE9180931C46EA210038162A /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; };
 /* End PBXFileReference section */
@@ -426,7 +426,7 @@
 		EE247AED1C3F06E900AE3E12 /* Core */ = {
 			isa = PBXGroup;
 			children = (
-				EE91808D1C46E5230038162A /* SQLite-Bridging.h */,
+				EE91808D1C46E5230038162A /* SQLiteObjc.h */,
 				EE247AEE1C3F06E900AE3E12 /* Blob.swift */,
 				EE247AEF1C3F06E900AE3E12 /* Connection.swift */,
 				EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */,
@@ -509,7 +509,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				03A65E781C6BB2EA0062603F /* fts3_tokenizer.h in Headers */,
-				03A65E751C6BB2DF0062603F /* SQLite-Bridging.h in Headers */,
+				03A65E751C6BB2DF0062603F /* SQLiteObjc.h in Headers */,
 				03A65E721C6BB2D30062603F /* SQLite.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -518,7 +518,7 @@
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				3D67B3FB1DB2470600A4F4C6 /* SQLite-Bridging.h in Headers */,
+				3D67B3FB1DB2470600A4F4C6 /* SQLiteObjc.h in Headers */,
 				3D67B3FC1DB2471B00A4F4C6 /* SQLite.h in Headers */,
 				3D67B3FD1DB2472D00A4F4C6 /* fts3_tokenizer.h in Headers */,
 			);
@@ -528,7 +528,7 @@
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				EE91808E1C46E5230038162A /* SQLite-Bridging.h in Headers */,
+				EE91808E1C46E5230038162A /* SQLiteObjc.h in Headers */,
 				EE247B051C3F06E900AE3E12 /* fts3_tokenizer.h in Headers */,
 				EE247AD71C3F04ED00AE3E12 /* SQLite.h in Headers */,
 			);
@@ -540,7 +540,7 @@
 			files = (
 				EE247B671C3F3FEC00AE3E12 /* fts3_tokenizer.h in Headers */,
 				EE247B621C3F3FDB00AE3E12 /* SQLite.h in Headers */,
-				EE91808F1C46E76D0038162A /* SQLite-Bridging.h in Headers */,
+				EE91808F1C46E76D0038162A /* SQLiteObjc.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/SQLite.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/SQLite.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 00000000..18d98100
--- /dev/null
+++ b/SQLite.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IDEDidComputeMac32BitWarning</key>
+	<true/>
+</dict>
+</plist>
diff --git a/Sources/SQLite/SQLite.h b/Sources/SQLite/SQLite.h
index 693ce323..69382ea0 100644
--- a/Sources/SQLite/SQLite.h
+++ b/Sources/SQLite/SQLite.h
@@ -3,4 +3,4 @@
 FOUNDATION_EXPORT double SQLiteVersionNumber;
 FOUNDATION_EXPORT const unsigned char SQLiteVersionString[];
 
-#import <SQLite/SQLite-Bridging.h>
+#import <SQLite/SQLiteObjc.h>
diff --git a/Sources/SQLiteObjc/SQLite-Bridging.m b/Sources/SQLiteObjc/SQLite-Bridging.m
index e00a7315..9f2be0bd 100644
--- a/Sources/SQLiteObjc/SQLite-Bridging.m
+++ b/Sources/SQLiteObjc/SQLite-Bridging.m
@@ -22,7 +22,7 @@
 // THE SOFTWARE.
 //
 
-#import "SQLite-Bridging.h"
+#import "SQLiteObjc.h"
 #import "fts3_tokenizer.h"
 
 #pragma mark - FTS
diff --git a/Sources/SQLiteObjc/include/SQLite-Bridging.h b/Sources/SQLiteObjc/include/SQLiteObjc.h
similarity index 100%
rename from Sources/SQLiteObjc/include/SQLite-Bridging.h
rename to Sources/SQLiteObjc/include/SQLiteObjc.h

From dc38f8c2da63aa238b3361e20893714d9c93bf42 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simon=20K=C3=A5gedal=20Reimer?= <skagedal@gmail.com>
Date: Thu, 30 May 2019 22:05:11 +0200
Subject: [PATCH 353/685] Rename SQLite-Bridging.m -> SQLiteObjc.m

---
 SQLite.xcodeproj/project.pbxproj              | 20 +++++++++----------
 .../{SQLite-Bridging.m => SQLiteObjc.m}       |  0
 2 files changed, 10 insertions(+), 10 deletions(-)
 rename Sources/SQLiteObjc/{SQLite-Bridging.m => SQLiteObjc.m} (100%)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 2d7735db..30a40214 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -15,7 +15,7 @@
 		03A65E761C6BB2E60062603F /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
 		03A65E771C6BB2E60062603F /* Connection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEF1C3F06E900AE3E12 /* Connection.swift */; };
 		03A65E781C6BB2EA0062603F /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */; };
-		03A65E791C6BB2EF0062603F /* SQLite-Bridging.m in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */; };
+		03A65E791C6BB2EF0062603F /* SQLiteObjc.m in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF11C3F06E900AE3E12 /* SQLiteObjc.m */; };
 		03A65E7A1C6BB2F70062603F /* Statement.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF21C3F06E900AE3E12 /* Statement.swift */; };
 		03A65E7B1C6BB2F70062603F /* Value.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF31C3F06E900AE3E12 /* Value.swift */; };
 		03A65E7C1C6BB2F70062603F /* FTS4.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF51C3F06E900AE3E12 /* FTS4.swift */; };
@@ -100,7 +100,7 @@
 		3D67B3F61DB246D100A4F4C6 /* Setter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B021C3F06E900AE3E12 /* Setter.swift */; };
 		3D67B3F71DB246D700A4F4C6 /* Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF71C3F06E900AE3E12 /* Foundation.swift */; };
 		3D67B3F81DB246D700A4F4C6 /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF81C3F06E900AE3E12 /* Helpers.swift */; };
-		3D67B3F91DB246E700A4F4C6 /* SQLite-Bridging.m in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */; };
+		3D67B3F91DB246E700A4F4C6 /* SQLiteObjc.m in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF11C3F06E900AE3E12 /* SQLiteObjc.m */; };
 		3D67B3FB1DB2470600A4F4C6 /* SQLiteObjc.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808D1C46E5230038162A /* SQLiteObjc.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		3D67B3FC1DB2471B00A4F4C6 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		3D67B3FD1DB2472D00A4F4C6 /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */; };
@@ -113,7 +113,7 @@
 		EE247B031C3F06E900AE3E12 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
 		EE247B041C3F06E900AE3E12 /* Connection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEF1C3F06E900AE3E12 /* Connection.swift */; };
 		EE247B051C3F06E900AE3E12 /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */; };
-		EE247B061C3F06E900AE3E12 /* SQLite-Bridging.m in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */; };
+		EE247B061C3F06E900AE3E12 /* SQLiteObjc.m in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF11C3F06E900AE3E12 /* SQLiteObjc.m */; };
 		EE247B071C3F06E900AE3E12 /* Statement.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF21C3F06E900AE3E12 /* Statement.swift */; };
 		EE247B081C3F06E900AE3E12 /* Value.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF31C3F06E900AE3E12 /* Value.swift */; };
 		EE247B091C3F06E900AE3E12 /* FTS4.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF51C3F06E900AE3E12 /* FTS4.swift */; };
@@ -166,7 +166,7 @@
 		EE247B651C3F3FEC00AE3E12 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
 		EE247B661C3F3FEC00AE3E12 /* Connection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEF1C3F06E900AE3E12 /* Connection.swift */; };
 		EE247B671C3F3FEC00AE3E12 /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */; };
-		EE247B681C3F3FEC00AE3E12 /* SQLite-Bridging.m in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */; };
+		EE247B681C3F3FEC00AE3E12 /* SQLiteObjc.m in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF11C3F06E900AE3E12 /* SQLiteObjc.m */; };
 		EE247B691C3F3FEC00AE3E12 /* Statement.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF21C3F06E900AE3E12 /* Statement.swift */; };
 		EE247B6A1C3F3FEC00AE3E12 /* Value.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF31C3F06E900AE3E12 /* Value.swift */; };
 		EE247B6B1C3F3FEC00AE3E12 /* FTS4.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF51C3F06E900AE3E12 /* FTS4.swift */; };
@@ -236,7 +236,7 @@
 		EE247AEE1C3F06E900AE3E12 /* Blob.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Blob.swift; sourceTree = "<group>"; };
 		EE247AEF1C3F06E900AE3E12 /* Connection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Connection.swift; sourceTree = "<group>"; };
 		EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = fts3_tokenizer.h; path = ../../SQLiteObjc/fts3_tokenizer.h; sourceTree = "<group>"; };
-		EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "SQLite-Bridging.m"; path = "../../SQLiteObjc/SQLite-Bridging.m"; sourceTree = "<group>"; };
+		EE247AF11C3F06E900AE3E12 /* SQLiteObjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SQLiteObjc.m; path = ../../SQLiteObjc/SQLiteObjc.m; sourceTree = "<group>"; };
 		EE247AF21C3F06E900AE3E12 /* Statement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Statement.swift; sourceTree = "<group>"; };
 		EE247AF31C3F06E900AE3E12 /* Value.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Value.swift; sourceTree = "<group>"; };
 		EE247AF51C3F06E900AE3E12 /* FTS4.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS4.swift; sourceTree = "<group>"; };
@@ -430,7 +430,7 @@
 				EE247AEE1C3F06E900AE3E12 /* Blob.swift */,
 				EE247AEF1C3F06E900AE3E12 /* Connection.swift */,
 				EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */,
-				EE247AF11C3F06E900AE3E12 /* SQLite-Bridging.m */,
+				EE247AF11C3F06E900AE3E12 /* SQLiteObjc.m */,
 				EE247AF21C3F06E900AE3E12 /* Statement.swift */,
 				EE247AF31C3F06E900AE3E12 /* Value.swift */,
 				19A1710E73A46D5AC721CDA9 /* Errors.swift */,
@@ -800,7 +800,7 @@
 				49EB68C61F7B3CB400D89D40 /* Coding.swift in Sources */,
 				03A65E761C6BB2E60062603F /* Blob.swift in Sources */,
 				03A65E7D1C6BB2F70062603F /* RTree.swift in Sources */,
-				03A65E791C6BB2EF0062603F /* SQLite-Bridging.m in Sources */,
+				03A65E791C6BB2EF0062603F /* SQLiteObjc.m in Sources */,
 				03A65E7B1C6BB2F70062603F /* Value.swift in Sources */,
 				03A65E821C6BB2FB0062603F /* Expression.swift in Sources */,
 				03A65E731C6BB2D80062603F /* Foundation.swift in Sources */,
@@ -854,7 +854,7 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				3D67B3F91DB246E700A4F4C6 /* SQLite-Bridging.m in Sources */,
+				3D67B3F91DB246E700A4F4C6 /* SQLiteObjc.m in Sources */,
 				49EB68C71F7B3CB400D89D40 /* Coding.swift in Sources */,
 				3D67B3F71DB246D700A4F4C6 /* Foundation.swift in Sources */,
 				3D67B3F81DB246D700A4F4C6 /* Helpers.swift in Sources */,
@@ -900,7 +900,7 @@
 				EE247B121C3F06E900AE3E12 /* Operators.swift in Sources */,
 				EE247B141C3F06E900AE3E12 /* Schema.swift in Sources */,
 				EE247B131C3F06E900AE3E12 /* Query.swift in Sources */,
-				EE247B061C3F06E900AE3E12 /* SQLite-Bridging.m in Sources */,
+				EE247B061C3F06E900AE3E12 /* SQLiteObjc.m in Sources */,
 				EE247B071C3F06E900AE3E12 /* Statement.swift in Sources */,
 				EE247B0D1C3F06E900AE3E12 /* AggregateFunctions.swift in Sources */,
 				19A1717B10CC941ACB5533D6 /* FTS5.swift in Sources */,
@@ -946,7 +946,7 @@
 				49EB68C51F7B3CB400D89D40 /* Coding.swift in Sources */,
 				EE247B651C3F3FEC00AE3E12 /* Blob.swift in Sources */,
 				EE247B6C1C3F3FEC00AE3E12 /* RTree.swift in Sources */,
-				EE247B681C3F3FEC00AE3E12 /* SQLite-Bridging.m in Sources */,
+				EE247B681C3F3FEC00AE3E12 /* SQLiteObjc.m in Sources */,
 				EE247B6A1C3F3FEC00AE3E12 /* Value.swift in Sources */,
 				EE247B711C3F3FEC00AE3E12 /* Expression.swift in Sources */,
 				EE247B631C3F3FDB00AE3E12 /* Foundation.swift in Sources */,
diff --git a/Sources/SQLiteObjc/SQLite-Bridging.m b/Sources/SQLiteObjc/SQLiteObjc.m
similarity index 100%
rename from Sources/SQLiteObjc/SQLite-Bridging.m
rename to Sources/SQLiteObjc/SQLiteObjc.m

From 8dbbf80a28a42847e8b41a649c3a384c37106475 Mon Sep 17 00:00:00 2001
From: Yehor Popovych <yehor@crossroad.io>
Date: Wed, 19 Jun 2019 17:17:21 +0300
Subject: [PATCH 354/685] version bump

---
 SQLite.swift.podspec      | 2 +-
 Sources/SQLite/Info.plist | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 57eda40a..524e721c 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.12.0"
+  s.version          = "0.12.1"
   s.summary          = "A type-safe, Swift-language layer over SQLite3 for iOS and macOS."
 
   s.description      = <<-DESC
diff --git a/Sources/SQLite/Info.plist b/Sources/SQLite/Info.plist
index db84c711..f7f7ce7f 100644
--- a/Sources/SQLite/Info.plist
+++ b/Sources/SQLite/Info.plist
@@ -15,7 +15,7 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>0.12.0</string>
+	<string>0.12.1</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>

From 1b1ec920f1e168707b1a6af80d297d8f0d77bbd1 Mon Sep 17 00:00:00 2001
From: Yehor Popovych <yehor@crossroad.io>
Date: Thu, 20 Jun 2019 22:52:43 +0300
Subject: [PATCH 355/685] Fixed build with module headers

---
 SQLite.swift.podspec    | 28 +++++++++++++++++++++-------
 Sources/SQLite/SQLite.h |  2 +-
 2 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 524e721c..cae73653 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -15,14 +15,19 @@ Pod::Spec.new do |s|
   s.social_media_url = 'https://twitter.com/stephencelis'
 
   s.module_name      = 'SQLite'
-  s.ios.deployment_target = "8.0"
-  s.tvos.deployment_target = "9.1"
-  s.osx.deployment_target = "10.10"
-  s.watchos.deployment_target = "2.2"
   s.default_subspec  = 'standard'
-  s.pod_target_xcconfig = {
-    'SWIFT_VERSION' => '5',
-  }
+  s.swift_versions = ['4.2', '5']
+  
+  
+  ios_deployment_target = '8.0'
+  tvos_deployment_target = '9.1'
+  osx_deployment_target = '10.10'
+  watchos_deployment_target = '2.2'
+  
+  s.ios.deployment_target = ios_deployment_target
+  s.tvos.deployment_target = tvos_deployment_target
+  s.osx.deployment_target = osx_deployment_target
+  s.watchos.deployment_target = watchos_deployment_target
 
   s.subspec 'standard' do |ss|
     ss.source_files = 'Sources/{SQLite,SQLiteObjc}/**/*.{c,h,m,swift}'
@@ -33,6 +38,9 @@ Pod::Spec.new do |s|
     ss.test_spec 'tests' do |test_spec|
       test_spec.resources = 'Tests/SQLiteTests/fixtures/*'
       test_spec.source_files = 'Tests/SQLiteTests/*.swift'
+      test_spec.ios.deployment_target = ios_deployment_target
+      test_spec.tvos.deployment_target = tvos_deployment_target
+      test_spec.osx.deployment_target = osx_deployment_target
     end
   end
 
@@ -49,6 +57,9 @@ Pod::Spec.new do |s|
     ss.test_spec 'tests' do |test_spec|
       test_spec.resources = 'Tests/SQLiteTests/fixtures/*'
       test_spec.source_files = 'Tests/SQLiteTests/*.swift'
+      test_spec.ios.deployment_target = ios_deployment_target
+      test_spec.tvos.deployment_target = tvos_deployment_target
+      test_spec.osx.deployment_target = osx_deployment_target
     end
   end
 
@@ -64,6 +75,9 @@ Pod::Spec.new do |s|
     ss.test_spec 'tests' do |test_spec|
       test_spec.resources = 'Tests/SQLiteTests/fixtures/*'
       test_spec.source_files = 'Tests/SQLiteTests/*.swift'
+      test_spec.ios.deployment_target = ios_deployment_target
+      test_spec.tvos.deployment_target = tvos_deployment_target
+      test_spec.osx.deployment_target = osx_deployment_target
     end
   end
 end
diff --git a/Sources/SQLite/SQLite.h b/Sources/SQLite/SQLite.h
index 69382ea0..fe1e3dfe 100644
--- a/Sources/SQLite/SQLite.h
+++ b/Sources/SQLite/SQLite.h
@@ -3,4 +3,4 @@
 FOUNDATION_EXPORT double SQLiteVersionNumber;
 FOUNDATION_EXPORT const unsigned char SQLiteVersionString[];
 
-#import <SQLite/SQLiteObjc.h>
+#import "SQLiteObjc.h"

From d0d802e3f99b78112cfb0b71894eeec021a7436c Mon Sep 17 00:00:00 2001
From: Yehor Popovych <yehor@crossroad.io>
Date: Fri, 21 Jun 2019 13:18:14 +0300
Subject: [PATCH 356/685] version bump

---
 SQLite.swift.podspec      | 2 +-
 Sources/SQLite/Info.plist | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index cae73653..2341cfc4 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.12.1"
+  s.version          = "0.12.2"
   s.summary          = "A type-safe, Swift-language layer over SQLite3 for iOS and macOS."
 
   s.description      = <<-DESC
diff --git a/Sources/SQLite/Info.plist b/Sources/SQLite/Info.plist
index f7f7ce7f..2d956da2 100644
--- a/Sources/SQLite/Info.plist
+++ b/Sources/SQLite/Info.plist
@@ -15,7 +15,7 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>0.12.1</string>
+	<string>0.12.2</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>

From 4de5dc458788bc09111d26f97c4ea46c8f08d946 Mon Sep 17 00:00:00 2001
From: Guillaume Algis <guillaume.algis@ipsosante.fr>
Date: Wed, 14 Aug 2019 12:44:15 +0200
Subject: [PATCH 357/685] Add @discardableResult to all FTSConfig methods
 returning Self for chaining

---
 Sources/SQLite/Extensions/FTS4.swift | 18 +++++++++---------
 Sources/SQLite/Extensions/FTS5.swift |  6 +++---
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/Sources/SQLite/Extensions/FTS4.swift b/Sources/SQLite/Extensions/FTS4.swift
index 5ef84dd7..f0184565 100644
--- a/Sources/SQLite/Extensions/FTS4.swift
+++ b/Sources/SQLite/Extensions/FTS4.swift
@@ -194,25 +194,25 @@ open class FTSConfig {
     }
 
     /// [Tokenizers](https://www.sqlite.org/fts3.html#tokenizer)
-    open func tokenizer(_ tokenizer: Tokenizer?) -> Self {
+    @discardableResult open func tokenizer(_ tokenizer: Tokenizer?) -> Self {
         self.tokenizer = tokenizer
         return self
     }
 
     /// [The prefix= option](https://www.sqlite.org/fts3.html#section_6_6)
-    open func prefix(_ prefix: [Int]) -> Self {
+    @discardableResult open func prefix(_ prefix: [Int]) -> Self {
         self.prefixes += prefix
         return self
     }
 
     /// [The content= option](https://www.sqlite.org/fts3.html#section_6_2)
-    open func externalContent(_ schema: SchemaType) -> Self {
+    @discardableResult open func externalContent(_ schema: SchemaType) -> Self {
         self.externalContentSchema = schema
         return self
     }
 
     /// [Contentless FTS4 Tables](https://www.sqlite.org/fts3.html#section_6_2_1)
-    open func contentless() -> Self {
+    @discardableResult open func contentless() -> Self {
         self.isContentless = true
         return self
     }
@@ -308,31 +308,31 @@ open class FTS4Config : FTSConfig {
     }
 
     /// [The compress= and uncompress= options](https://www.sqlite.org/fts3.html#section_6_1)
-    open func compress(_ functionName: String) -> Self {
+    @discardableResult open func compress(_ functionName: String) -> Self {
         self.compressFunction = functionName
         return self
     }
 
     /// [The compress= and uncompress= options](https://www.sqlite.org/fts3.html#section_6_1)
-    open func uncompress(_ functionName: String) -> Self {
+    @discardableResult open func uncompress(_ functionName: String) -> Self {
         self.uncompressFunction = functionName
         return self
     }
 
     /// [The languageid= option](https://www.sqlite.org/fts3.html#section_6_3)
-    open func languageId(_ columnName: String) -> Self {
+    @discardableResult open func languageId(_ columnName: String) -> Self {
         self.languageId = columnName
         return self
     }
 
     /// [The matchinfo= option](https://www.sqlite.org/fts3.html#section_6_4)
-    open func matchInfo(_ matchInfo: MatchInfo) -> Self {
+    @discardableResult open func matchInfo(_ matchInfo: MatchInfo) -> Self {
         self.matchInfo = matchInfo
         return self
     }
 
     /// [FTS4 options](https://www.sqlite.org/fts3.html#fts4_options)
-    open func order(_ order: Order) -> Self {
+    @discardableResult open func order(_ order: Order) -> Self {
         self.order = order
         return self
     }
diff --git a/Sources/SQLite/Extensions/FTS5.swift b/Sources/SQLite/Extensions/FTS5.swift
index 763927ff..cf13f3d8 100644
--- a/Sources/SQLite/Extensions/FTS5.swift
+++ b/Sources/SQLite/Extensions/FTS5.swift
@@ -58,19 +58,19 @@ open class FTS5Config : FTSConfig {
     }
 
     /// [External Content Tables](https://www.sqlite.org/fts5.html#section_4_4_2)
-    open func contentRowId(_ column: Expressible) -> Self {
+    @discardableResult open func contentRowId(_ column: Expressible) -> Self {
         self.contentRowId = column
         return self
     }
 
     /// [The Columnsize Option](https://www.sqlite.org/fts5.html#section_4_5)
-    open func columnSize(_ size: Int) -> Self {
+    @discardableResult open func columnSize(_ size: Int) -> Self {
         self.columnSize = size
         return self
     }
 
     /// [The Detail Option](https://www.sqlite.org/fts5.html#section_4_6)
-    open func detail(_ detail: Detail) -> Self {
+    @discardableResult open func detail(_ detail: Detail) -> Self {
         self.detail = detail
         return self
     }

From 115ad41835b9de8c2f69fa510c222ce85e526a71 Mon Sep 17 00:00:00 2001
From: Johannes Ebeling <johannes.ebeling@wandelbots.com>
Date: Sat, 17 Aug 2019 00:15:34 +0200
Subject: [PATCH 358/685] Enable the encodable api to pass the onConflict
 parameter to the QueryType.insert function

---
 Sources/SQLite/Typed/Coding.swift | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index c3fb931b..d4f99e6e 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -44,6 +44,30 @@ extension QueryType {
         try encodable.encode(to: encoder)
         return self.insert(encoder.setters + otherSetters)
     }
+    
+    /// Creates an `INSERT` statement by encoding the given object
+    /// This method converts any custom nested types to JSON data and does not handle any sort
+    /// of object relationships. If you want to support relationships between objects you will
+    /// have to provide your own Encodable implementations that encode the correct ids.
+    /// The onConflict will be passed to the actual insert function to define what should happen
+    /// when an error occurs during the insert operation.
+    ///
+    /// - Parameters:
+    ///
+    ///   - onConlict: Define what happens when an insert operation fails
+    ///
+    ///   - encodable: An encodable object to insert
+    ///
+    ///   - userInfo: User info to be passed to encoder
+    ///
+    ///   - otherSetters: Any other setters to include in the insert
+    ///
+    /// - Returns: An `INSERT` statement fort the encodable object
+    public func insert(or onConflict: OnConflict, encodable: Encodable, userInfo: [CodingUserInfoKey:Any] = [:], otherSetters: [Setter] = []) throws -> Insert {
+        let encoder = SQLiteEncoder(userInfo: userInfo)
+        try encodable.encode(to: encoder)
+        return self.insert(or: onConflict, encoder.setters + otherSetters)
+    }
 
     /// Creates an `UPDATE` statement by encoding the given object
     /// This method converts any custom nested types to JSON data and does not handle any sort

From d8193fb00255186802fe5182cd84fa4de041f917 Mon Sep 17 00:00:00 2001
From: Bartek <ktoosiu@gmail.com>
Date: Tue, 5 Nov 2019 08:40:20 +0100
Subject: [PATCH 359/685] closing brackets/aposthrophes

few things wasnt closed properly
---
 Documentation/Index.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 70d67c2d..c6c54437 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1792,12 +1792,12 @@ let config = FTS5Config()
     .column(subject)
     .column(body, [.unindexed])
 
-try db.run(emails.create(.FTS5(config))
+try db.run(emails.create(.FTS5(config)))
 // CREATE VIRTUAL TABLE "emails" USING fts5("subject", "body" UNINDEXED)
 
 // Note that FTS5 uses a different syntax to select columns, so we need to rewrite
 // the last FTS4 query above as:
-let replies = emails.filter(emails.match("subject:\"Re:\"*))
+let replies = emails.filter(emails.match("subject:\"Re:\"*"))
 // SELECT * FROM "emails" WHERE "emails" MATCH 'subject:"Re:"*'
 
 // https://www.sqlite.org/fts5.html#_changes_to_select_statements_

From ef3f88f7d02116c95088d7c5dae9a0af42f4dbfc Mon Sep 17 00:00:00 2001
From: Bradley Walters <bwalters@anonyome.com>
Date: Fri, 15 Nov 2019 09:52:51 -0700
Subject: [PATCH 360/685] Fix building with standalone sqlite3 >= 3.30.0

SQLite 3.30.0 changed the definition of SQLITE_DETERMINISTIC:
`-#define SQLITE_DETERMINISTIC    0x800`
`+#define SQLITE_DETERMINISTIC    0x000000800`

Meaning that the (older) system sqlite3 library and the pod have
different definitions, even though they're the same value.

We've been importing the system sqlite3 module in SQLiteObjc.h
even when linking against standalone sqlite.

I added a check to SQLiteObjc.h to import the sqlite3 pod when
we're using it, instead of always importing the system module.

This leads to there being only one definition in scope.
---
 SQLite.swift.podspec                    | 3 ++-
 Sources/SQLiteObjc/include/SQLiteObjc.h | 4 ++++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 2341cfc4..712ddc36 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -50,7 +50,8 @@ Pod::Spec.new do |s|
     ss.private_header_files = 'Sources/SQLiteObjc/*.h'
 
     ss.xcconfig = {
-      'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_SWIFT_STANDALONE'
+      'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_SWIFT_STANDALONE',
+      'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SQLITE_SWIFT_STANDALONE=1'
     }
     ss.dependency 'sqlite3'
 
diff --git a/Sources/SQLiteObjc/include/SQLiteObjc.h b/Sources/SQLiteObjc/include/SQLiteObjc.h
index f8c2a3b3..e8ba9a7d 100644
--- a/Sources/SQLiteObjc/include/SQLiteObjc.h
+++ b/Sources/SQLiteObjc/include/SQLiteObjc.h
@@ -23,7 +23,11 @@
 //
 
 @import Foundation;
+#if defined(SQLITE_SWIFT_STANDALONE)
+@import sqlite3;
+#else
 @import SQLite3;
+#endif
 
 NS_ASSUME_NONNULL_BEGIN
 typedef NSString * _Nullable (^_SQLiteTokenizerNextCallback)(const char *input, int *inputOffset, int *inputLength);

From 23f4aa42553119aab2e0118afc6b080e70a8d101 Mon Sep 17 00:00:00 2001
From: Svetlana Korosteleva <svetlana.korosteleva@concur.com>
Date: Mon, 2 Dec 2019 15:14:59 -0800
Subject: [PATCH 361/685] Add interface to perform migration to new major
 SQLCipher immediately after setting a key

This change adds `keyAndMigrate` methods which perform "PRAGMA cipher_migrate;" call
immediately after calling `sqlite3_key_v2`
This call is needed to open the database files created in older major SQLCipher version (e.g. 3.x.x)
by newer SQLCipher version (e.g. 4.x.x).
These calls should be performed only once, when opening older database files for the first time.
See https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_migrate
and https://discuss.zetetic.net/t/upgrading-to-sqlcipher-4/3283 for more details regarding SQLCipher upgrade
---
 Sources/SQLite/Extensions/Cipher.swift | 33 +++++++++++++++++++++++++-
 1 file changed, 32 insertions(+), 1 deletion(-)

diff --git a/Sources/SQLite/Extensions/Cipher.swift b/Sources/SQLite/Extensions/Cipher.swift
index 44919aab..4d8d426b 100644
--- a/Sources/SQLite/Extensions/Cipher.swift
+++ b/Sources/SQLite/Extensions/Cipher.swift
@@ -32,6 +32,25 @@ extension Connection {
         try _key_v2(db: db, keyPointer: key.bytes, keySize: key.bytes.count)
     }
 
+    /// Same as `key(_ key: String, db: String = "main")`, running "PRAGMA cipher_migrate;"
+    /// immediately after calling `sqlite3_key_v2`, which performs the migration of
+    /// SQLCipher database created by older major version of SQLCipher, to be able to
+    /// open this database with new major version of SQLCipher
+    /// (e.g. to open database created by SQLCipher version 3.x.x with SQLCipher version 4.x.x).
+    /// As "PRAGMA cipher_migrate;" is time-consuming, it is recommended to use this function
+    /// only after failure of `key(_ key: String, db: String = "main")`, if older versions of
+    /// your app may ise older version of SQLCipher
+    /// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_migrate
+    /// and https://discuss.zetetic.net/t/upgrading-to-sqlcipher-4/3283
+    /// for more details regarding SQLCipher upgrade
+    public func keyAndMigrate(_ key: String, db: String = "main") throws {
+        try _key_v2(db: db, keyPointer: key, keySize: key.utf8.count, migrate: true)
+    }
+
+    /// Same as `[`keyAndMigrate(_ key: String, db: String = "main")` accepting byte array as key
+    public func keyAndMigrate(_ key: Blob, db: String = "main") throws {
+        try _key_v2(db: db, keyPointer: key.bytes, keySize: key.bytes.count, migrate: true)
+    }
 
     /// Change the key on an open database.  If the current database is not encrypted, this routine
     /// will encrypt it.
@@ -47,8 +66,20 @@ extension Connection {
     }
 
     // MARK: - private
-    private func _key_v2(db: String, keyPointer: UnsafePointer<UInt8>, keySize: Int) throws {
+    private func _key_v2(db: String,
+                         keyPointer: UnsafePointer<UInt8>,
+                         keySize: Int,
+                         migrate: Bool = false) throws {
         try check(sqlite3_key_v2(handle, db, keyPointer, Int32(keySize)))
+        if migrate {
+            // Run "PRAGMA cipher_migrate;" immediately after `sqlite3_key_v2`
+            // per recommendation of SQLCipher authors
+            let migrateResult = try scalar("PRAGMA cipher_migrate;")
+            if (migrateResult as? String) != "0" {
+                // "0" is the result of successfull migration
+                throw Result.error(message: "Error in cipher migration, result \(migrateResult.debugDescription)", code: 1, statement: nil)
+            }
+        }
         try cipher_key_check()
     }
 

From 3b57e6963303adbca4cbc435e8ef1c43dee02726 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Luthi?= <cedric.luthi@gmail.com>
Date: Wed, 22 Jan 2020 09:13:54 +0100
Subject: [PATCH 362/685] Add support for storing and retrieving UUID objects

Storing them as string for better readability in the database
---
 Sources/SQLite/Foundation.swift         | 16 ++++++++++++++++
 Tests/SQLiteTests/FoundationTests.swift | 12 ++++++++++++
 2 files changed, 28 insertions(+)

diff --git a/Sources/SQLite/Foundation.swift b/Sources/SQLite/Foundation.swift
index cfb79bec..9986f581 100644
--- a/Sources/SQLite/Foundation.swift
+++ b/Sources/SQLite/Foundation.swift
@@ -68,3 +68,19 @@ public var dateFormatter: DateFormatter = {
     formatter.timeZone = TimeZone(secondsFromGMT: 0)
     return formatter
 }()
+
+extension UUID : Value {
+
+    public static var declaredDatatype: String {
+        return String.declaredDatatype
+    }
+
+    public static func fromDatatypeValue(_ stringValue: String) -> UUID {
+        return UUID(uuidString: stringValue)!
+    }
+
+    public var datatypeValue: String {
+        return self.uuidString
+    }
+
+}
diff --git a/Tests/SQLiteTests/FoundationTests.swift b/Tests/SQLiteTests/FoundationTests.swift
index dd80afc1..ba9685b7 100644
--- a/Tests/SQLiteTests/FoundationTests.swift
+++ b/Tests/SQLiteTests/FoundationTests.swift
@@ -13,4 +13,16 @@ class FoundationTests : XCTestCase {
         let data = Data.fromDatatypeValue(blob)
         XCTAssertEqual(Data([1, 2, 3]), data)
     }
+
+    func testStringFromUUID() {
+        let uuid = UUID(uuidString: "4ABE10C9-FF12-4CD4-90C1-4B429001BAD3")!
+        let string = uuid.datatypeValue
+        XCTAssertEqual("4ABE10C9-FF12-4CD4-90C1-4B429001BAD3", string)
+    }
+
+    func testUUIDFromString() {
+        let string = "4ABE10C9-FF12-4CD4-90C1-4B429001BAD3"
+        let uuid = UUID.fromDatatypeValue(string)
+        XCTAssertEqual(UUID(uuidString: "4ABE10C9-FF12-4CD4-90C1-4B429001BAD3"), uuid)
+    }
 }

From 806f03c91f473d5003372a19083e27ab5e8897a6 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Wed, 15 Apr 2020 11:29:23 +0200
Subject: [PATCH 363/685] Improving README.md

Because of #988 and #983, I added a do...catch in the usage section, and a production implementation example in the related section.
---
 README.md | 119 ++++++++++++++++++++++++++++++------------------------
 1 file changed, 66 insertions(+), 53 deletions(-)

diff --git a/README.md b/README.md
index b7a18e0b..8b0972f6 100644
--- a/README.md
+++ b/README.md
@@ -34,67 +34,79 @@ syntax _and_ intent.
 ```swift
 import SQLite
 
-let db = try Connection("path/to/db.sqlite3")
-
-let users = Table("users")
-let id = Expression<Int64>("id")
-let name = Expression<String?>("name")
-let email = Expression<String>("email")
-
-try db.run(users.create { t in
-    t.column(id, primaryKey: true)
-    t.column(name)
-    t.column(email, unique: true)
-})
-// CREATE TABLE "users" (
-//     "id" INTEGER PRIMARY KEY NOT NULL,
-//     "name" TEXT,
-//     "email" TEXT NOT NULL UNIQUE
-// )
-
-let insert = users.insert(name <- "Alice", email <- "alice@mac.com")
-let rowid = try db.run(insert)
-// INSERT INTO "users" ("name", "email") VALUES ('Alice', 'alice@mac.com')
-
-for user in try db.prepare(users) {
-    print("id: \(user[id]), name: \(user[name]), email: \(user[email])")
-    // id: 1, name: Optional("Alice"), email: alice@mac.com
+// Wrap everything in a do...catch to handle errors
+do {
+    let db = try Connection("path/to/db.sqlite3")
+
+    let users = Table("users")
+    let id = Expression<Int64>("id")
+    let name = Expression<String?>("name")
+    let email = Expression<String>("email")
+
+    try db.run(users.create { t in
+        t.column(id, primaryKey: true)
+        t.column(name)
+        t.column(email, unique: true)
+    })
+    // CREATE TABLE "users" (
+    //     "id" INTEGER PRIMARY KEY NOT NULL,
+    //     "name" TEXT,
+    //     "email" TEXT NOT NULL UNIQUE
+    // )
+
+    let insert = users.insert(name <- "Alice", email <- "alice@mac.com")
+    let rowid = try db.run(insert)
+    // INSERT INTO "users" ("name", "email") VALUES ('Alice', 'alice@mac.com')
+
+    for user in try db.prepare(users) {
+        print("id: \(user[id]), name: \(user[name]), email: \(user[email])")
+        // id: 1, name: Optional("Alice"), email: alice@mac.com
+    }
+    // SELECT * FROM "users"
+
+    let alice = users.filter(id == rowid)
+
+    try db.run(alice.update(email <- email.replace("mac.com", with: "me.com")))
+    // UPDATE "users" SET "email" = replace("email", 'mac.com', 'me.com')
+    // WHERE ("id" = 1)
+
+    try db.run(alice.delete())
+    // DELETE FROM "users" WHERE ("id" = 1)
+
+    try db.scalar(users.count) // 0
+    // SELECT count(*) FROM "users"
+} catch {
+    print (error)
 }
-// SELECT * FROM "users"
-
-let alice = users.filter(id == rowid)
-
-try db.run(alice.update(email <- email.replace("mac.com", with: "me.com")))
-// UPDATE "users" SET "email" = replace("email", 'mac.com', 'me.com')
-// WHERE ("id" = 1)
-
-try db.run(alice.delete())
-// DELETE FROM "users" WHERE ("id" = 1)
-
-try db.scalar(users.count) // 0
-// SELECT count(*) FROM "users"
 ```
 
 SQLite.swift also works as a lightweight, Swift-friendly wrapper over the C
 API.
 
 ```swift
-let stmt = try db.prepare("INSERT INTO users (email) VALUES (?)")
-for email in ["betty@icloud.com", "cathy@icloud.com"] {
-    try stmt.run(email)
+// Wrap everything in a do...catch to handle errors
+do {
+    // ...
+    
+    let stmt = try db.prepare("INSERT INTO users (email) VALUES (?)")
+    for email in ["betty@icloud.com", "cathy@icloud.com"] {
+        try stmt.run(email)
+    }
+
+    db.totalChanges    // 3
+    db.changes         // 1
+    db.lastInsertRowid // 3
+
+    for row in try db.prepare("SELECT id, email FROM users") {
+        print("id: \(row[0]), email: \(row[1])")
+        // id: Optional(2), email: Optional("betty@icloud.com")
+        // id: Optional(3), email: Optional("cathy@icloud.com")
+    }
+
+    try db.scalar("SELECT count(*) FROM users") // 2
+} catch {
+    print (error)
 }
-
-db.totalChanges    // 3
-db.changes         // 1
-db.lastInsertRowid // 3
-
-for row in try db.prepare("SELECT id, email FROM users") {
-    print("id: \(row[0]), email: \(row[1])")
-    // id: Optional(2), email: Optional("betty@icloud.com")
-    // id: Optional(3), email: Optional("cathy@icloud.com")
-}
-
-try db.scalar("SELECT count(*) FROM users") // 2
 ```
 
 [Read the documentation][See Documentation] or explore more,
@@ -253,6 +265,7 @@ These projects enhance or use SQLite.swift:
 
  - [SQLiteMigrationManager.swift][] (inspired by
    [FMDBMigrationManager][])
+ - [Delta: Math helper](https://apps.apple.com/app/delta-math-helper/id1436506800) (see [Delta/Utils/Database.swift](https://github.com/GroupeMINASTE/Delta-iOS/blob/master/Delta/Utils/Database.swift) for production implementation example)
 
 
 ## Alternatives

From f040e145d328042a4a0f042086ac09b28f4b1b41 Mon Sep 17 00:00:00 2001
From: Daniel Shelley <dshelley@ancestry.com>
Date: Fri, 17 Jul 2020 10:59:47 -0600
Subject: [PATCH 364/685] set deployment target to iOS 9 to fix Archiving with
 Xcode 12

---
 SQLite.xcodeproj/project.pbxproj | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 30a40214..80719c33 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1173,7 +1173,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 				MACOSX_DEPLOYMENT_TARGET = 10.9;
 				MTL_ENABLE_DEBUG_INFO = YES;
 				ONLY_ACTIVE_ARCH = YES;
@@ -1229,7 +1229,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 				MACOSX_DEPLOYMENT_TARGET = 10.9;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				PRODUCT_NAME = "";
@@ -1255,7 +1255,7 @@
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
-				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
@@ -1276,7 +1276,7 @@
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
-				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;

From 135b2fc8b854f8b528956a56d8af8a89f6708d17 Mon Sep 17 00:00:00 2001
From: Jake-B <jake-b@users.noreply.github.com>
Date: Thu, 13 Aug 2020 07:09:38 -0400
Subject: [PATCH 365/685] =?UTF-8?q?Added=20=3D=3D=3D=20as=20explicit=20?=
 =?UTF-8?q?=E2=80=9CIS=E2=80=9D=20operator=20for=20expressions?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Added === as explicit “IS” operator for expressions.
Added tests for === operator.
---
 Sources/SQLite/Typed/Operators.swift   | 27 ++++++++++++++++++++++++++
 Tests/SQLiteTests/OperatorsTests.swift | 14 +++++++++++++
 2 files changed, 41 insertions(+)

diff --git a/Sources/SQLite/Typed/Operators.swift b/Sources/SQLite/Typed/Operators.swift
index b5637ea3..0a323b90 100644
--- a/Sources/SQLite/Typed/Operators.swift
+++ b/Sources/SQLite/Typed/Operators.swift
@@ -378,6 +378,33 @@ public func ==<V : Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> whe
     return Operator.eq.infix(lhs, rhs)
 }
 
+public func ===<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
+    return "IS".infix(lhs, rhs)
+}
+public func ===<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
+    return "IS".infix(lhs, rhs)
+}
+public func ===<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Equatable {
+    return "IS".infix(lhs, rhs)
+}
+public func ===<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
+    return "IS".infix(lhs, rhs)
+}
+public func ===<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Equatable {
+    return "IS".infix(lhs, rhs)
+}
+public func ===<V : Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype : Equatable {
+    guard let rhs = rhs else { return "IS".infix(lhs, Expression<V?>(value: nil)) }
+    return "IS".infix(lhs, rhs)
+}
+public func ===<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
+    return "IS".infix(lhs, rhs)
+}
+public func ===<V : Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
+    guard let lhs = lhs else { return "IS".infix(Expression<V?>(value: nil), rhs) }
+    return "IS".infix(lhs, rhs)
+}
+
 public func !=<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
     return Operator.neq.infix(lhs, rhs)
 }
diff --git a/Tests/SQLiteTests/OperatorsTests.swift b/Tests/SQLiteTests/OperatorsTests.swift
index 948eb0a4..18a1f52e 100644
--- a/Tests/SQLiteTests/OperatorsTests.swift
+++ b/Tests/SQLiteTests/OperatorsTests.swift
@@ -187,6 +187,20 @@ class OperatorsTests : XCTestCase {
         AssertSQL("(NULL IS \"boolOptional\")", nil == boolOptional)
     }
 
+    func test_isOperator_withEquatableExpressions_buildsBooleanExpression() {
+       AssertSQL("(\"bool\" IS \"bool\")", bool === bool)
+       AssertSQL("(\"bool\" IS \"boolOptional\")", bool === boolOptional)
+       AssertSQL("(\"boolOptional\" IS \"bool\")", boolOptional === bool)
+       AssertSQL("(\"boolOptional\" IS \"boolOptional\")", boolOptional === boolOptional)
+       AssertSQL("(\"bool\" IS 1)", bool === true)
+       AssertSQL("(\"boolOptional\" IS 1)", boolOptional === true)
+       AssertSQL("(1 IS \"bool\")", true === bool)
+       AssertSQL("(1 IS \"boolOptional\")", true === boolOptional)
+
+       AssertSQL("(\"boolOptional\" IS NULL)", boolOptional === nil)
+       AssertSQL("(NULL IS \"boolOptional\")", nil === boolOptional)
+    }
+
     func test_inequalityOperator_withEquatableExpressions_buildsBooleanExpression() {
         AssertSQL("(\"bool\" != \"bool\")", bool != bool)
         AssertSQL("(\"bool\" != \"boolOptional\")", bool != boolOptional)

From 113872d8d01b2b0c927d9b450abfb5fe6a8f312a Mon Sep 17 00:00:00 2001
From: Jake-B <jake-b@users.noreply.github.com>
Date: Thu, 13 Aug 2020 08:17:00 -0400
Subject: [PATCH 366/685] =?UTF-8?q?Add=20!=3D=3D=20as=20explicit=20?=
 =?UTF-8?q?=E2=80=9CIS=20NOT=E2=80=9D=20operator=20for=20exprsns?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Added !== as explicit “IS” operator for expressions.
Added tests for !== operator.
---
 Sources/SQLite/Typed/Operators.swift   | 28 ++++++++++++++++++++++++++
 Tests/SQLiteTests/OperatorsTests.swift | 14 +++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/Sources/SQLite/Typed/Operators.swift b/Sources/SQLite/Typed/Operators.swift
index 0a323b90..594f08a0 100644
--- a/Sources/SQLite/Typed/Operators.swift
+++ b/Sources/SQLite/Typed/Operators.swift
@@ -432,6 +432,34 @@ public func !=<V : Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> whe
     return Operator.neq.infix(lhs, rhs)
 }
 
+public func !==<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
+    return "IS NOT".infix(lhs, rhs)
+}
+public func !==<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
+    return "IS NOT".infix(lhs, rhs)
+}
+public func !==<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Equatable {
+    return "IS NOT".infix(lhs, rhs)
+}
+public func !==<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
+    return "IS NOT".infix(lhs, rhs)
+}
+public func !==<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Equatable {
+    return "IS NOT".infix(lhs, rhs)
+}
+public func !==<V : Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype : Equatable {
+    guard let rhs = rhs else { return "IS NOT".infix(lhs, Expression<V?>(value: nil)) }
+    return "IS NOT".infix(lhs, rhs)
+}
+public func !==<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
+    return "IS NOT".infix(lhs, rhs)
+}
+public func !==<V : Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
+    guard let lhs = lhs else { return "IS NOT".infix(Expression<V?>(value: nil), rhs) }
+    return "IS NOT".infix(lhs, rhs)
+}
+
+
 public func ><V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
     return Operator.gt.infix(lhs, rhs)
 }
diff --git a/Tests/SQLiteTests/OperatorsTests.swift b/Tests/SQLiteTests/OperatorsTests.swift
index 18a1f52e..c2416844 100644
--- a/Tests/SQLiteTests/OperatorsTests.swift
+++ b/Tests/SQLiteTests/OperatorsTests.swift
@@ -200,6 +200,20 @@ class OperatorsTests : XCTestCase {
        AssertSQL("(\"boolOptional\" IS NULL)", boolOptional === nil)
        AssertSQL("(NULL IS \"boolOptional\")", nil === boolOptional)
     }
+    
+    func test_isNotOperator_withEquatableExpressions_buildsBooleanExpression() {
+        AssertSQL("(\"bool\" IS NOT \"bool\")", bool !== bool)
+        AssertSQL("(\"bool\" IS NOT \"boolOptional\")", bool !== boolOptional)
+        AssertSQL("(\"boolOptional\" IS NOT \"bool\")", boolOptional !== bool)
+        AssertSQL("(\"boolOptional\" IS NOT \"boolOptional\")", boolOptional !== boolOptional)
+        AssertSQL("(\"bool\" IS NOT 1)", bool !== true)
+        AssertSQL("(\"boolOptional\" IS NOT 1)", boolOptional !== true)
+        AssertSQL("(1 IS NOT \"bool\")", true !== bool)
+        AssertSQL("(1 IS NOT \"boolOptional\")", true !== boolOptional)
+
+        AssertSQL("(\"boolOptional\" IS NOT NULL)", boolOptional !== nil)
+        AssertSQL("(NULL IS NOT \"boolOptional\")", nil !== boolOptional)
+     }
 
     func test_inequalityOperator_withEquatableExpressions_buildsBooleanExpression() {
         AssertSQL("(\"bool\" != \"bool\")", bool != bool)

From e3e031df66fe6f8a35f50a6d2f3cfcd1a3439656 Mon Sep 17 00:00:00 2001
From: Denis <denis.couras@solinftec.com.br>
Date: Thu, 5 Nov 2020 16:37:47 -0300
Subject: [PATCH 367/685] Removed the force unwrap in the FailableIterator
 extension for the next () method

Although the method accepts an optional return, the function forces unwrap
---
 SQLite.xcodeproj/project.pbxproj    | 2 ++
 Sources/SQLite/Core/Statement.swift | 2 +-
 Sources/SQLite/Info.plist           | 2 +-
 3 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 30a40214..9972b3f7 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1257,6 +1257,7 @@
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				MARKETING_VERSION = 0.12.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
@@ -1278,6 +1279,7 @@
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				MARKETING_VERSION = 0.12.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index dc91d3d8..237d4812 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -208,7 +208,7 @@ public protocol FailableIterator : IteratorProtocol {
 
 extension FailableIterator {
     public func next() -> Element? {
-        return try! failableNext()
+        return try? failableNext()
     }
 }
 
diff --git a/Sources/SQLite/Info.plist b/Sources/SQLite/Info.plist
index 2d956da2..ca23c84f 100644
--- a/Sources/SQLite/Info.plist
+++ b/Sources/SQLite/Info.plist
@@ -15,7 +15,7 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>0.12.2</string>
+	<string>$(MARKETING_VERSION)</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>

From 12ac2fd4928e690957e2d3cad57884d450a8cea7 Mon Sep 17 00:00:00 2001
From: turtlemaster19 <46784000+UInt2048@users.noreply.github.com>
Date: Thu, 3 Dec 2020 14:29:36 -0500
Subject: [PATCH 368/685] Fix #920

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index b7a18e0b..a12fe539 100644
--- a/README.md
+++ b/README.md
@@ -112,7 +112,7 @@ and the [companion repository][SQLiteDataAccessLayer2].
 
 ## Installation
 
-> _Note:_ Version 0.12 requires Swift 5 (and [Xcode](https://developer.apple.com/xcode/downloads/) 10.2) or greater. Version 0.11.6 requires Swift 4.2 (and [Xcode](https://developer.apple.com/xcode/downloads/) 10.1) or greater.
+> _Note:_ Version 0.11.6 and later requires Swift 5 (and [Xcode](https://developer.apple.com/xcode/downloads/) 10.2) or greater. Version 0.11.5 requires Swift 4.2 (and [Xcode](https://developer.apple.com/xcode/downloads/) 10.1) or greater.
 
 ### Carthage
 

From 140374a1f25df9a50c9e014679844bb2de70542d Mon Sep 17 00:00:00 2001
From: Geoff MacDonald <geoffmacd@gmail.com>
Date: Fri, 30 Apr 2021 11:09:45 -0700
Subject: [PATCH 369/685] implement batch insert, insertMany()

---
 Sources/SQLite/Typed/Coding.swift  | 25 +++++++++++++++++++-
 Sources/SQLite/Typed/Query.swift   | 37 ++++++++++++++++++++++++++++++
 Tests/SQLiteTests/QueryTests.swift | 37 ++++++++++++++++++++++++++++++
 3 files changed, 98 insertions(+), 1 deletion(-)

diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index c3fb931b..34edbc49 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -38,13 +38,36 @@ extension QueryType {
     ///
     ///   - otherSetters: Any other setters to include in the insert
     ///
-    /// - Returns: An `INSERT` statement fort the encodable object
+    /// - Returns: An `INSERT` statement for the encodable object
     public func insert(_ encodable: Encodable, userInfo: [CodingUserInfoKey:Any] = [:], otherSetters: [Setter] = []) throws -> Insert {
         let encoder = SQLiteEncoder(userInfo: userInfo)
         try encodable.encode(to: encoder)
         return self.insert(encoder.setters + otherSetters)
     }
 
+    /// Creates a batch `INSERT` statement by encoding the array of given objects
+    /// This method converts any custom nested types to JSON data and does not handle any sort
+    /// of object relationships. If you want to support relationships between objects you will
+    /// have to provide your own Encodable implementations that encode the correct ids.
+    ///
+    /// - Parameters:
+    ///
+    ///   - encodables: Encodable objects to insert
+    ///
+    ///   - userInfo: User info to be passed to encoder
+    ///
+    ///   - otherSetters: Any other setters to include in the inserts, per row/object.
+    ///
+    /// - Returns: An `INSERT` statement for the encodable objects
+    public func insertMany(_ encodables: [Encodable], userInfo: [CodingUserInfoKey:Any] = [:], otherSetters: [Setter] = []) throws -> Insert {
+        let combinedSetters = try encodables.map { encodable -> [Setter] in
+            let encoder = SQLiteEncoder(userInfo: userInfo)
+            try encodable.encode(to: encoder)
+            return encoder.setters + otherSetters
+        }
+        return self.insertMany(combinedSetters)
+    }
+
     /// Creates an `UPDATE` statement by encoding the given object
     /// This method converts any custom nested types to JSON data and does not handle any sort
     /// of object relationships. If you want to support relationships between objects you will
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index f6ef6df8..61deaa1f 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -631,6 +631,18 @@ extension QueryType {
         return insert(onConflict, values)
     }
 
+    public func insertMany( _ values: [[Setter]]) -> Insert {
+        return insertMany(nil, values)
+    }
+
+    public func insertMany(or onConflict: OnConflict, _ values: [[Setter]]) -> Insert {
+        return insertMany(onConflict, values)
+    }
+
+    public func insertMany(or onConflict: OnConflict, _ values: [Setter]...) -> Insert {
+        return insertMany(onConflict, values)
+    }
+
     fileprivate func insert(_ or: OnConflict?, _ values: [Setter]) -> Insert {
         let insert = values.reduce((columns: [Expressible](), values: [Expressible]())) { insert, setter in
             (insert.columns + [setter.column], insert.values + [setter.value])
@@ -650,6 +662,29 @@ extension QueryType {
         return Insert(" ".join(clauses.compactMap { $0 }).expression)
     }
 
+    fileprivate func insertMany(_ or: OnConflict?, _ values: [[Setter]]) -> Insert {
+        guard values.count > 0 else {
+            return insert()
+        }
+        let insertRows = values.map { rowValues in
+            rowValues.reduce((columns: [Expressible](), values: [Expressible]())) { insert, setter in
+                (insert.columns + [setter.column], insert.values + [setter.value])
+            }
+        }
+
+        let clauses: [Expressible?] = [
+            Expression<Void>(literal: "INSERT"),
+            or.map { Expression<Void>(literal: "OR \($0.rawValue)") },
+            Expression<Void>(literal: "INTO"),
+            tableName(),
+            "".wrap(insertRows[0].columns) as Expression<Void>,
+            Expression<Void>(literal: "VALUES"),
+            ", ".join(insertRows.map(\.values).map({ "".wrap($0) as Expression<Void> })),
+            whereClause
+        ]
+        return Insert(" ".join(clauses.compactMap { $0 }).expression)
+    }
+
     /// Runs an `INSERT` statement against the query with `DEFAULT VALUES`.
     public func insert() -> Insert {
         return Insert(" ".join([
@@ -1010,6 +1045,8 @@ extension Connection {
     /// - SeeAlso: `QueryType.insert(value:_:)`
     /// - SeeAlso: `QueryType.insert(values:)`
     /// - SeeAlso: `QueryType.insert(or:_:)`
+    /// - SeeAlso: `QueryType.insertMany(values:)`
+    /// - SeeAlso: `QueryType.insertMany(or:_:)`
     /// - SeeAlso: `QueryType.insert()`
     ///
     /// - Parameter query: An insert query.
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index 2a9e4ecb..f48f49b9 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -247,6 +247,26 @@ class QueryTests : XCTestCase {
         )
     }
 
+    func test_insert_many_compilesInsertManyExpression() {
+        AssertSQL(
+            "INSERT INTO \"users\" (\"email\", \"age\") VALUES ('alice@example.com', 30), ('geoff@example.com', 32), ('alex@example.com', 83)",
+            users.insertMany([[email <- "alice@example.com", age <- 30], [email <- "geoff@example.com", age <- 32], [email <- "alex@example.com", age <- 83]])
+        )
+    }
+    func test_insert_many_compilesInsertManyNoneExpression() {
+        AssertSQL(
+            "INSERT INTO \"users\" DEFAULT VALUES",
+            users.insertMany([])
+        )
+    }
+
+    func test_insert_many_withOnConflict_compilesInsertManyOrOnConflictExpression() {
+        AssertSQL(
+            "INSERT OR REPLACE INTO \"users\" (\"email\", \"age\") VALUES ('alice@example.com', 30), ('geoff@example.com', 32), ('alex@example.com', 83)",
+            users.insertMany(or: .replace, [[email <- "alice@example.com", age <- 30], [email <- "geoff@example.com", age <- 32], [email <- "alex@example.com", age <- 83]])
+        )
+    }
+
     func test_insert_encodable() throws {
         let emails = Table("emails")
         let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil)
@@ -270,6 +290,18 @@ class QueryTests : XCTestCase {
         )
     }
 
+    func test_insert_many_encodable() throws {
+        let emails = Table("emails")
+        let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil)
+        let value2 = TestCodable(int: 2, string: "3", bool: true, float: 3, double: 5, optional: nil, sub: nil)
+        let value3 = TestCodable(int: 3, string: "4", bool: true, float: 3, double: 6, optional: nil, sub: nil)
+        let insert = try emails.insertMany([value1, value2, value3])
+        AssertSQL(
+            "INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\") VALUES (1, '2', 1, 3.0, 4.0), (2, '3', 1, 3.0, 5.0), (3, '4', 1, 3.0, 6.0)",
+            insert
+        )
+    }
+
     func test_update_compilesUpdateExpression() {
         AssertSQL(
             "UPDATE \"users\" SET \"age\" = 30, \"admin\" = 1 WHERE (\"id\" = 1)",
@@ -483,6 +515,11 @@ class QueryIntegrationTests : SQLiteTestCase {
         XCTAssertEqual(1, id)
     }
 
+    func test_insert_many() {
+        let id = try! db.run(users.insertMany([[email <- "alice@example.com"], [email <- "geoff@example.com"]]))
+        XCTAssertEqual(2, id)
+    }
+
     func test_update() {
         let changes = try! db.run(users.update(email <- "alice@example.com"))
         XCTAssertEqual(0, changes)

From 087264792a7c75c446106ef4090d9fd669b37e8a Mon Sep 17 00:00:00 2001
From: Geoff MacDonald <geoffmacd@gmail.com>
Date: Fri, 30 Apr 2021 11:27:42 -0700
Subject: [PATCH 370/685] Update Index.md

---
 Documentation/Index.md | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 70d67c2d..2f441c8c 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -638,6 +638,18 @@ do {
 }
 ```
 
+Multiple rows can be inserted at once by similarily calling `insertMany` with an array of per-row [setters](#setters).
+
+```swift
+do {
+    let rowid = try db.run(users.insertMany([mail <- "alice@mac.com"], [email <- "geoff@mac.com"]))
+    print("inserted id: \(rowid)")
+} catch {
+    print("insertion failed: \(error)")
+}
+```
+
+
 The [`update`](#updating-rows) and [`delete`](#deleting-rows) functions
 follow similar patterns.
 

From 05c404fcec8df8043d68d38617a9c69f54772f50 Mon Sep 17 00:00:00 2001
From: Geoff MacDonald <geoffmacd@gmail.com>
Date: Fri, 30 Apr 2021 11:37:22 -0700
Subject: [PATCH 371/685] cleanup sql creation

---
 Sources/SQLite/Typed/Query.swift | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index 61deaa1f..54e44fa5 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -663,12 +663,14 @@ extension QueryType {
     }
 
     fileprivate func insertMany(_ or: OnConflict?, _ values: [[Setter]]) -> Insert {
-        guard values.count > 0 else {
+        guard let firstInsert = values.first else {
+            // must be at least 1 object or else we don't know columns. Default to default inserts.
             return insert()
         }
-        let insertRows = values.map { rowValues in
-            rowValues.reduce((columns: [Expressible](), values: [Expressible]())) { insert, setter in
-                (insert.columns + [setter.column], insert.values + [setter.value])
+        let columns = firstInsert.map { $0.column }
+        let insertValues = values.map { rowValues in
+            rowValues.reduce([Expressible]()) { insert, setter in
+                insert + [setter.value]
             }
         }
 
@@ -677,9 +679,9 @@ extension QueryType {
             or.map { Expression<Void>(literal: "OR \($0.rawValue)") },
             Expression<Void>(literal: "INTO"),
             tableName(),
-            "".wrap(insertRows[0].columns) as Expression<Void>,
+            "".wrap(columns) as Expression<Void>,
             Expression<Void>(literal: "VALUES"),
-            ", ".join(insertRows.map(\.values).map({ "".wrap($0) as Expression<Void> })),
+            ", ".join(insertValues.map({ "".wrap($0) as Expression<Void> })),
             whereClause
         ]
         return Insert(" ".join(clauses.compactMap { $0 }).expression)

From 4fde8dba065b213ae0a5a067a1d8d31680091b5a Mon Sep 17 00:00:00 2001
From: Geoff MacDonald <geoffmac@dropbox.com>
Date: Fri, 30 Apr 2021 14:52:52 -0700
Subject: [PATCH 372/685] try and fix travis?

---
 .travis.yml | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index c8fc5feb..ea60b063 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,11 +1,11 @@
 language: objective-c
-rvm: 2.3
+rvm: 2.7.3
 # https://docs.travis-ci.com/user/reference/osx
-osx_image: xcode10.2
+osx_image: xcode12.2
 env:
   global:
-    - IOS_SIMULATOR="iPhone XS"
-    - IOS_VERSION="12.2"
+    - IOS_SIMULATOR="iPhone 11"
+    - IOS_VERSION="14.2"
 matrix:
   include:
     - env: BUILD_SCHEME="SQLite iOS"
@@ -25,7 +25,4 @@ before_install:
   - brew update
   - brew outdated carthage || brew upgrade carthage
 script:
-# Workaround for Xcode 10.2/tvOS 9.1 bug
-# See https://stackoverflow.com/questions/55389080/xcode-10-2-failed-to-run-app-on-simulator-with-ios-10
-  - sudo mkdir /Library/Developer/CoreSimulator/Profiles/Runtimes/tvOS\ 9.1.simruntime/Contents/Resources/RuntimeRoot/usr/lib/swift
   - ./run-tests.sh

From 183a43948f40637643c15e6e19a4b983d2df8325 Mon Sep 17 00:00:00 2001
From: Geoff MacDonald <geoffmac@dropbox.com>
Date: Fri, 30 Apr 2021 15:32:43 -0700
Subject: [PATCH 373/685] Update Planning.md

---
 Documentation/Planning.md | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/Documentation/Planning.md b/Documentation/Planning.md
index 5f885de8..62df1f24 100644
--- a/Documentation/Planning.md
+++ b/Documentation/Planning.md
@@ -33,6 +33,3 @@ be referred to when it comes time to add the corresponding feature._
 _Features that are not actively being considered, perhaps because of no clean
 type-safe way to implement them with the current Swift, or bugs, or just
 general uncertainty._
-
- * provide a mechanism for INSERT INTO multiple values, per
-   [#168](https://github.com/stephencelis/SQLite.swift/issues/168)

From b260b0a4aa1754b609ac48c637578ef1cea0898c Mon Sep 17 00:00:00 2001
From: Geoff MacDonald <geoffmac@dropbox.com>
Date: Fri, 30 Apr 2021 15:35:12 -0700
Subject: [PATCH 374/685] upgrade test deps to force it working

---
 .travis.yml                  |  2 +-
 Tests/CocoaPods/Gemfile.lock | 46 ++++++++++++++++++------------------
 2 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index ea60b063..2a0460bb 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -20,7 +20,7 @@ matrix:
     - env: CARTHAGE_PLATFORM="tvOS"
     - env: PACKAGE_MANAGER_COMMAND="test"
 before_install:
-  - gem update bundler
+ -  gem install bundler
   - gem install xcpretty --no-document
   - brew update
   - brew outdated carthage || brew upgrade carthage
diff --git a/Tests/CocoaPods/Gemfile.lock b/Tests/CocoaPods/Gemfile.lock
index b5172144..e5c53ea3 100644
--- a/Tests/CocoaPods/Gemfile.lock
+++ b/Tests/CocoaPods/Gemfile.lock
@@ -1,18 +1,18 @@
 GEM
   remote: https://rubygems.org/
   specs:
-    CFPropertyList (3.0.0)
-    activesupport (4.2.11)
+    CFPropertyList (3.0.3)
+    activesupport (4.2.11.3)
       i18n (~> 0.7)
       minitest (~> 5.1)
       thread_safe (~> 0.3, >= 0.3.4)
       tzinfo (~> 1.1)
     atomos (0.1.3)
-    claide (1.0.2)
-    cocoapods (1.6.0.beta.2)
+    claide (1.0.3)
+    cocoapods (1.6.2)
       activesupport (>= 4.0.2, < 5)
       claide (>= 1.0.2, < 2.0)
-      cocoapods-core (= 1.6.0.beta.2)
+      cocoapods-core (= 1.6.2)
       cocoapods-deintegrate (>= 1.0.2, < 2.0)
       cocoapods-downloader (>= 1.2.2, < 2.0)
       cocoapods-plugins (>= 1.0.0, < 2.0)
@@ -22,56 +22,56 @@ GEM
       cocoapods-try (>= 1.1.0, < 2.0)
       colored2 (~> 3.1)
       escape (~> 0.0.4)
-      fourflusher (~> 2.0.1)
+      fourflusher (>= 2.2.0, < 3.0)
       gh_inspector (~> 1.0)
       molinillo (~> 0.6.6)
       nap (~> 1.0)
-      ruby-macho (~> 1.3, >= 1.3.1)
-      xcodeproj (>= 1.7.0, < 2.0)
-    cocoapods-core (1.6.0.beta.2)
+      ruby-macho (~> 1.4)
+      xcodeproj (>= 1.8.1, < 2.0)
+    cocoapods-core (1.6.2)
       activesupport (>= 4.0.2, < 6)
       fuzzy_match (~> 2.0.4)
       nap (~> 1.0)
-    cocoapods-deintegrate (1.0.2)
-    cocoapods-downloader (1.2.2)
+    cocoapods-deintegrate (1.0.4)
+    cocoapods-downloader (1.4.0)
     cocoapods-plugins (1.0.0)
       nap
     cocoapods-search (1.0.0)
-    cocoapods-stats (1.0.0)
-    cocoapods-trunk (1.3.1)
+    cocoapods-stats (1.1.0)
+    cocoapods-trunk (1.5.0)
       nap (>= 0.8, < 2.0)
       netrc (~> 0.11)
-    cocoapods-try (1.1.0)
+    cocoapods-try (1.2.0)
     colored2 (3.1.2)
-    concurrent-ruby (1.1.4)
+    concurrent-ruby (1.1.8)
     escape (0.0.4)
-    fourflusher (2.0.1)
+    fourflusher (2.3.1)
     fuzzy_match (2.0.4)
     gh_inspector (1.1.3)
     i18n (0.9.5)
       concurrent-ruby (~> 1.0)
     minitest (5.11.3)
     molinillo (0.6.6)
-    nanaimo (0.2.6)
+    nanaimo (0.3.0)
     nap (1.1.0)
     netrc (0.11.0)
-    ruby-macho (1.3.1)
+    ruby-macho (1.4.0)
     thread_safe (0.3.6)
-    tzinfo (1.2.5)
+    tzinfo (1.2.9)
       thread_safe (~> 0.1)
-    xcodeproj (1.7.0)
+    xcodeproj (1.19.0)
       CFPropertyList (>= 2.3.3, < 4.0)
       atomos (~> 0.1.3)
       claide (>= 1.0.2, < 2.0)
       colored2 (~> 3.1)
-      nanaimo (~> 0.2.6)
+      nanaimo (~> 0.3.0)
 
 PLATFORMS
   ruby
 
 DEPENDENCIES
-  cocoapods (~> 1.6.0beta2)
+  cocoapods (~> 1.6.1)
   minitest
 
 BUNDLED WITH
-   1.17.1
+   1.17.2

From e40e3369c14319df540bbac476c419cfea20294e Mon Sep 17 00:00:00 2001
From: Geoff MacDonald <geoffmac@dropbox.com>
Date: Fri, 30 Apr 2021 17:43:16 -0700
Subject: [PATCH 375/685] update deps

---
 Tests/CocoaPods/Gemfile             |  2 +-
 Tests/CocoaPods/Gemfile.lock        | 51 +++++++++++++++++++----------
 Tests/CocoaPods/integration_test.rb |  2 +-
 3 files changed, 36 insertions(+), 19 deletions(-)

diff --git a/Tests/CocoaPods/Gemfile b/Tests/CocoaPods/Gemfile
index 77d90eec..19db2b36 100644
--- a/Tests/CocoaPods/Gemfile
+++ b/Tests/CocoaPods/Gemfile
@@ -1,4 +1,4 @@
 source 'https://rubygems.org'
 
-gem 'cocoapods', '~> 1.6.1'
+gem 'cocoapods', '~> 1.10.1'
 gem 'minitest'
diff --git a/Tests/CocoaPods/Gemfile.lock b/Tests/CocoaPods/Gemfile.lock
index e5c53ea3..d99ac49a 100644
--- a/Tests/CocoaPods/Gemfile.lock
+++ b/Tests/CocoaPods/Gemfile.lock
@@ -2,42 +2,51 @@ GEM
   remote: https://rubygems.org/
   specs:
     CFPropertyList (3.0.3)
-    activesupport (4.2.11.3)
-      i18n (~> 0.7)
+    activesupport (5.2.5)
+      concurrent-ruby (~> 1.0, >= 1.0.2)
+      i18n (>= 0.7, < 2)
       minitest (~> 5.1)
-      thread_safe (~> 0.3, >= 0.3.4)
       tzinfo (~> 1.1)
+    addressable (2.7.0)
+      public_suffix (>= 2.0.2, < 5.0)
+    algoliasearch (1.27.5)
+      httpclient (~> 2.8, >= 2.8.3)
+      json (>= 1.5.1)
     atomos (0.1.3)
     claide (1.0.3)
-    cocoapods (1.6.2)
-      activesupport (>= 4.0.2, < 5)
+    cocoapods (1.10.1)
+      addressable (~> 2.6)
       claide (>= 1.0.2, < 2.0)
-      cocoapods-core (= 1.6.2)
-      cocoapods-deintegrate (>= 1.0.2, < 2.0)
-      cocoapods-downloader (>= 1.2.2, < 2.0)
+      cocoapods-core (= 1.10.1)
+      cocoapods-deintegrate (>= 1.0.3, < 2.0)
+      cocoapods-downloader (>= 1.4.0, < 2.0)
       cocoapods-plugins (>= 1.0.0, < 2.0)
       cocoapods-search (>= 1.0.0, < 2.0)
-      cocoapods-stats (>= 1.0.0, < 2.0)
-      cocoapods-trunk (>= 1.3.1, < 2.0)
+      cocoapods-trunk (>= 1.4.0, < 2.0)
       cocoapods-try (>= 1.1.0, < 2.0)
       colored2 (~> 3.1)
       escape (~> 0.0.4)
-      fourflusher (>= 2.2.0, < 3.0)
+      fourflusher (>= 2.3.0, < 3.0)
       gh_inspector (~> 1.0)
       molinillo (~> 0.6.6)
       nap (~> 1.0)
       ruby-macho (~> 1.4)
-      xcodeproj (>= 1.8.1, < 2.0)
-    cocoapods-core (1.6.2)
-      activesupport (>= 4.0.2, < 6)
+      xcodeproj (>= 1.19.0, < 2.0)
+    cocoapods-core (1.10.1)
+      activesupport (> 5.0, < 6)
+      addressable (~> 2.6)
+      algoliasearch (~> 1.0)
+      concurrent-ruby (~> 1.1)
       fuzzy_match (~> 2.0.4)
       nap (~> 1.0)
+      netrc (~> 0.11)
+      public_suffix
+      typhoeus (~> 1.0)
     cocoapods-deintegrate (1.0.4)
     cocoapods-downloader (1.4.0)
     cocoapods-plugins (1.0.0)
       nap
     cocoapods-search (1.0.0)
-    cocoapods-stats (1.1.0)
     cocoapods-trunk (1.5.0)
       nap (>= 0.8, < 2.0)
       netrc (~> 0.11)
@@ -45,18 +54,26 @@ GEM
     colored2 (3.1.2)
     concurrent-ruby (1.1.8)
     escape (0.0.4)
+    ethon (0.14.0)
+      ffi (>= 1.15.0)
+    ffi (1.15.0)
     fourflusher (2.3.1)
     fuzzy_match (2.0.4)
     gh_inspector (1.1.3)
-    i18n (0.9.5)
+    httpclient (2.8.3)
+    i18n (1.8.10)
       concurrent-ruby (~> 1.0)
+    json (2.5.1)
     minitest (5.11.3)
     molinillo (0.6.6)
     nanaimo (0.3.0)
     nap (1.1.0)
     netrc (0.11.0)
+    public_suffix (4.0.6)
     ruby-macho (1.4.0)
     thread_safe (0.3.6)
+    typhoeus (1.4.0)
+      ethon (>= 0.9.0)
     tzinfo (1.2.9)
       thread_safe (~> 0.1)
     xcodeproj (1.19.0)
@@ -70,7 +87,7 @@ PLATFORMS
   ruby
 
 DEPENDENCIES
-  cocoapods (~> 1.6.1)
+  cocoapods (~> 1.10.1)
   minitest
 
 BUNDLED WITH
diff --git a/Tests/CocoaPods/integration_test.rb b/Tests/CocoaPods/integration_test.rb
index 98a539b5..2ce2997c 100755
--- a/Tests/CocoaPods/integration_test.rb
+++ b/Tests/CocoaPods/integration_test.rb
@@ -40,7 +40,7 @@ def test_pod
       super unless consumer.platform_name == :watchos
     end
 
-    def xcodebuild(action, scheme, configuration)
+    def xcodebuild(action, scheme, configuration, _)
       require 'fourflusher'
       command = %W(#{action} -workspace #{File.join(validation_dir, 'App.xcworkspace')} -scheme #{scheme} -configuration #{configuration})
       case consumer.platform_name

From 0742ee04976029504502b6212b60462017519887 Mon Sep 17 00:00:00 2001
From: Geoff MacDonald <geoffmac@dropbox.com>
Date: Fri, 30 Apr 2021 17:46:47 -0700
Subject: [PATCH 376/685] apparently carthage doesnt support xcode 12 out of
 box

---
 .travis.yml             | 8 ++++----
 Makefile                | 2 +-
 Tests/Carthage/Makefile | 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 2a0460bb..b8b2eaba 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,11 +1,11 @@
 language: objective-c
 rvm: 2.7.3
 # https://docs.travis-ci.com/user/reference/osx
-osx_image: xcode12.2
+osx_image: xcode11.6
 env:
   global:
-    - IOS_SIMULATOR="iPhone 11"
-    - IOS_VERSION="14.2"
+    - IOS_SIMULATOR="iPhone XS"
+    - IOS_VERSION="13.6"
 matrix:
   include:
     - env: BUILD_SCHEME="SQLite iOS"
@@ -20,7 +20,7 @@ matrix:
     - env: CARTHAGE_PLATFORM="tvOS"
     - env: PACKAGE_MANAGER_COMMAND="test"
 before_install:
- -  gem install bundler
+  - gem install bundler
   - gem install xcpretty --no-document
   - brew update
   - brew outdated carthage || brew upgrade carthage
diff --git a/Makefile b/Makefile
index 50d07148..b38b90e0 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 BUILD_TOOL = xcodebuild
 BUILD_SCHEME = SQLite Mac
 IOS_SIMULATOR = iPhone XS
-IOS_VERSION = 12.2
+IOS_VERSION = 13.6
 ifeq ($(BUILD_SCHEME),SQLite iOS)
 	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -destination "platform=iOS Simulator,name=$(IOS_SIMULATOR),OS=$(IOS_VERSION)"
 else
diff --git a/Tests/Carthage/Makefile b/Tests/Carthage/Makefile
index f28eb25b..7f068985 100644
--- a/Tests/Carthage/Makefile
+++ b/Tests/Carthage/Makefile
@@ -3,7 +3,7 @@ CARTHAGE_PLATFORM := iOS
 CARTHAGE_CONFIGURATION := Release
 CARTHAGE_DIR := Carthage
 CARTHAGE_ARGS := --no-use-binaries
-CARTHAGE_TOOLCHAIN := com.apple.dt.toolchain.Swift_3_0
+CARTHAGE_TOOLCHAIN := com.apple.dt.toolchain.XcodeDefault
 CARTHAGE_CMDLINE := --configuration $(CARTHAGE_CONFIGURATION) --platform $(CARTHAGE_PLATFORM) --toolchain $(CARTHAGE_TOOLCHAIN) $(CARTHAGE_ARGS)
 
 test: $(CARTHAGE) Cartfile

From a78d8c4ae303c7d4875a29a01bc307e48095f7d6 Mon Sep 17 00:00:00 2001
From: Geoff MacDonald <geoffmac@dropbox.com>
Date: Fri, 30 Apr 2021 18:04:29 -0700
Subject: [PATCH 377/685] try 2.6

---
 .travis.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index b8b2eaba..e9d5ec2a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,5 @@
 language: objective-c
-rvm: 2.7.3
+rvm: 2.6
 # https://docs.travis-ci.com/user/reference/osx
 osx_image: xcode11.6
 env:

From 5052cbbd6d881396c87a9ede9de2e30a8f86a706 Mon Sep 17 00:00:00 2001
From: Geoff MacDonald <geoffmac@dropbox.com>
Date: Fri, 30 Apr 2021 18:13:28 -0700
Subject: [PATCH 378/685] use iphone 11

---
 .travis.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index e9d5ec2a..7bff9ce2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,7 +4,7 @@ rvm: 2.6
 osx_image: xcode11.6
 env:
   global:
-    - IOS_SIMULATOR="iPhone XS"
+    - IOS_SIMULATOR="iPhone 11"
     - IOS_VERSION="13.6"
 matrix:
   include:

From f961db5344375ea667f3f5d44c8df202a5cfc5aa Mon Sep 17 00:00:00 2001
From: Bennett Smith <bennett.smith@blueowl.xyz>
Date: Mon, 17 May 2021 18:23:32 -0700
Subject: [PATCH 379/685] Updates for Xcode 12.5

* Updates ruby version used by Travis-CI.
* Updates Xcode image to 12.5 for Travis-CI.
* Removes workaround in run-tests.sh for older simulators.
* Updates Carthage toolchain.
* Updates Package.swift tool version.
* Fixes up SPM build for SQLiteObjc module.
* Updated Xcode build settings.
---
 .travis.yml                                   | 10 ++---
 CHANGELOG.md                                  |  8 ++++
 Makefile                                      |  2 +-
 Package.swift                                 | 45 ++++++++++++++++---
 SQLite.xcodeproj/project.pbxproj              | 30 +++++--------
 .../xcschemes/SQLite Mac.xcscheme             | 24 +++++-----
 .../xcschemes/SQLite iOS.xcscheme             | 24 +++++-----
 .../xcschemes/SQLite tvOS.xcscheme            | 24 +++++-----
 .../xcschemes/SQLite watchOS.xcscheme         |  6 +--
 Sources/SQLiteObjc/SQLiteObjc.h               | 36 +++++++++++++++
 Sources/SQLiteObjc/include/README.md          |  7 +++
 Tests/Carthage/Makefile                       |  5 ++-
 12 files changed, 141 insertions(+), 80 deletions(-)
 create mode 100644 Sources/SQLiteObjc/SQLiteObjc.h
 create mode 100644 Sources/SQLiteObjc/include/README.md

diff --git a/.travis.yml b/.travis.yml
index c8fc5feb..98987db1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,11 +1,11 @@
 language: objective-c
-rvm: 2.3
+rvm: 2.6
 # https://docs.travis-ci.com/user/reference/osx
-osx_image: xcode10.2
+osx_image: xcode12.5
 env:
   global:
     - IOS_SIMULATOR="iPhone XS"
-    - IOS_VERSION="12.2"
+    - IOS_VERSION="12.4"
 matrix:
   include:
     - env: BUILD_SCHEME="SQLite iOS"
@@ -25,7 +25,7 @@ before_install:
   - brew update
   - brew outdated carthage || brew upgrade carthage
 script:
-# Workaround for Xcode 10.2/tvOS 9.1 bug
+# Workaround for Xcode 10.2/tvOS 9.1 bug (This is an outdated workaround; commenting out.)
 # See https://stackoverflow.com/questions/55389080/xcode-10-2-failed-to-run-app-on-simulator-with-ios-10
-  - sudo mkdir /Library/Developer/CoreSimulator/Profiles/Runtimes/tvOS\ 9.1.simruntime/Contents/Resources/RuntimeRoot/usr/lib/swift
+#  - sudo mkdir /Library/Developer/CoreSimulator/Profiles/Runtimes/tvOS\ 9.1.simruntime/Contents/Resources/RuntimeRoot/usr/lib/swift
   - ./run-tests.sh
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 027611ee..1f29afeb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,11 @@
+0.12.3 (18-05-2021), [diff][diff-0.12.2]
+========================================
+
+* Swift 5.3 support.
+* Xcode 12.5 support.
+* Bumps minimum deployment versions.
+* Fixes up Package.swift to build SQLiteObjc module.
+
 0.11.6 (xxx), [diff][diff-0.11.6]
 ========================================
 
diff --git a/Makefile b/Makefile
index 50d07148..be426dc1 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 BUILD_TOOL = xcodebuild
 BUILD_SCHEME = SQLite Mac
 IOS_SIMULATOR = iPhone XS
-IOS_VERSION = 12.2
+IOS_VERSION = 12.4
 ifeq ($(BUILD_SCHEME),SQLite iOS)
 	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -destination "platform=iOS Simulator,name=$(IOS_SIMULATOR),OS=$(IOS_VERSION)"
 else
diff --git a/Package.swift b/Package.swift
index 430ae6f2..73339b7b 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,15 +1,46 @@
-// swift-tools-version:4.0
+// swift-tools-version:5.3
 import PackageDescription
 
 let package = Package(
     name: "SQLite.swift",
-    products: [.library(name: "SQLite", targets: ["SQLite"])],
+    products: [
+			.library(
+				name: "SQLite", 
+				targets: ["SQLite"]
+			)
+		],
     targets: [
-        .target(name: "SQLite", dependencies: ["SQLiteObjc"]),
-        .target(name: "SQLiteObjc"),
-        .testTarget(name: "SQLiteTests", dependencies: ["SQLite"], path: "Tests/SQLiteTests")
-    ],
-    swiftLanguageVersions: [4, 5]
+        .target(
+					name: "SQLite", 
+					dependencies: ["SQLiteObjc"],
+					exclude: [
+						"Info.plist"
+					]
+				),
+        .target(
+					name: "SQLiteObjc",
+					dependencies: [],
+					exclude: [
+						"SQLiteObjc.h",
+						"fts3_tokenizer.h",
+						"include/README.md"
+					]
+				),
+        .testTarget(
+					name: "SQLiteTests", 
+					dependencies: [
+						"SQLite"
+					], 
+					path: "Tests/SQLiteTests",
+					exclude: [
+						"Info.plist"
+					],
+					resources: [
+						.copy("fixtures/encrypted-3.x.sqlite"),
+						.copy("fixtures/encrypted-4.x.sqlite")
+					]
+				)
+    ]
 )
 
 #if os(Linux)
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 30a40214..2e8807ed 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -277,7 +277,7 @@
 		EE247B911C3F822500AE3E12 /* installation@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "installation@2x.png"; sourceTree = "<group>"; };
 		EE247B921C3F822600AE3E12 /* playground@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "playground@2x.png"; sourceTree = "<group>"; };
 		EE247B931C3F826100AE3E12 /* SQLite.swift.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; path = SQLite.swift.podspec; sourceTree = "<group>"; };
-		EE91808D1C46E5230038162A /* SQLiteObjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SQLiteObjc.h; path = ../../SQLiteObjc/include/SQLiteObjc.h; sourceTree = "<group>"; };
+		EE91808D1C46E5230038162A /* SQLiteObjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SQLiteObjc.h; path = ../../SQLiteObjc/SQLiteObjc.h; sourceTree = "<group>"; };
 		EE9180911C46E9D30038162A /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
 		EE9180931C46EA210038162A /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; };
 /* End PBXFileReference section */
@@ -680,7 +680,7 @@
 			isa = PBXProject;
 			attributes = {
 				LastSwiftUpdateCheck = 0720;
-				LastUpgradeCheck = 1020;
+				LastUpgradeCheck = 1250;
 				TargetAttributes = {
 					03A65E591C6BB0F50062603F = {
 						CreatedOnToolsVersion = 7.2;
@@ -1033,7 +1033,7 @@
 				PRODUCT_NAME = SQLite;
 				SDKROOT = appletvos;
 				SKIP_INSTALL = YES;
-				TVOS_DEPLOYMENT_TARGET = 9.1;
+				TVOS_DEPLOYMENT_TARGET = 12.0;
 			};
 			name = Debug;
 		};
@@ -1053,7 +1053,7 @@
 				PRODUCT_NAME = SQLite;
 				SDKROOT = appletvos;
 				SKIP_INSTALL = YES;
-				TVOS_DEPLOYMENT_TARGET = 9.1;
+				TVOS_DEPLOYMENT_TARGET = 12.0;
 			};
 			name = Release;
 		};
@@ -1065,7 +1065,7 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = appletvos;
-				TVOS_DEPLOYMENT_TARGET = 9.1;
+				TVOS_DEPLOYMENT_TARGET = 12.0;
 			};
 			name = Debug;
 		};
@@ -1077,7 +1077,7 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = appletvos;
-				TVOS_DEPLOYMENT_TARGET = 9.1;
+				TVOS_DEPLOYMENT_TARGET = 12.0;
 			};
 			name = Release;
 		};
@@ -1148,6 +1148,7 @@
 				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
 				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
 				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
 				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
 				CLANG_WARN_STRICT_PROTOTYPES = YES;
 				CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -1173,8 +1174,8 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
-				MACOSX_DEPLOYMENT_TARGET = 10.9;
+				IPHONEOS_DEPLOYMENT_TARGET = 12.3;
+				MACOSX_DEPLOYMENT_TARGET = 10.15;
 				MTL_ENABLE_DEBUG_INFO = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				PRODUCT_NAME = "";
@@ -1210,6 +1211,7 @@
 				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
 				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
 				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
 				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
 				CLANG_WARN_STRICT_PROTOTYPES = YES;
 				CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -1229,8 +1231,8 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
-				MACOSX_DEPLOYMENT_TARGET = 10.9;
+				IPHONEOS_DEPLOYMENT_TARGET = 12.3;
+				MACOSX_DEPLOYMENT_TARGET = 10.15;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				PRODUCT_NAME = "";
 				SDKROOT = iphoneos;
@@ -1255,7 +1257,6 @@
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
-				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
@@ -1276,7 +1277,6 @@
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
-				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
@@ -1288,7 +1288,6 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
-				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1299,7 +1298,6 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
-				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1320,7 +1318,6 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
-				MACOSX_DEPLOYMENT_TARGET = 10.10;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SDKROOT = macosx;
@@ -1343,7 +1340,6 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
-				MACOSX_DEPLOYMENT_TARGET = 10.10;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SDKROOT = macosx;
@@ -1359,7 +1355,6 @@
 				COMBINE_HIDPI_IMAGES = YES;
 				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
-				MACOSX_DEPLOYMENT_TARGET = 10.10;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = macosx;
@@ -1373,7 +1368,6 @@
 				COMBINE_HIDPI_IMAGES = YES;
 				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
-				MACOSX_DEPLOYMENT_TARGET = 10.10;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = macosx;
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme
index 4e94e80a..a0db21a2 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite Mac.xcscheme	
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "1020"
+   LastUpgradeVersion = "1250"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -27,6 +27,15 @@
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
       shouldUseLaunchSchemeArgsEnv = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "EE247B3B1C3F3ED000AE3E12"
+            BuildableName = "SQLite.framework"
+            BlueprintName = "SQLite Mac"
+            ReferencedContainer = "container:SQLite.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
       <Testables>
          <TestableReference
             skipped = "NO">
@@ -39,17 +48,6 @@
             </BuildableReference>
          </TestableReference>
       </Testables>
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "EE247B3B1C3F3ED000AE3E12"
-            BuildableName = "SQLite.framework"
-            BlueprintName = "SQLite Mac"
-            ReferencedContainer = "container:SQLite.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </TestAction>
    <LaunchAction
       buildConfiguration = "Debug"
@@ -70,8 +68,6 @@
             ReferencedContainer = "container:SQLite.xcodeproj">
          </BuildableReference>
       </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </LaunchAction>
    <ProfileAction
       buildConfiguration = "Release"
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme
index f4ba4231..6cadc289 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite iOS.xcscheme	
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "1020"
+   LastUpgradeVersion = "1250"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -27,6 +27,15 @@
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
       shouldUseLaunchSchemeArgsEnv = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "EE247AD21C3F04ED00AE3E12"
+            BuildableName = "SQLite.framework"
+            BlueprintName = "SQLite iOS"
+            ReferencedContainer = "container:SQLite.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
       <Testables>
          <TestableReference
             skipped = "NO">
@@ -39,17 +48,6 @@
             </BuildableReference>
          </TestableReference>
       </Testables>
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "EE247AD21C3F04ED00AE3E12"
-            BuildableName = "SQLite.framework"
-            BlueprintName = "SQLite iOS"
-            ReferencedContainer = "container:SQLite.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </TestAction>
    <LaunchAction
       buildConfiguration = "Debug"
@@ -70,8 +68,6 @@
             ReferencedContainer = "container:SQLite.xcodeproj">
          </BuildableReference>
       </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </LaunchAction>
    <ProfileAction
       buildConfiguration = "Release"
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme
index 7a3ddbfb..01966aa1 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite tvOS.xcscheme	
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "1020"
+   LastUpgradeVersion = "1250"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -27,6 +27,15 @@
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
       shouldUseLaunchSchemeArgsEnv = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "03A65E591C6BB0F50062603F"
+            BuildableName = "SQLite.framework"
+            BlueprintName = "SQLite tvOS"
+            ReferencedContainer = "container:SQLite.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
       <Testables>
          <TestableReference
             skipped = "NO">
@@ -39,17 +48,6 @@
             </BuildableReference>
          </TestableReference>
       </Testables>
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "03A65E591C6BB0F50062603F"
-            BuildableName = "SQLite.framework"
-            BlueprintName = "SQLite tvOS"
-            ReferencedContainer = "container:SQLite.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </TestAction>
    <LaunchAction
       buildConfiguration = "Debug"
@@ -70,8 +68,6 @@
             ReferencedContainer = "container:SQLite.xcodeproj">
          </BuildableReference>
       </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </LaunchAction>
    <ProfileAction
       buildConfiguration = "Release"
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite watchOS.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite watchOS.xcscheme
index ace02712..be1ef0ee 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite watchOS.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite watchOS.xcscheme	
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "1020"
+   LastUpgradeVersion = "1250"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -29,8 +29,6 @@
       shouldUseLaunchSchemeArgsEnv = "YES">
       <Testables>
       </Testables>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </TestAction>
    <LaunchAction
       buildConfiguration = "Debug"
@@ -51,8 +49,6 @@
             ReferencedContainer = "container:SQLite.xcodeproj">
          </BuildableReference>
       </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </LaunchAction>
    <ProfileAction
       buildConfiguration = "Release"
diff --git a/Sources/SQLiteObjc/SQLiteObjc.h b/Sources/SQLiteObjc/SQLiteObjc.h
new file mode 100644
index 00000000..e8ba9a7d
--- /dev/null
+++ b/Sources/SQLiteObjc/SQLiteObjc.h
@@ -0,0 +1,36 @@
+//
+// SQLite.swift
+// https://github.com/stephencelis/SQLite.swift
+// Copyright © 2014-2015 Stephen Celis.
+//
+// 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.
+//
+
+@import Foundation;
+#if defined(SQLITE_SWIFT_STANDALONE)
+@import sqlite3;
+#else
+@import SQLite3;
+#endif
+
+NS_ASSUME_NONNULL_BEGIN
+typedef NSString * _Nullable (^_SQLiteTokenizerNextCallback)(const char *input, int *inputOffset, int *inputLength);
+int _SQLiteRegisterTokenizer(sqlite3 *db, const char *module, const char *tokenizer, _Nullable _SQLiteTokenizerNextCallback callback);
+NS_ASSUME_NONNULL_END
+
diff --git a/Sources/SQLiteObjc/include/README.md b/Sources/SQLiteObjc/include/README.md
new file mode 100644
index 00000000..54b375e5
--- /dev/null
+++ b/Sources/SQLiteObjc/include/README.md
@@ -0,0 +1,7 @@
+# README
+
+This folder contains the public interface for the SQLiteObjc module. It is a duplicate
+copy of the header file found in the Sources/SQLiteObjc folder. If you change one, change
+the other too!
+
+
diff --git a/Tests/Carthage/Makefile b/Tests/Carthage/Makefile
index f28eb25b..f5185854 100644
--- a/Tests/Carthage/Makefile
+++ b/Tests/Carthage/Makefile
@@ -2,8 +2,9 @@ CARTHAGE := /usr/local/bin/carthage
 CARTHAGE_PLATFORM := iOS
 CARTHAGE_CONFIGURATION := Release
 CARTHAGE_DIR := Carthage
-CARTHAGE_ARGS := --no-use-binaries
-CARTHAGE_TOOLCHAIN := com.apple.dt.toolchain.Swift_3_0
+CARTHAGE_ARGS := --no-use-binaries --use-xcframeworks
+# CARTHAGE_TOOLCHAIN := com.apple.dt.toolchain.Swift_3_0
+CARTHAGE_TOOLCHAIN := com.apple.dt.toolchain.XcodeDefault
 CARTHAGE_CMDLINE := --configuration $(CARTHAGE_CONFIGURATION) --platform $(CARTHAGE_PLATFORM) --toolchain $(CARTHAGE_TOOLCHAIN) $(CARTHAGE_ARGS)
 
 test: $(CARTHAGE) Cartfile

From 3476f89153bcd31cc2836bdcc6ae95875ed6eb1c Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 24 Jun 2021 01:24:18 +0200
Subject: [PATCH 380/685] - Set iOS deployment target to 9.0 - Bump watchOS
 deployment version to 3.0 #971 - Fix SQLCipher compilation #1024

---
 .travis.yml                             |  3 -
 SQLite.swift.podspec                    | 14 ++---
 SQLite.xcodeproj/project.pbxproj        |  8 +--
 Sources/SQLiteObjc/SQLiteObjc.h         |  2 +
 Sources/SQLiteObjc/include/README.md    |  7 ---
 Sources/SQLiteObjc/include/SQLiteObjc.h | 36 -----------
 Tests/CocoaPods/Gemfile                 |  2 +-
 Tests/CocoaPods/Gemfile.lock            | 83 +++++++++++++++----------
 Tests/CocoaPods/integration_test.rb     | 37 +----------
 Tests/SQLiteTests/ConnectionTests.swift |  6 +-
 10 files changed, 69 insertions(+), 129 deletions(-)
 delete mode 100644 Sources/SQLiteObjc/include/README.md
 delete mode 100644 Sources/SQLiteObjc/include/SQLiteObjc.h

diff --git a/.travis.yml b/.travis.yml
index 98987db1..90ff205c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -25,7 +25,4 @@ before_install:
   - brew update
   - brew outdated carthage || brew upgrade carthage
 script:
-# Workaround for Xcode 10.2/tvOS 9.1 bug (This is an outdated workaround; commenting out.)
-# See https://stackoverflow.com/questions/55389080/xcode-10-2-failed-to-run-app-on-simulator-with-ios-10
-#  - sudo mkdir /Library/Developer/CoreSimulator/Profiles/Runtimes/tvOS\ 9.1.simruntime/Contents/Resources/RuntimeRoot/usr/lib/swift
   - ./run-tests.sh
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 712ddc36..bcefa5fe 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -19,10 +19,10 @@ Pod::Spec.new do |s|
   s.swift_versions = ['4.2', '5']
   
   
-  ios_deployment_target = '8.0'
+  ios_deployment_target = '9.0'
   tvos_deployment_target = '9.1'
   osx_deployment_target = '10.10'
-  watchos_deployment_target = '2.2'
+  watchos_deployment_target = '3.0'
   
   s.ios.deployment_target = ios_deployment_target
   s.tvos.deployment_target = tvos_deployment_target
@@ -32,7 +32,7 @@ Pod::Spec.new do |s|
   s.subspec 'standard' do |ss|
     ss.source_files = 'Sources/{SQLite,SQLiteObjc}/**/*.{c,h,m,swift}'
     ss.exclude_files = 'Sources/**/Cipher.swift'
-    ss.private_header_files = 'Sources/SQLiteObjc/*.h'
+    ss.private_header_files = 'Sources/SQLiteObjc/fts3_tokenizer.h'
     ss.library = 'sqlite3'
 
     ss.test_spec 'tests' do |test_spec|
@@ -47,7 +47,7 @@ Pod::Spec.new do |s|
   s.subspec 'standalone' do |ss|
     ss.source_files = 'Sources/{SQLite,SQLiteObjc}/**/*.{c,h,m,swift}'
     ss.exclude_files = 'Sources/**/Cipher.swift'
-    ss.private_header_files = 'Sources/SQLiteObjc/*.h'
+    ss.private_header_files = 'Sources/SQLiteObjc/fts3_tokenizer.h'
 
     ss.xcconfig = {
       'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_SWIFT_STANDALONE',
@@ -66,12 +66,12 @@ Pod::Spec.new do |s|
 
   s.subspec 'SQLCipher' do |ss|
     ss.source_files = 'Sources/{SQLite,SQLiteObjc}/**/*.{c,h,m,swift}'
-    ss.private_header_files = 'Sources/SQLiteObjc/*.h'
+    ss.private_header_files = 'Sources/SQLiteObjc/fts3_tokenizer.h'
     ss.xcconfig = {
       'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_SWIFT_SQLCIPHER',
-      'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SQLITE_HAS_CODEC=1'
+      'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SQLITE_HAS_CODEC=1 SQLITE_SWIFT_SQLCIPHER=1'
     }
-    ss.dependency 'SQLCipher', '>= 3.4.0'
+    ss.dependency 'SQLCipher', '>= 4.0.0'
 
     ss.test_spec 'tests' do |test_spec|
       test_spec.resources = 'Tests/SQLiteTests/fixtures/*'
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 2e8807ed..92795299 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1099,7 +1099,7 @@
 				SDKROOT = watchos;
 				SKIP_INSTALL = YES;
 				TARGETED_DEVICE_FAMILY = 4;
-				WATCHOS_DEPLOYMENT_TARGET = 2.2;
+				WATCHOS_DEPLOYMENT_TARGET = 3.0;
 			};
 			name = Debug;
 		};
@@ -1121,7 +1121,7 @@
 				SDKROOT = watchos;
 				SKIP_INSTALL = YES;
 				TARGETED_DEVICE_FAMILY = 4;
-				WATCHOS_DEPLOYMENT_TARGET = 2.2;
+				WATCHOS_DEPLOYMENT_TARGET = 3.0;
 			};
 			name = Release;
 		};
@@ -1174,7 +1174,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 12.3;
+				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 				MACOSX_DEPLOYMENT_TARGET = 10.15;
 				MTL_ENABLE_DEBUG_INFO = YES;
 				ONLY_ACTIVE_ARCH = YES;
@@ -1231,7 +1231,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 12.3;
+				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 				MACOSX_DEPLOYMENT_TARGET = 10.15;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				PRODUCT_NAME = "";
diff --git a/Sources/SQLiteObjc/SQLiteObjc.h b/Sources/SQLiteObjc/SQLiteObjc.h
index e8ba9a7d..610cdf10 100644
--- a/Sources/SQLiteObjc/SQLiteObjc.h
+++ b/Sources/SQLiteObjc/SQLiteObjc.h
@@ -25,6 +25,8 @@
 @import Foundation;
 #if defined(SQLITE_SWIFT_STANDALONE)
 @import sqlite3;
+#elif defined(SQLITE_SWIFT_SQLCIPHER)
+@import SQLCipher;
 #else
 @import SQLite3;
 #endif
diff --git a/Sources/SQLiteObjc/include/README.md b/Sources/SQLiteObjc/include/README.md
deleted file mode 100644
index 54b375e5..00000000
--- a/Sources/SQLiteObjc/include/README.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# README
-
-This folder contains the public interface for the SQLiteObjc module. It is a duplicate
-copy of the header file found in the Sources/SQLiteObjc folder. If you change one, change
-the other too!
-
-
diff --git a/Sources/SQLiteObjc/include/SQLiteObjc.h b/Sources/SQLiteObjc/include/SQLiteObjc.h
deleted file mode 100644
index e8ba9a7d..00000000
--- a/Sources/SQLiteObjc/include/SQLiteObjc.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// SQLite.swift
-// https://github.com/stephencelis/SQLite.swift
-// Copyright © 2014-2015 Stephen Celis.
-//
-// 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.
-//
-
-@import Foundation;
-#if defined(SQLITE_SWIFT_STANDALONE)
-@import sqlite3;
-#else
-@import SQLite3;
-#endif
-
-NS_ASSUME_NONNULL_BEGIN
-typedef NSString * _Nullable (^_SQLiteTokenizerNextCallback)(const char *input, int *inputOffset, int *inputLength);
-int _SQLiteRegisterTokenizer(sqlite3 *db, const char *module, const char *tokenizer, _Nullable _SQLiteTokenizerNextCallback callback);
-NS_ASSUME_NONNULL_END
-
diff --git a/Tests/CocoaPods/Gemfile b/Tests/CocoaPods/Gemfile
index 77d90eec..19db2b36 100644
--- a/Tests/CocoaPods/Gemfile
+++ b/Tests/CocoaPods/Gemfile
@@ -1,4 +1,4 @@
 source 'https://rubygems.org'
 
-gem 'cocoapods', '~> 1.6.1'
+gem 'cocoapods', '~> 1.10.1'
 gem 'minitest'
diff --git a/Tests/CocoaPods/Gemfile.lock b/Tests/CocoaPods/Gemfile.lock
index b5172144..0cf77eda 100644
--- a/Tests/CocoaPods/Gemfile.lock
+++ b/Tests/CocoaPods/Gemfile.lock
@@ -1,77 +1,94 @@
 GEM
   remote: https://rubygems.org/
   specs:
-    CFPropertyList (3.0.0)
-    activesupport (4.2.11)
-      i18n (~> 0.7)
+    CFPropertyList (3.0.3)
+    activesupport (5.2.6)
+      concurrent-ruby (~> 1.0, >= 1.0.2)
+      i18n (>= 0.7, < 2)
       minitest (~> 5.1)
-      thread_safe (~> 0.3, >= 0.3.4)
       tzinfo (~> 1.1)
+    addressable (2.7.0)
+      public_suffix (>= 2.0.2, < 5.0)
+    algoliasearch (1.27.5)
+      httpclient (~> 2.8, >= 2.8.3)
+      json (>= 1.5.1)
     atomos (0.1.3)
-    claide (1.0.2)
-    cocoapods (1.6.0.beta.2)
-      activesupport (>= 4.0.2, < 5)
+    claide (1.0.3)
+    cocoapods (1.10.1)
+      addressable (~> 2.6)
       claide (>= 1.0.2, < 2.0)
-      cocoapods-core (= 1.6.0.beta.2)
-      cocoapods-deintegrate (>= 1.0.2, < 2.0)
-      cocoapods-downloader (>= 1.2.2, < 2.0)
+      cocoapods-core (= 1.10.1)
+      cocoapods-deintegrate (>= 1.0.3, < 2.0)
+      cocoapods-downloader (>= 1.4.0, < 2.0)
       cocoapods-plugins (>= 1.0.0, < 2.0)
       cocoapods-search (>= 1.0.0, < 2.0)
-      cocoapods-stats (>= 1.0.0, < 2.0)
-      cocoapods-trunk (>= 1.3.1, < 2.0)
+      cocoapods-trunk (>= 1.4.0, < 2.0)
       cocoapods-try (>= 1.1.0, < 2.0)
       colored2 (~> 3.1)
       escape (~> 0.0.4)
-      fourflusher (~> 2.0.1)
+      fourflusher (>= 2.3.0, < 3.0)
       gh_inspector (~> 1.0)
       molinillo (~> 0.6.6)
       nap (~> 1.0)
-      ruby-macho (~> 1.3, >= 1.3.1)
-      xcodeproj (>= 1.7.0, < 2.0)
-    cocoapods-core (1.6.0.beta.2)
-      activesupport (>= 4.0.2, < 6)
+      ruby-macho (~> 1.4)
+      xcodeproj (>= 1.19.0, < 2.0)
+    cocoapods-core (1.10.1)
+      activesupport (> 5.0, < 6)
+      addressable (~> 2.6)
+      algoliasearch (~> 1.0)
+      concurrent-ruby (~> 1.1)
       fuzzy_match (~> 2.0.4)
       nap (~> 1.0)
-    cocoapods-deintegrate (1.0.2)
-    cocoapods-downloader (1.2.2)
+      netrc (~> 0.11)
+      public_suffix
+      typhoeus (~> 1.0)
+    cocoapods-deintegrate (1.0.4)
+    cocoapods-downloader (1.4.0)
     cocoapods-plugins (1.0.0)
       nap
     cocoapods-search (1.0.0)
-    cocoapods-stats (1.0.0)
-    cocoapods-trunk (1.3.1)
+    cocoapods-trunk (1.5.0)
       nap (>= 0.8, < 2.0)
       netrc (~> 0.11)
-    cocoapods-try (1.1.0)
+    cocoapods-try (1.2.0)
     colored2 (3.1.2)
-    concurrent-ruby (1.1.4)
+    concurrent-ruby (1.1.9)
     escape (0.0.4)
-    fourflusher (2.0.1)
+    ethon (0.14.0)
+      ffi (>= 1.15.0)
+    ffi (1.15.3)
+    fourflusher (2.3.1)
     fuzzy_match (2.0.4)
     gh_inspector (1.1.3)
-    i18n (0.9.5)
+    httpclient (2.8.3)
+    i18n (1.8.10)
       concurrent-ruby (~> 1.0)
-    minitest (5.11.3)
+    json (2.5.1)
+    minitest (5.14.4)
     molinillo (0.6.6)
-    nanaimo (0.2.6)
+    nanaimo (0.3.0)
     nap (1.1.0)
     netrc (0.11.0)
-    ruby-macho (1.3.1)
+    public_suffix (4.0.6)
+    ruby-macho (1.4.0)
     thread_safe (0.3.6)
-    tzinfo (1.2.5)
+    typhoeus (1.4.0)
+      ethon (>= 0.9.0)
+    tzinfo (1.2.9)
       thread_safe (~> 0.1)
-    xcodeproj (1.7.0)
+    xcodeproj (1.19.0)
       CFPropertyList (>= 2.3.3, < 4.0)
       atomos (~> 0.1.3)
       claide (>= 1.0.2, < 2.0)
       colored2 (~> 3.1)
-      nanaimo (~> 0.2.6)
+      nanaimo (~> 0.3.0)
 
 PLATFORMS
   ruby
 
 DEPENDENCIES
-  cocoapods (~> 1.6.0beta2)
+  cocoapods (~> 1.10.1)
   minitest
 
 BUNDLED WITH
-   1.17.1
+   1.17.3
diff --git a/Tests/CocoaPods/integration_test.rb b/Tests/CocoaPods/integration_test.rb
index 98a539b5..67b13385 100755
--- a/Tests/CocoaPods/integration_test.rb
+++ b/Tests/CocoaPods/integration_test.rb
@@ -13,7 +13,7 @@ def test_validate_project
   private
 
   def validator
-    @validator ||= CustomValidator.new(podspec, ['https://github.com/CocoaPods/Specs.git']).tap do |validator|
+    @validator ||= Pod::Validator.new(podspec, ['https://github.com/CocoaPods/Specs.git']).tap do |validator|
         validator.config.verbose = true
         validator.no_clean = true
         validator.use_frameworks = true
@@ -32,39 +32,4 @@ def validator
   def podspec
     File.expand_path(File.dirname(__FILE__) + '/../../SQLite.swift.podspec')
   end
-
-
-  class CustomValidator < Pod::Validator
-    def test_pod
-      # https://github.com/CocoaPods/CocoaPods/issues/7009
-      super unless consumer.platform_name == :watchos
-    end
-
-    def xcodebuild(action, scheme, configuration)
-      require 'fourflusher'
-      command = %W(#{action} -workspace #{File.join(validation_dir, 'App.xcworkspace')} -scheme #{scheme} -configuration #{configuration})
-      case consumer.platform_name
-      when :osx, :macos
-        command += %w(CODE_SIGN_IDENTITY=)
-      when :ios
-        command += %w(CODE_SIGN_IDENTITY=- -sdk iphonesimulator)
-        command += Fourflusher::SimControl.new.destination(nil, 'iOS', deployment_target)
-      when :watchos
-        command += %w(CODE_SIGN_IDENTITY=- -sdk watchsimulator)
-        command += Fourflusher::SimControl.new.destination(:oldest, 'watchOS', deployment_target)
-      when :tvos
-        command += %w(CODE_SIGN_IDENTITY=- -sdk appletvsimulator)
-        command += Fourflusher::SimControl.new.destination(:oldest, 'tvOS', deployment_target)
-      end
-
-      begin
-        _xcodebuild(command, true)
-      rescue => e
-        message = 'Returned an unsuccessful exit code.'
-        message += ' You can use `--verbose` for more information.' unless config.verbose?
-        error('xcodebuild', message)
-        e.message
-      end
-    end
-  end
 end
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index eab3cf00..fdfc9637 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -38,12 +38,14 @@ class ConnectionTests : SQLiteTestCase {
 
     func test_init_withURI_returnsURIConnection() {
         let db = try! Connection(.uri("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3"))
-        XCTAssertEqual("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3", db.description)
+        let url = URL(fileURLWithPath: db.description)
+        XCTAssertEqual(url.lastPathComponent, "SQLite.swift Tests.sqlite3")
     }
 
     func test_init_withString_returnsURIConnection() {
         let db = try! Connection("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3")
-        XCTAssertEqual("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3", db.description)
+        let url = URL(fileURLWithPath: db.description)
+        XCTAssertEqual(url.lastPathComponent, "SQLite.swift Tests.sqlite3")
     }
 
     func test_readonly_returnsFalseOnReadWriteConnections() {

From 3976805368faf2d5ba9fbf00a397ec8b3a4d81c8 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Wed, 18 Aug 2021 17:39:36 +0200
Subject: [PATCH 381/685] Moving to GitHub Actions

---
 .../template.md}                              |  0
 .github/workflows/build.yml                   | 60 +++++++++++++++++++
 .travis.yml                                   | 31 ----------
 3 files changed, 60 insertions(+), 31 deletions(-)
 rename .github/{ISSUE_TEMPLATE.md => ISSUE_TEMPLATE/template.md} (100%)
 create mode 100644 .github/workflows/build.yml
 delete mode 100644 .travis.yml

diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE/template.md
similarity index 100%
rename from .github/ISSUE_TEMPLATE.md
rename to .github/ISSUE_TEMPLATE/template.md
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 00000000..462233d4
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,60 @@
+name: Build and test
+on: [push, pull_request]
+env:
+  IOS_SIMULATOR: iPhone XS
+  IOS_VERSION: 12.4
+jobs:
+  build:
+    runs-on: macos-latest
+    steps:
+    - uses: actions/checkout@v2
+    - name: Install
+      run: |
+        gem update bundler
+        gem install xcpretty --no-document
+        brew update
+        brew outdated carthage || brew upgrade carthage
+    - name: "Run tests (BUILD_SCHEME: SQLite iOS)"
+      env:
+        BUILD_SCHEME: SQLite iOS
+      run: ./run-tests.sh
+    - name: "Run tests (BUILD_SCHEME: SQLite Mac)"
+      env:
+        BUILD_SCHEME: SQLite Mac
+      run: ./run-tests.sh
+    - name: "Run tests (VALIDATOR_SUBSPEC: none)"
+      env:
+        VALIDATOR_SUBSPEC: none
+      run: ./run-tests.sh
+    - name: "Run tests (VALIDATOR_SUBSPEC: standard)"
+      env:
+        VALIDATOR_SUBSPEC: standard
+      run: ./run-tests.sh
+    - name: "Run tests (VALIDATOR_SUBSPEC: standalone)"
+      env:
+        VALIDATOR_SUBSPEC: standalone
+      run: ./run-tests.sh
+    - name: "Run tests (VALIDATOR_SUBSPEC: SQLCipher)"
+      env:
+        VALIDATOR_SUBSPEC: SQLCipher
+      run: ./run-tests.sh
+    - name: "Run tests (CARTHAGE_PLATFORM: iOS)"
+      env:
+        CARTHAGE_PLATFORM: iOS
+      run: ./run-tests.sh
+    - name: "Run tests (CARTHAGE_PLATFORM: Mac)"
+      env:
+        CARTHAGE_PLATFORM: Mac
+      run: ./run-tests.sh
+    - name: "Run tests (CARTHAGE_PLATFORM: watchOS)"
+      env:
+        CARTHAGE_PLATFORM: watchOS
+      run: ./run-tests.sh
+    - name: "Run tests (CARTHAGE_PLATFORM: tvOS)"
+      env:
+        CARTHAGE_PLATFORM: tvOS
+      run: ./run-tests.sh
+    - name: "Run tests (PACKAGE_MANAGER_COMMAND: test)"
+      env:
+        PACKAGE_MANAGER_COMMAND: test
+      run: ./run-tests.sh
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 98987db1..00000000
--- a/.travis.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-language: objective-c
-rvm: 2.6
-# https://docs.travis-ci.com/user/reference/osx
-osx_image: xcode12.5
-env:
-  global:
-    - IOS_SIMULATOR="iPhone XS"
-    - IOS_VERSION="12.4"
-matrix:
-  include:
-    - env: BUILD_SCHEME="SQLite iOS"
-    - env: BUILD_SCHEME="SQLite Mac"
-    - env: VALIDATOR_SUBSPEC="none"
-    - env: VALIDATOR_SUBSPEC="standard"
-    - env: VALIDATOR_SUBSPEC="standalone"
-    - env: VALIDATOR_SUBSPEC="SQLCipher"
-    - env: CARTHAGE_PLATFORM="iOS"
-    - env: CARTHAGE_PLATFORM="Mac"
-    - env: CARTHAGE_PLATFORM="watchOS"
-    - env: CARTHAGE_PLATFORM="tvOS"
-    - env: PACKAGE_MANAGER_COMMAND="test"
-before_install:
-  - gem update bundler
-  - gem install xcpretty --no-document
-  - brew update
-  - brew outdated carthage || brew upgrade carthage
-script:
-# Workaround for Xcode 10.2/tvOS 9.1 bug (This is an outdated workaround; commenting out.)
-# See https://stackoverflow.com/questions/55389080/xcode-10-2-failed-to-run-app-on-simulator-with-ios-10
-#  - sudo mkdir /Library/Developer/CoreSimulator/Profiles/Runtimes/tvOS\ 9.1.simruntime/Contents/Resources/RuntimeRoot/usr/lib/swift
-  - ./run-tests.sh

From 4b91f07fe16d6d4ca42f81d845aa37181913b2d8 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Wed, 18 Aug 2021 17:46:22 +0200
Subject: [PATCH 382/685] Updating iOS test device

---
 .github/workflows/build.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 462233d4..1c47e3a6 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,8 +1,8 @@
 name: Build and test
 on: [push, pull_request]
 env:
-  IOS_SIMULATOR: iPhone XS
-  IOS_VERSION: 12.4
+  IOS_SIMULATOR: iPhone 12
+  IOS_VERSION: 14.4
 jobs:
   build:
     runs-on: macos-latest

From de2059b37a4da218367685368fa01093a7817d7a Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Wed, 18 Aug 2021 18:03:26 +0200
Subject: [PATCH 383/685] Update Cocoapods version

---
 Tests/CocoaPods/Gemfile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Tests/CocoaPods/Gemfile b/Tests/CocoaPods/Gemfile
index 77d90eec..da52ec89 100644
--- a/Tests/CocoaPods/Gemfile
+++ b/Tests/CocoaPods/Gemfile
@@ -1,4 +1,4 @@
 source 'https://rubygems.org'
 
-gem 'cocoapods', '~> 1.6.1'
+gem 'cocoapods', '~> 1.10.2'
 gem 'minitest'

From 1e4a1f8092980b93cef68f64edba92dc2b65c573 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Wed, 18 Aug 2021 18:16:27 +0200
Subject: [PATCH 384/685] Updating Cocoapods gemfile lock

---
 Tests/CocoaPods/Gemfile.lock | 85 ++++++++++++++++++++++--------------
 1 file changed, 52 insertions(+), 33 deletions(-)

diff --git a/Tests/CocoaPods/Gemfile.lock b/Tests/CocoaPods/Gemfile.lock
index b5172144..e0383a67 100644
--- a/Tests/CocoaPods/Gemfile.lock
+++ b/Tests/CocoaPods/Gemfile.lock
@@ -1,77 +1,96 @@
 GEM
   remote: https://rubygems.org/
   specs:
-    CFPropertyList (3.0.0)
-    activesupport (4.2.11)
-      i18n (~> 0.7)
+    CFPropertyList (3.0.3)
+    activesupport (5.2.6)
+      concurrent-ruby (~> 1.0, >= 1.0.2)
+      i18n (>= 0.7, < 2)
       minitest (~> 5.1)
-      thread_safe (~> 0.3, >= 0.3.4)
       tzinfo (~> 1.1)
+    addressable (2.8.0)
+      public_suffix (>= 2.0.2, < 5.0)
+    algoliasearch (1.27.5)
+      httpclient (~> 2.8, >= 2.8.3)
+      json (>= 1.5.1)
     atomos (0.1.3)
-    claide (1.0.2)
-    cocoapods (1.6.0.beta.2)
-      activesupport (>= 4.0.2, < 5)
+    claide (1.0.3)
+    cocoapods (1.10.2)
+      addressable (~> 2.6)
       claide (>= 1.0.2, < 2.0)
-      cocoapods-core (= 1.6.0.beta.2)
-      cocoapods-deintegrate (>= 1.0.2, < 2.0)
-      cocoapods-downloader (>= 1.2.2, < 2.0)
+      cocoapods-core (= 1.10.2)
+      cocoapods-deintegrate (>= 1.0.3, < 2.0)
+      cocoapods-downloader (>= 1.4.0, < 2.0)
       cocoapods-plugins (>= 1.0.0, < 2.0)
       cocoapods-search (>= 1.0.0, < 2.0)
-      cocoapods-stats (>= 1.0.0, < 2.0)
-      cocoapods-trunk (>= 1.3.1, < 2.0)
+      cocoapods-trunk (>= 1.4.0, < 2.0)
       cocoapods-try (>= 1.1.0, < 2.0)
       colored2 (~> 3.1)
       escape (~> 0.0.4)
-      fourflusher (~> 2.0.1)
+      fourflusher (>= 2.3.0, < 3.0)
       gh_inspector (~> 1.0)
       molinillo (~> 0.6.6)
       nap (~> 1.0)
-      ruby-macho (~> 1.3, >= 1.3.1)
-      xcodeproj (>= 1.7.0, < 2.0)
-    cocoapods-core (1.6.0.beta.2)
-      activesupport (>= 4.0.2, < 6)
+      ruby-macho (~> 1.4)
+      xcodeproj (>= 1.19.0, < 2.0)
+    cocoapods-core (1.10.2)
+      activesupport (> 5.0, < 6)
+      addressable (~> 2.6)
+      algoliasearch (~> 1.0)
+      concurrent-ruby (~> 1.1)
       fuzzy_match (~> 2.0.4)
       nap (~> 1.0)
-    cocoapods-deintegrate (1.0.2)
-    cocoapods-downloader (1.2.2)
+      netrc (~> 0.11)
+      public_suffix
+      typhoeus (~> 1.0)
+    cocoapods-deintegrate (1.0.5)
+    cocoapods-downloader (1.4.0)
     cocoapods-plugins (1.0.0)
       nap
-    cocoapods-search (1.0.0)
-    cocoapods-stats (1.0.0)
-    cocoapods-trunk (1.3.1)
+    cocoapods-search (1.0.1)
+    cocoapods-trunk (1.5.0)
       nap (>= 0.8, < 2.0)
       netrc (~> 0.11)
-    cocoapods-try (1.1.0)
+    cocoapods-try (1.2.0)
     colored2 (3.1.2)
-    concurrent-ruby (1.1.4)
+    concurrent-ruby (1.1.9)
     escape (0.0.4)
-    fourflusher (2.0.1)
+    ethon (0.14.0)
+      ffi (>= 1.15.0)
+    ffi (1.15.3)
+    fourflusher (2.3.1)
     fuzzy_match (2.0.4)
     gh_inspector (1.1.3)
-    i18n (0.9.5)
+    httpclient (2.8.3)
+    i18n (1.8.10)
       concurrent-ruby (~> 1.0)
+    json (2.5.1)
     minitest (5.11.3)
     molinillo (0.6.6)
-    nanaimo (0.2.6)
+    nanaimo (0.3.0)
     nap (1.1.0)
     netrc (0.11.0)
-    ruby-macho (1.3.1)
+    public_suffix (4.0.6)
+    rexml (3.2.5)
+    ruby-macho (1.4.0)
     thread_safe (0.3.6)
-    tzinfo (1.2.5)
+    typhoeus (1.4.0)
+      ethon (>= 0.9.0)
+    tzinfo (1.2.9)
       thread_safe (~> 0.1)
-    xcodeproj (1.7.0)
+    xcodeproj (1.21.0)
       CFPropertyList (>= 2.3.3, < 4.0)
       atomos (~> 0.1.3)
       claide (>= 1.0.2, < 2.0)
       colored2 (~> 3.1)
-      nanaimo (~> 0.2.6)
+      nanaimo (~> 0.3.0)
+      rexml (~> 3.2.4)
 
 PLATFORMS
   ruby
 
 DEPENDENCIES
-  cocoapods (~> 1.6.0beta2)
+  cocoapods (~> 1.10.2)
   minitest
 
 BUNDLED WITH
-   1.17.1
+   2.2.22

From 9016160ae16bc0376f00dd0d50132319b996c750 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Wed, 18 Aug 2021 18:41:08 +0200
Subject: [PATCH 385/685] Fixed Carthage Makefil for GitHub Actions

---
 Tests/Carthage/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Tests/Carthage/Makefile b/Tests/Carthage/Makefile
index f5185854..b44d85b9 100644
--- a/Tests/Carthage/Makefile
+++ b/Tests/Carthage/Makefile
@@ -11,7 +11,7 @@ test: $(CARTHAGE) Cartfile
 	$< bootstrap $(CARTHAGE_CMDLINE)
 
 Cartfile:
-	echo 'git "$(TRAVIS_BUILD_DIR)" "HEAD"' > $@
+	echo 'git "$(GITHUB_WORKSPACE)" "HEAD"' > $@
 
 clean:
 	@rm -f Cartfile Cartfile.resolved

From 6ccf8a8e7f03d1909bb0452b344151091d664bf5 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Wed, 18 Aug 2021 20:01:29 +0200
Subject: [PATCH 386/685] Totally removing Travis from repository

---
 README.md                        | 5 ++---
 SQLite.xcodeproj/project.pbxproj | 2 --
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index 8b0972f6..c3c89ce5 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # SQLite.swift
 
-[![Build Status][TravisBadge]][TravisLink] [![CocoaPods Version][CocoaPodsVersionBadge]][CocoaPodsVersionLink] [![Swift5 compatible][Swift5Badge]][Swift5Link] [![Platform][PlatformBadge]][PlatformLink] [![Carthage compatible][CartagheBadge]][CarthageLink] [![Join the chat at https://gitter.im/stephencelis/SQLite.swift][GitterBadge]][GitterLink]
+![Build Status][GitHubActionBadge] [![CocoaPods Version][CocoaPodsVersionBadge]][CocoaPodsVersionLink] [![Swift5 compatible][Swift5Badge]][Swift5Link] [![Platform][PlatformBadge]][PlatformLink] [![Carthage compatible][CartagheBadge]][CarthageLink] [![Join the chat at https://gitter.im/stephencelis/SQLite.swift][GitterBadge]][GitterLink]
 
 A type-safe, [Swift][]-language layer over [SQLite3][].
 
@@ -283,8 +283,7 @@ Looking for something else? Try another Swift wrapper (or [FMDB][]):
 [SQLite3]: http://www.sqlite.org
 [SQLite.swift]: https://github.com/stephencelis/SQLite.swift
 
-[TravisBadge]: https://img.shields.io/travis/stephencelis/SQLite.swift/master.svg?style=flat
-[TravisLink]: https://travis-ci.org/stephencelis/SQLite.swift
+[GitHubActionBadge]: https://img.shields.io/github/workflow/status/stephencelis/SQLite.swift/Build%20and%20test
 
 [CocoaPodsVersionBadge]: https://cocoapod-badges.herokuapp.com/v/SQLite.swift/badge.png
 [CocoaPodsVersionLink]: http://cocoadocs.org/docsets/SQLite.swift
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 92795299..1db9c2b7 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -271,7 +271,6 @@
 		EE247B451C3F3ED000AE3E12 /* SQLiteTests Mac.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SQLiteTests Mac.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247B771C3F40D700AE3E12 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
 		EE247B8B1C3F820300AE3E12 /* CONTRIBUTING.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CONTRIBUTING.md; sourceTree = "<group>"; };
-		EE247B8C1C3F821200AE3E12 /* .travis.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = .travis.yml; sourceTree = "<group>"; };
 		EE247B8D1C3F821200AE3E12 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
 		EE247B8F1C3F822500AE3E12 /* Index.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Index.md; sourceTree = "<group>"; };
 		EE247B911C3F822500AE3E12 /* installation@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "installation@2x.png"; sourceTree = "<group>"; };
@@ -473,7 +472,6 @@
 				EE247B771C3F40D700AE3E12 /* README.md */,
 				EE247B8B1C3F820300AE3E12 /* CONTRIBUTING.md */,
 				EE247B931C3F826100AE3E12 /* SQLite.swift.podspec */,
-				EE247B8C1C3F821200AE3E12 /* .travis.yml */,
 				EE247B8D1C3F821200AE3E12 /* Makefile */,
 				EE9180931C46EA210038162A /* libsqlite3.tbd */,
 				EE9180911C46E9D30038162A /* libsqlite3.tbd */,

From 65b0989dbefdb1163ac419d7121a176335a90a85 Mon Sep 17 00:00:00 2001
From: Jake-B <jake-b@users.noreply.github.com>
Date: Wed, 18 Aug 2021 14:56:18 -0400
Subject: [PATCH 387/685] Updated documentation for `===` and `!==` operators.

---
 Documentation/Index.md | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index c6c54437..76a69206 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -955,8 +955,10 @@ equate or compare different types will prevent compilation.
 | `~=`  | `(Interval, Comparable) -> Bool` | `BETWEEN`      |
 | `&&`  | `Bool -> Bool`                   | `AND`          |
 | `\|\|`| `Bool -> Bool`                   | `OR`           |
+| `===` | `Equatable -> Bool`              | `IS`           |
+| `!==` | `Equatable -> Bool`              | `IS NOT`       |
 
-> *When comparing against `nil`, SQLite.swift will use `IS` and `IS NOT`
+> * When comparing against `nil`, SQLite.swift will use `IS` and `IS NOT`
 > accordingly.
 
 

From b7302f6ed19b1994ef9d68882d1cb447be8fd238 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Wed, 18 Aug 2021 23:21:01 +0200
Subject: [PATCH 388/685] SPM as first installation method

---
 README.md | 42 +++++++++++++++++++++---------------------
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/README.md b/README.md
index 009167b0..81fb4b5d 100644
--- a/README.md
+++ b/README.md
@@ -126,6 +126,27 @@ and the [companion repository][SQLiteDataAccessLayer2].
 
 > _Note:_ Version 0.11.6 and later requires Swift 5 (and [Xcode](https://developer.apple.com/xcode/downloads/) 10.2) or greater. Version 0.11.5 requires Swift 4.2 (and [Xcode](https://developer.apple.com/xcode/downloads/) 10.1) or greater.
 
+### Swift Package Manager
+
+The [Swift Package Manager][] is a tool for managing the distribution of
+Swift code.
+
+1. Add the following to your `Package.swift` file:
+
+  ```swift
+  dependencies: [
+      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.12.0")
+  ]
+  ```
+
+2. Build your project:
+
+  ```sh
+  $ swift build
+  ```
+
+[Swift Package Manager]: https://swift.org/package-manager
+
 ### Carthage
 
 [Carthage][] is a simple, decentralized dependency manager for Cocoa. To
@@ -177,27 +198,6 @@ SQLite.swift with CocoaPods:
 [CocoaPods]: https://cocoapods.org
 [CocoaPods Installation]: https://guides.cocoapods.org/using/getting-started.html#getting-started
 
-### Swift Package Manager
-
-The [Swift Package Manager][] is a tool for managing the distribution of
-Swift code.
-
-1. Add the following to your `Package.swift` file:
-
-  ```swift
-  dependencies: [
-      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.12.0")
-  ]
-  ```
-
-2. Build your project:
-
-  ```sh
-  $ swift build
-  ```
-
-[Swift Package Manager]: https://swift.org/package-manager
-
 ### Manual
 
 To install SQLite.swift as an Xcode sub-project:

From c5b7258ac175751b966a25bc6ba06f1be4ae2caa Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Thu, 19 Aug 2021 00:03:18 +0200
Subject: [PATCH 389/685] Fixing missing date in upsert test

---
 Tests/SQLiteTests/QueryTests.swift | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index 9a19945f..fc47ab27 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -280,10 +280,10 @@ class QueryTests : XCTestCase {
     func test_upsert_encodable() throws {
         let emails = Table("emails")
         let string = Expression<String>("string")
-        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil)
+        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
         let insert = try emails.upsert(value, onConflictOf: string)
         AssertSQL(
-            "INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\") VALUES (1, '2', 1, 3.0, 4.0) ON CONFLICT (\"string\") DO UPDATE SET \"int\" = \"excluded\".\"int\", \"bool\" = \"excluded\".\"bool\", \"float\" = \"excluded\".\"float\", \"double\" = \"excluded\".\"double\"",
+            "INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\") VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000') ON CONFLICT (\"string\") DO UPDATE SET \"int\" = \"excluded\".\"int\", \"bool\" = \"excluded\".\"bool\", \"float\" = \"excluded\".\"float\", \"double\" = \"excluded\".\"double\"",
             insert
         )
     }

From 5c49d0ed90279d5f90a22997c95ca4c6bfb5bb9f Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Thu, 19 Aug 2021 00:09:34 +0200
Subject: [PATCH 390/685] Oups

---
 Tests/SQLiteTests/QueryTests.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index fc47ab27..9b845a97 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -283,7 +283,7 @@ class QueryTests : XCTestCase {
         let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
         let insert = try emails.upsert(value, onConflictOf: string)
         AssertSQL(
-            "INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\") VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000') ON CONFLICT (\"string\") DO UPDATE SET \"int\" = \"excluded\".\"int\", \"bool\" = \"excluded\".\"bool\", \"float\" = \"excluded\".\"float\", \"double\" = \"excluded\".\"double\"",
+            "INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\") VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000') ON CONFLICT (\"string\") DO UPDATE SET \"int\" = \"excluded\".\"int\", \"bool\" = \"excluded\".\"bool\", \"float\" = \"excluded\".\"float\", \"double\" = \"excluded\".\"double\", \"date\" = \"excluded\".\"date\"",
             insert
         )
     }

From b20d6baca11636ac28de51aa797312811d50c2b5 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 19 Aug 2021 00:11:54 +0200
Subject: [PATCH 391/685] Fix spm package structure

---
 Package.swift                                 | 78 +++++++++----------
 SQLite.xcodeproj/project.pbxproj              | 20 ++---
 Sources/SQLiteObjc/{ => include}/SQLiteObjc.h |  0
 3 files changed, 48 insertions(+), 50 deletions(-)
 rename Sources/SQLiteObjc/{ => include}/SQLiteObjc.h (100%)

diff --git a/Package.swift b/Package.swift
index 73339b7b..7522fa45 100644
--- a/Package.swift
+++ b/Package.swift
@@ -4,52 +4,50 @@ import PackageDescription
 let package = Package(
     name: "SQLite.swift",
     products: [
-			.library(
-				name: "SQLite", 
-				targets: ["SQLite"]
-			)
-		],
+        .library(
+            name: "SQLite",
+            targets: ["SQLite"]
+        )
+    ],
     targets: [
         .target(
-					name: "SQLite", 
-					dependencies: ["SQLiteObjc"],
-					exclude: [
-						"Info.plist"
-					]
-				),
+            name: "SQLite",
+            dependencies: ["SQLiteObjc"],
+            exclude: [
+                "Info.plist"
+            ]
+        ),
         .target(
-					name: "SQLiteObjc",
-					dependencies: [],
-					exclude: [
-						"SQLiteObjc.h",
-						"fts3_tokenizer.h",
-						"include/README.md"
-					]
-				),
+            name: "SQLiteObjc",
+            dependencies: [],
+            exclude: [
+                "fts3_tokenizer.h"
+            ]
+        ),
         .testTarget(
-					name: "SQLiteTests", 
-					dependencies: [
-						"SQLite"
-					], 
-					path: "Tests/SQLiteTests",
-					exclude: [
-						"Info.plist"
-					],
-					resources: [
-						.copy("fixtures/encrypted-3.x.sqlite"),
-						.copy("fixtures/encrypted-4.x.sqlite")
-					]
-				)
+            name: "SQLiteTests",
+            dependencies: [
+                "SQLite"
+            ],
+            path: "Tests/SQLiteTests",
+            exclude: [
+                "Info.plist"
+            ],
+            resources: [
+                .copy("fixtures/encrypted-3.x.sqlite"),
+                .copy("fixtures/encrypted-4.x.sqlite")
+            ]
+        )
     ]
 )
 
 #if os(Linux)
-    package.dependencies = [.package(url: "https://github.com/stephencelis/CSQLite.git", from: "0.0.3")]
-    package.targets = [
-        .target(name: "SQLite", exclude: ["Extensions/FTS4.swift", "Extensions/FTS5.swift"]),
-        .testTarget(name: "SQLiteTests", dependencies: ["SQLite"], path: "Tests/SQLiteTests", exclude: [
-            "FTS4Tests.swift",
-            "FTS5Tests.swift"
-        ])
-    ]
+package.dependencies = [.package(url: "https://github.com/stephencelis/CSQLite.git", from: "0.0.3")]
+package.targets = [
+    .target(name: "SQLite", exclude: ["Extensions/FTS4.swift", "Extensions/FTS5.swift"]),
+    .testTarget(name: "SQLiteTests", dependencies: ["SQLite"], path: "Tests/SQLiteTests", exclude: [
+        "FTS4Tests.swift",
+        "FTS5Tests.swift"
+    ])
+]
 #endif
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 1b5bb0f4..a730284d 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -11,7 +11,6 @@
 		03A65E721C6BB2D30062603F /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		03A65E731C6BB2D80062603F /* Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF71C3F06E900AE3E12 /* Foundation.swift */; };
 		03A65E741C6BB2DA0062603F /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF81C3F06E900AE3E12 /* Helpers.swift */; };
-		03A65E751C6BB2DF0062603F /* SQLiteObjc.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808D1C46E5230038162A /* SQLiteObjc.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		03A65E761C6BB2E60062603F /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
 		03A65E771C6BB2E60062603F /* Connection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEF1C3F06E900AE3E12 /* Connection.swift */; };
 		03A65E781C6BB2EA0062603F /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */; };
@@ -101,9 +100,12 @@
 		3D67B3F71DB246D700A4F4C6 /* Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF71C3F06E900AE3E12 /* Foundation.swift */; };
 		3D67B3F81DB246D700A4F4C6 /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF81C3F06E900AE3E12 /* Helpers.swift */; };
 		3D67B3F91DB246E700A4F4C6 /* SQLiteObjc.m in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF11C3F06E900AE3E12 /* SQLiteObjc.m */; };
-		3D67B3FB1DB2470600A4F4C6 /* SQLiteObjc.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808D1C46E5230038162A /* SQLiteObjc.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		3D67B3FC1DB2471B00A4F4C6 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		3D67B3FD1DB2472D00A4F4C6 /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */; };
+		3DDC112F26CDBA0200CE369F /* SQLiteObjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 3DDC112E26CDBA0200CE369F /* SQLiteObjc.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3DDC113626CDBE1900CE369F /* SQLiteObjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 3DDC112E26CDBA0200CE369F /* SQLiteObjc.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3DDC113726CDBE1900CE369F /* SQLiteObjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 3DDC112E26CDBA0200CE369F /* SQLiteObjc.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3DDC113826CDBE1C00CE369F /* SQLiteObjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 3DDC112E26CDBA0200CE369F /* SQLiteObjc.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		49EB68C41F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
 		49EB68C51F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
 		49EB68C61F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
@@ -183,8 +185,6 @@
 		EE247B731C3F3FEC00AE3E12 /* Query.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B001C3F06E900AE3E12 /* Query.swift */; };
 		EE247B741C3F3FEC00AE3E12 /* Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B011C3F06E900AE3E12 /* Schema.swift */; };
 		EE247B751C3F3FEC00AE3E12 /* Setter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B021C3F06E900AE3E12 /* Setter.swift */; };
-		EE91808E1C46E5230038162A /* SQLiteObjc.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808D1C46E5230038162A /* SQLiteObjc.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		EE91808F1C46E76D0038162A /* SQLiteObjc.h in Headers */ = {isa = PBXBuildFile; fileRef = EE91808D1C46E5230038162A /* SQLiteObjc.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		EE9180941C46EA210038162A /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = EE9180931C46EA210038162A /* libsqlite3.tbd */; };
 		EE9180951C46EBCC0038162A /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = EE9180911C46E9D30038162A /* libsqlite3.tbd */; };
 /* End PBXBuildFile section */
@@ -229,6 +229,7 @@
 		19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAndTimeFunctions.swift; sourceTree = "<group>"; };
 		19A17E2695737FAB5D6086E3 /* fixtures */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = folder; path = fixtures; sourceTree = "<group>"; };
 		3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.0.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
+		3DDC112E26CDBA0200CE369F /* SQLiteObjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SQLiteObjc.h; path = ../SQLiteObjc/include/SQLiteObjc.h; sourceTree = "<group>"; };
 		49EB68C31F7B3CB400D89D40 /* Coding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coding.swift; sourceTree = "<group>"; };
 		A121AC451CA35C79005A31D1 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		D4DB368A20C09C9B00D5A58E /* SelectTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectTests.swift; sourceTree = "<group>"; };
@@ -280,7 +281,6 @@
 		EE247B911C3F822500AE3E12 /* installation@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "installation@2x.png"; sourceTree = "<group>"; };
 		EE247B921C3F822600AE3E12 /* playground@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "playground@2x.png"; sourceTree = "<group>"; };
 		EE247B931C3F826100AE3E12 /* SQLite.swift.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; path = SQLite.swift.podspec; sourceTree = "<group>"; };
-		EE91808D1C46E5230038162A /* SQLiteObjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SQLiteObjc.h; path = ../../SQLiteObjc/SQLiteObjc.h; sourceTree = "<group>"; };
 		EE9180911C46E9D30038162A /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
 		EE9180931C46EA210038162A /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; };
 /* End PBXFileReference section */
@@ -384,6 +384,7 @@
 			isa = PBXGroup;
 			children = (
 				EE247AD61C3F04ED00AE3E12 /* SQLite.h */,
+				3DDC112E26CDBA0200CE369F /* SQLiteObjc.h */,
 				EE247AF71C3F06E900AE3E12 /* Foundation.swift */,
 				EE247AF81C3F06E900AE3E12 /* Helpers.swift */,
 				EE247AD81C3F04ED00AE3E12 /* Info.plist */,
@@ -430,7 +431,6 @@
 		EE247AED1C3F06E900AE3E12 /* Core */ = {
 			isa = PBXGroup;
 			children = (
-				EE91808D1C46E5230038162A /* SQLiteObjc.h */,
 				EE247AEE1C3F06E900AE3E12 /* Blob.swift */,
 				EE247AEF1C3F06E900AE3E12 /* Connection.swift */,
 				EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */,
@@ -512,7 +512,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				03A65E781C6BB2EA0062603F /* fts3_tokenizer.h in Headers */,
-				03A65E751C6BB2DF0062603F /* SQLiteObjc.h in Headers */,
+				3DDC113626CDBE1900CE369F /* SQLiteObjc.h in Headers */,
 				03A65E721C6BB2D30062603F /* SQLite.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -521,8 +521,8 @@
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				3D67B3FB1DB2470600A4F4C6 /* SQLiteObjc.h in Headers */,
 				3D67B3FC1DB2471B00A4F4C6 /* SQLite.h in Headers */,
+				3DDC113726CDBE1900CE369F /* SQLiteObjc.h in Headers */,
 				3D67B3FD1DB2472D00A4F4C6 /* fts3_tokenizer.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -531,8 +531,8 @@
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				EE91808E1C46E5230038162A /* SQLiteObjc.h in Headers */,
 				EE247B051C3F06E900AE3E12 /* fts3_tokenizer.h in Headers */,
+				3DDC113826CDBE1C00CE369F /* SQLiteObjc.h in Headers */,
 				EE247AD71C3F04ED00AE3E12 /* SQLite.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -542,8 +542,8 @@
 			buildActionMask = 2147483647;
 			files = (
 				EE247B671C3F3FEC00AE3E12 /* fts3_tokenizer.h in Headers */,
+				3DDC112F26CDBA0200CE369F /* SQLiteObjc.h in Headers */,
 				EE247B621C3F3FDB00AE3E12 /* SQLite.h in Headers */,
-				EE91808F1C46E76D0038162A /* SQLiteObjc.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/Sources/SQLiteObjc/SQLiteObjc.h b/Sources/SQLiteObjc/include/SQLiteObjc.h
similarity index 100%
rename from Sources/SQLiteObjc/SQLiteObjc.h
rename to Sources/SQLiteObjc/include/SQLiteObjc.h

From 4ddcb1cc6fdec3e4dd24d89e35a1f31630d81632 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 19 Aug 2021 00:12:59 +0200
Subject: [PATCH 392/685] Fix query tests

---
 Tests/SQLiteTests/QueryTests.swift | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index 9b845a97..29cbd7e4 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -397,7 +397,7 @@ class QueryIntegrationTests : SQLiteTestCase {
     let id = Expression<Int64>("id")
     let email = Expression<String>("email")
     let age = Expression<Int>("age")
-    
+
     override func setUp() {
         super.setUp()
 
@@ -509,16 +509,16 @@ class QueryIntegrationTests : SQLiteTestCase {
         let fetchAge = { () throws -> Int? in
             return try self.db.pluck(self.users.filter(self.email == "alice@example.com")).flatMap { $0[self.age] }
         }
-        
+
         let id = try db.run(users.upsert(email <- "alice@example.com", age <- 30, onConflictOf: email))
         XCTAssertEqual(1, id)
         XCTAssertEqual(30, try fetchAge())
-        
+
         let nextId = try db.run(users.upsert(email <- "alice@example.com", age <- 42, onConflictOf: email))
         XCTAssertEqual(1, nextId)
         XCTAssertEqual(42, try fetchAge())
     }
-    
+
     func test_update() {
         let changes = try! db.run(users.update(email <- "alice@example.com"))
         XCTAssertEqual(0, changes)
@@ -528,24 +528,24 @@ class QueryIntegrationTests : SQLiteTestCase {
         let changes = try! db.run(users.delete())
         XCTAssertEqual(0, changes)
     }
-    
+
     func test_union() throws {
         let expectedIDs = [
             try db.run(users.insert(email <- "alice@example.com")),
             try db.run(users.insert(email <- "sally@example.com"))
         ]
-        
+
         let query1 = users.filter(email == "alice@example.com")
         let query2 = users.filter(email == "sally@example.com")
-        
+
         let actualIDs = try db.prepare(query1.union(query2)).map { $0[id] }
         XCTAssertEqual(expectedIDs, actualIDs)
-        
+
         let query3 = users.select(users[*], Expression<Int>(literal: "1 AS weight")).filter(email == "sally@example.com")
         let query4 = users.select(users[*], Expression<Int>(literal: "2 AS weight")).filter(email == "alice@example.com")
-        
+
         print(query3.union(query4).order(Expression<Int>(literal: "weight")).asSQL())
-        
+
         let orderedIDs = try db.prepare(query3.union(query4).order(Expression<Int>(literal: "weight"), email)).map { $0[id] }
         XCTAssertEqual(Array(expectedIDs.reversed()), orderedIDs)
     }

From 75a177a688ada617cef0efbc910f2fc3bdfbd1ff Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Sat, 21 Aug 2021 18:03:32 +0200
Subject: [PATCH 393/685] Fixed codable insert many

---
 Tests/SQLiteTests/QueryTests.swift | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index 9e6e9f7e..79e6871e 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -310,12 +310,12 @@ class QueryTests : XCTestCase {
 
     func test_insert_many_encodable() throws {
         let emails = Table("emails")
-        let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, optional: nil, sub: nil)
-        let value2 = TestCodable(int: 2, string: "3", bool: true, float: 3, double: 5, optional: nil, sub: nil)
-        let value3 = TestCodable(int: 3, string: "4", bool: true, float: 3, double: 6, optional: nil, sub: nil)
+        let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+        let value2 = TestCodable(int: 2, string: "3", bool: true, float: 3, double: 5, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+        let value3 = TestCodable(int: 3, string: "4", bool: true, float: 3, double: 6, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
         let insert = try emails.insertMany([value1, value2, value3])
         AssertSQL(
-            "INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\") VALUES (1, '2', 1, 3.0, 4.0), (2, '3', 1, 3.0, 5.0), (3, '4', 1, 3.0, 6.0)",
+            "INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\") VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000'), (2, '3', 1, 3.0, 5.0, '1970-01-01T00:00:00.000'), (3, '4', 1, 3.0, 6.0, '1970-01-01T00:00:00.000')",
             insert
         )
     }

From 449edebfd6c91c2dd376ee61359b4c4b65032032 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Sat, 21 Aug 2021 19:24:45 +0200
Subject: [PATCH 394/685] Updating to 0.13.0

---
 .swift-version       | 2 +-
 SQLite.swift.podspec | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/.swift-version b/.swift-version
index bf77d549..819e07a2 100644
--- a/.swift-version
+++ b/.swift-version
@@ -1 +1 @@
-4.2
+5.0
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index bcefa5fe..499012c1 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.12.2"
+  s.version          = "0.13.0"
   s.summary          = "A type-safe, Swift-language layer over SQLite3 for iOS and macOS."
 
   s.description      = <<-DESC
@@ -16,12 +16,12 @@ Pod::Spec.new do |s|
 
   s.module_name      = 'SQLite'
   s.default_subspec  = 'standard'
-  s.swift_versions = ['4.2', '5']
+  s.swift_versions = ['5']
   
   
   ios_deployment_target = '9.0'
   tvos_deployment_target = '9.1'
-  osx_deployment_target = '10.10'
+  osx_deployment_target = '10.15'
   watchos_deployment_target = '3.0'
   
   s.ios.deployment_target = ios_deployment_target

From 8096e9b9c5cc694f373d2176f96889d3e4afe053 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Sat, 21 Aug 2021 20:22:10 +0200
Subject: [PATCH 395/685] Deleted .swift-version

---
 .swift-version | 1 -
 1 file changed, 1 deletion(-)
 delete mode 100644 .swift-version

diff --git a/.swift-version b/.swift-version
deleted file mode 100644
index 819e07a2..00000000
--- a/.swift-version
+++ /dev/null
@@ -1 +0,0 @@
-5.0

From 31f667f71f5e6b401a4ec2391d8e44d835e5d7fa Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 22 Aug 2021 03:13:48 +0200
Subject: [PATCH 396/685] Pod lint fixes

---
 Sources/SQLite/Core/Connection.swift | 82 +++++++++++++---------------
 Tests/SQLiteTests/QueryTests.swift   | 15 ++++-
 2 files changed, 50 insertions(+), 47 deletions(-)

diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 1bbf7f73..f4a9e8cb 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -415,17 +415,17 @@ public final class Connection {
     ///
     ///       db.trace { SQL in print(SQL) }
     public func trace(_ callback: ((String) -> Void)?) {
-        #if SQLITE_SWIFT_SQLCIPHER || os(Linux)
+        if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) {
+            trace_v2(callback)
+        } else {
             trace_v1(callback)
-        #else
-            if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) {
-                trace_v2(callback)
-            } else {
-                trace_v1(callback)
-            }
-        #endif
+        }
     }
 
+    @available(OSX, deprecated: 10.2)
+    @available(iOS, deprecated: 10.0)
+    @available(watchOS, deprecated: 3.0)
+    @available(tvOS, deprecated: 10.0)
     fileprivate func trace_v1(_ callback: ((String) -> Void)?) {
         guard let callback = callback else {
             sqlite3_trace(handle, nil /* xCallback */, nil /* pCtx */)
@@ -447,8 +447,36 @@ public final class Connection {
         trace = box
     }
 
+    @available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *)
+    fileprivate func trace_v2(_ callback: ((String) -> Void)?) {
+        guard let callback = callback else {
+            // If the X callback is NULL or if the M mask is zero, then tracing is disabled.
+            sqlite3_trace_v2(handle, 0 /* mask */, nil /* xCallback */, nil /* pCtx */)
+            trace = nil
+            return
+        }
 
-
+        let box: Trace = { (pointer: UnsafeRawPointer) in
+            callback(String(cString: pointer.assumingMemoryBound(to: UInt8.self)))
+        }
+        sqlite3_trace_v2(handle, UInt32(SQLITE_TRACE_STMT) /* mask */,
+             {
+                 // A trace callback is invoked with four arguments: callback(T,C,P,X).
+                 // The T argument is one of the SQLITE_TRACE constants to indicate why the
+                 // callback was invoked. The C argument is a copy of the context pointer.
+                 // The P and X arguments are pointers whose meanings depend on T.
+                 (T: UInt32, C: UnsafeMutableRawPointer?, P: UnsafeMutableRawPointer?, X: UnsafeMutableRawPointer?) in
+                 if let P = P,
+                    let expandedSQL = sqlite3_expanded_sql(OpaquePointer(P)) {
+                     unsafeBitCast(C, to: Trace.self)(expandedSQL)
+                     sqlite3_free(expandedSQL)
+                 }
+                 return Int32(0) // currently ignored
+             },
+             unsafeBitCast(box, to: UnsafeMutableRawPointer.self) /* pCtx */
+        )
+        trace = box
+    }
 
     fileprivate typealias Trace = @convention(block) (UnsafeRawPointer) -> Void
     fileprivate var trace: Trace?
@@ -712,39 +740,3 @@ extension Result : CustomStringConvertible {
         }
     }
 }
-
-#if !SQLITE_SWIFT_SQLCIPHER && !os(Linux)
-@available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *)
-extension Connection {
-    fileprivate func trace_v2(_ callback: ((String) -> Void)?) {
-        guard let callback = callback else {
-            // If the X callback is NULL or if the M mask is zero, then tracing is disabled.
-            sqlite3_trace_v2(handle, 0 /* mask */, nil /* xCallback */, nil /* pCtx */)
-            trace = nil
-            return
-        }
-
-        let box: Trace = { (pointer: UnsafeRawPointer) in
-            callback(String(cString: pointer.assumingMemoryBound(to: UInt8.self)))
-        }
-        sqlite3_trace_v2(handle,
-            UInt32(SQLITE_TRACE_STMT) /* mask */,
-            {
-                // A trace callback is invoked with four arguments: callback(T,C,P,X).
-                // The T argument is one of the SQLITE_TRACE constants to indicate why the
-                // callback was invoked. The C argument is a copy of the context pointer.
-                // The P and X arguments are pointers whose meanings depend on T.
-                (T: UInt32, C: UnsafeMutableRawPointer?, P: UnsafeMutableRawPointer?, X: UnsafeMutableRawPointer?) in
-                    if let P = P,
-                       let expandedSQL = sqlite3_expanded_sql(OpaquePointer(P)) {
-                        unsafeBitCast(C, to: Trace.self)(expandedSQL)
-                        sqlite3_free(expandedSQL)
-                    }
-                    return Int32(0) // currently ignored
-            },
-            unsafeBitCast(box, to: UnsafeMutableRawPointer.self) /* pCtx */
-        )
-        trace = box
-    }
-}
-#endif
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index 79e6871e..041b7d0c 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -541,10 +541,11 @@ class QueryIntegrationTests : SQLiteTestCase {
         let id = try! db.run(users.insertMany([[email <- "alice@example.com"], [email <- "geoff@example.com"]]))
         XCTAssertEqual(2, id)
     }
-    
+
     func test_upsert() throws {
+        guard db.satisfiesMinimumVersion(minor: 24) else { return }
         let fetchAge = { () throws -> Int? in
-            return try self.db.pluck(self.users.filter(self.email == "alice@example.com")).flatMap { $0[self.age] }
+            try self.db.pluck(self.users.filter(self.email == "alice@example.com")).flatMap { $0[self.age] }
         }
 
         let id = try db.run(users.upsert(email <- "alice@example.com", age <- 30, onConflictOf: email))
@@ -613,3 +614,13 @@ class QueryIntegrationTests : SQLiteTestCase {
         }
     }
 }
+
+private extension Connection {
+    func satisfiesMinimumVersion(minor: Int, patch: Int = 0) -> Bool {
+        guard let version = try? scalar("SELECT sqlite_version()") as? String else { return false }
+        let components = version.split(separator: ".", maxSplits: 3).compactMap { Int($0) }
+        guard components.count == 3 else { return false }
+
+        return components[1] >= minor && components[2] >= patch
+    }
+}

From af4801483adf9fa26fa4e80df120b1913b380652 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Sun, 22 Aug 2021 17:11:01 +0200
Subject: [PATCH 397/685] Adding a `vacuum()` fonction to `Connection`

---
 Sources/SQLite/Core/Connection.swift    | 11 +++++++++++
 Tests/SQLiteTests/ConnectionTests.swift |  4 ++++
 2 files changed, 15 insertions(+)

diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index f4a9e8cb..8fd07cc1 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -252,6 +252,17 @@ public final class Connection {
     @discardableResult public func run(_ statement: String, _ bindings: [String: Binding?]) throws -> Statement {
         return try prepare(statement).run(bindings)
     }
+    
+    // MARK: - VACUUM
+    
+    /// Run a vacuum on the database
+    ///
+    /// - Throws: `Result.Error` if query execution fails.
+    ///
+    /// - Returns: The statement.
+    @discardableResult public func vacuum() throws -> Statement {
+        return try run("VACUUM")
+    }
 
     // MARK: - Scalar
 
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index fdfc9637..a05cceb5 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -111,6 +111,10 @@ class ConnectionTests : SQLiteTestCase {
         try! db.run("SELECT * FROM users WHERE admin = $admin", ["$admin": 0])
         AssertSQL("SELECT * FROM users WHERE admin = 0", 4)
     }
+    
+    func test_vacuum() {
+        try! db.vacuum()
+    }
 
     func test_scalar_preparesRunsAndReturnsScalarValues() {
         XCTAssertEqual(0, try! db.scalar("SELECT count(*) FROM users WHERE admin = 0") as? Int64)

From e48d1469f7fda8175de4abdc45638a25e3409f6b Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Sun, 22 Aug 2021 17:28:37 +0200
Subject: [PATCH 398/685] SPM as first installation method

---
 Documentation/Index.md | 51 +++++++++++++++++++++---------------------
 1 file changed, 25 insertions(+), 26 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index bc8bb52e..14b29b37 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1,9 +1,9 @@
 # SQLite.swift Documentation
 
   - [Installation](#installation)
+    - [Swift Package Manager](#swift-package-manager)
     - [Carthage](#carthage)
     - [CocoaPods](#cocoapods)
-    - [Swift Package Manager](#swift-package-manager)
     - [Manual](#manual)
   - [Getting Started](#getting-started)
     - [Connecting to a Database](#connecting-to-a-database)
@@ -71,6 +71,30 @@
 > _Note:_ SQLite.swift requires Swift 5 (and
 > [Xcode 10.2](https://developer.apple.com/xcode/downloads/)) or greater.
 
+### Swift Package Manager
+
+The [Swift Package Manager][] is a tool for managing the distribution of
+Swift code. It’s integrated with the Swift build system to automate the
+process of downloading, compiling, and linking dependencies.
+
+It is the recommended approach for using SQLite.swift in OSX CLI
+applications.
+
+ 1. Add the following to your `Package.swift` file:
+
+  ```swift
+  dependencies: [
+    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.12.0")
+  ]
+  ```
+
+ 2. Build your project:
+
+  ```sh
+  $ swift build
+  ```
+
+[Swift Package Manager]: https://swift.org/package-manager
 
 ### Carthage
 
@@ -169,31 +193,6 @@ try db.rekey("another secret")
 [sqlite3pod]: https://github.com/clemensg/sqlite3pod
 [SQLCipher]: https://www.zetetic.net/sqlcipher/
 
-### Swift Package Manager
-
-The [Swift Package Manager][] is a tool for managing the distribution of
-Swift code. It’s integrated with the Swift build system to automate the
-process of downloading, compiling, and linking dependencies.
-
-It is the recommended approach for using SQLite.swift in OSX CLI
-applications.
-
- 1. Add the following to your `Package.swift` file:
-
-  ```swift
-  dependencies: [
-    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.12.0")
-  ]
-  ```
-
- 2. Build your project:
-
-  ```sh
-  $ swift build
-  ```
-
-[Swift Package Manager]: https://swift.org/package-manager
-
 ### Manual
 
 To install SQLite.swift as an Xcode sub-project:

From c648408e467e84d9d2e191fe354080fde23b980c Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 22 Aug 2021 21:14:27 +0200
Subject: [PATCH 399/685] Ensure file can be cleaned up

---
 Tests/SQLiteTests/CipherTests.swift | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Tests/SQLiteTests/CipherTests.swift b/Tests/SQLiteTests/CipherTests.swift
index abecffba..a27ac17d 100644
--- a/Tests/SQLiteTests/CipherTests.swift
+++ b/Tests/SQLiteTests/CipherTests.swift
@@ -88,6 +88,11 @@ class CipherTests: XCTestCase {
         try! FileManager.default.setAttributes([FileAttributeKey.immutable : 1], ofItemAtPath: encryptedFile)
         XCTAssertFalse(FileManager.default.isWritableFile(atPath: encryptedFile))
 
+        defer {
+            // ensure file can be cleaned up afterwards
+            try! FileManager.default.setAttributes([FileAttributeKey.immutable : 0], ofItemAtPath: encryptedFile)
+        }
+
         let conn = try! Connection(encryptedFile)
         try! conn.key("sqlcipher-test")
         XCTAssertEqual(1, try! conn.scalar("SELECT count(*) FROM foo") as? Int64)

From 368c873e75cc3de9e39464ff82a09fc65649607e Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 22 Aug 2021 21:42:01 +0200
Subject: [PATCH 400/685] Update CHANGELOG

---
 CHANGELOG.md | 25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1f29afeb..465438bc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,12 +1,22 @@
-0.12.3 (18-05-2021), [diff][diff-0.12.2]
+0.13.0 (22-08-2021), [diff][diff-0.13.0]
 ========================================
 
-* Swift 5.3 support.
-* Xcode 12.5 support.
-* Bumps minimum deployment versions.
-* Fixes up Package.swift to build SQLiteObjc module.
+* Swift 5.3 support
+* Xcode 12.5 support
+* Bumps minimum deployment versions
+* Fixes up Package.swift to build SQLiteObjc module
 
-0.11.6 (xxx), [diff][diff-0.11.6]
+0.12.1, 0.12.2 (21-06-2019) [diff][diff-0.12.2]
+========================================
+
+* CocoaPods modular headers support
+
+0.12.0 (24-04-2019) [diff][diff-0.12.0]
+========================================
+
+* Version with Swift 5 Support
+
+0.11.6 (19-04-2019), [diff][diff-0.11.6]
 ========================================
 
 * Swift 4.2, SQLCipher 4.x ([#866][])
@@ -71,6 +81,9 @@
 [diff-0.11.4]: https://github.com/stephencelis/SQLite.swift/compare/0.11.3...0.11.4
 [diff-0.11.5]: https://github.com/stephencelis/SQLite.swift/compare/0.11.4...0.11.5
 [diff-0.11.6]: https://github.com/stephencelis/SQLite.swift/compare/0.11.5...0.11.6
+[diff-0.12.0]: https://github.com/stephencelis/SQLite.swift/compare/0.11.6...0.12.0
+[diff-0.12.2]: https://github.com/stephencelis/SQLite.swift/compare/0.12.0...0.12.2
+[diff-0.13.0]: https://github.com/stephencelis/SQLite.swift/compare/0.12.2...0.13.0
 
 [#142]: https://github.com/stephencelis/SQLite.swift/issues/142
 [#315]: https://github.com/stephencelis/SQLite.swift/issues/315

From d27a078f24164c58827f3adba612415b10016190 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 22 Aug 2021 21:53:16 +0200
Subject: [PATCH 401/685] Update version

---
 README.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index 81fb4b5d..98a625c4 100644
--- a/README.md
+++ b/README.md
@@ -135,7 +135,7 @@ Swift code.
 
   ```swift
   dependencies: [
-      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.12.0")
+      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.13.0")
   ]
   ```
 
@@ -157,7 +157,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.12.0
+    github "stephencelis/SQLite.swift" ~> 0.13.0
     ```
 
  3. Run `carthage update` and
@@ -189,7 +189,7 @@ SQLite.swift with CocoaPods:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.12.0'
+        pod 'SQLite.swift', '~> 0.13.0'
     end
     ```
 

From 9af51e2edf491c0ea632e369a6566e09b65aa333 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 22 Aug 2021 22:09:47 +0200
Subject: [PATCH 402/685] Bump version

---
 Documentation/Index.md           | 12 ++++++------
 SQLite.xcodeproj/project.pbxproj |  4 ++--
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 14b29b37..21b1c995 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -84,7 +84,7 @@ applications.
 
   ```swift
   dependencies: [
-    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.12.0")
+    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.13.0")
   ]
   ```
 
@@ -105,7 +105,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.12.0
+    github "stephencelis/SQLite.swift" ~> 0.13.0
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -135,7 +135,7 @@ install SQLite.swift with Carthage:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.12.0'
+        pod 'SQLite.swift', '~> 0.13.0'
     end
     ```
 
@@ -149,7 +149,7 @@ with the OS you can require the `standalone` subspec:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.12.0'
+  pod 'SQLite.swift/standalone', '~> 0.13.0'
 end
 ```
 
@@ -159,7 +159,7 @@ dependency to sqlite3 or one of its subspecs:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.12.0'
+  pod 'SQLite.swift/standalone', '~> 0.13.0'
   pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
 end
 ```
@@ -173,7 +173,7 @@ If you want to use [SQLCipher][] with SQLite.swift you can require the
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/SQLCipher', '~> 0.12.0'
+  pod 'SQLite.swift/SQLCipher', '~> 0.13.0'
 end
 ```
 
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index a730284d..3056bd74 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1265,7 +1265,7 @@
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
-				MARKETING_VERSION = 0.12.3;
+				MARKETING_VERSION = 0.13.0;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
@@ -1287,7 +1287,7 @@
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
-				MARKETING_VERSION = 0.12.3;
+				MARKETING_VERSION = 0.13.0;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;

From 474f966e1159fb7b14e9ca20e891f980a4f9e84c Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Mon, 23 Aug 2021 11:05:13 +0200
Subject: [PATCH 403/685] Start GitHub Actions workflow


From 1e5ab952f37e3fb8fb6759dc14c151c618395c23 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 23 Aug 2021 01:18:03 +0200
Subject: [PATCH 404/685] Add linting

---
 .github/workflows/build.yml                   |   3 +
 .swiftlint.yml                                |  32 ++
 Makefile                                      |   3 +
 Sources/SQLite/Core/Blob.swift                |   4 +-
 Sources/SQLite/Core/Connection.swift          |  42 +-
 Sources/SQLite/Core/Statement.swift           |  17 +-
 Sources/SQLite/Core/Value.swift               |  18 +-
 Sources/SQLite/Extensions/Cipher.swift        |   4 +-
 Sources/SQLite/Extensions/FTS4.swift          |  19 +-
 Sources/SQLite/Extensions/FTS5.swift          |   4 +-
 Sources/SQLite/Extensions/RTree.swift         |   6 +-
 Sources/SQLite/Foundation.swift               |   6 +-
 Sources/SQLite/Helpers.swift                  |   9 +-
 Sources/SQLite/Typed/AggregateFunctions.swift |  14 +-
 Sources/SQLite/Typed/Coding.swift             | 119 ++--
 Sources/SQLite/Typed/Collation.swift          |   6 +-
 Sources/SQLite/Typed/CoreFunctions.swift      |  28 +-
 Sources/SQLite/Typed/CustomFunctions.swift    |  58 +-
 Sources/SQLite/Typed/Expression.swift         |  12 +-
 Sources/SQLite/Typed/Operators.swift          | 328 +++++------
 Sources/SQLite/Typed/Query.swift              |  84 ++-
 Sources/SQLite/Typed/Schema.swift             | 172 ++++--
 Sources/SQLite/Typed/Setter.swift             | 130 ++---
 Tests/.swiftlint.yml                          |  20 +
 .../SQLiteTests/AggregateFunctionsTests.swift |  78 +--
 Tests/SQLiteTests/BlobTests.swift             |   2 +-
 Tests/SQLiteTests/CipherTests.swift           |   6 +-
 Tests/SQLiteTests/ConnectionTests.swift       | 113 ++--
 Tests/SQLiteTests/CoreFunctionsTests.swift    | 146 ++---
 Tests/SQLiteTests/CustomFunctionsTests.swift  |  16 +-
 .../DateAndTimeFunctionTests.swift            |  42 +-
 Tests/SQLiteTests/ExpressionTests.swift       |   3 +-
 Tests/SQLiteTests/FTS4Tests.swift             |  51 +-
 Tests/SQLiteTests/FTS5Tests.swift             |   5 +-
 Tests/SQLiteTests/FoundationTests.swift       |   2 +-
 Tests/SQLiteTests/OperatorsTests.swift        | 530 +++++++++---------
 Tests/SQLiteTests/QueryTests.swift            | 263 +++++----
 Tests/SQLiteTests/RTreeTests.swift            |   4 +-
 Tests/SQLiteTests/RowTests.swift              |   2 +-
 Tests/SQLiteTests/SchemaTests.swift           |  98 +++-
 Tests/SQLiteTests/SelectTests.swift           |  21 +-
 Tests/SQLiteTests/SetterTests.swift           | 180 +++---
 Tests/SQLiteTests/StatementTests.swift        |   6 +-
 Tests/SQLiteTests/TestHelpers.swift           |  29 +-
 Tests/SQLiteTests/ValueTests.swift            |   2 +-
 45 files changed, 1509 insertions(+), 1228 deletions(-)
 create mode 100644 .swiftlint.yml
 create mode 100644 Tests/.swiftlint.yml

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 1c47e3a6..0b9d0cf1 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -14,6 +14,9 @@ jobs:
         gem install xcpretty --no-document
         brew update
         brew outdated carthage || brew upgrade carthage
+        brew install swiftlint
+    - name: "Lint"
+      run: make lint
     - name: "Run tests (BUILD_SCHEME: SQLite iOS)"
       env:
         BUILD_SCHEME: SQLite iOS
diff --git a/.swiftlint.yml b/.swiftlint.yml
new file mode 100644
index 00000000..e18c09a1
--- /dev/null
+++ b/.swiftlint.yml
@@ -0,0 +1,32 @@
+disabled_rules: # rule identifiers to exclude from running
+  - todo
+  - operator_whitespace
+  - large_tuple
+  - closure_parameter_position
+included: # paths to include during linting. `--path` is ignored if present. takes precendence over `excluded`.
+  - Sources
+  - Tests
+excluded: # paths to ignore during linting. overridden by `included`.
+
+identifier_name:
+  excluded:
+    - db
+    - to
+    - by
+    - or
+    - eq
+    - gt
+    - lt
+    - fn
+    - a
+    - b
+
+line_length:
+  warning: 150
+  error: 150
+  ignores_comments: true
+
+
+file_length:
+  warning: 700
+  error: 700
diff --git a/Makefile b/Makefile
index f3f355ab..5e4ff388 100644
--- a/Makefile
+++ b/Makefile
@@ -18,6 +18,9 @@ default: test
 build:
 	$(BUILD_TOOL) $(BUILD_ARGUMENTS)
 
+lint:
+	swiftlint
+
 test:
 ifdef XCPRETTY
 	@set -o pipefail && $(BUILD_TOOL) $(BUILD_ARGUMENTS) $(TEST_ACTIONS) | $(XCPRETTY) -c
diff --git a/Sources/SQLite/Core/Blob.swift b/Sources/SQLite/Core/Blob.swift
index 2f5d2a14..a49ef23b 100644
--- a/Sources/SQLite/Core/Blob.swift
+++ b/Sources/SQLite/Core/Blob.swift
@@ -43,7 +43,7 @@ public struct Blob {
 
 }
 
-extension Blob : CustomStringConvertible {
+extension Blob: CustomStringConvertible {
 
     public var description: String {
         return "x'\(toHex())'"
@@ -51,7 +51,7 @@ extension Blob : CustomStringConvertible {
 
 }
 
-extension Blob : Equatable {
+extension Blob: Equatable {
 
 }
 
diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 9273b36a..a4dad4a6 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -70,7 +70,7 @@ public final class Connection {
         /// A DELETE operation.
         case delete
 
-        fileprivate init(rawValue:Int32) {
+        fileprivate init(rawValue: Int32) {
             switch rawValue {
             case SQLITE_INSERT:
                 self = .insert
@@ -86,7 +86,7 @@ public final class Connection {
 
     public var handle: OpaquePointer { return _handle! }
 
-    fileprivate var _handle: OpaquePointer? = nil
+    fileprivate var _handle: OpaquePointer?
 
     /// Initializes a new SQLite connection.
     ///
@@ -252,9 +252,9 @@ public final class Connection {
     @discardableResult public func run(_ statement: String, _ bindings: [String: Binding?]) throws -> Statement {
         return try prepare(statement).run(bindings)
     }
-    
+
     // MARK: - VACUUM
-    
+
     /// Run a vacuum on the database
     ///
     /// - Throws: `Result.Error` if query execution fails.
@@ -311,7 +311,7 @@ public final class Connection {
     // MARK: - Transactions
 
     /// The mode in which a transaction acquires a lock.
-    public enum TransactionMode : String {
+    public enum TransactionMode: String {
 
         /// Defers locking the database till the first read/write executes.
         case deferred = "DEFERRED"
@@ -446,11 +446,9 @@ public final class Connection {
         let box: Trace = { (pointer: UnsafeRawPointer) in
             callback(String(cString: pointer.assumingMemoryBound(to: UInt8.self)))
         }
-        sqlite3_trace(handle,
-            {
-                (C: UnsafeMutableRawPointer?, SQL: UnsafePointer<Int8>?) in
-                    if let C = C, let SQL = SQL {
-                        unsafeBitCast(C, to: Trace.self)(SQL)
+        sqlite3_trace(handle, { (context: UnsafeMutableRawPointer?, SQL: UnsafePointer<Int8>?) in
+                    if let context = context, let SQL = SQL {
+                        unsafeBitCast(context, to: Trace.self)(SQL)
                     }
             },
             unsafeBitCast(box, to: UnsafeMutableRawPointer.self)
@@ -470,13 +468,12 @@ public final class Connection {
         let box: Trace = { (pointer: UnsafeRawPointer) in
             callback(String(cString: pointer.assumingMemoryBound(to: UInt8.self)))
         }
-        sqlite3_trace_v2(handle, UInt32(SQLITE_TRACE_STMT) /* mask */,
-             {
+        sqlite3_trace_v2(handle, UInt32(SQLITE_TRACE_STMT) /* mask */, {
                  // A trace callback is invoked with four arguments: callback(T,C,P,X).
                  // The T argument is one of the SQLITE_TRACE constants to indicate why the
                  // callback was invoked. The C argument is a copy of the context pointer.
                  // The P and X arguments are pointers whose meanings depend on T.
-                 (T: UInt32, C: UnsafeMutableRawPointer?, P: UnsafeMutableRawPointer?, X: UnsafeMutableRawPointer?) in
+                 (_: UInt32, C: UnsafeMutableRawPointer?, P: UnsafeMutableRawPointer?, _: UnsafeMutableRawPointer?) in
                  if let P = P,
                     let expandedSQL = sqlite3_expanded_sql(OpaquePointer(P)) {
                      unsafeBitCast(C, to: Trace.self)(expandedSQL)
@@ -588,7 +585,9 @@ public final class Connection {
     ///   - block: A block of code to run when the function is called. The block
     ///     is called with an array of raw SQL values mapped to the function’s
     ///     parameters and should return a raw SQL value (or nil).
-    public func createFunction(_ function: String, argumentCount: UInt? = nil, deterministic: Bool = false, _ block: @escaping (_ args: [Binding?]) -> Binding?) {
+    // swiftlint:disable:next cyclomatic_complexity
+    public func createFunction(_ function: String, argumentCount: UInt? = nil, deterministic: Bool = false,
+                               _ block: @escaping (_ args: [Binding?]) -> Binding?) {
         let argc = argumentCount.map { Int($0) } ?? -1
         let box: Function = { context, argc, argv in
             let arguments: [Binding?] = (0..<Int(argc)).map { idx in
@@ -629,7 +628,8 @@ public final class Connection {
             flags |= SQLITE_DETERMINISTIC
         }
         #endif
-        sqlite3_create_function_v2(handle, function, Int32(argc), flags, unsafeBitCast(box, to: UnsafeMutableRawPointer.self), { context, argc, value in
+        sqlite3_create_function_v2(handle, function, Int32(argc), flags,
+                                   unsafeBitCast(box, to: UnsafeMutableRawPointer.self), { context, argc, value in
             let function = unsafeBitCast(sqlite3_user_data(context), to: Function.self)
             function(context, argc, value)
         }, nil, nil, nil)
@@ -768,8 +768,8 @@ public final class Connection {
             return Int32(block(lstr, rstr).rawValue)
         }
         try check(sqlite3_create_collation_v2(handle, collation, SQLITE_UTF8,
-            unsafeBitCast(box, to: UnsafeMutableRawPointer.self),
-            { (callback: UnsafeMutableRawPointer?, _, lhs: UnsafeRawPointer?, _, rhs: UnsafeRawPointer?) in /* xCompare */
+            unsafeBitCast(box, to: UnsafeMutableRawPointer.self), { (callback: UnsafeMutableRawPointer?, _,
+                                                                     lhs: UnsafeRawPointer?, _, rhs: UnsafeRawPointer?) in /* xCompare */
             if let lhs = lhs, let rhs = rhs {
                 return unsafeBitCast(callback, to: Collation.self)(lhs, rhs)
             } else {
@@ -807,7 +807,7 @@ public final class Connection {
 
 }
 
-extension Connection : CustomStringConvertible {
+extension Connection: CustomStringConvertible {
 
     public var description: String {
         return String(cString: sqlite3_db_filename(handle, nil))
@@ -815,7 +815,7 @@ extension Connection : CustomStringConvertible {
 
 }
 
-extension Connection.Location : CustomStringConvertible {
+extension Connection.Location: CustomStringConvertible {
 
     public var description: String {
         switch self {
@@ -830,7 +830,7 @@ extension Connection.Location : CustomStringConvertible {
 
 }
 
-public enum Result : Error {
+public enum Result: Error {
 
     fileprivate static let successCodes: Set = [SQLITE_OK, SQLITE_ROW, SQLITE_DONE]
 
@@ -852,7 +852,7 @@ public enum Result : Error {
 
 }
 
-extension Result : CustomStringConvertible {
+extension Result: CustomStringConvertible {
 
     public var description: String {
         switch self {
diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index 237d4812..dfb67d22 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -35,7 +35,7 @@ import SQLite3
 /// A single SQL statement.
 public final class Statement {
 
-    fileprivate var handle: OpaquePointer? = nil
+    fileprivate var handle: OpaquePointer?
 
     fileprivate let connection: Connection
 
@@ -173,7 +173,6 @@ public final class Statement {
         return try bind(bindings).scalar()
     }
 
-
     /// - Parameter bindings: A dictionary of named parameters to bind to the
     ///   statement.
     ///
@@ -188,12 +187,12 @@ public final class Statement {
 
     fileprivate func reset(clearBindings shouldClear: Bool = true) {
         sqlite3_reset(handle)
-        if (shouldClear) { sqlite3_clear_bindings(handle) }
+        if shouldClear { sqlite3_clear_bindings(handle) }
     }
 
 }
 
-extension Statement : Sequence {
+extension Statement: Sequence {
 
     public func makeIterator() -> Statement {
         reset(clearBindings: false)
@@ -202,7 +201,7 @@ extension Statement : Sequence {
 
 }
 
-public protocol FailableIterator : IteratorProtocol {
+public protocol FailableIterator: IteratorProtocol {
     func failableNext() throws -> Self.Element?
 }
 
@@ -221,14 +220,14 @@ extension Array {
     }
 }
 
-extension Statement : FailableIterator {
+extension Statement: FailableIterator {
     public typealias Element = [Binding?]
     public func failableNext() throws -> [Binding?]? {
         return try step() ? Array(row) : nil
     }
 }
 
-extension Statement : CustomStringConvertible {
+extension Statement: CustomStringConvertible {
 
     public var description: String {
         return String(cString: sqlite3_sql(handle))
@@ -283,7 +282,7 @@ public struct Cursor {
 }
 
 /// Cursors provide direct access to a statement’s current row.
-extension Cursor : Sequence {
+extension Cursor: Sequence {
 
     public subscript(idx: Int) -> Binding? {
         switch sqlite3_column_type(handle, Int32(idx)) {
@@ -306,7 +305,7 @@ extension Cursor : Sequence {
         var idx = 0
         return AnyIterator {
             if idx >= self.columnCount {
-                return Optional<Binding?>.none
+                return Binding??.none
             } else {
                 idx += 1
                 return self[idx - 1]
diff --git a/Sources/SQLite/Core/Value.swift b/Sources/SQLite/Core/Value.swift
index 608f0ce6..b8686eab 100644
--- a/Sources/SQLite/Core/Value.swift
+++ b/Sources/SQLite/Core/Value.swift
@@ -29,13 +29,13 @@
 ///   protocol, instead.
 public protocol Binding {}
 
-public protocol Number : Binding {}
+public protocol Number: Binding {}
 
-public protocol Value : Expressible { // extensions cannot have inheritance clauses
+public protocol Value: Expressible { // extensions cannot have inheritance clauses
 
     associatedtype ValueType = Self
 
-    associatedtype Datatype : Binding
+    associatedtype Datatype: Binding
 
     static var declaredDatatype: String { get }
 
@@ -45,7 +45,7 @@ public protocol Value : Expressible { // extensions cannot have inheritance clau
 
 }
 
-extension Double : Number, Value {
+extension Double: Number, Value {
 
     public static let declaredDatatype = "REAL"
 
@@ -59,7 +59,7 @@ extension Double : Number, Value {
 
 }
 
-extension Int64 : Number, Value {
+extension Int64: Number, Value {
 
     public static let declaredDatatype = "INTEGER"
 
@@ -73,7 +73,7 @@ extension Int64 : Number, Value {
 
 }
 
-extension String : Binding, Value {
+extension String: Binding, Value {
 
     public static let declaredDatatype = "TEXT"
 
@@ -87,7 +87,7 @@ extension String : Binding, Value {
 
 }
 
-extension Blob : Binding, Value {
+extension Blob: Binding, Value {
 
     public static let declaredDatatype = "BLOB"
 
@@ -103,7 +103,7 @@ extension Blob : Binding, Value {
 
 // MARK: -
 
-extension Bool : Binding, Value {
+extension Bool: Binding, Value {
 
     public static var declaredDatatype = Int64.declaredDatatype
 
@@ -117,7 +117,7 @@ extension Bool : Binding, Value {
 
 }
 
-extension Int : Number, Value {
+extension Int: Number, Value {
 
     public static var declaredDatatype = Int64.declaredDatatype
 
diff --git a/Sources/SQLite/Extensions/Cipher.swift b/Sources/SQLite/Extensions/Cipher.swift
index 44919aab..9fce42f7 100644
--- a/Sources/SQLite/Extensions/Cipher.swift
+++ b/Sources/SQLite/Extensions/Cipher.swift
@@ -1,7 +1,6 @@
 #if SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
 
-
 /// Extension methods for [SQLCipher](https://www.zetetic.net/sqlcipher/).
 /// @see [sqlcipher api](https://www.zetetic.net/sqlcipher/sqlcipher-api/)
 extension Connection {
@@ -32,7 +31,6 @@ extension Connection {
         try _key_v2(db: db, keyPointer: key.bytes, keySize: key.bytes.count)
     }
 
-
     /// Change the key on an open database.  If the current database is not encrypted, this routine
     /// will encrypt it.
     /// To change the key on an existing encrypted database, it must first be unlocked with the
@@ -60,7 +58,7 @@ extension Connection {
     // the key provided is incorrect. To test that the database can be successfully opened with the
     // provided key, it is necessary to perform some operation on the database (i.e. read from it).
     private func cipher_key_check() throws {
-        let _ = try scalar("SELECT count(*) FROM sqlite_master;")
+        _ = try scalar("SELECT count(*) FROM sqlite_master;")
     }
 }
 #endif
diff --git a/Sources/SQLite/Extensions/FTS4.swift b/Sources/SQLite/Extensions/FTS4.swift
index f0184565..a3c253f2 100644
--- a/Sources/SQLite/Extensions/FTS4.swift
+++ b/Sources/SQLite/Extensions/FTS4.swift
@@ -97,7 +97,8 @@ public struct Tokenizer {
 
     public static let Porter = Tokenizer("porter")
 
-    public static func Unicode61(removeDiacritics: Bool? = nil, tokenchars: Set<Character> = [], separators: Set<Character> = []) -> Tokenizer {
+    public static func Unicode61(removeDiacritics: Bool? = nil, tokenchars: Set<Character> = [],
+                                 separators: Set<Character> = []) -> Tokenizer {
         var arguments = [String]()
 
         if let removeDiacritics = removeDiacritics {
@@ -134,7 +135,7 @@ public struct Tokenizer {
 
 }
 
-extension Tokenizer : CustomStringConvertible {
+extension Tokenizer: CustomStringConvertible {
 
     public var description: String {
         return ([name] + arguments).joined(separator: " ")
@@ -145,13 +146,13 @@ extension Tokenizer : CustomStringConvertible {
 extension Connection {
 
     public func registerTokenizer(_ submoduleName: String, next: @escaping (String) -> (String, Range<String.Index>)?) throws {
-        try check(_SQLiteRegisterTokenizer(handle, Tokenizer.moduleName, submoduleName) { (
-                input: UnsafePointer<Int8>, offset: UnsafeMutablePointer<Int32>, length: UnsafeMutablePointer<Int32>) in
+        try check(_SQLiteRegisterTokenizer(handle, Tokenizer.moduleName, submoduleName) {
+            (input: UnsafePointer<Int8>, offset: UnsafeMutablePointer<Int32>, length: UnsafeMutablePointer<Int32>) in
             let string = String(cString: input)
 
             guard let (token, range) = next(string) else { return nil }
 
-            let view:String.UTF8View = string.utf8
+            let view: String.UTF8View = string.utf8
 
             if let from = range.lowerBound.samePosition(in: view),
                let to = range.upperBound.samePosition(in: view) {
@@ -231,7 +232,7 @@ open class FTSConfig {
         if let tokenizer = tokenizer {
             options.append("tokenize", value: Expression<Void>(literal: tokenizer.description))
         }
-        options.appendCommaSeparated("prefix", values:prefixes.sorted().map { String($0) })
+        options.appendCommaSeparated("prefix", values: prefixes.sorted().map { String($0) })
         if isContentless {
             options.append("content", value: "")
         } else if let externalContentSchema = externalContentSchema {
@@ -274,9 +275,9 @@ open class FTSConfig {
 }
 
 /// Configuration for the [FTS4](https://www.sqlite.org/fts3.html) extension.
-open class FTS4Config : FTSConfig {
+open class FTS4Config: FTSConfig {
     /// [The matchinfo= option](https://www.sqlite.org/fts3.html#section_6_4)
-    public enum MatchInfo : CustomStringConvertible {
+    public enum MatchInfo: CustomStringConvertible {
         case fts3
         public var description: String {
             return "fts3"
@@ -284,7 +285,7 @@ open class FTS4Config : FTSConfig {
     }
 
     /// [FTS4 options](https://www.sqlite.org/fts3.html#fts4_options)
-    public enum Order : CustomStringConvertible {
+    public enum Order: CustomStringConvertible {
         /// Data structures are optimized for returning results in ascending order by docid (default)
         case asc
         /// FTS4 stores its data in such a way as to optimize returning results in descending order by docid.
diff --git a/Sources/SQLite/Extensions/FTS5.swift b/Sources/SQLite/Extensions/FTS5.swift
index cf13f3d8..07f49ffc 100644
--- a/Sources/SQLite/Extensions/FTS5.swift
+++ b/Sources/SQLite/Extensions/FTS5.swift
@@ -32,8 +32,8 @@ extension Module {
 ///
 /// **Note:** this is currently only applicable when using SQLite.swift together with a FTS5-enabled version
 /// of SQLite.
-open class FTS5Config : FTSConfig {
-    public enum Detail : CustomStringConvertible {
+open class FTS5Config: FTSConfig {
+    public enum Detail: CustomStringConvertible {
         /// store rowid, column number, term offset
         case full
         /// store rowid, column number
diff --git a/Sources/SQLite/Extensions/RTree.swift b/Sources/SQLite/Extensions/RTree.swift
index 4fc1a235..5ecdf78b 100644
--- a/Sources/SQLite/Extensions/RTree.swift
+++ b/Sources/SQLite/Extensions/RTree.swift
@@ -23,8 +23,9 @@
 //
 
 extension Module {
-
-    public static func RTree<T : Value, U : Value>(_ primaryKey: Expression<T>, _ pairs: (Expression<U>, Expression<U>)...) -> Module where T.Datatype == Int64, U.Datatype == Double {
+    public static func RTree<T: Value, U: Value>(_ primaryKey: Expression<T>,
+                                                 _ pairs: (Expression<U>, Expression<U>)...)
+                    -> Module where T.Datatype == Int64, U.Datatype == Double {
         var arguments: [Expressible] = [primaryKey]
 
         for pair in pairs {
@@ -33,5 +34,4 @@ extension Module {
 
         return Module(name: "rtree", arguments: arguments)
     }
-
 }
diff --git a/Sources/SQLite/Foundation.swift b/Sources/SQLite/Foundation.swift
index 9986f581..d837d8ba 100644
--- a/Sources/SQLite/Foundation.swift
+++ b/Sources/SQLite/Foundation.swift
@@ -24,7 +24,7 @@
 
 import Foundation
 
-extension Data : Value {
+extension Data: Value {
 
     public static var declaredDatatype: String {
         return Blob.declaredDatatype
@@ -42,7 +42,7 @@ extension Data : Value {
 
 }
 
-extension Date : Value {
+extension Date: Value {
 
     public static var declaredDatatype: String {
         return String.declaredDatatype
@@ -69,7 +69,7 @@ public var dateFormatter: DateFormatter = {
     return formatter
 }()
 
-extension UUID : Value {
+extension UUID: Value {
 
     public static var declaredDatatype: String {
         return String.declaredDatatype
diff --git a/Sources/SQLite/Helpers.swift b/Sources/SQLite/Helpers.swift
index 44aaec19..0e3385e3 100644
--- a/Sources/SQLite/Helpers.swift
+++ b/Sources/SQLite/Helpers.swift
@@ -44,7 +44,7 @@ public protocol _OptionalType {
 
 }
 
-extension Optional : _OptionalType {
+extension Optional: _OptionalType {
 
     public typealias WrappedType = Wrapped
 
@@ -75,7 +75,7 @@ extension String {
     func infix<T>(_ lhs: Expressible, _ rhs: Expressible, wrap: Bool = true) -> Expression<T> {
         return infix([lhs, rhs], wrap: wrap)
     }
-    
+
     func infix<T>(_ terms: [Expressible], wrap: Bool = true) -> Expression<T> {
         let expression = Expression<T>(" \(self) ".join(terms).expression)
         guard wrap else {
@@ -115,10 +115,11 @@ func transcode(_ literal: Binding?) -> String {
     }
 }
 
+//swiftlint:disable force_cast
 func value<A: Value>(_ v: Binding) -> A {
-    return A.fromDatatypeValue(v as! A.Datatype) as! A
+    A.fromDatatypeValue(v as! A.Datatype) as! A
 }
 
 func value<A: Value>(_ v: Binding?) -> A {
-    return value(v!)
+    value(v!)
 }
diff --git a/Sources/SQLite/Typed/AggregateFunctions.swift b/Sources/SQLite/Typed/AggregateFunctions.swift
index 2ec28288..325b0277 100644
--- a/Sources/SQLite/Typed/AggregateFunctions.swift
+++ b/Sources/SQLite/Typed/AggregateFunctions.swift
@@ -29,13 +29,13 @@ private enum Function: String {
     case avg
     case sum
     case total
-    
+
     func wrap<T>(_ expression: Expressible) -> Expression<T> {
         return self.rawValue.wrap(expression)
     }
 }
 
-extension ExpressionType where UnderlyingType : Value {
+extension ExpressionType where UnderlyingType: Value {
 
     /// Builds a copy of the expression prefixed with the `DISTINCT` keyword.
     ///
@@ -66,7 +66,7 @@ extension ExpressionType where UnderlyingType : Value {
 
 }
 
-extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.WrappedType : Value {
+extension ExpressionType where UnderlyingType: _OptionalType, UnderlyingType.WrappedType: Value {
 
     /// Builds a copy of the expression prefixed with the `DISTINCT` keyword.
     ///
@@ -97,7 +97,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
 
 }
 
-extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype : Comparable {
+extension ExpressionType where UnderlyingType: Value, UnderlyingType.Datatype: Comparable {
 
     /// Builds a copy of the expression wrapped with the `max` aggregate
     /// function.
@@ -127,7 +127,7 @@ extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype :
 
 }
 
-extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.WrappedType : Value, UnderlyingType.WrappedType.Datatype : Comparable {
+extension ExpressionType where UnderlyingType: _OptionalType, UnderlyingType.WrappedType: Value, UnderlyingType.WrappedType.Datatype: Comparable {
 
     /// Builds a copy of the expression wrapped with the `max` aggregate
     /// function.
@@ -157,7 +157,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
 
 }
 
-extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype : Number {
+extension ExpressionType where UnderlyingType: Value, UnderlyingType.Datatype: Number {
 
     /// Builds a copy of the expression wrapped with the `avg` aggregate
     /// function.
@@ -200,7 +200,7 @@ extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype :
 
 }
 
-extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.WrappedType : Value, UnderlyingType.WrappedType.Datatype : Number {
+extension ExpressionType where UnderlyingType: _OptionalType, UnderlyingType.WrappedType: Value, UnderlyingType.WrappedType.Datatype: Number {
 
     /// Builds a copy of the expression wrapped with the `avg` aggregate
     /// function.
diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index 7044bc37..5a672883 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -39,12 +39,12 @@ extension QueryType {
     ///   - otherSetters: Any other setters to include in the insert
     ///
     /// - Returns: An `INSERT` statement for the encodable object
-    public func insert(_ encodable: Encodable, userInfo: [CodingUserInfoKey:Any] = [:], otherSetters: [Setter] = []) throws -> Insert {
+    public func insert(_ encodable: Encodable, userInfo: [CodingUserInfoKey: Any] = [:], otherSetters: [Setter] = []) throws -> Insert {
         let encoder = SQLiteEncoder(userInfo: userInfo)
         try encodable.encode(to: encoder)
         return self.insert(encoder.setters + otherSetters)
     }
-    
+
     /// Creates an `INSERT` statement by encoding the given object
     /// This method converts any custom nested types to JSON data and does not handle any sort
     /// of object relationships. If you want to support relationships between objects you will
@@ -63,7 +63,8 @@ extension QueryType {
     ///   - otherSetters: Any other setters to include in the insert
     ///
     /// - Returns: An `INSERT` statement fort the encodable object
-    public func insert(or onConflict: OnConflict, encodable: Encodable, userInfo: [CodingUserInfoKey:Any] = [:], otherSetters: [Setter] = []) throws -> Insert {
+    public func insert(or onConflict: OnConflict, encodable: Encodable, userInfo: [CodingUserInfoKey: Any] = [:],
+                       otherSetters: [Setter] = []) throws -> Insert {
         let encoder = SQLiteEncoder(userInfo: userInfo)
         try encodable.encode(to: encoder)
         return self.insert(or: onConflict, encoder.setters + otherSetters)
@@ -83,7 +84,8 @@ extension QueryType {
     ///   - otherSetters: Any other setters to include in the inserts, per row/object.
     ///
     /// - Returns: An `INSERT` statement for the encodable objects
-    public func insertMany(_ encodables: [Encodable], userInfo: [CodingUserInfoKey:Any] = [:], otherSetters: [Setter] = []) throws -> Insert {
+    public func insertMany(_ encodables: [Encodable], userInfo: [CodingUserInfoKey: Any] = [:],
+                           otherSetters: [Setter] = []) throws -> Insert {
         let combinedSetters = try encodables.map { encodable -> [Setter] in
             let encoder = SQLiteEncoder(userInfo: userInfo)
             try encodable.encode(to: encoder)
@@ -108,7 +110,8 @@ extension QueryType {
     ///   - onConflictOf: The column that if conflicts should trigger an update instead of insert.
     ///
     /// - Returns: An `INSERT` statement fort the encodable object
-    public func upsert(_ encodable: Encodable, userInfo: [CodingUserInfoKey:Any] = [:], otherSetters: [Setter] = [], onConflictOf conflicting: Expressible) throws -> Insert {
+    public func upsert(_ encodable: Encodable, userInfo: [CodingUserInfoKey: Any] = [:],
+                       otherSetters: [Setter] = [], onConflictOf conflicting: Expressible) throws -> Insert {
         let encoder = SQLiteEncoder(userInfo: userInfo)
         try encodable.encode(to: encoder)
         return self.upsert(encoder.setters + otherSetters, onConflictOf: conflicting)
@@ -128,7 +131,8 @@ extension QueryType {
     ///   - otherSetters: Any other setters to include in the insert
     ///
     /// - Returns: An `UPDATE` statement fort the encodable object
-    public func update(_ encodable: Encodable, userInfo: [CodingUserInfoKey:Any] = [:], otherSetters: [Setter] = []) throws -> Update {
+    public func update(_ encodable: Encodable, userInfo: [CodingUserInfoKey: Any] = [:],
+                       otherSetters: [Setter] = []) throws -> Update {
         let encoder = SQLiteEncoder(userInfo: userInfo)
         try encodable.encode(to: encoder)
         return self.update(encoder.setters + otherSetters)
@@ -154,8 +158,9 @@ extension Row {
 }
 
 /// Generates a list of settings for an Encodable object
-fileprivate class SQLiteEncoder: Encoder {
+private class SQLiteEncoder: Encoder {
     class SQLiteKeyedEncodingContainer<MyKey: CodingKey>: KeyedEncodingContainerProtocol {
+        // swiftlint:disable nesting
         typealias Key = MyKey
 
         let encoder: SQLiteEncoder
@@ -197,14 +202,12 @@ fileprivate class SQLiteEncoder: Encoder {
             self.encoder.setters.append(Expression(key.stringValue) <- value)
         }
 
-        func encode<T>(_ value: T, forKey key: Key) throws where T : Swift.Encodable {
+        func encode<T>(_ value: T, forKey key: Key) throws where T: Swift.Encodable {
             if let data = value as? Data {
                 self.encoder.setters.append(Expression(key.stringValue) <- data)
-            }
-            else if let date = value as? Date {
+            } else if let date = value as? Date {
                 self.encoder.setters.append(Expression(key.stringValue) <- date.datatypeValue)
-            }
-            else {
+            } else {
                 let encoded = try JSONEncoder().encode(value)
                 let string = String(data: encoded, encoding: .utf8)
                 self.encoder.setters.append(Expression(key.stringValue) <- string)
@@ -212,15 +215,18 @@ fileprivate class SQLiteEncoder: Encoder {
         }
 
         func encode(_ value: Int8, forKey key: Key) throws {
-            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an Int8 is not supported"))
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath,
+                                                                          debugDescription: "encoding an Int8 is not supported"))
         }
 
         func encode(_ value: Int16, forKey key: Key) throws {
-            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an Int16 is not supported"))
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath,
+                                                                          debugDescription: "encoding an Int16 is not supported"))
         }
 
         func encode(_ value: Int32, forKey key: Key) throws {
-            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an Int32 is not supported"))
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath,
+                                                                          debugDescription: "encoding an Int32 is not supported"))
         }
 
         func encode(_ value: Int64, forKey key: Key) throws {
@@ -228,26 +234,32 @@ fileprivate class SQLiteEncoder: Encoder {
         }
 
         func encode(_ value: UInt, forKey key: Key) throws {
-            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an UInt is not supported"))
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath,
+                                                                          debugDescription: "encoding an UInt is not supported"))
         }
 
         func encode(_ value: UInt8, forKey key: Key) throws {
-            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an UInt8 is not supported"))
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath,
+                                                                          debugDescription: "encoding an UInt8 is not supported"))
         }
 
         func encode(_ value: UInt16, forKey key: Key) throws {
-            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an UInt16 is not supported"))
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath,
+                                                                          debugDescription: "encoding an UInt16 is not supported"))
         }
 
         func encode(_ value: UInt32, forKey key: Key) throws {
-            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an UInt32 is not supported"))
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath,
+                                                                          debugDescription: "encoding an UInt32 is not supported"))
         }
 
         func encode(_ value: UInt64, forKey key: Key) throws {
-            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath, debugDescription: "encoding an UInt64 is not supported"))
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath,
+                                                                          debugDescription: "encoding an UInt64 is not supported"))
         }
 
-        func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> where NestedKey : CodingKey {
+        func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key)
+                        -> KeyedEncodingContainer<NestedKey> where NestedKey: CodingKey {
             fatalError("encoding a nested container is not supported")
         }
 
@@ -272,13 +284,13 @@ fileprivate class SQLiteEncoder: Encoder {
         fatalError("not supported")
     }
 
-    func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key : CodingKey {
+    func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key: CodingKey {
         return KeyedEncodingContainer(SQLiteKeyedEncodingContainer(encoder: self))
     }
 }
 
-fileprivate class SQLiteDecoder : Decoder {
-    class SQLiteKeyedDecodingContainer<MyKey: CodingKey> : KeyedDecodingContainerProtocol {
+private class SQLiteDecoder: Decoder {
+    class SQLiteKeyedDecodingContainer<MyKey: CodingKey>: KeyedDecodingContainerProtocol {
         typealias Key = MyKey
 
         let codingPath: [CodingKey] = []
@@ -309,15 +321,18 @@ fileprivate class SQLiteDecoder : Decoder {
         }
 
         func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 {
-            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an Int8 is not supported"))
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath,
+                                                                         debugDescription: "decoding an Int8 is not supported"))
         }
 
         func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 {
-            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an Int16 is not supported"))
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath,
+                                                                         debugDescription: "decoding an Int16 is not supported"))
         }
 
         func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 {
-            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an Int32 is not supported"))
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath,
+                                                                         debugDescription: "decoding an Int32 is not supported"))
         }
 
         func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
@@ -325,24 +340,29 @@ fileprivate class SQLiteDecoder : Decoder {
         }
 
         func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {
-            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an UInt is not supported"))
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath,
+                                                                         debugDescription: "decoding an UInt is not supported"))
 
         }
 
         func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 {
-            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an UInt8 is not supported"))
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath,
+                                                                         debugDescription: "decoding an UInt8 is not supported"))
         }
 
         func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 {
-            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an UInt16 is not supported"))
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath,
+                                                                         debugDescription: "decoding an UInt16 is not supported"))
         }
 
         func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 {
-            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an UInt32 is not supported"))
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath,
+                                                                         debugDescription: "decoding an UInt32 is not supported"))
         }
 
         func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 {
-            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an UInt64 is not supported"))
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath,
+                                                                         debugDescription: "decoding an UInt64 is not supported"))
         }
 
         func decode(_ type: Float.Type, forKey key: Key) throws -> Float {
@@ -358,37 +378,45 @@ fileprivate class SQLiteDecoder : Decoder {
         }
 
         func decode<T>(_ type: T.Type, forKey key: Key) throws -> T where T: Swift.Decodable {
+            // swiftlint:disable force_cast
             if type == Data.self {
                 let data = try self.row.get(Expression<Data>(key.stringValue))
                 return data as! T
-            }
-            else if type == Date.self {
+            } else if type == Date.self {
                 let date = try self.row.get(Expression<Date>(key.stringValue))
                 return date as! T
             }
+            // swiftlint:enable force_cast
             guard let JSONString = try self.row.get(Expression<String?>(key.stringValue)) else {
-                throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "an unsupported type was found"))
+                throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath,
+                                                                             debugDescription: "an unsupported type was found"))
             }
             guard let data = JSONString.data(using: .utf8) else {
-                throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "invalid utf8 data found"))
+                throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath,
+                                                                        debugDescription: "invalid utf8 data found"))
             }
             return try JSONDecoder().decode(type, from: data)
         }
 
-        func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer<NestedKey> where NestedKey : CodingKey {
-            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding nested containers is not supported"))
+        func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws
+                        -> KeyedDecodingContainer<NestedKey> where NestedKey: CodingKey {
+            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath,
+                                                                    debugDescription: "decoding nested containers is not supported"))
         }
 
         func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
-            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding unkeyed containers is not supported"))
+            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath,
+                                                                    debugDescription: "decoding unkeyed containers is not supported"))
         }
 
         func superDecoder() throws -> Swift.Decoder {
-            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding super encoders containers is not supported"))
+            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath,
+                                                                    debugDescription: "decoding super encoders containers is not supported"))
         }
 
         func superDecoder(forKey key: Key) throws -> Swift.Decoder {
-            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding super decoders is not supported"))
+            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath,
+                                                                    debugDescription: "decoding super decoders is not supported"))
         }
     }
 
@@ -401,16 +429,17 @@ fileprivate class SQLiteDecoder : Decoder {
         self.userInfo = userInfo
     }
 
-    func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> where Key : CodingKey {
+    func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> where Key: CodingKey {
         return KeyedDecodingContainer(SQLiteKeyedDecodingContainer(row: self.row))
     }
 
     func unkeyedContainer() throws -> UnkeyedDecodingContainer {
-        throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding an unkeyed container is not supported"))
+        throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath,
+                                                                debugDescription: "decoding an unkeyed container is not supported"))
     }
 
     func singleValueContainer() throws -> SingleValueDecodingContainer {
-        throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "decoding a single value container is not supported"))
+        throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath,
+                                                                debugDescription: "decoding a single value container is not supported"))
     }
 }
-
diff --git a/Sources/SQLite/Typed/Collation.swift b/Sources/SQLite/Typed/Collation.swift
index e2ff9d10..3b268ce0 100644
--- a/Sources/SQLite/Typed/Collation.swift
+++ b/Sources/SQLite/Typed/Collation.swift
@@ -43,7 +43,7 @@ public enum Collation {
 
 }
 
-extension Collation : Expressible {
+extension Collation: Expressible {
 
     public var expression: Expression<Void> {
         return Expression(literal: description)
@@ -51,9 +51,9 @@ extension Collation : Expressible {
 
 }
 
-extension Collation : CustomStringConvertible {
+extension Collation: CustomStringConvertible {
 
-    public var description : String {
+    public var description: String {
         switch self {
         case .binary:
             return "BINARY"
diff --git a/Sources/SQLite/Typed/CoreFunctions.swift b/Sources/SQLite/Typed/CoreFunctions.swift
index 068dcf02..053f17e5 100644
--- a/Sources/SQLite/Typed/CoreFunctions.swift
+++ b/Sources/SQLite/Typed/CoreFunctions.swift
@@ -45,21 +45,21 @@ private enum Function: String {
     case regexp = "REGEXP"
     case collate = "COLLATE"
     case ifnull
-    
+
     func infix<T>(_ lhs: Expressible, _ rhs: Expressible, wrap: Bool = true) -> Expression<T> {
         return self.rawValue.infix(lhs, rhs, wrap: wrap)
     }
-    
+
     func wrap<T>(_ expression: Expressible) -> Expression<T> {
         return self.rawValue.wrap(expression)
     }
-    
+
     func wrap<T>(_ expressions: [Expressible]) -> Expression<T> {
         return self.rawValue.wrap(", ".join(expressions))
     }
 }
 
-extension ExpressionType where UnderlyingType : Number {
+extension ExpressionType where UnderlyingType: Number {
 
     /// Builds a copy of the expression wrapped with the `abs` function.
     ///
@@ -68,13 +68,13 @@ extension ExpressionType where UnderlyingType : Number {
     ///     // abs("x")
     ///
     /// - Returns: A copy of the expression wrapped with the `abs` function.
-    public var absoluteValue : Expression<UnderlyingType> {
+    public var absoluteValue: Expression<UnderlyingType> {
         return Function.abs.wrap(self)
     }
 
 }
 
-extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.WrappedType : Number {
+extension ExpressionType where UnderlyingType: _OptionalType, UnderlyingType.WrappedType: Number {
 
     /// Builds a copy of the expression wrapped with the `abs` function.
     ///
@@ -83,7 +83,7 @@ extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.Wr
     ///     // abs("x")
     ///
     /// - Returns: A copy of the expression wrapped with the `abs` function.
-    public var absoluteValue : Expression<UnderlyingType> {
+    public var absoluteValue: Expression<UnderlyingType> {
         return Function.abs.wrap(self)
     }
 
@@ -129,7 +129,7 @@ extension ExpressionType where UnderlyingType == Double? {
 
 }
 
-extension ExpressionType where UnderlyingType : Value, UnderlyingType.Datatype == Int64 {
+extension ExpressionType where UnderlyingType: Value, UnderlyingType.Datatype == Int64 {
 
     /// Builds an expression representing the `random` function.
     ///
@@ -481,7 +481,7 @@ extension ExpressionType where UnderlyingType == String? {
         }
         return Expression("(\(template) LIKE ? ESCAPE ?)", bindings + [pattern, String(character)])
     }
-    
+
     /// Builds a copy of the expression appended with a `LIKE` query against the
     /// given pattern.
     ///
@@ -671,7 +671,7 @@ extension ExpressionType where UnderlyingType == String? {
 
 }
 
-extension Collection where Iterator.Element : Value {
+extension Collection where Iterator.Element: Value {
 
     /// Builds a copy of the expression prepended with an `IN` check against the
     /// collection.
@@ -708,7 +708,7 @@ extension Collection where Iterator.Element : Value {
 }
 
 extension String {
-    
+
     /// Builds a copy of the expression appended with a `LIKE` query against the
     /// given pattern.
     ///
@@ -751,7 +751,7 @@ extension String {
 ///
 /// - Returns: A copy of the given expressions wrapped with the `ifnull`
 ///   function.
-public func ??<V : Value>(optional: Expression<V?>, defaultValue: V) -> Expression<V> {
+public func ??<V: Value>(optional: Expression<V?>, defaultValue: V) -> Expression<V> {
     return Function.ifnull.wrap([optional, defaultValue])
 }
 
@@ -771,7 +771,7 @@ public func ??<V : Value>(optional: Expression<V?>, defaultValue: V) -> Expressi
 ///
 /// - Returns: A copy of the given expressions wrapped with the `ifnull`
 ///   function.
-public func ??<V : Value>(optional: Expression<V?>, defaultValue: Expression<V>) -> Expression<V> {
+public func ??<V: Value>(optional: Expression<V?>, defaultValue: Expression<V>) -> Expression<V> {
     return Function.ifnull.wrap([optional, defaultValue])
 }
 
@@ -791,6 +791,6 @@ public func ??<V : Value>(optional: Expression<V?>, defaultValue: Expression<V>)
 ///
 /// - Returns: A copy of the given expressions wrapped with the `ifnull`
 ///   function.
-public func ??<V : Value>(optional: Expression<V?>, defaultValue: Expression<V?>) -> Expression<V> {
+public func ??<V: Value>(optional: Expression<V?>, defaultValue: Expression<V?>) -> Expression<V> {
     return Function.ifnull.wrap([optional, defaultValue])
 }
diff --git a/Sources/SQLite/Typed/CustomFunctions.swift b/Sources/SQLite/Typed/CustomFunctions.swift
index 4d3e69ee..88fb5aaa 100644
--- a/Sources/SQLite/Typed/CustomFunctions.swift
+++ b/Sources/SQLite/Typed/CustomFunctions.swift
@@ -39,83 +39,107 @@ public extension Connection {
     ///     The assigned types must be explicit.
     ///
     /// - Returns: A closure returning an SQL expression to call the function.
-    func createFunction<Z : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping () -> Z) throws -> (() -> Expression<Z>) {
+    func createFunction<Z: Value>(_ function: String, deterministic: Bool = false, _ block: @escaping () -> Z) throws
+                    -> () -> Expression<Z> {
         let fn = try createFunction(function, 0, deterministic) { _ in block() }
         return { fn([]) }
     }
 
-    func createFunction<Z : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping () -> Z?) throws -> (() -> Expression<Z?>) {
+    func createFunction<Z: Value>(_ function: String, deterministic: Bool = false, _ block: @escaping () -> Z?) throws
+                    -> () -> Expression<Z?> {
         let fn = try createFunction(function, 0, deterministic) { _ in block() }
         return { fn([]) }
     }
 
     // MARK: -
 
-    func createFunction<Z : Value, A : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A) -> Z) throws -> ((Expression<A>) -> Expression<Z>) {
+    func createFunction<Z: Value, A: Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A) -> Z) throws
+                    -> (Expression<A>) -> Expression<Z> {
         let fn = try createFunction(function, 1, deterministic) { args in block(value(args[0])) }
         return { arg in fn([arg]) }
     }
 
-    func createFunction<Z : Value, A : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?) -> Z) throws -> ((Expression<A?>) -> Expression<Z>) {
+    func createFunction<Z: Value, A: Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?) -> Z) throws
+                    -> (Expression<A?>) -> Expression<Z> {
         let fn = try createFunction(function, 1, deterministic) { args in block(args[0].map(value)) }
         return { arg in fn([arg]) }
     }
 
-    func createFunction<Z : Value, A : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A) -> Z?) throws -> ((Expression<A>) -> Expression<Z?>) {
+    func createFunction<Z: Value, A: Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A) -> Z?) throws
+                    -> (Expression<A>) -> Expression<Z?> {
         let fn = try createFunction(function, 1, deterministic) { args in block(value(args[0])) }
         return { arg in fn([arg]) }
     }
 
-    func createFunction<Z : Value, A : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?) -> Z?) throws -> ((Expression<A?>) -> Expression<Z?>) {
+    func createFunction<Z: Value, A: Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?) -> Z?) throws
+                    -> (Expression<A?>) -> Expression<Z?> {
         let fn = try createFunction(function, 1, deterministic) { args in block(args[0].map(value)) }
         return { arg in fn([arg]) }
     }
 
     // MARK: -
 
-    func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B) -> Z) throws -> (Expression<A>, Expression<B>) -> Expression<Z> {
+    func createFunction<Z: Value, A: Value, B: Value>(_ function: String, deterministic: Bool = false,
+                                                      _ block: @escaping (A, B) -> Z) throws -> (Expression<A>, Expression<B>)
+    -> Expression<Z> {
         let fn = try createFunction(function, 2, deterministic) { args in block(value(args[0]), value(args[1])) }
         return { a, b in fn([a, b]) }
     }
 
-    func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B) -> Z) throws -> (Expression<A?>, Expression<B>) -> Expression<Z> {
+    func createFunction<Z: Value, A: Value, B: Value>(_ function: String, deterministic: Bool = false,
+                                                      _ block: @escaping (A?, B) -> Z) throws
+                    -> (Expression<A?>, Expression<B>) -> Expression<Z> {
         let fn = try createFunction(function, 2, deterministic) { args in block(args[0].map(value), value(args[1])) }
         return { a, b in fn([a, b]) }
     }
 
-    func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B?) -> Z) throws -> (Expression<A>, Expression<B?>) -> Expression<Z> {
+    func createFunction<Z: Value, A: Value, B: Value>(_ function: String, deterministic: Bool = false,
+                                                      _ block: @escaping (A, B?) -> Z) throws ->
+            (Expression<A>, Expression<B?>) -> Expression<Z> {
         let fn = try createFunction(function, 2, deterministic) { args in block(value(args[0]), args[1].map(value)) }
         return { a, b in fn([a, b]) }
     }
 
-    func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B) -> Z?) throws -> (Expression<A>, Expression<B>) -> Expression<Z?> {
+    func createFunction<Z: Value, A: Value, B: Value>(_ function: String, deterministic: Bool = false,
+                                                      _ block: @escaping (A, B) -> Z?) throws
+                    -> (Expression<A>, Expression<B>) -> Expression<Z?> {
         let fn = try createFunction(function, 2, deterministic) { args in block(value(args[0]), value(args[1])) }
         return { a, b in fn([a, b]) }
     }
 
-    func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B?) -> Z) throws -> (Expression<A?>, Expression<B?>) -> Expression<Z> {
+    func createFunction<Z: Value, A: Value, B: Value>(_ function: String, deterministic: Bool = false,
+                                                      _ block: @escaping (A?, B?) -> Z) throws
+                    -> (Expression<A?>, Expression<B?>) -> Expression<Z> {
         let fn = try createFunction(function, 2, deterministic) { args in block(args[0].map(value), args[1].map(value)) }
         return { a, b in fn([a, b]) }
     }
 
-    func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B) -> Z?) throws -> (Expression<A?>, Expression<B>) -> Expression<Z?> {
+    func createFunction<Z: Value, A: Value, B: Value>(_ function: String, deterministic: Bool = false,
+                                                      _ block: @escaping (A?, B) -> Z?) throws
+                    -> (Expression<A?>, Expression<B>) -> Expression<Z?> {
         let fn = try createFunction(function, 2, deterministic) { args in block(args[0].map(value), value(args[1])) }
         return { a, b in fn([a, b]) }
     }
 
-    func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A, B?) -> Z?) throws -> (Expression<A>, Expression<B?>) -> Expression<Z?> {
+    func createFunction<Z: Value, A: Value, B: Value>(_ function: String, deterministic: Bool = false,
+                                                      _ block: @escaping (A, B?) -> Z?) throws
+                    -> (Expression<A>, Expression<B?>) -> Expression<Z?> {
         let fn = try createFunction(function, 2, deterministic) { args in block(value(args[0]), args[1].map(value)) }
         return { a, b in fn([a, b]) }
     }
 
-    func createFunction<Z : Value, A : Value, B : Value>(_ function: String, deterministic: Bool = false, _ block: @escaping (A?, B?) -> Z?) throws -> (Expression<A?>, Expression<B?>) -> Expression<Z?> {
+    func createFunction<Z: Value, A: Value, B: Value>(_ function: String, deterministic: Bool = false,
+                                                      _ block: @escaping (A?, B?) -> Z?) throws
+                    -> (Expression<A?>, Expression<B?>) -> Expression<Z?> {
         let fn = try createFunction(function, 2, deterministic) { args in block(args[0].map(value), args[1].map(value)) }
         return { a, b in fn([a, b]) }
     }
 
     // MARK: -
 
-    fileprivate func createFunction<Z : Value>(_ function: String, _ argumentCount: UInt, _ deterministic: Bool, _ block: @escaping ([Binding?]) -> Z) throws -> (([Expressible]) -> Expression<Z>) {
+    fileprivate func createFunction<Z: Value>(_ function: String, _ argumentCount: UInt, _ deterministic: Bool,
+                                              _ block: @escaping ([Binding?]) -> Z) throws
+                    -> ([Expressible]) -> Expression<Z> {
         createFunction(function, argumentCount: argumentCount, deterministic: deterministic) { arguments in
             block(arguments).datatypeValue
         }
@@ -124,7 +148,9 @@ public extension Connection {
         }
     }
 
-    fileprivate func createFunction<Z : Value>(_ function: String, _ argumentCount: UInt, _ deterministic: Bool, _ block: @escaping ([Binding?]) -> Z?) throws -> (([Expressible]) -> Expression<Z?>) {
+    fileprivate func createFunction<Z: Value>(_ function: String, _ argumentCount: UInt, _ deterministic: Bool,
+                                              _ block: @escaping ([Binding?]) -> Z?) throws
+                    -> ([Expressible]) -> Expression<Z?> {
         createFunction(function, argumentCount: argumentCount, deterministic: deterministic) { arguments in
             block(arguments)?.datatypeValue
         }
diff --git a/Sources/SQLite/Typed/Expression.swift b/Sources/SQLite/Typed/Expression.swift
index 76ba04c4..39a3c62f 100644
--- a/Sources/SQLite/Typed/Expression.swift
+++ b/Sources/SQLite/Typed/Expression.swift
@@ -22,7 +22,7 @@
 // THE SOFTWARE.
 //
 
-public protocol ExpressionType : Expressible { // extensions cannot have inheritance clauses
+public protocol ExpressionType: Expressible { // extensions cannot have inheritance clauses
 
     associatedtype UnderlyingType = Void
 
@@ -43,14 +43,14 @@ extension ExpressionType {
         self.init(literal: identifier.quote())
     }
 
-    public init<U : ExpressionType>(_ expression: U) {
+    public init<U: ExpressionType>(_ expression: U) {
         self.init(expression.template, expression.bindings)
     }
 
 }
 
 /// An `Expression` represents a raw SQL fragment and any associated bindings.
-public struct Expression<Datatype> : ExpressionType {
+public struct Expression<Datatype>: ExpressionType {
 
     public typealias UnderlyingType = Datatype
 
@@ -79,7 +79,7 @@ extension Expressible {
         var idx = 0
         return expressed.template.reduce("") { template, character in
             let transcoded: String
-            
+
             if character == "?" {
                 transcoded = transcode(expressed.bindings[idx])
                 idx += 1
@@ -108,7 +108,7 @@ extension ExpressionType {
 
 }
 
-extension ExpressionType where UnderlyingType : Value {
+extension ExpressionType where UnderlyingType: Value {
 
     public init(value: UnderlyingType) {
         self.init("?", [value.datatypeValue])
@@ -116,7 +116,7 @@ extension ExpressionType where UnderlyingType : Value {
 
 }
 
-extension ExpressionType where UnderlyingType : _OptionalType, UnderlyingType.WrappedType : Value {
+extension ExpressionType where UnderlyingType: _OptionalType, UnderlyingType.WrappedType: Value {
 
     public static var null: Self {
         return self.init(value: nil)
diff --git a/Sources/SQLite/Typed/Operators.swift b/Sources/SQLite/Typed/Operators.swift
index 954a4af4..32d39fa7 100644
--- a/Sources/SQLite/Typed/Operators.swift
+++ b/Sources/SQLite/Typed/Operators.swift
@@ -45,11 +45,11 @@ private enum Operator: String {
     case gte = ">="
     case lte = "<="
     case concatenate = "||"
-    
+
     func infix<T>(_ lhs: Expressible, _ rhs: Expressible, wrap: Bool = true) -> Expression<T> {
         return self.rawValue.infix(lhs, rhs, wrap: wrap)
     }
-    
+
     func wrap<T>(_ expression: Expressible) -> Expression<T> {
         return self.rawValue.wrap(expression)
     }
@@ -83,520 +83,521 @@ public func +(lhs: String, rhs: Expression<String?>) -> Expression<String?> {
 
 // MARK: -
 
-public func +<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
+public func +<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype: Number {
     return Operator.plus.infix(lhs, rhs)
 }
-public func +<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
+public func +<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
     return Operator.plus.infix(lhs, rhs)
 }
-public func +<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype : Number {
+public func +<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype: Number {
     return Operator.plus.infix(lhs, rhs)
 }
-public func +<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
+public func +<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
     return Operator.plus.infix(lhs, rhs)
 }
-public func +<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype : Number {
+public func +<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype: Number {
     return Operator.plus.infix(lhs, rhs)
 }
-public func +<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype : Number {
+public func +<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype: Number {
     return Operator.plus.infix(lhs, rhs)
 }
-public func +<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
+public func +<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype: Number {
     return Operator.plus.infix(lhs, rhs)
 }
-public func +<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
+public func +<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
     return Operator.plus.infix(lhs, rhs)
 }
 
-public func -<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
+public func -<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype: Number {
     return Operator.minus.infix(lhs, rhs)
 }
-public func -<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
+public func -<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
     return Operator.minus.infix(lhs, rhs)
 }
-public func -<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype : Number {
+public func -<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype: Number {
     return Operator.minus.infix(lhs, rhs)
 }
-public func -<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
+public func -<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
     return Operator.minus.infix(lhs, rhs)
 }
-public func -<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype : Number {
+public func -<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype: Number {
     return Operator.minus.infix(lhs, rhs)
 }
-public func -<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype : Number {
+public func -<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype: Number {
     return Operator.minus.infix(lhs, rhs)
 }
-public func -<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
+public func -<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype: Number {
     return Operator.minus.infix(lhs, rhs)
 }
-public func -<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
+public func -<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
     return Operator.minus.infix(lhs, rhs)
 }
 
-public func *<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
+public func *<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype: Number {
     return Operator.mul.infix(lhs, rhs)
 }
-public func *<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
+public func *<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
     return Operator.mul.infix(lhs, rhs)
 }
-public func *<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype : Number {
+public func *<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype: Number {
     return Operator.mul.infix(lhs, rhs)
 }
-public func *<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
+public func *<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
     return Operator.mul.infix(lhs, rhs)
 }
-public func *<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype : Number {
+public func *<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype: Number {
     return Operator.mul.infix(lhs, rhs)
 }
-public func *<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype : Number {
+public func *<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype: Number {
     return Operator.mul.infix(lhs, rhs)
 }
-public func *<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
+public func *<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype: Number {
     return Operator.mul.infix(lhs, rhs)
 }
-public func *<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
+public func *<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
     return Operator.mul.infix(lhs, rhs)
 }
 
-public func /<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
+public func /<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype: Number {
     return Operator.div.infix(lhs, rhs)
 }
-public func /<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
+public func /<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
     return Operator.div.infix(lhs, rhs)
 }
-public func /<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype : Number {
+public func /<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype: Number {
     return Operator.div.infix(lhs, rhs)
 }
-public func /<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
+public func /<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
     return Operator.div.infix(lhs, rhs)
 }
-public func /<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype : Number {
+public func /<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype: Number {
     return Operator.div.infix(lhs, rhs)
 }
-public func /<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype : Number {
+public func /<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype: Number {
     return Operator.div.infix(lhs, rhs)
 }
-public func /<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
+public func /<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype: Number {
     return Operator.div.infix(lhs, rhs)
 }
-public func /<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
+public func /<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
     return Operator.div.infix(lhs, rhs)
 }
 
-public prefix func -<V : Value>(rhs: Expression<V>) -> Expression<V> where V.Datatype : Number {
+public prefix func -<V: Value>(rhs: Expression<V>) -> Expression<V> where V.Datatype: Number {
     return Operator.minus.wrap(rhs)
 }
-public prefix func -<V : Value>(rhs: Expression<V?>) -> Expression<V?> where V.Datatype : Number {
+public prefix func -<V: Value>(rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
     return Operator.minus.wrap(rhs)
 }
 
 // MARK: -
 
-public func %<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
+public func %<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return Operator.mod.infix(lhs, rhs)
 }
-public func %<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
+public func %<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.mod.infix(lhs, rhs)
 }
-public func %<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
+public func %<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.mod.infix(lhs, rhs)
 }
-public func %<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
+public func %<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.mod.infix(lhs, rhs)
 }
-public func %<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
+public func %<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
     return Operator.mod.infix(lhs, rhs)
 }
-public func %<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
+public func %<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.mod.infix(lhs, rhs)
 }
-public func %<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
+public func %<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return Operator.mod.infix(lhs, rhs)
 }
-public func %<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
+public func %<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.mod.infix(lhs, rhs)
 }
 
-public func <<<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
+public func <<<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return Operator.bitwiseLeft.infix(lhs, rhs)
 }
-public func <<<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
+public func <<<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.bitwiseLeft.infix(lhs, rhs)
 }
-public func <<<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
+public func <<<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.bitwiseLeft.infix(lhs, rhs)
 }
-public func <<<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
+public func <<<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.bitwiseLeft.infix(lhs, rhs)
 }
-public func <<<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
+public func <<<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
     return Operator.bitwiseLeft.infix(lhs, rhs)
 }
-public func <<<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
+public func <<<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.bitwiseLeft.infix(lhs, rhs)
 }
-public func <<<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
+public func <<<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return Operator.bitwiseLeft.infix(lhs, rhs)
 }
-public func <<<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
+public func <<<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.bitwiseLeft.infix(lhs, rhs)
 }
 
-public func >><V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
+public func >><V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return Operator.bitwiseRight.infix(lhs, rhs)
 }
-public func >><V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
+public func >><V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.bitwiseRight.infix(lhs, rhs)
 }
-public func >><V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
+public func >><V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.bitwiseRight.infix(lhs, rhs)
 }
-public func >><V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
+public func >><V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.bitwiseRight.infix(lhs, rhs)
 }
-public func >><V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
+public func >><V: Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
     return Operator.bitwiseRight.infix(lhs, rhs)
 }
-public func >><V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
+public func >><V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.bitwiseRight.infix(lhs, rhs)
 }
-public func >><V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
+public func >><V: Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return Operator.bitwiseRight.infix(lhs, rhs)
 }
-public func >><V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
+public func >><V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.bitwiseRight.infix(lhs, rhs)
 }
 
-public func &<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
+public func &<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return Operator.bitwiseAnd.infix(lhs, rhs)
 }
-public func &<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
+public func &<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.bitwiseAnd.infix(lhs, rhs)
 }
-public func &<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
+public func &<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.bitwiseAnd.infix(lhs, rhs)
 }
-public func &<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
+public func &<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.bitwiseAnd.infix(lhs, rhs)
 }
-public func &<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
+public func &<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
     return Operator.bitwiseAnd.infix(lhs, rhs)
 }
-public func &<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
+public func &<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.bitwiseAnd.infix(lhs, rhs)
 }
-public func &<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
+public func &<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return Operator.bitwiseAnd.infix(lhs, rhs)
 }
-public func &<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
+public func &<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.bitwiseAnd.infix(lhs, rhs)
 }
 
-public func |<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
+public func |<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return Operator.bitwiseOr.infix(lhs, rhs)
 }
-public func |<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
+public func |<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.bitwiseOr.infix(lhs, rhs)
 }
-public func |<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
+public func |<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.bitwiseOr.infix(lhs, rhs)
 }
-public func |<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
+public func |<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.bitwiseOr.infix(lhs, rhs)
 }
-public func |<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
+public func |<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
     return Operator.bitwiseOr.infix(lhs, rhs)
 }
-public func |<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
+public func |<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.bitwiseOr.infix(lhs, rhs)
 }
-public func |<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
+public func |<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return Operator.bitwiseOr.infix(lhs, rhs)
 }
-public func |<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
+public func |<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.bitwiseOr.infix(lhs, rhs)
 }
 
-public func ^<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
+public func ^<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return (~(lhs & rhs)) & (lhs | rhs)
 }
-public func ^<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
+public func ^<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return (~(lhs & rhs)) & (lhs | rhs)
 }
-public func ^<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
+public func ^<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
     return (~(lhs & rhs)) & (lhs | rhs)
 }
-public func ^<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
+public func ^<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return (~(lhs & rhs)) & (lhs | rhs)
 }
-public func ^<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
+public func ^<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
     return (~(lhs & rhs)) & (lhs | rhs)
 }
-public func ^<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
+public func ^<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
     return (~(lhs & rhs)) & (lhs | rhs)
 }
-public func ^<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
+public func ^<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return (~(lhs & rhs)) & (lhs | rhs)
 }
-public func ^<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
+public func ^<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return (~(lhs & rhs)) & (lhs | rhs)
 }
 
-public prefix func ~<V : Value>(rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
+public prefix func ~<V: Value>(rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
     return Operator.bitwiseXor.wrap(rhs)
 }
-public prefix func ~<V : Value>(rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
+public prefix func ~<V: Value>(rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
     return Operator.bitwiseXor.wrap(rhs)
 }
 
 // MARK: -
 
-public func ==<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
+public func ==<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Equatable {
     return Operator.eq.infix(lhs, rhs)
 }
-public func ==<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
+public func ==<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
     return Operator.eq.infix(lhs, rhs)
 }
-public func ==<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Equatable {
+public func ==<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype: Equatable {
     return Operator.eq.infix(lhs, rhs)
 }
-public func ==<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
+public func ==<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
     return Operator.eq.infix(lhs, rhs)
 }
-public func ==<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Equatable {
+public func ==<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype: Equatable {
     return Operator.eq.infix(lhs, rhs)
 }
-public func ==<V : Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype : Equatable {
+public func ==<V: Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype: Equatable {
     guard let rhs = rhs else { return "IS".infix(lhs, Expression<V?>(value: nil)) }
     return Operator.eq.infix(lhs, rhs)
 }
-public func ==<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
+public func ==<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Equatable {
     return Operator.eq.infix(lhs, rhs)
 }
-public func ==<V : Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
+public func ==<V: Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
     guard let lhs = lhs else { return "IS".infix(Expression<V?>(value: nil), rhs) }
     return Operator.eq.infix(lhs, rhs)
 }
 
-public func ===<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
+public func ===<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Equatable {
     return "IS".infix(lhs, rhs)
 }
-public func ===<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
+public func ===<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
     return "IS".infix(lhs, rhs)
 }
-public func ===<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Equatable {
+public func ===<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype: Equatable {
     return "IS".infix(lhs, rhs)
 }
-public func ===<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
+public func ===<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
     return "IS".infix(lhs, rhs)
 }
-public func ===<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Equatable {
+public func ===<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype: Equatable {
     return "IS".infix(lhs, rhs)
 }
-public func ===<V : Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype : Equatable {
+public func ===<V: Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype: Equatable {
     guard let rhs = rhs else { return "IS".infix(lhs, Expression<V?>(value: nil)) }
     return "IS".infix(lhs, rhs)
 }
-public func ===<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
+public func ===<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Equatable {
     return "IS".infix(lhs, rhs)
 }
-public func ===<V : Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
+public func ===<V: Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
     guard let lhs = lhs else { return "IS".infix(Expression<V?>(value: nil), rhs) }
     return "IS".infix(lhs, rhs)
 }
 
-public func !=<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
+public func !=<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Equatable {
     return Operator.neq.infix(lhs, rhs)
 }
-public func !=<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
+public func !=<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
     return Operator.neq.infix(lhs, rhs)
 }
-public func !=<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Equatable {
+public func !=<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype: Equatable {
     return Operator.neq.infix(lhs, rhs)
 }
-public func !=<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
+public func !=<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
     return Operator.neq.infix(lhs, rhs)
 }
-public func !=<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Equatable {
+public func !=<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype: Equatable {
     return Operator.neq.infix(lhs, rhs)
 }
-public func !=<V : Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype : Equatable {
+public func !=<V: Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype: Equatable {
     guard let rhs = rhs else { return "IS NOT".infix(lhs, Expression<V?>(value: nil)) }
     return Operator.neq.infix(lhs, rhs)
 }
-public func !=<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
+public func !=<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Equatable {
     return Operator.neq.infix(lhs, rhs)
 }
-public func !=<V : Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
+public func !=<V: Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
     guard let lhs = lhs else { return "IS NOT".infix(Expression<V?>(value: nil), rhs) }
     return Operator.neq.infix(lhs, rhs)
 }
 
-public func !==<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
+public func !==<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Equatable {
     return "IS NOT".infix(lhs, rhs)
 }
-public func !==<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
+public func !==<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
     return "IS NOT".infix(lhs, rhs)
 }
-public func !==<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Equatable {
+public func !==<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype: Equatable {
     return "IS NOT".infix(lhs, rhs)
 }
-public func !==<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
+public func !==<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
     return "IS NOT".infix(lhs, rhs)
 }
-public func !==<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Equatable {
+public func !==<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype: Equatable {
     return "IS NOT".infix(lhs, rhs)
 }
-public func !==<V : Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype : Equatable {
+public func !==<V: Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype: Equatable {
     guard let rhs = rhs else { return "IS NOT".infix(lhs, Expression<V?>(value: nil)) }
     return "IS NOT".infix(lhs, rhs)
 }
-public func !==<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Equatable {
+public func !==<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Equatable {
     return "IS NOT".infix(lhs, rhs)
 }
-public func !==<V : Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Equatable {
+public func !==<V: Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
     guard let lhs = lhs else { return "IS NOT".infix(Expression<V?>(value: nil), rhs) }
     return "IS NOT".infix(lhs, rhs)
 }
 
-
-public func ><V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
+public func ><V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable {
     return Operator.gt.infix(lhs, rhs)
 }
-public func ><V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
+public func ><V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
     return Operator.gt.infix(lhs, rhs)
 }
-public func ><V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Comparable {
+public func ><V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype: Comparable {
     return Operator.gt.infix(lhs, rhs)
 }
-public func ><V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
+public func ><V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
     return Operator.gt.infix(lhs, rhs)
 }
-public func ><V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Comparable {
+public func ><V: Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype: Comparable {
     return Operator.gt.infix(lhs, rhs)
 }
-public func ><V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype : Comparable {
+public func ><V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype: Comparable {
     return Operator.gt.infix(lhs, rhs)
 }
-public func ><V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
+public func ><V: Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable {
     return Operator.gt.infix(lhs, rhs)
 }
-public func ><V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
+public func ><V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
     return Operator.gt.infix(lhs, rhs)
 }
 
-public func >=<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
+public func >=<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable {
     return Operator.gte.infix(lhs, rhs)
 }
-public func >=<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
+public func >=<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
     return Operator.gte.infix(lhs, rhs)
 }
-public func >=<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Comparable {
+public func >=<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype: Comparable {
     return Operator.gte.infix(lhs, rhs)
 }
-public func >=<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
+public func >=<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
     return Operator.gte.infix(lhs, rhs)
 }
-public func >=<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Comparable {
+public func >=<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype: Comparable {
     return Operator.gte.infix(lhs, rhs)
 }
-public func >=<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype : Comparable {
+public func >=<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype: Comparable {
     return Operator.gte.infix(lhs, rhs)
 }
-public func >=<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
+public func >=<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable {
     return Operator.gte.infix(lhs, rhs)
 }
-public func >=<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
+public func >=<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
     return Operator.gte.infix(lhs, rhs)
 }
 
-public func <<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
+public func <<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable {
     return Operator.lt.infix(lhs, rhs)
 }
-public func <<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
+public func <<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
     return Operator.lt.infix(lhs, rhs)
 }
-public func <<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Comparable {
+public func <<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype: Comparable {
     return Operator.lt.infix(lhs, rhs)
 }
-public func <<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
+public func <<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
     return Operator.lt.infix(lhs, rhs)
 }
-public func <<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Comparable {
+public func <<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype: Comparable {
     return Operator.lt.infix(lhs, rhs)
 }
-public func <<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype : Comparable {
+public func <<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype: Comparable {
     return Operator.lt.infix(lhs, rhs)
 }
-public func <<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
+public func <<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable {
     return Operator.lt.infix(lhs, rhs)
 }
-public func <<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
+public func <<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
     return Operator.lt.infix(lhs, rhs)
 }
 
-public func <=<V : Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
+public func <=<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable {
     return Operator.lte.infix(lhs, rhs)
 }
-public func <=<V : Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
+public func <=<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
     return Operator.lte.infix(lhs, rhs)
 }
-public func <=<V : Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype : Comparable {
+public func <=<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype: Comparable {
     return Operator.lte.infix(lhs, rhs)
 }
-public func <=<V : Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
+public func <=<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
     return Operator.lte.infix(lhs, rhs)
 }
-public func <=<V : Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype : Comparable {
+public func <=<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype: Comparable {
     return Operator.lte.infix(lhs, rhs)
 }
-public func <=<V : Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype : Comparable {
+public func <=<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype: Comparable {
     return Operator.lte.infix(lhs, rhs)
 }
-public func <=<V : Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable {
+public func <=<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable {
     return Operator.lte.infix(lhs, rhs)
 }
-public func <=<V : Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable {
+public func <=<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
     return Operator.lte.infix(lhs, rhs)
 }
 
-public func ~=<V : Value>(lhs: ClosedRange<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable & Value {
+public func ~=<V: Value>(lhs: ClosedRange<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable & Value {
     return Expression("\(rhs.template) BETWEEN ? AND ?", rhs.bindings + [lhs.lowerBound.datatypeValue, lhs.upperBound.datatypeValue])
 }
 
-public func ~=<V : Value>(lhs: ClosedRange<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable & Value {
+public func ~=<V: Value>(lhs: ClosedRange<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable & Value {
     return Expression("\(rhs.template) BETWEEN ? AND ?", rhs.bindings + [lhs.lowerBound.datatypeValue, lhs.upperBound.datatypeValue])
 }
 
-public func ~=<V : Value>(lhs: Range<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable & Value {
-    return Expression("\(rhs.template) >= ? AND \(rhs.template) < ?", rhs.bindings + [lhs.lowerBound.datatypeValue] + rhs.bindings + [lhs.upperBound.datatypeValue])
+public func ~=<V: Value>(lhs: Range<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable & Value {
+    return Expression("\(rhs.template) >= ? AND \(rhs.template) < ?", rhs.bindings + [lhs.lowerBound.datatypeValue] +
+            rhs.bindings + [lhs.upperBound.datatypeValue])
 }
 
-public func ~=<V : Value>(lhs: Range<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable & Value {
-    return Expression("\(rhs.template) >= ? AND \(rhs.template) < ?", rhs.bindings + [lhs.lowerBound.datatypeValue] + rhs.bindings + [lhs.upperBound.datatypeValue])
+public func ~=<V: Value>(lhs: Range<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable & Value {
+    return Expression("\(rhs.template) >= ? AND \(rhs.template) < ?", rhs.bindings + [lhs.lowerBound.datatypeValue] +
+            rhs.bindings + [lhs.upperBound.datatypeValue])
 }
 
-public func ~=<V : Value>(lhs: PartialRangeThrough<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable & Value {
+public func ~=<V: Value>(lhs: PartialRangeThrough<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable & Value {
     return Expression("\(rhs.template) <= ?", rhs.bindings + [lhs.upperBound.datatypeValue])
 }
 
-public func ~=<V : Value>(lhs: PartialRangeThrough<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable & Value {
+public func ~=<V: Value>(lhs: PartialRangeThrough<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable & Value {
     return Expression("\(rhs.template) <= ?", rhs.bindings + [lhs.upperBound.datatypeValue])
 }
 
-public func ~=<V : Value>(lhs: PartialRangeUpTo<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable & Value {
+public func ~=<V: Value>(lhs: PartialRangeUpTo<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable & Value {
     return Expression("\(rhs.template) < ?", rhs.bindings + [lhs.upperBound.datatypeValue])
 }
 
-public func ~=<V : Value>(lhs: PartialRangeUpTo<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable & Value {
+public func ~=<V: Value>(lhs: PartialRangeUpTo<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable & Value {
     return Expression("\(rhs.template) < ?", rhs.bindings + [lhs.upperBound.datatypeValue])
 }
 
-public func ~=<V : Value>(lhs: PartialRangeFrom<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype : Comparable & Value {
+public func ~=<V: Value>(lhs: PartialRangeFrom<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable & Value {
     return Expression("\(rhs.template) >= ?", rhs.bindings + [lhs.lowerBound.datatypeValue])
 }
 
-public func ~=<V : Value>(lhs: PartialRangeFrom<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype : Comparable & Value {
+public func ~=<V: Value>(lhs: PartialRangeFrom<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable & Value {
     return Expression("\(rhs.template) >= ?", rhs.bindings + [lhs.lowerBound.datatypeValue])
 }
 
@@ -667,6 +668,7 @@ public func ||(lhs: Bool, rhs: Expression<Bool?>) -> Expression<Bool?> {
 public prefix func !(rhs: Expression<Bool>) -> Expression<Bool> {
     return Operator.not.wrap(rhs)
 }
+
 public prefix func !(rhs: Expression<Bool?>) -> Expression<Bool?> {
     return Operator.not.wrap(rhs)
 }
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index 669001d3..8d3ded52 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -21,10 +21,10 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 //
-
+// swiftlint:disable file_length
 import Foundation
 
-public protocol QueryType : Expressible {
+public protocol QueryType: Expressible {
 
     var clauses: QueryClauses { get set }
 
@@ -32,7 +32,7 @@ public protocol QueryType : Expressible {
 
 }
 
-public protocol SchemaType : QueryType {
+public protocol SchemaType: QueryType {
 
     static var identifier: String { get }
 
@@ -141,10 +141,10 @@ extension SchemaType {
     /// - Parameter all: A list of expressions to select.
     ///
     /// - Returns: A query with the given `SELECT` clause applied.
-    public func select<V : Value>(_ column: Expression<V>) -> ScalarQuery<V> {
+    public func select<V: Value>(_ column: Expression<V>) -> ScalarQuery<V> {
         return select(false, [column])
     }
-    public func select<V : Value>(_ column: Expression<V?>) -> ScalarQuery<V?> {
+    public func select<V: Value>(_ column: Expression<V?>) -> ScalarQuery<V?> {
         return select(false, [column])
     }
 
@@ -160,10 +160,10 @@ extension SchemaType {
     /// - Parameter column: A list of expressions to select.
     ///
     /// - Returns: A query with the given `SELECT DISTINCT` clause applied.
-    public func select<V : Value>(distinct column: Expression<V>) -> ScalarQuery<V> {
+    public func select<V: Value>(distinct column: Expression<V>) -> ScalarQuery<V> {
         return select(true, [column])
     }
-    public func select<V : Value>(distinct column: Expression<V?>) -> ScalarQuery<V?> {
+    public func select<V: Value>(distinct column: Expression<V?>) -> ScalarQuery<V?> {
         return select(true, [column])
     }
 
@@ -175,7 +175,7 @@ extension SchemaType {
 
 extension QueryType {
 
-    fileprivate func select<Q : QueryType>(_ distinct: Bool, _ columns: [Expressible]) -> Q {
+    fileprivate func select<Q: QueryType>(_ distinct: Bool, _ columns: [Expressible]) -> Q {
         var query = Q.init(clauses.from.name, database: clauses.from.database)
         query.clauses = clauses
         query.clauses.select = (distinct, columns)
@@ -183,7 +183,7 @@ extension QueryType {
     }
 
     // MARK: UNION
-    
+
     /// Adds a `UNION` clause to the query.
     ///
     ///     let users = Table("users")
@@ -202,7 +202,7 @@ extension QueryType {
         query.clauses.union.append(table)
         return query
     }
-    
+
     // MARK: JOIN
 
     /// Adds a `JOIN` clause to the query.
@@ -589,12 +589,12 @@ extension QueryType {
             Expression<Void>(literal: "OFFSET \(offset)")
         ])
     }
-    
+
     fileprivate var unionClause: Expressible? {
         guard !clauses.union.isEmpty else {
             return nil
         }
-        
+
         return " ".join(clauses.union.map { query in
             " ".join([
                 Expression<Void>(literal: "UNION"),
@@ -709,28 +709,28 @@ extension QueryType {
             query.expression
         ]).expression)
     }
-    
+
     // MARK: UPSERT
-    
+
     public func upsert(_ insertValues: Setter..., onConflictOf conflicting: Expressible) -> Insert {
         return upsert(insertValues, onConflictOf: conflicting)
     }
-    
+
     public func upsert(_ insertValues: [Setter], onConflictOf conflicting: Expressible) -> Insert {
         let setValues = insertValues.filter { $0.column.asSQL() != conflicting.asSQL() }
             .map { Setter(excluded: $0.column) }
         return upsert(insertValues, onConflictOf: conflicting, set: setValues)
     }
-    
+
     public func upsert(_ insertValues: Setter..., onConflictOf conflicting: Expressible, set setValues: [Setter]) -> Insert {
         return upsert(insertValues, onConflictOf: conflicting, set: setValues)
     }
-    
+
     public func upsert(_ insertValues: [Setter], onConflictOf conflicting: Expressible, set setValues: [Setter]) -> Insert {
         let insert = insertValues.reduce((columns: [Expressible](), values: [Expressible]())) { insert, setter in
             (insert.columns + [setter.column], insert.values + [setter.value])
         }
-        
+
         let clauses: [Expressible?] = [
             Expression<Void>(literal: "INSERT"),
             Expression<Void>(literal: "INTO"),
@@ -744,11 +744,10 @@ extension QueryType {
             Expression<Void>(literal: "DO UPDATE SET"),
             ", ".join(setValues.map { $0.expression })
         ]
-        
+
         return Insert(" ".join(clauses.compactMap { $0 }).expression)
     }
 
-
     // MARK: UPDATE
 
     public func update(_ values: Setter...) -> Update {
@@ -826,7 +825,7 @@ extension QueryType {
 
     // TODO: alias support
     func tableName(alias aliased: Bool = false) -> Expressible {
-        guard let alias = clauses.from.alias , aliased else {
+        guard let alias = clauses.from.alias, aliased else {
             return database(namespace: clauses.from.alias ?? clauses.from.name)
         }
 
@@ -874,7 +873,7 @@ extension QueryType {
 
 /// Queries a collection of chainable helper functions and expressions to build
 /// executable SQL statements.
-public struct Table : SchemaType {
+public struct Table: SchemaType {
 
     public static let identifier = "TABLE"
 
@@ -886,7 +885,7 @@ public struct Table : SchemaType {
 
 }
 
-public struct View : SchemaType {
+public struct View: SchemaType {
 
     public static let identifier = "VIEW"
 
@@ -898,7 +897,7 @@ public struct View : SchemaType {
 
 }
 
-public struct VirtualTable : SchemaType {
+public struct VirtualTable: SchemaType {
 
     public static let identifier = "VIRTUAL TABLE"
 
@@ -912,7 +911,7 @@ public struct VirtualTable : SchemaType {
 
 // TODO: make `ScalarQuery` work in `QueryType.select()`, `.filter()`, etc.
 
-public struct ScalarQuery<V> : QueryType {
+public struct ScalarQuery<V>: QueryType {
 
     public var clauses: QueryClauses
 
@@ -924,7 +923,7 @@ public struct ScalarQuery<V> : QueryType {
 
 // TODO: decide: simplify the below with a boxed type instead
 
-public struct Select<T> : ExpressionType {
+public struct Select<T>: ExpressionType {
 
     public var template: String
     public var bindings: [Binding?]
@@ -936,7 +935,7 @@ public struct Select<T> : ExpressionType {
 
 }
 
-public struct Insert : ExpressionType {
+public struct Insert: ExpressionType {
 
     public var template: String
     public var bindings: [Binding?]
@@ -948,7 +947,7 @@ public struct Insert : ExpressionType {
 
 }
 
-public struct Update : ExpressionType {
+public struct Update: ExpressionType {
 
     public var template: String
     public var bindings: [Binding?]
@@ -960,7 +959,7 @@ public struct Update : ExpressionType {
 
 }
 
-public struct Delete : ExpressionType {
+public struct Delete: ExpressionType {
 
     public var template: String
     public var bindings: [Binding?]
@@ -972,7 +971,6 @@ public struct Delete : ExpressionType {
 
 }
 
-
 public struct RowIterator: FailableIterator {
     public typealias Element = Row
     let statement: Statement
@@ -1003,7 +1001,6 @@ extension Connection {
             AnyIterator { statement.next().map { Row(columnNames, $0) } }
         }
     }
-    
 
     public func prepareRowIterator(_ query: QueryType) throws -> RowIterator {
         let expression = query.expression
@@ -1017,9 +1014,9 @@ extension Connection {
             var names = each.expression.template.split { $0 == "." }.map(String.init)
             let column = names.removeLast()
             let namespace = names.joined(separator: ".")
-            
+
             func expandGlob(_ namespace: Bool) -> ((QueryType) throws -> Void) {
-                return { (query: QueryType) throws -> (Void) in
+                return { (query: QueryType) throws -> Void in
                     var q = type(of: query).init(query.clauses.from.name, database: query.clauses.from.database)
                     q.clauses.select = query.clauses.select
                     let e = q.expression
@@ -1028,7 +1025,7 @@ extension Connection {
                     for name in names { columnNames[name] = idx; idx += 1 }
                 }
             }
-            
+
             if column == "*" {
                 var select = query
                 select.clauses.select = (false, [Expression<Void>(literal: "*") as Expressible])
@@ -1047,30 +1044,30 @@ extension Connection {
                 }
                 continue
             }
-            
+
             columnNames[each.expression.template] = idx
             idx += 1
         }
         return columnNames
     }
 
-    public func scalar<V : Value>(_ query: ScalarQuery<V>) throws -> V {
+    public func scalar<V: Value>(_ query: ScalarQuery<V>) throws -> V {
         let expression = query.expression
         return value(try scalar(expression.template, expression.bindings))
     }
 
-    public func scalar<V : Value>(_ query: ScalarQuery<V?>) throws -> V.ValueType? {
+    public func scalar<V: Value>(_ query: ScalarQuery<V?>) throws -> V.ValueType? {
         let expression = query.expression
         guard let value = try scalar(expression.template, expression.bindings) as? V.Datatype else { return nil }
         return V.fromDatatypeValue(value)
     }
 
-    public func scalar<V : Value>(_ query: Select<V>) throws -> V {
+    public func scalar<V: Value>(_ query: Select<V>) throws -> V {
         let expression = query.expression
         return value(try scalar(expression.template, expression.bindings))
     }
 
-    public func scalar<V : Value>(_ query: Select<V?>) throws ->  V.ValueType? {
+    public func scalar<V: Value>(_ query: Select<V?>) throws ->  V.ValueType? {
         let expression = query.expression
         guard let value = try scalar(expression.template, expression.bindings) as? V.Datatype else { return nil }
         return V.fromDatatypeValue(value)
@@ -1186,17 +1183,17 @@ public struct Row {
         return valueAtIndex(idx)
     }
 
-    public subscript<T : Value>(column: Expression<T>) -> T {
+    public subscript<T: Value>(column: Expression<T>) -> T {
         return try! get(column)
     }
 
-    public subscript<T : Value>(column: Expression<T?>) -> T? {
+    public subscript<T: Value>(column: Expression<T?>) -> T? {
         return try! get(column)
     }
 }
 
 /// Determines the join operator for a query’s `JOIN` clause.
-public enum JoinType : String {
+public enum JoinType: String {
 
     /// A `CROSS` join.
     case cross = "CROSS"
@@ -1241,7 +1238,7 @@ public struct QueryClauses {
     var order = [Expressible]()
 
     var limit: (length: Int, offset: Int?)?
-    
+
     var union = [QueryType]()
 
     fileprivate init(_ name: String, alias: String?, database: String?) {
@@ -1249,4 +1246,3 @@ public struct QueryClauses {
     }
 
 }
-
diff --git a/Sources/SQLite/Typed/Schema.swift b/Sources/SQLite/Typed/Schema.swift
index febfe68c..d8d45e41 100644
--- a/Sources/SQLite/Typed/Schema.swift
+++ b/Sources/SQLite/Typed/Schema.swift
@@ -36,7 +36,8 @@ extension Table {
 
     // MARK: - CREATE TABLE
 
-    public func create(temporary: Bool = false, ifNotExists: Bool = false, withoutRowid: Bool = false, block: (TableBuilder) -> Void) -> String {
+    public func create(temporary: Bool = false, ifNotExists: Bool = false, withoutRowid: Bool = false,
+                       block: (TableBuilder) -> Void) -> String {
         let builder = TableBuilder()
 
         block(builder)
@@ -62,51 +63,59 @@ extension Table {
 
     // MARK: - ALTER TABLE … ADD COLUMN
 
-    public func addColumn<V : Value>(_ name: Expression<V>, check: Expression<Bool>? = nil, defaultValue: V) -> String {
+    public func addColumn<V: Value>(_ name: Expression<V>, check: Expression<Bool>? = nil, defaultValue: V) -> String {
         return addColumn(definition(name, V.declaredDatatype, nil, false, false, check, defaultValue, nil, nil))
     }
 
-    public func addColumn<V : Value>(_ name: Expression<V>, check: Expression<Bool?>, defaultValue: V) -> String {
+    public func addColumn<V: Value>(_ name: Expression<V>, check: Expression<Bool?>, defaultValue: V) -> String {
         return addColumn(definition(name, V.declaredDatatype, nil, false, false, check, defaultValue, nil, nil))
     }
 
-    public func addColumn<V : Value>(_ name: Expression<V?>, check: Expression<Bool>? = nil, defaultValue: V? = nil) -> String {
+    public func addColumn<V: Value>(_ name: Expression<V?>, check: Expression<Bool>? = nil, defaultValue: V? = nil) -> String {
         return addColumn(definition(name, V.declaredDatatype, nil, true, false, check, defaultValue, nil, nil))
     }
 
-    public func addColumn<V : Value>(_ name: Expression<V?>, check: Expression<Bool?>, defaultValue: V? = nil) -> String {
+    public func addColumn<V: Value>(_ name: Expression<V?>, check: Expression<Bool?>, defaultValue: V? = nil) -> String {
         return addColumn(definition(name, V.declaredDatatype, nil, true, false, check, defaultValue, nil, nil))
     }
 
-    public func addColumn<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil, references table: QueryType, _ other: Expression<V>) -> String where V.Datatype == Int64 {
+    public func addColumn<V: Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil,
+                                    references table: QueryType, _ other: Expression<V>) -> String where V.Datatype == Int64 {
         return addColumn(definition(name, V.declaredDatatype, nil, false, unique, check, nil, (table, other), nil))
     }
 
-    public func addColumn<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool?>, references table: QueryType, _ other: Expression<V>) -> String where V.Datatype == Int64 {
+    public func addColumn<V: Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool?>,
+                                    references table: QueryType, _ other: Expression<V>) -> String where V.Datatype == Int64 {
         return addColumn(definition(name, V.declaredDatatype, nil, false, unique, check, nil, (table, other), nil))
     }
 
-    public func addColumn<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, references table: QueryType, _ other: Expression<V>) -> String where V.Datatype == Int64 {
+    public func addColumn<V: Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil,
+                                    references table: QueryType, _ other: Expression<V>) -> String where V.Datatype == Int64 {
         return addColumn(definition(name, V.declaredDatatype, nil, true, unique, check, nil, (table, other), nil))
     }
 
-    public func addColumn<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, references table: QueryType, _ other: Expression<V>) -> String where V.Datatype == Int64 {
+    public func addColumn<V: Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>,
+                                    references table: QueryType, _ other: Expression<V>) -> String where V.Datatype == Int64 {
         return addColumn(definition(name, V.declaredDatatype, nil, true, unique, check, nil, (table, other), nil))
     }
 
-    public func addColumn<V : Value>(_ name: Expression<V>, check: Expression<Bool>? = nil, defaultValue: V, collate: Collation) -> String where V.Datatype == String {
+    public func addColumn<V: Value>(_ name: Expression<V>, check: Expression<Bool>? = nil, defaultValue: V,
+                                    collate: Collation) -> String where V.Datatype == String {
         return addColumn(definition(name, V.declaredDatatype, nil, false, false, check, defaultValue, nil, collate))
     }
 
-    public func addColumn<V : Value>(_ name: Expression<V>, check: Expression<Bool?>, defaultValue: V, collate: Collation) -> String where V.Datatype == String {
+    public func addColumn<V: Value>(_ name: Expression<V>, check: Expression<Bool?>, defaultValue: V,
+                                    collate: Collation) -> String where V.Datatype == String {
         return addColumn(definition(name, V.declaredDatatype, nil, false, false, check, defaultValue, nil, collate))
     }
 
-    public func addColumn<V : Value>(_ name: Expression<V?>, check: Expression<Bool>? = nil, defaultValue: V? = nil, collate: Collation) -> String where V.Datatype == String {
+    public func addColumn<V: Value>(_ name: Expression<V?>, check: Expression<Bool>? = nil, defaultValue: V? = nil,
+                                    collate: Collation) -> String where V.Datatype == String {
         return addColumn(definition(name, V.declaredDatatype, nil, true, false, check, defaultValue, nil, collate))
     }
 
-    public func addColumn<V : Value>(_ name: Expression<V?>, check: Expression<Bool?>, defaultValue: V? = nil, collate: Collation) -> String where V.Datatype == String {
+    public func addColumn<V: Value>(_ name: Expression<V?>, check: Expression<Bool?>, defaultValue: V? = nil,
+                                    collate: Collation) -> String where V.Datatype == String {
         return addColumn(definition(name, V.declaredDatatype, nil, true, false, check, defaultValue, nil, collate))
     }
 
@@ -140,7 +149,6 @@ extension Table {
 
     // MARK: - DROP INDEX
 
-
     public func dropIndex(_ columns: Expressible..., ifExists: Bool = false) -> String {
         return drop("INDEX", indexName(columns), ifExists)
     }
@@ -211,138 +219,175 @@ public final class TableBuilder {
 
     fileprivate var definitions = [Expressible]()
 
-    public func column<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: Expression<V>? = nil) {
+    public func column<V: Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil,
+                                 defaultValue: Expression<V>? = nil) {
         column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: V) {
+    public func column<V: Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil,
+                                 defaultValue: V) {
         column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool?>, defaultValue: Expression<V>? = nil) {
+    public func column<V: Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool?>,
+                                 defaultValue: Expression<V>? = nil) {
         column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool?>, defaultValue: V) {
+    public func column<V: Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool?>,
+                                 defaultValue: V) {
         column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: Expression<V>? = nil) {
+    public func column<V: Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil,
+                                 defaultValue: Expression<V>? = nil) {
         column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: Expression<V?>) {
+    public func column<V: Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil,
+                                 defaultValue: Expression<V?>) {
         column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: V) {
+    public func column<V: Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil,
+                                 defaultValue: V) {
         column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, defaultValue: Expression<V>? = nil) {
+    public func column<V: Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>,
+                                 defaultValue: Expression<V>? = nil) {
         column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, defaultValue: Expression<V?>) {
+    public func column<V: Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>,
+                                 defaultValue: Expression<V?>) {
         column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, defaultValue: V) {
+    public func column<V: Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>,
+                                 defaultValue: V) {
         column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value>(_ name: Expression<V>, primaryKey: Bool, check: Expression<Bool>? = nil, defaultValue: Expression<V>? = nil) {
+    public func column<V: Value>(_ name: Expression<V>, primaryKey: Bool, check: Expression<Bool>? = nil,
+                                 defaultValue: Expression<V>? = nil) {
         column(name, V.declaredDatatype, primaryKey ? .default : nil, false, false, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value>(_ name: Expression<V>, primaryKey: Bool, check: Expression<Bool?>, defaultValue: Expression<V>? = nil) {
+    public func column<V: Value>(_ name: Expression<V>, primaryKey: Bool, check: Expression<Bool?>,
+                                 defaultValue: Expression<V>? = nil) {
         column(name, V.declaredDatatype, primaryKey ? .default : nil, false, false, check, defaultValue, nil, nil)
     }
 
-    public func column<V : Value>(_ name: Expression<V>, primaryKey: PrimaryKey, check: Expression<Bool>? = nil) where V.Datatype == Int64 {
+    public func column<V: Value>(_ name: Expression<V>, primaryKey: PrimaryKey,
+                                 check: Expression<Bool>? = nil) where V.Datatype == Int64 {
         column(name, V.declaredDatatype, primaryKey, false, false, check, nil, nil, nil)
     }
 
-    public func column<V : Value>(_ name: Expression<V>, primaryKey: PrimaryKey, check: Expression<Bool?>) where V.Datatype == Int64 {
+    public func column<V: Value>(_ name: Expression<V>, primaryKey: PrimaryKey,
+                                 check: Expression<Bool?>) where V.Datatype == Int64 {
         column(name, V.declaredDatatype, primaryKey, false, false, check, nil, nil, nil)
     }
 
-    public func column<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil, references table: QueryType, _ other: Expression<V>) where V.Datatype == Int64 {
+    public func column<V: Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil,
+                                 references table: QueryType, _ other: Expression<V>) where V.Datatype == Int64 {
         column(name, V.declaredDatatype, nil, false, unique, check, nil, (table, other), nil)
     }
 
-    public func column<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool?>, references table: QueryType, _ other: Expression<V>) where V.Datatype == Int64 {
+    public func column<V: Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool?>,
+                                 references table: QueryType, _ other: Expression<V>) where V.Datatype == Int64 {
         column(name, V.declaredDatatype, nil, false, unique, check, nil, (table, other), nil)
     }
 
-    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, references table: QueryType, _ other: Expression<V>) where V.Datatype == Int64 {
+    public func column<V: Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil,
+                                 references table: QueryType, _ other: Expression<V>) where V.Datatype == Int64 {
         column(name, V.declaredDatatype, nil, true, unique, check, nil, (table, other), nil)
     }
 
-    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, references table: QueryType, _ other: Expression<V>) where V.Datatype == Int64 {
+    public func column<V: Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>,
+                                 references table: QueryType, _ other: Expression<V>) where V.Datatype == Int64 {
         column(name, V.declaredDatatype, nil, true, unique, check, nil, (table, other), nil)
     }
 
-    public func column<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: Expression<V>? = nil, collate: Collation) where V.Datatype == String {
+    public func column<V: Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil,
+                                 defaultValue: Expression<V>? = nil, collate: Collation) where V.Datatype == String {
         column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate)
     }
 
-    public func column<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: V, collate: Collation) where V.Datatype == String {
+    public func column<V: Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil,
+                                 defaultValue: V, collate: Collation) where V.Datatype == String {
         column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate)
     }
 
-    public func column<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool?>, defaultValue: Expression<V>? = nil, collate: Collation) where V.Datatype == String {
+    public func column<V: Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool?>,
+                                 defaultValue: Expression<V>? = nil, collate: Collation) where V.Datatype == String {
         column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate)
     }
 
-    public func column<V : Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool?>, defaultValue: V, collate: Collation) where V.Datatype == String {
+    public func column<V: Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool?>,
+                                 defaultValue: V, collate: Collation) where V.Datatype == String {
         column(name, V.declaredDatatype, nil, false, unique, check, defaultValue, nil, collate)
     }
 
-    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: Expression<V>? = nil, collate: Collation) where V.Datatype == String {
+    public func column<V: Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil,
+                                 defaultValue: Expression<V>? = nil, collate: Collation) where V.Datatype == String {
         column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, collate)
     }
 
-    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: Expression<V?>, collate: Collation) where V.Datatype == String {
+    public func column<V: Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil,
+                                 defaultValue: Expression<V?>, collate: Collation) where V.Datatype == String {
         column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, collate)
     }
 
-    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil, defaultValue: V, collate: Collation) where V.Datatype == String {
+    public func column<V: Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil,
+                                 defaultValue: V, collate: Collation) where V.Datatype == String {
         column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, collate)
     }
 
-    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, defaultValue: Expression<V>? = nil, collate: Collation) where V.Datatype == String {
+    public func column<V: Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>,
+                                 defaultValue: Expression<V>? = nil, collate: Collation) where V.Datatype == String {
         column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, collate)
     }
 
-    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, defaultValue: Expression<V?>, collate: Collation) where V.Datatype == String {
+    public func column<V: Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>,
+                                 defaultValue: Expression<V?>, collate: Collation) where V.Datatype == String {
         column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, collate)
     }
 
-    public func column<V : Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>, defaultValue: V, collate: Collation) where V.Datatype == String {
+    public func column<V: Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>,
+                                 defaultValue: V, collate: Collation) where V.Datatype == String {
         column(name, V.declaredDatatype, nil, true, unique, check, defaultValue, nil, collate)
     }
 
-    fileprivate func column(_ name: Expressible, _ datatype: String, _ primaryKey: PrimaryKey?, _ null: Bool, _ unique: Bool, _ check: Expressible?, _ defaultValue: Expressible?, _ references: (QueryType, Expressible)?, _ collate: Collation?) {
+    // swiftlint:disable:next function_parameter_count
+    fileprivate func column(_ name: Expressible, _ datatype: String, _ primaryKey: PrimaryKey?, _ null: Bool,
+                            _ unique: Bool, _ check: Expressible?, _ defaultValue: Expressible?,
+                            _ references: (QueryType, Expressible)?, _ collate: Collation?) {
         definitions.append(definition(name, datatype, primaryKey, null, unique, check, defaultValue, references, collate))
     }
 
     // MARK: -
 
-    public func primaryKey<T : Value>(_ column: Expression<T>) {
+    public func primaryKey<T: Value>(_ column: Expression<T>) {
         primaryKey([column])
     }
 
-    public func primaryKey<T : Value, U : Value>(_ compositeA: Expression<T>, _ b: Expression<U>) {
-        primaryKey([compositeA, b])
+    public func primaryKey<T: Value, U: Value>(_ compositeA: Expression<T>,
+                                               _ expr: Expression<U>) {
+        primaryKey([compositeA, expr])
     }
 
-    public func primaryKey<T : Value, U : Value, V : Value>(_ compositeA: Expression<T>, _ b: Expression<U>, _ c: Expression<V>) {
-        primaryKey([compositeA, b, c])
+    public func primaryKey<T: Value, U: Value, V: Value>(_ compositeA: Expression<T>,
+                                                         _ expr1: Expression<U>,
+                                                         _ expr2: Expression<V>) {
+        primaryKey([compositeA, expr1, expr2])
     }
 
-    public func primaryKey<T : Value, U : Value, V : Value, W : Value>(_ compositeA: Expression<T>, _ b: Expression<U>, _ c: Expression<V>, _ d: Expression<W>) {
-        primaryKey([compositeA, b, c, d])
+    public func primaryKey<T: Value, U: Value, V: Value, W: Value>(_ compositeA: Expression<T>,
+                                                                   _ expr1: Expression<U>,
+                                                                   _ expr2: Expression<V>,
+                                                                   _ expr3: Expression<W>) {
+        primaryKey([compositeA, expr1, expr2, expr3])
     }
 
     fileprivate func primaryKey(_ composite: [Expressible]) {
@@ -379,29 +424,37 @@ public final class TableBuilder {
 
     }
 
-    public func foreignKey<T : Value>(_ column: Expression<T>, references table: QueryType, _ other: Expression<T>, update: Dependency? = nil, delete: Dependency? = nil) {
+    public func foreignKey<T: Value>(_ column: Expression<T>, references table: QueryType, _ other: Expression<T>,
+                                     update: Dependency? = nil, delete: Dependency? = nil) {
         foreignKey(column, (table, other), update, delete)
     }
 
-    public func foreignKey<T : Value>(_ column: Expression<T?>, references table: QueryType, _ other: Expression<T>, update: Dependency? = nil, delete: Dependency? = nil) {
+    public func foreignKey<T: Value>(_ column: Expression<T?>, references table: QueryType, _ other: Expression<T>,
+                                     update: Dependency? = nil, delete: Dependency? = nil) {
         foreignKey(column, (table, other), update, delete)
     }
 
-    public func foreignKey<T : Value, U : Value>(_ composite: (Expression<T>, Expression<U>), references table: QueryType, _ other: (Expression<T>, Expression<U>), update: Dependency? = nil, delete: Dependency? = nil) {
+    public func foreignKey<T: Value, U: Value>(_ composite: (Expression<T>, Expression<U>),
+                                               references table: QueryType, _ other: (Expression<T>, Expression<U>),
+                                               update: Dependency? = nil, delete: Dependency? = nil) {
         let composite = ", ".join([composite.0, composite.1])
         let references = (table, ", ".join([other.0, other.1]))
 
         foreignKey(composite, references, update, delete)
     }
 
-    public func foreignKey<T : Value, U : Value, V : Value>(_ composite: (Expression<T>, Expression<U>, Expression<V>), references table: QueryType, _ other: (Expression<T>, Expression<U>, Expression<V>), update: Dependency? = nil, delete: Dependency? = nil) {
+    public func foreignKey<T: Value, U: Value, V: Value>(_ composite: (Expression<T>, Expression<U>, Expression<V>),
+                                                         references table: QueryType,
+                                                         _ other: (Expression<T>, Expression<U>, Expression<V>),
+                                                         update: Dependency? = nil, delete: Dependency? = nil) {
         let composite = ", ".join([composite.0, composite.1, composite.2])
         let references = (table, ", ".join([other.0, other.1, other.2]))
 
         foreignKey(composite, references, update, delete)
     }
 
-    fileprivate func foreignKey(_ column: Expressible, _ references: (QueryType, Expressible), _ update: Dependency?, _ delete: Dependency?) {
+    fileprivate func foreignKey(_ column: Expressible, _ references: (QueryType, Expressible),
+                                _ update: Dependency?, _ delete: Dependency?) {
         let clauses: [Expressible?] = [
             "FOREIGN KEY".prefix(column),
             reference(references),
@@ -439,7 +492,7 @@ public struct Module {
 
 }
 
-extension Module : Expressible {
+extension Module: Expressible {
 
     public var expression: Expression<Void> {
         return name.wrap(arguments)
@@ -484,7 +537,10 @@ private extension QueryType {
 
 }
 
-private func definition(_ column: Expressible, _ datatype: String, _ primaryKey: PrimaryKey?, _ null: Bool, _ unique: Bool, _ check: Expressible?, _ defaultValue: Expressible?, _ references: (QueryType, Expressible)?, _ collate: Collation?) -> Expressible {
+// swiftlint:disable:next function_parameter_count
+private func definition(_ column: Expressible, _ datatype: String, _ primaryKey: PrimaryKey?, _ null: Bool,
+                        _ unique: Bool, _ check: Expressible?, _ defaultValue: Expressible?,
+                        _ references: (QueryType, Expressible)?, _ collate: Collation?) -> Expressible {
     let clauses: [Expressible?] = [
         column,
         Expression<Void>(literal: datatype),
@@ -508,7 +564,7 @@ private func reference(_ primary: (QueryType, Expressible)) -> Expressible {
     ])
 }
 
-private enum Modifier : String {
+private enum Modifier: String {
 
     case unique = "UNIQUE"
 
diff --git a/Sources/SQLite/Typed/Setter.swift b/Sources/SQLite/Typed/Setter.swift
index 3d3170f6..25e88342 100644
--- a/Sources/SQLite/Typed/Setter.swift
+++ b/Sources/SQLite/Typed/Setter.swift
@@ -35,27 +35,27 @@ public struct Setter {
     let column: Expressible
     let value: Expressible
 
-    fileprivate init<V : Value>(column: Expression<V>, value: Expression<V>) {
+    fileprivate init<V: Value>(column: Expression<V>, value: Expression<V>) {
         self.column = column
         self.value = value
     }
 
-    fileprivate init<V : Value>(column: Expression<V>, value: V) {
+    fileprivate init<V: Value>(column: Expression<V>, value: V) {
         self.column = column
         self.value = value
     }
 
-    fileprivate init<V : Value>(column: Expression<V?>, value: Expression<V>) {
+    fileprivate init<V: Value>(column: Expression<V?>, value: Expression<V>) {
         self.column = column
         self.value = value
     }
 
-    fileprivate init<V : Value>(column: Expression<V?>, value: Expression<V?>) {
+    fileprivate init<V: Value>(column: Expression<V?>, value: Expression<V?>) {
         self.column = column
         self.value = value
     }
 
-    fileprivate init<V : Value>(column: Expression<V?>, value: V?) {
+    fileprivate init<V: Value>(column: Expression<V?>, value: V?) {
         self.column = column
         self.value = Expression<V?>(value: value)
     }
@@ -67,7 +67,7 @@ public struct Setter {
     }
 }
 
-extension Setter : Expressible {
+extension Setter: Expressible {
 
     public var expression: Expression<Void> {
         return "=".infix(column, value, wrap: false)
@@ -75,19 +75,19 @@ extension Setter : Expressible {
 
 }
 
-public func <-<V : Value>(column: Expression<V>, value: Expression<V>) -> Setter {
+public func <-<V: Value>(column: Expression<V>, value: Expression<V>) -> Setter {
     return Setter(column: column, value: value)
 }
-public func <-<V : Value>(column: Expression<V>, value: V) -> Setter {
+public func <-<V: Value>(column: Expression<V>, value: V) -> Setter {
     return Setter(column: column, value: value)
 }
-public func <-<V : Value>(column: Expression<V?>, value: Expression<V>) -> Setter {
+public func <-<V: Value>(column: Expression<V?>, value: Expression<V>) -> Setter {
     return Setter(column: column, value: value)
 }
-public func <-<V : Value>(column: Expression<V?>, value: Expression<V?>) -> Setter {
+public func <-<V: Value>(column: Expression<V?>, value: Expression<V?>) -> Setter {
     return Setter(column: column, value: value)
 }
-public func <-<V : Value>(column: Expression<V?>, value: V?) -> Setter {
+public func <-<V: Value>(column: Expression<V?>, value: V?) -> Setter {
     return Setter(column: column, value: value)
 }
 
@@ -107,176 +107,176 @@ public func +=(column: Expression<String?>, value: String) -> Setter {
     return column <- column + value
 }
 
-public func +=<V : Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype : Number {
+public func +=<V: Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype: Number {
     return column <- column + value
 }
-public func +=<V : Value>(column: Expression<V>, value: V) -> Setter where V.Datatype : Number {
+public func +=<V: Value>(column: Expression<V>, value: V) -> Setter where V.Datatype: Number {
     return column <- column + value
 }
-public func +=<V : Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype : Number {
+public func +=<V: Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype: Number {
     return column <- column + value
 }
-public func +=<V : Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype : Number {
+public func +=<V: Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype: Number {
     return column <- column + value
 }
-public func +=<V : Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype : Number {
+public func +=<V: Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype: Number {
     return column <- column + value
 }
 
-public func -=<V : Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype : Number {
+public func -=<V: Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype: Number {
     return column <- column - value
 }
-public func -=<V : Value>(column: Expression<V>, value: V) -> Setter where V.Datatype : Number {
+public func -=<V: Value>(column: Expression<V>, value: V) -> Setter where V.Datatype: Number {
     return column <- column - value
 }
-public func -=<V : Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype : Number {
+public func -=<V: Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype: Number {
     return column <- column - value
 }
-public func -=<V : Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype : Number {
+public func -=<V: Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype: Number {
     return column <- column - value
 }
-public func -=<V : Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype : Number {
+public func -=<V: Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype: Number {
     return column <- column - value
 }
 
-public func *=<V : Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype : Number {
+public func *=<V: Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype: Number {
     return column <- column * value
 }
-public func *=<V : Value>(column: Expression<V>, value: V) -> Setter where V.Datatype : Number {
+public func *=<V: Value>(column: Expression<V>, value: V) -> Setter where V.Datatype: Number {
     return column <- column * value
 }
-public func *=<V : Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype : Number {
+public func *=<V: Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype: Number {
     return column <- column * value
 }
-public func *=<V : Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype : Number {
+public func *=<V: Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype: Number {
     return column <- column * value
 }
-public func *=<V : Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype : Number {
+public func *=<V: Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype: Number {
     return column <- column * value
 }
 
-public func /=<V : Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype : Number {
+public func /=<V: Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype: Number {
     return column <- column / value
 }
-public func /=<V : Value>(column: Expression<V>, value: V) -> Setter where V.Datatype : Number {
+public func /=<V: Value>(column: Expression<V>, value: V) -> Setter where V.Datatype: Number {
     return column <- column / value
 }
-public func /=<V : Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype : Number {
+public func /=<V: Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype: Number {
     return column <- column / value
 }
-public func /=<V : Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype : Number {
+public func /=<V: Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype: Number {
     return column <- column / value
 }
-public func /=<V : Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype : Number {
+public func /=<V: Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype: Number {
     return column <- column / value
 }
 
-public func %=<V : Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
+public func %=<V: Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column % value
 }
-public func %=<V : Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
+public func %=<V: Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column % value
 }
-public func %=<V : Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
+public func %=<V: Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column % value
 }
-public func %=<V : Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
+public func %=<V: Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
     return column <- column % value
 }
-public func %=<V : Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
+public func %=<V: Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column % value
 }
 
-public func <<=<V : Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
+public func <<=<V: Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column << value
 }
-public func <<=<V : Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
+public func <<=<V: Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column << value
 }
-public func <<=<V : Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
+public func <<=<V: Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column << value
 }
-public func <<=<V : Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
+public func <<=<V: Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
     return column <- column << value
 }
-public func <<=<V : Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
+public func <<=<V: Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column << value
 }
 
-public func >>=<V : Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
+public func >>=<V: Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column >> value
 }
-public func >>=<V : Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
+public func >>=<V: Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column >> value
 }
-public func >>=<V : Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
+public func >>=<V: Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column >> value
 }
-public func >>=<V : Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
+public func >>=<V: Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
     return column <- column >> value
 }
-public func >>=<V : Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
+public func >>=<V: Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column >> value
 }
 
-public func &=<V : Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
+public func &=<V: Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column & value
 }
-public func &=<V : Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
+public func &=<V: Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column & value
 }
-public func &=<V : Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
+public func &=<V: Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column & value
 }
-public func &=<V : Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
+public func &=<V: Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
     return column <- column & value
 }
-public func &=<V : Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
+public func &=<V: Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column & value
 }
 
-public func |=<V : Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
+public func |=<V: Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column | value
 }
-public func |=<V : Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
+public func |=<V: Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column | value
 }
-public func |=<V : Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
+public func |=<V: Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column | value
 }
-public func |=<V : Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
+public func |=<V: Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
     return column <- column | value
 }
-public func |=<V : Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
+public func |=<V: Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column | value
 }
 
-public func ^=<V : Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
+public func ^=<V: Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column ^ value
 }
-public func ^=<V : Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
+public func ^=<V: Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column ^ value
 }
-public func ^=<V : Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
+public func ^=<V: Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
     return column <- column ^ value
 }
-public func ^=<V : Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
+public func ^=<V: Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
     return column <- column ^ value
 }
-public func ^=<V : Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
+public func ^=<V: Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
     return column <- column ^ value
 }
 
-public postfix func ++<V : Value>(column: Expression<V>) -> Setter where V.Datatype == Int64 {
+public postfix func ++<V: Value>(column: Expression<V>) -> Setter where V.Datatype == Int64 {
     return Expression<Int>(column) += 1
 }
-public postfix func ++<V : Value>(column: Expression<V?>) -> Setter where V.Datatype == Int64 {
+public postfix func ++<V: Value>(column: Expression<V?>) -> Setter where V.Datatype == Int64 {
     return Expression<Int>(column) += 1
 }
 
-public postfix func --<V : Value>(column: Expression<V>) -> Setter where V.Datatype == Int64 {
+public postfix func --<V: Value>(column: Expression<V>) -> Setter where V.Datatype == Int64 {
     return Expression<Int>(column) -= 1
 }
-public postfix func --<V : Value>(column: Expression<V?>) -> Setter where V.Datatype == Int64 {
+public postfix func --<V: Value>(column: Expression<V?>) -> Setter where V.Datatype == Int64 {
     return Expression<Int>(column) -= 1
 }
diff --git a/Tests/.swiftlint.yml b/Tests/.swiftlint.yml
new file mode 100644
index 00000000..3537085c
--- /dev/null
+++ b/Tests/.swiftlint.yml
@@ -0,0 +1,20 @@
+parent_config: ../.swiftlint.yml
+
+disabled_rules:
+  - force_cast
+  - force_try
+  - identifier_name
+
+type_body_length:
+  warning: 800
+  error: 800
+
+function_body_length:
+  warning: 200
+  error: 200
+
+file_length:
+  warning: 1000
+  error: 1000
+
+
diff --git a/Tests/SQLiteTests/AggregateFunctionsTests.swift b/Tests/SQLiteTests/AggregateFunctionsTests.swift
index 6b583ccf..71ac79fb 100644
--- a/Tests/SQLiteTests/AggregateFunctionsTests.swift
+++ b/Tests/SQLiteTests/AggregateFunctionsTests.swift
@@ -1,68 +1,68 @@
 import XCTest
 import SQLite
 
-class AggregateFunctionsTests : XCTestCase {
+class AggregateFunctionsTests: XCTestCase {
 
     func test_distinct_prependsExpressionsWithDistinctKeyword() {
-        AssertSQL("DISTINCT \"int\"", int.distinct)
-        AssertSQL("DISTINCT \"intOptional\"", intOptional.distinct)
-        AssertSQL("DISTINCT \"double\"", double.distinct)
-        AssertSQL("DISTINCT \"doubleOptional\"", doubleOptional.distinct)
-        AssertSQL("DISTINCT \"string\"", string.distinct)
-        AssertSQL("DISTINCT \"stringOptional\"", stringOptional.distinct)
+        assertSQL("DISTINCT \"int\"", int.distinct)
+        assertSQL("DISTINCT \"intOptional\"", intOptional.distinct)
+        assertSQL("DISTINCT \"double\"", double.distinct)
+        assertSQL("DISTINCT \"doubleOptional\"", doubleOptional.distinct)
+        assertSQL("DISTINCT \"string\"", string.distinct)
+        assertSQL("DISTINCT \"stringOptional\"", stringOptional.distinct)
     }
 
     func test_count_wrapsOptionalExpressionsWithCountFunction() {
-        AssertSQL("count(\"intOptional\")", intOptional.count)
-        AssertSQL("count(\"doubleOptional\")", doubleOptional.count)
-        AssertSQL("count(\"stringOptional\")", stringOptional.count)
+        assertSQL("count(\"intOptional\")", intOptional.count)
+        assertSQL("count(\"doubleOptional\")", doubleOptional.count)
+        assertSQL("count(\"stringOptional\")", stringOptional.count)
     }
 
     func test_max_wrapsComparableExpressionsWithMaxFunction() {
-        AssertSQL("max(\"int\")", int.max)
-        AssertSQL("max(\"intOptional\")", intOptional.max)
-        AssertSQL("max(\"double\")", double.max)
-        AssertSQL("max(\"doubleOptional\")", doubleOptional.max)
-        AssertSQL("max(\"string\")", string.max)
-        AssertSQL("max(\"stringOptional\")", stringOptional.max)
-        AssertSQL("max(\"date\")", date.max)
-        AssertSQL("max(\"dateOptional\")", dateOptional.max)
+        assertSQL("max(\"int\")", int.max)
+        assertSQL("max(\"intOptional\")", intOptional.max)
+        assertSQL("max(\"double\")", double.max)
+        assertSQL("max(\"doubleOptional\")", doubleOptional.max)
+        assertSQL("max(\"string\")", string.max)
+        assertSQL("max(\"stringOptional\")", stringOptional.max)
+        assertSQL("max(\"date\")", date.max)
+        assertSQL("max(\"dateOptional\")", dateOptional.max)
     }
 
     func test_min_wrapsComparableExpressionsWithMinFunction() {
-        AssertSQL("min(\"int\")", int.min)
-        AssertSQL("min(\"intOptional\")", intOptional.min)
-        AssertSQL("min(\"double\")", double.min)
-        AssertSQL("min(\"doubleOptional\")", doubleOptional.min)
-        AssertSQL("min(\"string\")", string.min)
-        AssertSQL("min(\"stringOptional\")", stringOptional.min)
-        AssertSQL("min(\"date\")", date.min)
-        AssertSQL("min(\"dateOptional\")", dateOptional.min)
+        assertSQL("min(\"int\")", int.min)
+        assertSQL("min(\"intOptional\")", intOptional.min)
+        assertSQL("min(\"double\")", double.min)
+        assertSQL("min(\"doubleOptional\")", doubleOptional.min)
+        assertSQL("min(\"string\")", string.min)
+        assertSQL("min(\"stringOptional\")", stringOptional.min)
+        assertSQL("min(\"date\")", date.min)
+        assertSQL("min(\"dateOptional\")", dateOptional.min)
     }
 
     func test_average_wrapsNumericExpressionsWithAvgFunction() {
-        AssertSQL("avg(\"int\")", int.average)
-        AssertSQL("avg(\"intOptional\")", intOptional.average)
-        AssertSQL("avg(\"double\")", double.average)
-        AssertSQL("avg(\"doubleOptional\")", doubleOptional.average)
+        assertSQL("avg(\"int\")", int.average)
+        assertSQL("avg(\"intOptional\")", intOptional.average)
+        assertSQL("avg(\"double\")", double.average)
+        assertSQL("avg(\"doubleOptional\")", doubleOptional.average)
     }
 
     func test_sum_wrapsNumericExpressionsWithSumFunction() {
-        AssertSQL("sum(\"int\")", int.sum)
-        AssertSQL("sum(\"intOptional\")", intOptional.sum)
-        AssertSQL("sum(\"double\")", double.sum)
-        AssertSQL("sum(\"doubleOptional\")", doubleOptional.sum)
+        assertSQL("sum(\"int\")", int.sum)
+        assertSQL("sum(\"intOptional\")", intOptional.sum)
+        assertSQL("sum(\"double\")", double.sum)
+        assertSQL("sum(\"doubleOptional\")", doubleOptional.sum)
     }
 
     func test_total_wrapsNumericExpressionsWithTotalFunction() {
-        AssertSQL("total(\"int\")", int.total)
-        AssertSQL("total(\"intOptional\")", intOptional.total)
-        AssertSQL("total(\"double\")", double.total)
-        AssertSQL("total(\"doubleOptional\")", doubleOptional.total)
+        assertSQL("total(\"int\")", int.total)
+        assertSQL("total(\"intOptional\")", intOptional.total)
+        assertSQL("total(\"double\")", double.total)
+        assertSQL("total(\"doubleOptional\")", doubleOptional.total)
     }
 
     func test_count_withStar_wrapsStarWithCountFunction() {
-        AssertSQL("count(*)", count(*))
+        assertSQL("count(*)", count(*))
     }
 
 }
diff --git a/Tests/SQLiteTests/BlobTests.swift b/Tests/SQLiteTests/BlobTests.swift
index 817205d6..87eb5709 100644
--- a/Tests/SQLiteTests/BlobTests.swift
+++ b/Tests/SQLiteTests/BlobTests.swift
@@ -1,7 +1,7 @@
 import XCTest
 import SQLite
 
-class BlobTests : XCTestCase {
+class BlobTests: XCTestCase {
 
     func test_toHex() {
         let blob = Blob(bytes: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 150, 250, 255])
diff --git a/Tests/SQLiteTests/CipherTests.swift b/Tests/SQLiteTests/CipherTests.swift
index a27ac17d..77e8e7f0 100644
--- a/Tests/SQLiteTests/CipherTests.swift
+++ b/Tests/SQLiteTests/CipherTests.swift
@@ -77,7 +77,7 @@ class CipherTests: XCTestCase {
         // sqlite> pragma key = 'sqlcipher-test';
         // sqlite> CREATE TABLE foo (bar TEXT);
         // sqlite> INSERT INTO foo (bar) VALUES ('world');
-        guard let cipherVersion:String = db1.cipherVersion,
+        guard let cipherVersion: String = db1.cipherVersion,
             cipherVersion.starts(with: "3.") || cipherVersion.starts(with: "4.")
             else { return }
 
@@ -85,12 +85,12 @@ class CipherTests: XCTestCase {
             fixture("encrypted-3.x", withExtension: "sqlite") :
             fixture("encrypted-4.x", withExtension: "sqlite")
 
-        try! FileManager.default.setAttributes([FileAttributeKey.immutable : 1], ofItemAtPath: encryptedFile)
+        try! FileManager.default.setAttributes([FileAttributeKey.immutable: 1], ofItemAtPath: encryptedFile)
         XCTAssertFalse(FileManager.default.isWritableFile(atPath: encryptedFile))
 
         defer {
             // ensure file can be cleaned up afterwards
-            try! FileManager.default.setAttributes([FileAttributeKey.immutable : 0], ofItemAtPath: encryptedFile)
+            try! FileManager.default.setAttributes([FileAttributeKey.immutable: 0], ofItemAtPath: encryptedFile)
         }
 
         let conn = try! Connection(encryptedFile)
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index a05cceb5..00fe4f6b 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -13,12 +13,12 @@ import CSQLite
 import SQLite3
 #endif
 
-class ConnectionTests : SQLiteTestCase {
+class ConnectionTests: SQLiteTestCase {
 
     override func setUp() {
         super.setUp()
 
-        CreateUsersTable()
+        createUsersTable()
     }
 
     func test_init_withInMemory_returnsInMemoryConnection() {
@@ -62,13 +62,13 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_lastInsertRowid_returnsLastIdAfterInserts() {
-        try! InsertUser("alice")
+        try! insertUser("alice")
         XCTAssertEqual(1, db.lastInsertRowid)
     }
 
     func test_lastInsertRowid_doesNotResetAfterError() {
         XCTAssert(db.lastInsertRowid == 0)
-        try! InsertUser("alice")
+        try! insertUser("alice")
         XCTAssertEqual(1, db.lastInsertRowid)
         XCTAssertThrowsError(
             try db.run("INSERT INTO \"users\" (email, age, admin) values ('invalid@example.com', 12, 'invalid')")
@@ -83,17 +83,17 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_changes_returnsNumberOfChanges() {
-        try! InsertUser("alice")
+        try! insertUser("alice")
         XCTAssertEqual(1, db.changes)
-        try! InsertUser("betsy")
+        try! insertUser("betsy")
         XCTAssertEqual(1, db.changes)
     }
 
     func test_totalChanges_returnsTotalNumberOfChanges() {
         XCTAssertEqual(0, db.totalChanges)
-        try! InsertUser("alice")
+        try! insertUser("alice")
         XCTAssertEqual(1, db.totalChanges)
-        try! InsertUser("betsy")
+        try! insertUser("betsy")
         XCTAssertEqual(2, db.totalChanges)
     }
 
@@ -109,9 +109,9 @@ class ConnectionTests : SQLiteTestCase {
         try! db.run("SELECT * FROM users WHERE admin = ?", 0)
         try! db.run("SELECT * FROM users WHERE admin = ?", [0])
         try! db.run("SELECT * FROM users WHERE admin = $admin", ["$admin": 0])
-        AssertSQL("SELECT * FROM users WHERE admin = 0", 4)
+        assertSQL("SELECT * FROM users WHERE admin = 0", 4)
     }
-    
+
     func test_vacuum() {
         try! db.vacuum()
     }
@@ -121,31 +121,31 @@ class ConnectionTests : SQLiteTestCase {
         XCTAssertEqual(0, try! db.scalar("SELECT count(*) FROM users WHERE admin = ?", 0) as? Int64)
         XCTAssertEqual(0, try! db.scalar("SELECT count(*) FROM users WHERE admin = ?", [0]) as? Int64)
         XCTAssertEqual(0, try! db.scalar("SELECT count(*) FROM users WHERE admin = $admin", ["$admin": 0]) as? Int64)
-        AssertSQL("SELECT count(*) FROM users WHERE admin = 0", 4)
+        assertSQL("SELECT count(*) FROM users WHERE admin = 0", 4)
     }
 
     func test_execute_comment() {
         try! db.run("-- this is a comment\nSELECT 1")
-        AssertSQL("-- this is a comment", 0)
-        AssertSQL("SELECT 1", 0)
+        assertSQL("-- this is a comment", 0)
+        assertSQL("SELECT 1", 0)
     }
 
     func test_transaction_executesBeginDeferred() {
         try! db.transaction(.deferred) {}
 
-        AssertSQL("BEGIN DEFERRED TRANSACTION")
+        assertSQL("BEGIN DEFERRED TRANSACTION")
     }
 
     func test_transaction_executesBeginImmediate() {
         try! db.transaction(.immediate) {}
 
-        AssertSQL("BEGIN IMMEDIATE TRANSACTION")
+        assertSQL("BEGIN IMMEDIATE TRANSACTION")
     }
 
     func test_transaction_executesBeginExclusive() {
         try! db.transaction(.exclusive) {}
 
-        AssertSQL("BEGIN EXCLUSIVE TRANSACTION")
+        assertSQL("BEGIN EXCLUSIVE TRANSACTION")
     }
 
     func test_transaction_beginsAndCommitsTransactions() {
@@ -155,10 +155,10 @@ class ConnectionTests : SQLiteTestCase {
             try stmt.run()
         }
 
-        AssertSQL("BEGIN DEFERRED TRANSACTION")
-        AssertSQL("INSERT INTO users (email) VALUES ('alice@example.com')")
-        AssertSQL("COMMIT TRANSACTION")
-        AssertSQL("ROLLBACK TRANSACTION", 0)
+        assertSQL("BEGIN DEFERRED TRANSACTION")
+        assertSQL("INSERT INTO users (email) VALUES ('alice@example.com')")
+        assertSQL("COMMIT TRANSACTION")
+        assertSQL("ROLLBACK TRANSACTION", 0)
     }
 
     func test_transaction_rollsBackTransactionsIfCommitsFail() {
@@ -186,10 +186,10 @@ class ConnectionTests : SQLiteTestCase {
             XCTFail("unexpected error: \(error)")
         }
 
-        AssertSQL("BEGIN DEFERRED TRANSACTION")
-        AssertSQL("INSERT INTO users (email, manager_id) VALUES ('alice@example.com', 100)")
-        AssertSQL("COMMIT TRANSACTION")
-        AssertSQL("ROLLBACK TRANSACTION")
+        assertSQL("BEGIN DEFERRED TRANSACTION")
+        assertSQL("INSERT INTO users (email, manager_id) VALUES ('alice@example.com', 100)")
+        assertSQL("COMMIT TRANSACTION")
+        assertSQL("ROLLBACK TRANSACTION")
 
         // Run another transaction to ensure that a subsequent transaction does not fail with an "cannot start a
         // transaction within a transaction" error.
@@ -210,14 +210,14 @@ class ConnectionTests : SQLiteTestCase {
         } catch {
         }
 
-        AssertSQL("BEGIN DEFERRED TRANSACTION")
-        AssertSQL("INSERT INTO users (email) VALUES ('alice@example.com')", 2)
-        AssertSQL("ROLLBACK TRANSACTION")
-        AssertSQL("COMMIT TRANSACTION", 0)
+        assertSQL("BEGIN DEFERRED TRANSACTION")
+        assertSQL("INSERT INTO users (email) VALUES ('alice@example.com')", 2)
+        assertSQL("ROLLBACK TRANSACTION")
+        assertSQL("COMMIT TRANSACTION", 0)
     }
 
     func test_savepoint_beginsAndCommitsSavepoints() {
-        let db:Connection = self.db
+        let db: Connection = self.db
 
         try! db.savepoint("1") {
             try db.savepoint("2") {
@@ -225,17 +225,17 @@ class ConnectionTests : SQLiteTestCase {
             }
         }
 
-        AssertSQL("SAVEPOINT '1'")
-        AssertSQL("SAVEPOINT '2'")
-        AssertSQL("INSERT INTO users (email) VALUES ('alice@example.com')")
-        AssertSQL("RELEASE SAVEPOINT '2'")
-        AssertSQL("RELEASE SAVEPOINT '1'")
-        AssertSQL("ROLLBACK TO SAVEPOINT '2'", 0)
-        AssertSQL("ROLLBACK TO SAVEPOINT '1'", 0)
+        assertSQL("SAVEPOINT '1'")
+        assertSQL("SAVEPOINT '2'")
+        assertSQL("INSERT INTO users (email) VALUES ('alice@example.com')")
+        assertSQL("RELEASE SAVEPOINT '2'")
+        assertSQL("RELEASE SAVEPOINT '1'")
+        assertSQL("ROLLBACK TO SAVEPOINT '2'", 0)
+        assertSQL("ROLLBACK TO SAVEPOINT '1'", 0)
     }
 
     func test_savepoint_beginsAndRollsSavepointsBack() {
-        let db:Connection = self.db
+        let db: Connection = self.db
         let stmt = try! db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com")
 
         do {
@@ -254,13 +254,13 @@ class ConnectionTests : SQLiteTestCase {
         } catch {
         }
 
-        AssertSQL("SAVEPOINT '1'")
-        AssertSQL("SAVEPOINT '2'")
-        AssertSQL("INSERT INTO users (email) VALUES ('alice@example.com')", 2)
-        AssertSQL("ROLLBACK TO SAVEPOINT '2'")
-        AssertSQL("ROLLBACK TO SAVEPOINT '1'")
-        AssertSQL("RELEASE SAVEPOINT '2'", 0)
-        AssertSQL("RELEASE SAVEPOINT '1'", 0)
+        assertSQL("SAVEPOINT '1'")
+        assertSQL("SAVEPOINT '2'")
+        assertSQL("INSERT INTO users (email) VALUES ('alice@example.com')", 2)
+        assertSQL("ROLLBACK TO SAVEPOINT '2'")
+        assertSQL("ROLLBACK TO SAVEPOINT '1'")
+        assertSQL("RELEASE SAVEPOINT '2'", 0)
+        assertSQL("RELEASE SAVEPOINT '1'", 0)
     }
 
     func test_updateHook_setsUpdateHook_withInsert() {
@@ -272,12 +272,12 @@ class ConnectionTests : SQLiteTestCase {
                 XCTAssertEqual(1, rowid)
                 done()
             }
-            try! InsertUser("alice")
+            try! insertUser("alice")
         }
     }
 
     func test_updateHook_setsUpdateHook_withUpdate() {
-        try! InsertUser("alice")
+        try! insertUser("alice")
         async { done in
             db.updateHook { operation, db, table, rowid in
                 XCTAssertEqual(Connection.Operation.update, operation)
@@ -291,7 +291,7 @@ class ConnectionTests : SQLiteTestCase {
     }
 
     func test_updateHook_setsUpdateHook_withDelete() {
-        try! InsertUser("alice")
+        try! insertUser("alice")
         async { done in
             db.updateHook { operation, db, table, rowid in
                 XCTAssertEqual(Connection.Operation.delete, operation)
@@ -310,7 +310,7 @@ class ConnectionTests : SQLiteTestCase {
                 done()
             }
             try! db.transaction {
-                try self.InsertUser("alice")
+                try self.insertUser("alice")
             }
             XCTAssertEqual(1, try! db.scalar("SELECT count(*) FROM users") as? Int64)
         }
@@ -321,8 +321,8 @@ class ConnectionTests : SQLiteTestCase {
             db.rollbackHook(done)
             do {
                 try db.transaction {
-                    try self.InsertUser("alice")
-                    try self.InsertUser("alice") // throw
+                    try self.insertUser("alice")
+                    try self.insertUser("alice") // throw
                 }
             } catch {
             }
@@ -338,7 +338,7 @@ class ConnectionTests : SQLiteTestCase {
             db.rollbackHook(done)
             do {
                 try db.transaction {
-                    try self.InsertUser("alice")
+                    try self.insertUser("alice")
                 }
             } catch {
             }
@@ -376,7 +376,7 @@ class ConnectionTests : SQLiteTestCase {
 
     func test_interrupt_interruptsLongRunningQuery() {
         let semaphore = DispatchSemaphore(value: 0)
-        db.createFunction("sleep") { args in
+        db.createFunction("sleep") { _ in
             DispatchQueue.global(qos: .background).async {
                 self.db.interrupt()
                 semaphore.signal()
@@ -396,7 +396,7 @@ class ConnectionTests : SQLiteTestCase {
 
     func test_concurrent_access_single_connection() {
         // test can fail on iOS/tvOS 9.x: SQLite compile-time differences?
-        guard #available(iOS 10.0, OSX 10.10, tvOS 10.0, watchOS 2.2, *) else  { return }
+        guard #available(iOS 10.0, OSX 10.10, tvOS 10.0, watchOS 2.2, *) else { return }
 
         let conn = try! Connection("\(NSTemporaryDirectory())/\(UUID().uuidString)")
         try! conn.execute("DROP TABLE IF EXISTS test; CREATE TABLE test(value);")
@@ -416,8 +416,7 @@ class ConnectionTests : SQLiteTestCase {
     }
 }
 
-
-class ResultTests : XCTestCase {
+class ResultTests: XCTestCase {
     let connection = try! Connection(.inMemory)
 
     func test_init_with_ok_code_returns_nil() {
@@ -434,13 +433,13 @@ class ResultTests : XCTestCase {
 
     func test_init_with_other_code_returns_error() {
         if case .some(.error(let message, let code, let statement)) =
-            Result(errorCode: SQLITE_MISUSE, connection: connection, statement: nil)  {
+            Result(errorCode: SQLITE_MISUSE, connection: connection, statement: nil) {
             XCTAssertEqual("not an error", message)
             XCTAssertEqual(SQLITE_MISUSE, code)
             XCTAssertNil(statement)
             XCTAssert(self.connection === connection)
         } else {
-            XCTFail()
+            XCTFail("no error")
         }
     }
 
diff --git a/Tests/SQLiteTests/CoreFunctionsTests.swift b/Tests/SQLiteTests/CoreFunctionsTests.swift
index e7402de3..e03e3769 100644
--- a/Tests/SQLiteTests/CoreFunctionsTests.swift
+++ b/Tests/SQLiteTests/CoreFunctionsTests.swift
@@ -1,145 +1,145 @@
 import XCTest
 @testable import SQLite
 
-class CoreFunctionsTests : XCTestCase {
+class CoreFunctionsTests: XCTestCase {
 
     func test_round_wrapsDoubleExpressionsWithRoundFunction() {
-        AssertSQL("round(\"double\")", double.round())
-        AssertSQL("round(\"doubleOptional\")", doubleOptional.round())
+        assertSQL("round(\"double\")", double.round())
+        assertSQL("round(\"doubleOptional\")", doubleOptional.round())
 
-        AssertSQL("round(\"double\", 1)", double.round(1))
-        AssertSQL("round(\"doubleOptional\", 2)", doubleOptional.round(2))
+        assertSQL("round(\"double\", 1)", double.round(1))
+        assertSQL("round(\"doubleOptional\", 2)", doubleOptional.round(2))
     }
 
     func test_random_generatesExpressionWithRandomFunction() {
-        AssertSQL("random()", Expression<Int64>.random())
-        AssertSQL("random()", Expression<Int>.random())
+        assertSQL("random()", Expression<Int64>.random())
+        assertSQL("random()", Expression<Int>.random())
     }
 
     func test_length_wrapsStringExpressionWithLengthFunction() {
-        AssertSQL("length(\"string\")", string.length)
-        AssertSQL("length(\"stringOptional\")", stringOptional.length)
+        assertSQL("length(\"string\")", string.length)
+        assertSQL("length(\"stringOptional\")", stringOptional.length)
     }
 
     func test_lowercaseString_wrapsStringExpressionWithLowerFunction() {
-        AssertSQL("lower(\"string\")", string.lowercaseString)
-        AssertSQL("lower(\"stringOptional\")", stringOptional.lowercaseString)
+        assertSQL("lower(\"string\")", string.lowercaseString)
+        assertSQL("lower(\"stringOptional\")", stringOptional.lowercaseString)
     }
 
     func test_uppercaseString_wrapsStringExpressionWithUpperFunction() {
-        AssertSQL("upper(\"string\")", string.uppercaseString)
-        AssertSQL("upper(\"stringOptional\")", stringOptional.uppercaseString)
+        assertSQL("upper(\"string\")", string.uppercaseString)
+        assertSQL("upper(\"stringOptional\")", stringOptional.uppercaseString)
     }
 
     func test_like_buildsExpressionWithLikeOperator() {
-        AssertSQL("(\"string\" LIKE 'a%')", string.like("a%"))
-        AssertSQL("(\"stringOptional\" LIKE 'b%')", stringOptional.like("b%"))
-
-        AssertSQL("(\"string\" LIKE '%\\%' ESCAPE '\\')", string.like("%\\%", escape: "\\"))
-        AssertSQL("(\"stringOptional\" LIKE '_\\_' ESCAPE '\\')", stringOptional.like("_\\_", escape: "\\"))
-        
-        AssertSQL("(\"string\" LIKE \"a\")", string.like(Expression<String>("a")))
-        AssertSQL("(\"stringOptional\" LIKE \"a\")", stringOptional.like(Expression<String>("a")))
-        
-        AssertSQL("(\"string\" LIKE \"a\" ESCAPE '\\')", string.like(Expression<String>("a"), escape: "\\"))
-        AssertSQL("(\"stringOptional\" LIKE \"a\" ESCAPE '\\')", stringOptional.like(Expression<String>("a"), escape: "\\"))
-        
-        AssertSQL("('string' LIKE \"a\")", "string".like(Expression<String>("a")))
-        AssertSQL("('string' LIKE \"a\" ESCAPE '\\')", "string".like(Expression<String>("a"), escape: "\\"))
+        assertSQL("(\"string\" LIKE 'a%')", string.like("a%"))
+        assertSQL("(\"stringOptional\" LIKE 'b%')", stringOptional.like("b%"))
+
+        assertSQL("(\"string\" LIKE '%\\%' ESCAPE '\\')", string.like("%\\%", escape: "\\"))
+        assertSQL("(\"stringOptional\" LIKE '_\\_' ESCAPE '\\')", stringOptional.like("_\\_", escape: "\\"))
+
+        assertSQL("(\"string\" LIKE \"a\")", string.like(Expression<String>("a")))
+        assertSQL("(\"stringOptional\" LIKE \"a\")", stringOptional.like(Expression<String>("a")))
+
+        assertSQL("(\"string\" LIKE \"a\" ESCAPE '\\')", string.like(Expression<String>("a"), escape: "\\"))
+        assertSQL("(\"stringOptional\" LIKE \"a\" ESCAPE '\\')", stringOptional.like(Expression<String>("a"), escape: "\\"))
+
+        assertSQL("('string' LIKE \"a\")", "string".like(Expression<String>("a")))
+        assertSQL("('string' LIKE \"a\" ESCAPE '\\')", "string".like(Expression<String>("a"), escape: "\\"))
     }
 
     func test_glob_buildsExpressionWithGlobOperator() {
-        AssertSQL("(\"string\" GLOB 'a*')", string.glob("a*"))
-        AssertSQL("(\"stringOptional\" GLOB 'b*')", stringOptional.glob("b*"))
+        assertSQL("(\"string\" GLOB 'a*')", string.glob("a*"))
+        assertSQL("(\"stringOptional\" GLOB 'b*')", stringOptional.glob("b*"))
     }
 
     func test_match_buildsExpressionWithMatchOperator() {
-        AssertSQL("(\"string\" MATCH 'a*')", string.match("a*"))
-        AssertSQL("(\"stringOptional\" MATCH 'b*')", stringOptional.match("b*"))
+        assertSQL("(\"string\" MATCH 'a*')", string.match("a*"))
+        assertSQL("(\"stringOptional\" MATCH 'b*')", stringOptional.match("b*"))
     }
 
     func test_regexp_buildsExpressionWithRegexpOperator() {
-        AssertSQL("(\"string\" REGEXP '^.+@.+\\.com$')", string.regexp("^.+@.+\\.com$"))
-        AssertSQL("(\"stringOptional\" REGEXP '^.+@.+\\.net$')", stringOptional.regexp("^.+@.+\\.net$"))
+        assertSQL("(\"string\" REGEXP '^.+@.+\\.com$')", string.regexp("^.+@.+\\.com$"))
+        assertSQL("(\"stringOptional\" REGEXP '^.+@.+\\.net$')", stringOptional.regexp("^.+@.+\\.net$"))
     }
 
     func test_collate_buildsExpressionWithCollateOperator() {
-        AssertSQL("(\"string\" COLLATE BINARY)", string.collate(.binary))
-        AssertSQL("(\"string\" COLLATE NOCASE)", string.collate(.nocase))
-        AssertSQL("(\"string\" COLLATE RTRIM)", string.collate(.rtrim))
-        AssertSQL("(\"string\" COLLATE \"CUSTOM\")", string.collate(.custom("CUSTOM")))
+        assertSQL("(\"string\" COLLATE BINARY)", string.collate(.binary))
+        assertSQL("(\"string\" COLLATE NOCASE)", string.collate(.nocase))
+        assertSQL("(\"string\" COLLATE RTRIM)", string.collate(.rtrim))
+        assertSQL("(\"string\" COLLATE \"CUSTOM\")", string.collate(.custom("CUSTOM")))
 
-        AssertSQL("(\"stringOptional\" COLLATE BINARY)", stringOptional.collate(.binary))
-        AssertSQL("(\"stringOptional\" COLLATE NOCASE)", stringOptional.collate(.nocase))
-        AssertSQL("(\"stringOptional\" COLLATE RTRIM)", stringOptional.collate(.rtrim))
-        AssertSQL("(\"stringOptional\" COLLATE \"CUSTOM\")", stringOptional.collate(.custom("CUSTOM")))
+        assertSQL("(\"stringOptional\" COLLATE BINARY)", stringOptional.collate(.binary))
+        assertSQL("(\"stringOptional\" COLLATE NOCASE)", stringOptional.collate(.nocase))
+        assertSQL("(\"stringOptional\" COLLATE RTRIM)", stringOptional.collate(.rtrim))
+        assertSQL("(\"stringOptional\" COLLATE \"CUSTOM\")", stringOptional.collate(.custom("CUSTOM")))
     }
 
     func test_ltrim_wrapsStringWithLtrimFunction() {
-        AssertSQL("ltrim(\"string\")", string.ltrim())
-        AssertSQL("ltrim(\"stringOptional\")", stringOptional.ltrim())
+        assertSQL("ltrim(\"string\")", string.ltrim())
+        assertSQL("ltrim(\"stringOptional\")", stringOptional.ltrim())
 
-        AssertSQL("ltrim(\"string\", ' ')", string.ltrim([" "]))
-        AssertSQL("ltrim(\"stringOptional\", ' ')", stringOptional.ltrim([" "]))
+        assertSQL("ltrim(\"string\", ' ')", string.ltrim([" "]))
+        assertSQL("ltrim(\"stringOptional\", ' ')", stringOptional.ltrim([" "]))
     }
 
     func test_ltrim_wrapsStringWithRtrimFunction() {
-        AssertSQL("rtrim(\"string\")", string.rtrim())
-        AssertSQL("rtrim(\"stringOptional\")", stringOptional.rtrim())
+        assertSQL("rtrim(\"string\")", string.rtrim())
+        assertSQL("rtrim(\"stringOptional\")", stringOptional.rtrim())
 
-        AssertSQL("rtrim(\"string\", ' ')", string.rtrim([" "]))
-        AssertSQL("rtrim(\"stringOptional\", ' ')", stringOptional.rtrim([" "]))
+        assertSQL("rtrim(\"string\", ' ')", string.rtrim([" "]))
+        assertSQL("rtrim(\"stringOptional\", ' ')", stringOptional.rtrim([" "]))
     }
 
     func test_ltrim_wrapsStringWithTrimFunction() {
-        AssertSQL("trim(\"string\")", string.trim())
-        AssertSQL("trim(\"stringOptional\")", stringOptional.trim())
+        assertSQL("trim(\"string\")", string.trim())
+        assertSQL("trim(\"stringOptional\")", stringOptional.trim())
 
-        AssertSQL("trim(\"string\", ' ')", string.trim([" "]))
-        AssertSQL("trim(\"stringOptional\", ' ')", stringOptional.trim([" "]))
+        assertSQL("trim(\"string\", ' ')", string.trim([" "]))
+        assertSQL("trim(\"stringOptional\", ' ')", stringOptional.trim([" "]))
     }
 
     func test_replace_wrapsStringWithReplaceFunction() {
-        AssertSQL("replace(\"string\", '@example.com', '@example.net')", string.replace("@example.com", with: "@example.net"))
-        AssertSQL("replace(\"stringOptional\", '@example.net', '@example.com')", stringOptional.replace("@example.net", with: "@example.com"))
+        assertSQL("replace(\"string\", '@example.com', '@example.net')", string.replace("@example.com", with: "@example.net"))
+        assertSQL("replace(\"stringOptional\", '@example.net', '@example.com')", stringOptional.replace("@example.net", with: "@example.com"))
     }
 
     func test_substring_wrapsStringWithSubstrFunction() {
-        AssertSQL("substr(\"string\", 1, 2)", string.substring(1, length: 2))
-        AssertSQL("substr(\"stringOptional\", 2, 1)", stringOptional.substring(2, length: 1))
+        assertSQL("substr(\"string\", 1, 2)", string.substring(1, length: 2))
+        assertSQL("substr(\"stringOptional\", 2, 1)", stringOptional.substring(2, length: 1))
     }
 
     func test_subscriptWithRange_wrapsStringWithSubstrFunction() {
-        AssertSQL("substr(\"string\", 1, 2)", string[1..<3])
-        AssertSQL("substr(\"stringOptional\", 2, 1)", stringOptional[2..<3])
+        assertSQL("substr(\"string\", 1, 2)", string[1..<3])
+        assertSQL("substr(\"stringOptional\", 2, 1)", stringOptional[2..<3])
     }
 
     func test_nilCoalescingOperator_wrapsOptionalsWithIfnullFunction() {
-        AssertSQL("ifnull(\"intOptional\", 1)", intOptional ?? 1)
+        assertSQL("ifnull(\"intOptional\", 1)", intOptional ?? 1)
         // AssertSQL("ifnull(\"doubleOptional\", 1.0)", doubleOptional ?? 1) // rdar://problem/21677256
         XCTAssertEqual("ifnull(\"doubleOptional\", 1.0)", (doubleOptional ?? 1).asSQL())
-        AssertSQL("ifnull(\"stringOptional\", 'literal')", stringOptional ?? "literal")
+        assertSQL("ifnull(\"stringOptional\", 'literal')", stringOptional ?? "literal")
 
-        AssertSQL("ifnull(\"intOptional\", \"int\")", intOptional ?? int)
-        AssertSQL("ifnull(\"doubleOptional\", \"double\")", doubleOptional ?? double)
-        AssertSQL("ifnull(\"stringOptional\", \"string\")", stringOptional ?? string)
+        assertSQL("ifnull(\"intOptional\", \"int\")", intOptional ?? int)
+        assertSQL("ifnull(\"doubleOptional\", \"double\")", doubleOptional ?? double)
+        assertSQL("ifnull(\"stringOptional\", \"string\")", stringOptional ?? string)
 
-        AssertSQL("ifnull(\"intOptional\", \"intOptional\")", intOptional ?? intOptional)
-        AssertSQL("ifnull(\"doubleOptional\", \"doubleOptional\")", doubleOptional ?? doubleOptional)
-        AssertSQL("ifnull(\"stringOptional\", \"stringOptional\")", stringOptional ?? stringOptional)
+        assertSQL("ifnull(\"intOptional\", \"intOptional\")", intOptional ?? intOptional)
+        assertSQL("ifnull(\"doubleOptional\", \"doubleOptional\")", doubleOptional ?? doubleOptional)
+        assertSQL("ifnull(\"stringOptional\", \"stringOptional\")", stringOptional ?? stringOptional)
     }
 
     func test_absoluteValue_wrapsNumberWithAbsFucntion() {
-        AssertSQL("abs(\"int\")", int.absoluteValue)
-        AssertSQL("abs(\"intOptional\")", intOptional.absoluteValue)
+        assertSQL("abs(\"int\")", int.absoluteValue)
+        assertSQL("abs(\"intOptional\")", intOptional.absoluteValue)
 
-        AssertSQL("abs(\"double\")", double.absoluteValue)
-        AssertSQL("abs(\"doubleOptional\")", doubleOptional.absoluteValue)
+        assertSQL("abs(\"double\")", double.absoluteValue)
+        assertSQL("abs(\"doubleOptional\")", doubleOptional.absoluteValue)
     }
 
     func test_contains_buildsExpressionWithInOperator() {
-        AssertSQL("(\"string\" IN ('hello', 'world'))", ["hello", "world"].contains(string))
-        AssertSQL("(\"stringOptional\" IN ('hello', 'world'))", ["hello", "world"].contains(stringOptional))
+        assertSQL("(\"string\" IN ('hello', 'world'))", ["hello", "world"].contains(string))
+        assertSQL("(\"stringOptional\" IN ('hello', 'world'))", ["hello", "world"].contains(stringOptional))
     }
 
 }
diff --git a/Tests/SQLiteTests/CustomFunctionsTests.swift b/Tests/SQLiteTests/CustomFunctionsTests.swift
index 919986b6..0ebcd13c 100644
--- a/Tests/SQLiteTests/CustomFunctionsTests.swift
+++ b/Tests/SQLiteTests/CustomFunctionsTests.swift
@@ -1,7 +1,7 @@
 import XCTest
 import SQLite
 
-class CustomFunctionNoArgsTests : SQLiteTestCase {
+class CustomFunctionNoArgsTests: SQLiteTestCase {
     typealias FunctionNoOptional              = ()  -> Expression<String>
     typealias FunctionResultOptional          = ()  -> Expression<String?>
 
@@ -22,7 +22,7 @@ class CustomFunctionNoArgsTests : SQLiteTestCase {
     }
 }
 
-class CustomFunctionWithOneArgTests : SQLiteTestCase {
+class CustomFunctionWithOneArgTests: SQLiteTestCase {
     typealias FunctionNoOptional              = (Expression<String>)  -> Expression<String>
     typealias FunctionLeftOptional            = (Expression<String?>) -> Expression<String>
     typealias FunctionResultOptional          = (Expression<String>)  -> Expression<String?>
@@ -53,7 +53,7 @@ class CustomFunctionWithOneArgTests : SQLiteTestCase {
     }
 
     func testFunctionLeftResultOptional() {
-        let _: FunctionLeftResultOptional = try! db.createFunction("test", deterministic: true) { (a:String?) -> String? in
+        let _: FunctionLeftResultOptional = try! db.createFunction("test", deterministic: true) { (a: String?) -> String? in
             return "b"+a!
         }
         let result = try! db.prepare("SELECT test(?)").scalar("a") as! String
@@ -61,14 +61,14 @@ class CustomFunctionWithOneArgTests : SQLiteTestCase {
     }
 }
 
-class CustomFunctionWithTwoArgsTests : SQLiteTestCase {
-    typealias FunctionNoOptional              = (Expression<String>,  Expression<String>)  -> Expression<String>
+class CustomFunctionWithTwoArgsTests: SQLiteTestCase {
+    typealias FunctionNoOptional              = (Expression<String>, Expression<String>)  -> Expression<String>
     typealias FunctionLeftOptional            = (Expression<String?>, Expression<String>)  -> Expression<String>
-    typealias FunctionRightOptional           = (Expression<String>,  Expression<String?>) -> Expression<String>
-    typealias FunctionResultOptional          = (Expression<String>,  Expression<String>)  -> Expression<String?>
+    typealias FunctionRightOptional           = (Expression<String>, Expression<String?>) -> Expression<String>
+    typealias FunctionResultOptional          = (Expression<String>, Expression<String>)  -> Expression<String?>
     typealias FunctionLeftRightOptional       = (Expression<String?>, Expression<String?>) -> Expression<String>
     typealias FunctionLeftResultOptional      = (Expression<String?>, Expression<String>)  -> Expression<String?>
-    typealias FunctionRightResultOptional     = (Expression<String>,  Expression<String?>) -> Expression<String?>
+    typealias FunctionRightResultOptional     = (Expression<String>, Expression<String?>) -> Expression<String?>
     typealias FunctionLeftRightResultOptional = (Expression<String?>, Expression<String?>) -> Expression<String?>
 
     func testNoOptional() {
diff --git a/Tests/SQLiteTests/DateAndTimeFunctionTests.swift b/Tests/SQLiteTests/DateAndTimeFunctionTests.swift
index 628b5910..393e9c7c 100644
--- a/Tests/SQLiteTests/DateAndTimeFunctionTests.swift
+++ b/Tests/SQLiteTests/DateAndTimeFunctionTests.swift
@@ -1,66 +1,66 @@
 import XCTest
 @testable import SQLite
 
-class DateAndTimeFunctionsTests : XCTestCase {
+class DateAndTimeFunctionsTests: XCTestCase {
 
     func test_date() {
-        AssertSQL("date('now')", DateFunctions.date("now"))
-        AssertSQL("date('now', 'localtime')", DateFunctions.date("now", "localtime"))
+        assertSQL("date('now')", DateFunctions.date("now"))
+        assertSQL("date('now', 'localtime')", DateFunctions.date("now", "localtime"))
     }
 
     func test_time() {
-        AssertSQL("time('now')", DateFunctions.time("now"))
-        AssertSQL("time('now', 'localtime')", DateFunctions.time("now", "localtime"))
+        assertSQL("time('now')", DateFunctions.time("now"))
+        assertSQL("time('now', 'localtime')", DateFunctions.time("now", "localtime"))
     }
 
     func test_datetime() {
-        AssertSQL("datetime('now')", DateFunctions.datetime("now"))
-        AssertSQL("datetime('now', 'localtime')", DateFunctions.datetime("now", "localtime"))
+        assertSQL("datetime('now')", DateFunctions.datetime("now"))
+        assertSQL("datetime('now', 'localtime')", DateFunctions.datetime("now", "localtime"))
     }
 
     func test_julianday() {
-        AssertSQL("julianday('now')", DateFunctions.julianday("now"))
-        AssertSQL("julianday('now', 'localtime')", DateFunctions.julianday("now", "localtime"))
+        assertSQL("julianday('now')", DateFunctions.julianday("now"))
+        assertSQL("julianday('now', 'localtime')", DateFunctions.julianday("now", "localtime"))
     }
 
     func test_strftime() {
-        AssertSQL("strftime('%Y-%m-%d', 'now')", DateFunctions.strftime("%Y-%m-%d", "now"))
-        AssertSQL("strftime('%Y-%m-%d', 'now', 'localtime')", DateFunctions.strftime("%Y-%m-%d", "now", "localtime"))
+        assertSQL("strftime('%Y-%m-%d', 'now')", DateFunctions.strftime("%Y-%m-%d", "now"))
+        assertSQL("strftime('%Y-%m-%d', 'now', 'localtime')", DateFunctions.strftime("%Y-%m-%d", "now", "localtime"))
     }
 }
 
-class DateExtensionTests : XCTestCase {
+class DateExtensionTests: XCTestCase {
     func test_time() {
-        AssertSQL("time('1970-01-01T00:00:00.000')", Date(timeIntervalSince1970: 0).time)
+        assertSQL("time('1970-01-01T00:00:00.000')", Date(timeIntervalSince1970: 0).time)
     }
 
     func test_date() {
-        AssertSQL("date('1970-01-01T00:00:00.000')", Date(timeIntervalSince1970: 0).date)
+        assertSQL("date('1970-01-01T00:00:00.000')", Date(timeIntervalSince1970: 0).date)
     }
 
     func test_datetime() {
-        AssertSQL("datetime('1970-01-01T00:00:00.000')", Date(timeIntervalSince1970: 0).datetime)
+        assertSQL("datetime('1970-01-01T00:00:00.000')", Date(timeIntervalSince1970: 0).datetime)
     }
 
     func test_julianday() {
-        AssertSQL("julianday('1970-01-01T00:00:00.000')", Date(timeIntervalSince1970: 0).julianday)
+        assertSQL("julianday('1970-01-01T00:00:00.000')", Date(timeIntervalSince1970: 0).julianday)
     }
 }
 
-class DateExpressionTests : XCTestCase {
+class DateExpressionTests: XCTestCase {
     func test_date() {
-        AssertSQL("date(\"date\")", date.date)
+        assertSQL("date(\"date\")", date.date)
     }
 
     func test_time() {
-        AssertSQL("time(\"date\")", date.time)
+        assertSQL("time(\"date\")", date.time)
     }
 
     func test_datetime() {
-        AssertSQL("datetime(\"date\")", date.datetime)
+        assertSQL("datetime(\"date\")", date.datetime)
     }
 
     func test_julianday() {
-        AssertSQL("julianday(\"date\")", date.julianday)
+        assertSQL("julianday(\"date\")", date.julianday)
     }
 }
diff --git a/Tests/SQLiteTests/ExpressionTests.swift b/Tests/SQLiteTests/ExpressionTests.swift
index 036e10ce..32100d4d 100644
--- a/Tests/SQLiteTests/ExpressionTests.swift
+++ b/Tests/SQLiteTests/ExpressionTests.swift
@@ -1,6 +1,5 @@
 import XCTest
 import SQLite
 
-class ExpressionTests : XCTestCase {
-
+class ExpressionTests: XCTestCase {
 }
diff --git a/Tests/SQLiteTests/FTS4Tests.swift b/Tests/SQLiteTests/FTS4Tests.swift
index 79f0a8e2..b637955b 100644
--- a/Tests/SQLiteTests/FTS4Tests.swift
+++ b/Tests/SQLiteTests/FTS4Tests.swift
@@ -1,7 +1,7 @@
 import XCTest
 import SQLite
 
-class FTS4Tests : XCTestCase {
+class FTS4Tests: XCTestCase {
 
     func test_create_onVirtualTable_withFTS4_compilesCreateVirtualTableExpression() {
         XCTAssertEqual(
@@ -25,26 +25,33 @@ class FTS4Tests : XCTestCase {
             virtualTable.create(.FTS4(tokenize: .Unicode61(removeDiacritics: false)))
         )
         XCTAssertEqual(
-            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(tokenize=unicode61 \"removeDiacritics=1\" \"tokenchars=.\" \"separators=X\")",
-            virtualTable.create(.FTS4(tokenize: .Unicode61(removeDiacritics: true, tokenchars: ["."], separators: ["X"])))
+            """
+            CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(tokenize=unicode61 \"removeDiacritics=1\"
+             \"tokenchars=.\" \"separators=X\")
+            """.replacingOccurrences(of: "\n", with: ""),
+            virtualTable.create(.FTS4(tokenize: .Unicode61(removeDiacritics: true,
+                                                           tokenchars: ["."], separators: ["X"])))
         )
     }
 
     func test_match_onVirtualTableAsExpression_compilesMatchExpression() {
-        AssertSQL("(\"virtual_table\" MATCH 'string')", virtualTable.match("string") as Expression<Bool>)
-        AssertSQL("(\"virtual_table\" MATCH \"string\")", virtualTable.match(string) as Expression<Bool>)
-        AssertSQL("(\"virtual_table\" MATCH \"stringOptional\")", virtualTable.match(stringOptional) as Expression<Bool?>)
+        assertSQL("(\"virtual_table\" MATCH 'string')", virtualTable.match("string") as Expression<Bool>)
+        assertSQL("(\"virtual_table\" MATCH \"string\")", virtualTable.match(string) as Expression<Bool>)
+        assertSQL("(\"virtual_table\" MATCH \"stringOptional\")", virtualTable.match(stringOptional) as Expression<Bool?>)
     }
 
     func test_match_onVirtualTableAsQueryType_compilesMatchExpression() {
-        AssertSQL("SELECT * FROM \"virtual_table\" WHERE (\"virtual_table\" MATCH 'string')", virtualTable.match("string") as QueryType)
-        AssertSQL("SELECT * FROM \"virtual_table\" WHERE (\"virtual_table\" MATCH \"string\")", virtualTable.match(string) as QueryType)
-        AssertSQL("SELECT * FROM \"virtual_table\" WHERE (\"virtual_table\" MATCH \"stringOptional\")", virtualTable.match(stringOptional) as QueryType)
+        assertSQL("SELECT * FROM \"virtual_table\" WHERE (\"virtual_table\" MATCH 'string')",
+                  virtualTable.match("string") as QueryType)
+        assertSQL("SELECT * FROM \"virtual_table\" WHERE (\"virtual_table\" MATCH \"string\")",
+                  virtualTable.match(string) as QueryType)
+        assertSQL("SELECT * FROM \"virtual_table\" WHERE (\"virtual_table\" MATCH \"stringOptional\")",
+                  virtualTable.match(stringOptional) as QueryType)
     }
 
 }
 
-class FTS4ConfigTests : XCTestCase {
+class FTS4ConfigTests: XCTestCase {
     var config: FTS4Config!
 
     override func setUp() {
@@ -108,7 +115,10 @@ class FTS4ConfigTests : XCTestCase {
 
     func test_tokenizer_unicode61_with_options() {
         XCTAssertEqual(
-            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(tokenize=unicode61 \"removeDiacritics=1\" \"tokenchars=.\" \"separators=X\")",
+            """
+            CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(tokenize=unicode61 \"removeDiacritics=1\"
+             \"tokenchars=.\" \"separators=X\")
+            """.replacingOccurrences(of: "\n", with: ""),
             sql(config.tokenizer(.Unicode61(removeDiacritics: true, tokenchars: ["."], separators: ["X"]))))
     }
 
@@ -156,7 +166,11 @@ class FTS4ConfigTests : XCTestCase {
 
     func test_config_all() {
         XCTAssertEqual(
-            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(\"int\", \"string\", \"date\", tokenize=porter, prefix=\"2,4\", content=\"table\", notindexed=\"string\", notindexed=\"date\", languageid=\"lid\", matchinfo=\"fts3\", order=\"desc\")",
+            """
+            CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(\"int\", \"string\", \"date\",
+             tokenize=porter, prefix=\"2,4\", content=\"table\", notindexed=\"string\", notindexed=\"date\",
+             languageid=\"lid\", matchinfo=\"fts3\", order=\"desc\")
+            """.replacingOccurrences(of: "\n", with: ""),
             sql(config
                 .tokenizer(.Porter)
                 .column(int)
@@ -175,7 +189,7 @@ class FTS4ConfigTests : XCTestCase {
     }
 }
 
-class FTS4IntegrationTests : SQLiteTestCase {
+class FTS4IntegrationTests: SQLiteTestCase {
 #if !SQLITE_SWIFT_STANDALONE && !SQLITE_SWIFT_SQLCIPHER
     func test_registerTokenizer_registersTokenizer() {
         let emails = VirtualTable("emails")
@@ -184,9 +198,11 @@ class FTS4IntegrationTests : SQLiteTestCase {
 
         let locale = CFLocaleCopyCurrent()
         let tokenizerName = "tokenizer"
-        let tokenizer = CFStringTokenizerCreate(nil, "" as CFString, CFRangeMake(0, 0), UInt(kCFStringTokenizerUnitWord), locale)
+        let tokenizer = CFStringTokenizerCreate(nil, "" as CFString, CFRangeMake(0, 0),
+                                                UInt(kCFStringTokenizerUnitWord), locale)
         try! db.registerTokenizer(tokenizerName) { string in
-            CFStringTokenizerSetString(tokenizer, string as CFString, CFRangeMake(0, CFStringGetLength(string as CFString)))
+            CFStringTokenizerSetString(tokenizer, string as CFString,
+                                       CFRangeMake(0, CFStringGetLength(string as CFString)))
             if CFStringTokenizerAdvanceToNextToken(tokenizer).isEmpty {
                 return nil
             }
@@ -199,7 +215,10 @@ class FTS4IntegrationTests : SQLiteTestCase {
         }
 
         try! db.run(emails.create(.FTS4([subject, body], tokenize: .Custom(tokenizerName))))
-        AssertSQL("CREATE VIRTUAL TABLE \"emails\" USING fts4(\"subject\", \"body\", tokenize=\"SQLite.swift\" \"tokenizer\")")
+        assertSQL("""
+                  CREATE VIRTUAL TABLE \"emails\" USING fts4(\"subject\", \"body\",
+                   tokenize=\"SQLite.swift\" \"tokenizer\")
+                  """.replacingOccurrences(of: "\n", with: ""))
 
         try! _ = db.run(emails.insert(subject <- "Aún más cáfe!"))
         XCTAssertEqual(1, try! db.scalar(emails.filter(emails.match("aun")).count))
diff --git a/Tests/SQLiteTests/FTS5Tests.swift b/Tests/SQLiteTests/FTS5Tests.swift
index 63d8dc40..8079b28c 100644
--- a/Tests/SQLiteTests/FTS5Tests.swift
+++ b/Tests/SQLiteTests/FTS5Tests.swift
@@ -107,7 +107,10 @@ class FTS5Tests: XCTestCase {
 
     func test_fts5_config_all() {
         XCTAssertEqual(
-            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(\"int\", \"string\" UNINDEXED, \"date\" UNINDEXED, tokenize=porter, prefix=\"2,4\", content=\"table\")",
+            """
+            CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(\"int\", \"string\" UNINDEXED, \"date\" UNINDEXED,
+             tokenize=porter, prefix=\"2,4\", content=\"table\")
+            """.replacingOccurrences(of: "\n", with: ""),
             sql(config
                 .tokenizer(.Porter)
                 .column(int)
diff --git a/Tests/SQLiteTests/FoundationTests.swift b/Tests/SQLiteTests/FoundationTests.swift
index ba9685b7..cef485fc 100644
--- a/Tests/SQLiteTests/FoundationTests.swift
+++ b/Tests/SQLiteTests/FoundationTests.swift
@@ -1,7 +1,7 @@
 import XCTest
 import SQLite
 
-class FoundationTests : XCTestCase {
+class FoundationTests: XCTestCase {
     func testDataFromBlob() {
         let data = Data([1, 2, 3])
         let blob = data.datatypeValue
diff --git a/Tests/SQLiteTests/OperatorsTests.swift b/Tests/SQLiteTests/OperatorsTests.swift
index c9665671..370b910b 100644
--- a/Tests/SQLiteTests/OperatorsTests.swift
+++ b/Tests/SQLiteTests/OperatorsTests.swift
@@ -1,378 +1,378 @@
 import XCTest
 import SQLite
 
-class OperatorsTests : XCTestCase {
+class OperatorsTests: XCTestCase {
 
     func test_stringExpressionPlusStringExpression_buildsConcatenatingStringExpression() {
-        AssertSQL("(\"string\" || \"string\")", string + string)
-        AssertSQL("(\"string\" || \"stringOptional\")", string + stringOptional)
-        AssertSQL("(\"stringOptional\" || \"string\")", stringOptional + string)
-        AssertSQL("(\"stringOptional\" || \"stringOptional\")", stringOptional + stringOptional)
-        AssertSQL("(\"string\" || 'literal')", string + "literal")
-        AssertSQL("(\"stringOptional\" || 'literal')", stringOptional + "literal")
-        AssertSQL("('literal' || \"string\")", "literal" + string)
-        AssertSQL("('literal' || \"stringOptional\")", "literal" + stringOptional)
+        assertSQL("(\"string\" || \"string\")", string + string)
+        assertSQL("(\"string\" || \"stringOptional\")", string + stringOptional)
+        assertSQL("(\"stringOptional\" || \"string\")", stringOptional + string)
+        assertSQL("(\"stringOptional\" || \"stringOptional\")", stringOptional + stringOptional)
+        assertSQL("(\"string\" || 'literal')", string + "literal")
+        assertSQL("(\"stringOptional\" || 'literal')", stringOptional + "literal")
+        assertSQL("('literal' || \"string\")", "literal" + string)
+        assertSQL("('literal' || \"stringOptional\")", "literal" + stringOptional)
     }
 
     func test_numberExpression_plusNumberExpression_buildsAdditiveNumberExpression() {
-        AssertSQL("(\"int\" + \"int\")", int + int)
-        AssertSQL("(\"int\" + \"intOptional\")", int + intOptional)
-        AssertSQL("(\"intOptional\" + \"int\")", intOptional + int)
-        AssertSQL("(\"intOptional\" + \"intOptional\")", intOptional + intOptional)
-        AssertSQL("(\"int\" + 1)", int + 1)
-        AssertSQL("(\"intOptional\" + 1)", intOptional + 1)
-        AssertSQL("(1 + \"int\")", 1 + int)
-        AssertSQL("(1 + \"intOptional\")", 1 + intOptional)
-
-        AssertSQL("(\"double\" + \"double\")", double + double)
-        AssertSQL("(\"double\" + \"doubleOptional\")", double + doubleOptional)
-        AssertSQL("(\"doubleOptional\" + \"double\")", doubleOptional + double)
-        AssertSQL("(\"doubleOptional\" + \"doubleOptional\")", doubleOptional + doubleOptional)
-        AssertSQL("(\"double\" + 1.0)", double + 1)
-        AssertSQL("(\"doubleOptional\" + 1.0)", doubleOptional + 1)
-        AssertSQL("(1.0 + \"double\")", 1 + double)
-        AssertSQL("(1.0 + \"doubleOptional\")", 1 + doubleOptional)
+        assertSQL("(\"int\" + \"int\")", int + int)
+        assertSQL("(\"int\" + \"intOptional\")", int + intOptional)
+        assertSQL("(\"intOptional\" + \"int\")", intOptional + int)
+        assertSQL("(\"intOptional\" + \"intOptional\")", intOptional + intOptional)
+        assertSQL("(\"int\" + 1)", int + 1)
+        assertSQL("(\"intOptional\" + 1)", intOptional + 1)
+        assertSQL("(1 + \"int\")", 1 + int)
+        assertSQL("(1 + \"intOptional\")", 1 + intOptional)
+
+        assertSQL("(\"double\" + \"double\")", double + double)
+        assertSQL("(\"double\" + \"doubleOptional\")", double + doubleOptional)
+        assertSQL("(\"doubleOptional\" + \"double\")", doubleOptional + double)
+        assertSQL("(\"doubleOptional\" + \"doubleOptional\")", doubleOptional + doubleOptional)
+        assertSQL("(\"double\" + 1.0)", double + 1)
+        assertSQL("(\"doubleOptional\" + 1.0)", doubleOptional + 1)
+        assertSQL("(1.0 + \"double\")", 1 + double)
+        assertSQL("(1.0 + \"doubleOptional\")", 1 + doubleOptional)
     }
 
     func test_numberExpression_minusNumberExpression_buildsSubtractiveNumberExpression() {
-        AssertSQL("(\"int\" - \"int\")", int - int)
-        AssertSQL("(\"int\" - \"intOptional\")", int - intOptional)
-        AssertSQL("(\"intOptional\" - \"int\")", intOptional - int)
-        AssertSQL("(\"intOptional\" - \"intOptional\")", intOptional - intOptional)
-        AssertSQL("(\"int\" - 1)", int - 1)
-        AssertSQL("(\"intOptional\" - 1)", intOptional - 1)
-        AssertSQL("(1 - \"int\")", 1 - int)
-        AssertSQL("(1 - \"intOptional\")", 1 - intOptional)
-
-        AssertSQL("(\"double\" - \"double\")", double - double)
-        AssertSQL("(\"double\" - \"doubleOptional\")", double - doubleOptional)
-        AssertSQL("(\"doubleOptional\" - \"double\")", doubleOptional - double)
-        AssertSQL("(\"doubleOptional\" - \"doubleOptional\")", doubleOptional - doubleOptional)
-        AssertSQL("(\"double\" - 1.0)", double - 1)
-        AssertSQL("(\"doubleOptional\" - 1.0)", doubleOptional - 1)
-        AssertSQL("(1.0 - \"double\")", 1 - double)
-        AssertSQL("(1.0 - \"doubleOptional\")", 1 - doubleOptional)
+        assertSQL("(\"int\" - \"int\")", int - int)
+        assertSQL("(\"int\" - \"intOptional\")", int - intOptional)
+        assertSQL("(\"intOptional\" - \"int\")", intOptional - int)
+        assertSQL("(\"intOptional\" - \"intOptional\")", intOptional - intOptional)
+        assertSQL("(\"int\" - 1)", int - 1)
+        assertSQL("(\"intOptional\" - 1)", intOptional - 1)
+        assertSQL("(1 - \"int\")", 1 - int)
+        assertSQL("(1 - \"intOptional\")", 1 - intOptional)
+
+        assertSQL("(\"double\" - \"double\")", double - double)
+        assertSQL("(\"double\" - \"doubleOptional\")", double - doubleOptional)
+        assertSQL("(\"doubleOptional\" - \"double\")", doubleOptional - double)
+        assertSQL("(\"doubleOptional\" - \"doubleOptional\")", doubleOptional - doubleOptional)
+        assertSQL("(\"double\" - 1.0)", double - 1)
+        assertSQL("(\"doubleOptional\" - 1.0)", doubleOptional - 1)
+        assertSQL("(1.0 - \"double\")", 1 - double)
+        assertSQL("(1.0 - \"doubleOptional\")", 1 - doubleOptional)
     }
 
     func test_numberExpression_timesNumberExpression_buildsMultiplicativeNumberExpression() {
-        AssertSQL("(\"int\" * \"int\")", int * int)
-        AssertSQL("(\"int\" * \"intOptional\")", int * intOptional)
-        AssertSQL("(\"intOptional\" * \"int\")", intOptional * int)
-        AssertSQL("(\"intOptional\" * \"intOptional\")", intOptional * intOptional)
-        AssertSQL("(\"int\" * 1)", int * 1)
-        AssertSQL("(\"intOptional\" * 1)", intOptional * 1)
-        AssertSQL("(1 * \"int\")", 1 * int)
-        AssertSQL("(1 * \"intOptional\")", 1 * intOptional)
-
-        AssertSQL("(\"double\" * \"double\")", double * double)
-        AssertSQL("(\"double\" * \"doubleOptional\")", double * doubleOptional)
-        AssertSQL("(\"doubleOptional\" * \"double\")", doubleOptional * double)
-        AssertSQL("(\"doubleOptional\" * \"doubleOptional\")", doubleOptional * doubleOptional)
-        AssertSQL("(\"double\" * 1.0)", double * 1)
-        AssertSQL("(\"doubleOptional\" * 1.0)", doubleOptional * 1)
-        AssertSQL("(1.0 * \"double\")", 1 * double)
-        AssertSQL("(1.0 * \"doubleOptional\")", 1 * doubleOptional)
+        assertSQL("(\"int\" * \"int\")", int * int)
+        assertSQL("(\"int\" * \"intOptional\")", int * intOptional)
+        assertSQL("(\"intOptional\" * \"int\")", intOptional * int)
+        assertSQL("(\"intOptional\" * \"intOptional\")", intOptional * intOptional)
+        assertSQL("(\"int\" * 1)", int * 1)
+        assertSQL("(\"intOptional\" * 1)", intOptional * 1)
+        assertSQL("(1 * \"int\")", 1 * int)
+        assertSQL("(1 * \"intOptional\")", 1 * intOptional)
+
+        assertSQL("(\"double\" * \"double\")", double * double)
+        assertSQL("(\"double\" * \"doubleOptional\")", double * doubleOptional)
+        assertSQL("(\"doubleOptional\" * \"double\")", doubleOptional * double)
+        assertSQL("(\"doubleOptional\" * \"doubleOptional\")", doubleOptional * doubleOptional)
+        assertSQL("(\"double\" * 1.0)", double * 1)
+        assertSQL("(\"doubleOptional\" * 1.0)", doubleOptional * 1)
+        assertSQL("(1.0 * \"double\")", 1 * double)
+        assertSQL("(1.0 * \"doubleOptional\")", 1 * doubleOptional)
     }
 
     func test_numberExpression_dividedByNumberExpression_buildsDivisiveNumberExpression() {
-        AssertSQL("(\"int\" / \"int\")", int / int)
-        AssertSQL("(\"int\" / \"intOptional\")", int / intOptional)
-        AssertSQL("(\"intOptional\" / \"int\")", intOptional / int)
-        AssertSQL("(\"intOptional\" / \"intOptional\")", intOptional / intOptional)
-        AssertSQL("(\"int\" / 1)", int / 1)
-        AssertSQL("(\"intOptional\" / 1)", intOptional / 1)
-        AssertSQL("(1 / \"int\")", 1 / int)
-        AssertSQL("(1 / \"intOptional\")", 1 / intOptional)
-
-        AssertSQL("(\"double\" / \"double\")", double / double)
-        AssertSQL("(\"double\" / \"doubleOptional\")", double / doubleOptional)
-        AssertSQL("(\"doubleOptional\" / \"double\")", doubleOptional / double)
-        AssertSQL("(\"doubleOptional\" / \"doubleOptional\")", doubleOptional / doubleOptional)
-        AssertSQL("(\"double\" / 1.0)", double / 1)
-        AssertSQL("(\"doubleOptional\" / 1.0)", doubleOptional / 1)
-        AssertSQL("(1.0 / \"double\")", 1 / double)
-        AssertSQL("(1.0 / \"doubleOptional\")", 1 / doubleOptional)
+        assertSQL("(\"int\" / \"int\")", int / int)
+        assertSQL("(\"int\" / \"intOptional\")", int / intOptional)
+        assertSQL("(\"intOptional\" / \"int\")", intOptional / int)
+        assertSQL("(\"intOptional\" / \"intOptional\")", intOptional / intOptional)
+        assertSQL("(\"int\" / 1)", int / 1)
+        assertSQL("(\"intOptional\" / 1)", intOptional / 1)
+        assertSQL("(1 / \"int\")", 1 / int)
+        assertSQL("(1 / \"intOptional\")", 1 / intOptional)
+
+        assertSQL("(\"double\" / \"double\")", double / double)
+        assertSQL("(\"double\" / \"doubleOptional\")", double / doubleOptional)
+        assertSQL("(\"doubleOptional\" / \"double\")", doubleOptional / double)
+        assertSQL("(\"doubleOptional\" / \"doubleOptional\")", doubleOptional / doubleOptional)
+        assertSQL("(\"double\" / 1.0)", double / 1)
+        assertSQL("(\"doubleOptional\" / 1.0)", doubleOptional / 1)
+        assertSQL("(1.0 / \"double\")", 1 / double)
+        assertSQL("(1.0 / \"doubleOptional\")", 1 / doubleOptional)
     }
 
     func test_numberExpression_prefixedWithMinus_buildsInvertedNumberExpression() {
-        AssertSQL("-(\"int\")", -int)
-        AssertSQL("-(\"intOptional\")", -intOptional)
+        assertSQL("-(\"int\")", -int)
+        assertSQL("-(\"intOptional\")", -intOptional)
 
-        AssertSQL("-(\"double\")", -double)
-        AssertSQL("-(\"doubleOptional\")", -doubleOptional)
+        assertSQL("-(\"double\")", -double)
+        assertSQL("-(\"doubleOptional\")", -doubleOptional)
     }
 
     func test_integerExpression_moduloIntegerExpression_buildsModuloIntegerExpression() {
-        AssertSQL("(\"int\" % \"int\")", int % int)
-        AssertSQL("(\"int\" % \"intOptional\")", int % intOptional)
-        AssertSQL("(\"intOptional\" % \"int\")", intOptional % int)
-        AssertSQL("(\"intOptional\" % \"intOptional\")", intOptional % intOptional)
-        AssertSQL("(\"int\" % 1)", int % 1)
-        AssertSQL("(\"intOptional\" % 1)", intOptional % 1)
-        AssertSQL("(1 % \"int\")", 1 % int)
-        AssertSQL("(1 % \"intOptional\")", 1 % intOptional)
+        assertSQL("(\"int\" % \"int\")", int % int)
+        assertSQL("(\"int\" % \"intOptional\")", int % intOptional)
+        assertSQL("(\"intOptional\" % \"int\")", intOptional % int)
+        assertSQL("(\"intOptional\" % \"intOptional\")", intOptional % intOptional)
+        assertSQL("(\"int\" % 1)", int % 1)
+        assertSQL("(\"intOptional\" % 1)", intOptional % 1)
+        assertSQL("(1 % \"int\")", 1 % int)
+        assertSQL("(1 % \"intOptional\")", 1 % intOptional)
     }
 
     func test_integerExpression_bitShiftLeftIntegerExpression_buildsLeftShiftedIntegerExpression() {
-        AssertSQL("(\"int\" << \"int\")", int << int)
-        AssertSQL("(\"int\" << \"intOptional\")", int << intOptional)
-        AssertSQL("(\"intOptional\" << \"int\")", intOptional << int)
-        AssertSQL("(\"intOptional\" << \"intOptional\")", intOptional << intOptional)
-        AssertSQL("(\"int\" << 1)", int << 1)
-        AssertSQL("(\"intOptional\" << 1)", intOptional << 1)
-        AssertSQL("(1 << \"int\")", 1 << int)
-        AssertSQL("(1 << \"intOptional\")", 1 << intOptional)
+        assertSQL("(\"int\" << \"int\")", int << int)
+        assertSQL("(\"int\" << \"intOptional\")", int << intOptional)
+        assertSQL("(\"intOptional\" << \"int\")", intOptional << int)
+        assertSQL("(\"intOptional\" << \"intOptional\")", intOptional << intOptional)
+        assertSQL("(\"int\" << 1)", int << 1)
+        assertSQL("(\"intOptional\" << 1)", intOptional << 1)
+        assertSQL("(1 << \"int\")", 1 << int)
+        assertSQL("(1 << \"intOptional\")", 1 << intOptional)
     }
 
     func test_integerExpression_bitShiftRightIntegerExpression_buildsRightShiftedIntegerExpression() {
-        AssertSQL("(\"int\" >> \"int\")", int >> int)
-        AssertSQL("(\"int\" >> \"intOptional\")", int >> intOptional)
-        AssertSQL("(\"intOptional\" >> \"int\")", intOptional >> int)
-        AssertSQL("(\"intOptional\" >> \"intOptional\")", intOptional >> intOptional)
-        AssertSQL("(\"int\" >> 1)", int >> 1)
-        AssertSQL("(\"intOptional\" >> 1)", intOptional >> 1)
-        AssertSQL("(1 >> \"int\")", 1 >> int)
-        AssertSQL("(1 >> \"intOptional\")", 1 >> intOptional)
+        assertSQL("(\"int\" >> \"int\")", int >> int)
+        assertSQL("(\"int\" >> \"intOptional\")", int >> intOptional)
+        assertSQL("(\"intOptional\" >> \"int\")", intOptional >> int)
+        assertSQL("(\"intOptional\" >> \"intOptional\")", intOptional >> intOptional)
+        assertSQL("(\"int\" >> 1)", int >> 1)
+        assertSQL("(\"intOptional\" >> 1)", intOptional >> 1)
+        assertSQL("(1 >> \"int\")", 1 >> int)
+        assertSQL("(1 >> \"intOptional\")", 1 >> intOptional)
     }
 
     func test_integerExpression_bitwiseAndIntegerExpression_buildsAndedIntegerExpression() {
-        AssertSQL("(\"int\" & \"int\")", int & int)
-        AssertSQL("(\"int\" & \"intOptional\")", int & intOptional)
-        AssertSQL("(\"intOptional\" & \"int\")", intOptional & int)
-        AssertSQL("(\"intOptional\" & \"intOptional\")", intOptional & intOptional)
-        AssertSQL("(\"int\" & 1)", int & 1)
-        AssertSQL("(\"intOptional\" & 1)", intOptional & 1)
-        AssertSQL("(1 & \"int\")", 1 & int)
-        AssertSQL("(1 & \"intOptional\")", 1 & intOptional)
+        assertSQL("(\"int\" & \"int\")", int & int)
+        assertSQL("(\"int\" & \"intOptional\")", int & intOptional)
+        assertSQL("(\"intOptional\" & \"int\")", intOptional & int)
+        assertSQL("(\"intOptional\" & \"intOptional\")", intOptional & intOptional)
+        assertSQL("(\"int\" & 1)", int & 1)
+        assertSQL("(\"intOptional\" & 1)", intOptional & 1)
+        assertSQL("(1 & \"int\")", 1 & int)
+        assertSQL("(1 & \"intOptional\")", 1 & intOptional)
     }
 
     func test_integerExpression_bitwiseOrIntegerExpression_buildsOredIntegerExpression() {
-        AssertSQL("(\"int\" | \"int\")", int | int)
-        AssertSQL("(\"int\" | \"intOptional\")", int | intOptional)
-        AssertSQL("(\"intOptional\" | \"int\")", intOptional | int)
-        AssertSQL("(\"intOptional\" | \"intOptional\")", intOptional | intOptional)
-        AssertSQL("(\"int\" | 1)", int | 1)
-        AssertSQL("(\"intOptional\" | 1)", intOptional | 1)
-        AssertSQL("(1 | \"int\")", 1 | int)
-        AssertSQL("(1 | \"intOptional\")", 1 | intOptional)
+        assertSQL("(\"int\" | \"int\")", int | int)
+        assertSQL("(\"int\" | \"intOptional\")", int | intOptional)
+        assertSQL("(\"intOptional\" | \"int\")", intOptional | int)
+        assertSQL("(\"intOptional\" | \"intOptional\")", intOptional | intOptional)
+        assertSQL("(\"int\" | 1)", int | 1)
+        assertSQL("(\"intOptional\" | 1)", intOptional | 1)
+        assertSQL("(1 | \"int\")", 1 | int)
+        assertSQL("(1 | \"intOptional\")", 1 | intOptional)
     }
 
     func test_integerExpression_bitwiseExclusiveOrIntegerExpression_buildsOredIntegerExpression() {
-        AssertSQL("(~((\"int\" & \"int\")) & (\"int\" | \"int\"))", int ^ int)
-        AssertSQL("(~((\"int\" & \"intOptional\")) & (\"int\" | \"intOptional\"))", int ^ intOptional)
-        AssertSQL("(~((\"intOptional\" & \"int\")) & (\"intOptional\" | \"int\"))", intOptional ^ int)
-        AssertSQL("(~((\"intOptional\" & \"intOptional\")) & (\"intOptional\" | \"intOptional\"))", intOptional ^ intOptional)
-        AssertSQL("(~((\"int\" & 1)) & (\"int\" | 1))", int ^ 1)
-        AssertSQL("(~((\"intOptional\" & 1)) & (\"intOptional\" | 1))", intOptional ^ 1)
-        AssertSQL("(~((1 & \"int\")) & (1 | \"int\"))", 1 ^ int)
-        AssertSQL("(~((1 & \"intOptional\")) & (1 | \"intOptional\"))", 1 ^ intOptional)
+        assertSQL("(~((\"int\" & \"int\")) & (\"int\" | \"int\"))", int ^ int)
+        assertSQL("(~((\"int\" & \"intOptional\")) & (\"int\" | \"intOptional\"))", int ^ intOptional)
+        assertSQL("(~((\"intOptional\" & \"int\")) & (\"intOptional\" | \"int\"))", intOptional ^ int)
+        assertSQL("(~((\"intOptional\" & \"intOptional\")) & (\"intOptional\" | \"intOptional\"))", intOptional ^ intOptional)
+        assertSQL("(~((\"int\" & 1)) & (\"int\" | 1))", int ^ 1)
+        assertSQL("(~((\"intOptional\" & 1)) & (\"intOptional\" | 1))", intOptional ^ 1)
+        assertSQL("(~((1 & \"int\")) & (1 | \"int\"))", 1 ^ int)
+        assertSQL("(~((1 & \"intOptional\")) & (1 | \"intOptional\"))", 1 ^ intOptional)
     }
 
     func test_bitwiseNot_integerExpression_buildsComplementIntegerExpression() {
-        AssertSQL("~(\"int\")", ~int)
-        AssertSQL("~(\"intOptional\")", ~intOptional)
+        assertSQL("~(\"int\")", ~int)
+        assertSQL("~(\"intOptional\")", ~intOptional)
     }
 
     func test_equalityOperator_withEquatableExpressions_buildsBooleanExpression() {
-        AssertSQL("(\"bool\" = \"bool\")", bool == bool)
-        AssertSQL("(\"bool\" = \"boolOptional\")", bool == boolOptional)
-        AssertSQL("(\"boolOptional\" = \"bool\")", boolOptional == bool)
-        AssertSQL("(\"boolOptional\" = \"boolOptional\")", boolOptional == boolOptional)
-        AssertSQL("(\"bool\" = 1)", bool == true)
-        AssertSQL("(\"boolOptional\" = 1)", boolOptional == true)
-        AssertSQL("(1 = \"bool\")", true == bool)
-        AssertSQL("(1 = \"boolOptional\")", true == boolOptional)
+        assertSQL("(\"bool\" = \"bool\")", bool == bool)
+        assertSQL("(\"bool\" = \"boolOptional\")", bool == boolOptional)
+        assertSQL("(\"boolOptional\" = \"bool\")", boolOptional == bool)
+        assertSQL("(\"boolOptional\" = \"boolOptional\")", boolOptional == boolOptional)
+        assertSQL("(\"bool\" = 1)", bool == true)
+        assertSQL("(\"boolOptional\" = 1)", boolOptional == true)
+        assertSQL("(1 = \"bool\")", true == bool)
+        assertSQL("(1 = \"boolOptional\")", true == boolOptional)
 
-        AssertSQL("(\"boolOptional\" IS NULL)", boolOptional == nil)
-        AssertSQL("(NULL IS \"boolOptional\")", nil == boolOptional)
+        assertSQL("(\"boolOptional\" IS NULL)", boolOptional == nil)
+        assertSQL("(NULL IS \"boolOptional\")", nil == boolOptional)
     }
 
     func test_isOperator_withEquatableExpressions_buildsBooleanExpression() {
-       AssertSQL("(\"bool\" IS \"bool\")", bool === bool)
-       AssertSQL("(\"bool\" IS \"boolOptional\")", bool === boolOptional)
-       AssertSQL("(\"boolOptional\" IS \"bool\")", boolOptional === bool)
-       AssertSQL("(\"boolOptional\" IS \"boolOptional\")", boolOptional === boolOptional)
-       AssertSQL("(\"bool\" IS 1)", bool === true)
-       AssertSQL("(\"boolOptional\" IS 1)", boolOptional === true)
-       AssertSQL("(1 IS \"bool\")", true === bool)
-       AssertSQL("(1 IS \"boolOptional\")", true === boolOptional)
-
-       AssertSQL("(\"boolOptional\" IS NULL)", boolOptional === nil)
-       AssertSQL("(NULL IS \"boolOptional\")", nil === boolOptional)
-    }
-    
+       assertSQL("(\"bool\" IS \"bool\")", bool === bool)
+       assertSQL("(\"bool\" IS \"boolOptional\")", bool === boolOptional)
+       assertSQL("(\"boolOptional\" IS \"bool\")", boolOptional === bool)
+       assertSQL("(\"boolOptional\" IS \"boolOptional\")", boolOptional === boolOptional)
+       assertSQL("(\"bool\" IS 1)", bool === true)
+       assertSQL("(\"boolOptional\" IS 1)", boolOptional === true)
+       assertSQL("(1 IS \"bool\")", true === bool)
+       assertSQL("(1 IS \"boolOptional\")", true === boolOptional)
+
+       assertSQL("(\"boolOptional\" IS NULL)", boolOptional === nil)
+       assertSQL("(NULL IS \"boolOptional\")", nil === boolOptional)
+    }
+
     func test_isNotOperator_withEquatableExpressions_buildsBooleanExpression() {
-        AssertSQL("(\"bool\" IS NOT \"bool\")", bool !== bool)
-        AssertSQL("(\"bool\" IS NOT \"boolOptional\")", bool !== boolOptional)
-        AssertSQL("(\"boolOptional\" IS NOT \"bool\")", boolOptional !== bool)
-        AssertSQL("(\"boolOptional\" IS NOT \"boolOptional\")", boolOptional !== boolOptional)
-        AssertSQL("(\"bool\" IS NOT 1)", bool !== true)
-        AssertSQL("(\"boolOptional\" IS NOT 1)", boolOptional !== true)
-        AssertSQL("(1 IS NOT \"bool\")", true !== bool)
-        AssertSQL("(1 IS NOT \"boolOptional\")", true !== boolOptional)
-
-        AssertSQL("(\"boolOptional\" IS NOT NULL)", boolOptional !== nil)
-        AssertSQL("(NULL IS NOT \"boolOptional\")", nil !== boolOptional)
+        assertSQL("(\"bool\" IS NOT \"bool\")", bool !== bool)
+        assertSQL("(\"bool\" IS NOT \"boolOptional\")", bool !== boolOptional)
+        assertSQL("(\"boolOptional\" IS NOT \"bool\")", boolOptional !== bool)
+        assertSQL("(\"boolOptional\" IS NOT \"boolOptional\")", boolOptional !== boolOptional)
+        assertSQL("(\"bool\" IS NOT 1)", bool !== true)
+        assertSQL("(\"boolOptional\" IS NOT 1)", boolOptional !== true)
+        assertSQL("(1 IS NOT \"bool\")", true !== bool)
+        assertSQL("(1 IS NOT \"boolOptional\")", true !== boolOptional)
+
+        assertSQL("(\"boolOptional\" IS NOT NULL)", boolOptional !== nil)
+        assertSQL("(NULL IS NOT \"boolOptional\")", nil !== boolOptional)
      }
 
     func test_inequalityOperator_withEquatableExpressions_buildsBooleanExpression() {
-        AssertSQL("(\"bool\" != \"bool\")", bool != bool)
-        AssertSQL("(\"bool\" != \"boolOptional\")", bool != boolOptional)
-        AssertSQL("(\"boolOptional\" != \"bool\")", boolOptional != bool)
-        AssertSQL("(\"boolOptional\" != \"boolOptional\")", boolOptional != boolOptional)
-        AssertSQL("(\"bool\" != 1)", bool != true)
-        AssertSQL("(\"boolOptional\" != 1)", boolOptional != true)
-        AssertSQL("(1 != \"bool\")", true != bool)
-        AssertSQL("(1 != \"boolOptional\")", true != boolOptional)
+        assertSQL("(\"bool\" != \"bool\")", bool != bool)
+        assertSQL("(\"bool\" != \"boolOptional\")", bool != boolOptional)
+        assertSQL("(\"boolOptional\" != \"bool\")", boolOptional != bool)
+        assertSQL("(\"boolOptional\" != \"boolOptional\")", boolOptional != boolOptional)
+        assertSQL("(\"bool\" != 1)", bool != true)
+        assertSQL("(\"boolOptional\" != 1)", boolOptional != true)
+        assertSQL("(1 != \"bool\")", true != bool)
+        assertSQL("(1 != \"boolOptional\")", true != boolOptional)
 
-        AssertSQL("(\"boolOptional\" IS NOT NULL)", boolOptional != nil)
-        AssertSQL("(NULL IS NOT \"boolOptional\")", nil != boolOptional)
+        assertSQL("(\"boolOptional\" IS NOT NULL)", boolOptional != nil)
+        assertSQL("(NULL IS NOT \"boolOptional\")", nil != boolOptional)
     }
 
     func test_greaterThanOperator_withComparableExpressions_buildsBooleanExpression() {
-        AssertSQL("(\"bool\" > \"bool\")", bool > bool)
-        AssertSQL("(\"bool\" > \"boolOptional\")", bool > boolOptional)
-        AssertSQL("(\"boolOptional\" > \"bool\")", boolOptional > bool)
-        AssertSQL("(\"boolOptional\" > \"boolOptional\")", boolOptional > boolOptional)
-        AssertSQL("(\"bool\" > 1)", bool > true)
-        AssertSQL("(\"boolOptional\" > 1)", boolOptional > true)
-        AssertSQL("(1 > \"bool\")", true > bool)
-        AssertSQL("(1 > \"boolOptional\")", true > boolOptional)
+        assertSQL("(\"bool\" > \"bool\")", bool > bool)
+        assertSQL("(\"bool\" > \"boolOptional\")", bool > boolOptional)
+        assertSQL("(\"boolOptional\" > \"bool\")", boolOptional > bool)
+        assertSQL("(\"boolOptional\" > \"boolOptional\")", boolOptional > boolOptional)
+        assertSQL("(\"bool\" > 1)", bool > true)
+        assertSQL("(\"boolOptional\" > 1)", boolOptional > true)
+        assertSQL("(1 > \"bool\")", true > bool)
+        assertSQL("(1 > \"boolOptional\")", true > boolOptional)
     }
 
     func test_greaterThanOrEqualToOperator_withComparableExpressions_buildsBooleanExpression() {
-        AssertSQL("(\"bool\" >= \"bool\")", bool >= bool)
-        AssertSQL("(\"bool\" >= \"boolOptional\")", bool >= boolOptional)
-        AssertSQL("(\"boolOptional\" >= \"bool\")", boolOptional >= bool)
-        AssertSQL("(\"boolOptional\" >= \"boolOptional\")", boolOptional >= boolOptional)
-        AssertSQL("(\"bool\" >= 1)", bool >= true)
-        AssertSQL("(\"boolOptional\" >= 1)", boolOptional >= true)
-        AssertSQL("(1 >= \"bool\")", true >= bool)
-        AssertSQL("(1 >= \"boolOptional\")", true >= boolOptional)
+        assertSQL("(\"bool\" >= \"bool\")", bool >= bool)
+        assertSQL("(\"bool\" >= \"boolOptional\")", bool >= boolOptional)
+        assertSQL("(\"boolOptional\" >= \"bool\")", boolOptional >= bool)
+        assertSQL("(\"boolOptional\" >= \"boolOptional\")", boolOptional >= boolOptional)
+        assertSQL("(\"bool\" >= 1)", bool >= true)
+        assertSQL("(\"boolOptional\" >= 1)", boolOptional >= true)
+        assertSQL("(1 >= \"bool\")", true >= bool)
+        assertSQL("(1 >= \"boolOptional\")", true >= boolOptional)
     }
 
     func test_lessThanOperator_withComparableExpressions_buildsBooleanExpression() {
-        AssertSQL("(\"bool\" < \"bool\")", bool < bool)
-        AssertSQL("(\"bool\" < \"boolOptional\")", bool < boolOptional)
-        AssertSQL("(\"boolOptional\" < \"bool\")", boolOptional < bool)
-        AssertSQL("(\"boolOptional\" < \"boolOptional\")", boolOptional < boolOptional)
-        AssertSQL("(\"bool\" < 1)", bool < true)
-        AssertSQL("(\"boolOptional\" < 1)", boolOptional < true)
-        AssertSQL("(1 < \"bool\")", true < bool)
-        AssertSQL("(1 < \"boolOptional\")", true < boolOptional)
+        assertSQL("(\"bool\" < \"bool\")", bool < bool)
+        assertSQL("(\"bool\" < \"boolOptional\")", bool < boolOptional)
+        assertSQL("(\"boolOptional\" < \"bool\")", boolOptional < bool)
+        assertSQL("(\"boolOptional\" < \"boolOptional\")", boolOptional < boolOptional)
+        assertSQL("(\"bool\" < 1)", bool < true)
+        assertSQL("(\"boolOptional\" < 1)", boolOptional < true)
+        assertSQL("(1 < \"bool\")", true < bool)
+        assertSQL("(1 < \"boolOptional\")", true < boolOptional)
     }
 
     func test_lessThanOrEqualToOperator_withComparableExpressions_buildsBooleanExpression() {
-        AssertSQL("(\"bool\" <= \"bool\")", bool <= bool)
-        AssertSQL("(\"bool\" <= \"boolOptional\")", bool <= boolOptional)
-        AssertSQL("(\"boolOptional\" <= \"bool\")", boolOptional <= bool)
-        AssertSQL("(\"boolOptional\" <= \"boolOptional\")", boolOptional <= boolOptional)
-        AssertSQL("(\"bool\" <= 1)", bool <= true)
-        AssertSQL("(\"boolOptional\" <= 1)", boolOptional <= true)
-        AssertSQL("(1 <= \"bool\")", true <= bool)
-        AssertSQL("(1 <= \"boolOptional\")", true <= boolOptional)
+        assertSQL("(\"bool\" <= \"bool\")", bool <= bool)
+        assertSQL("(\"bool\" <= \"boolOptional\")", bool <= boolOptional)
+        assertSQL("(\"boolOptional\" <= \"bool\")", boolOptional <= bool)
+        assertSQL("(\"boolOptional\" <= \"boolOptional\")", boolOptional <= boolOptional)
+        assertSQL("(\"bool\" <= 1)", bool <= true)
+        assertSQL("(\"boolOptional\" <= 1)", boolOptional <= true)
+        assertSQL("(1 <= \"bool\")", true <= bool)
+        assertSQL("(1 <= \"boolOptional\")", true <= boolOptional)
     }
 
     func test_patternMatchingOperator_withComparableCountableClosedRange_buildsBetweenBooleanExpression() {
-        AssertSQL("\"int\" BETWEEN 0 AND 5", 0...5 ~= int)
-        AssertSQL("\"intOptional\" BETWEEN 0 AND 5", 0...5 ~= intOptional)
+        assertSQL("\"int\" BETWEEN 0 AND 5", 0...5 ~= int)
+        assertSQL("\"intOptional\" BETWEEN 0 AND 5", 0...5 ~= intOptional)
     }
 
     func test_patternMatchingOperator_withComparableClosedRange_buildsBetweenBooleanExpression() {
-        AssertSQL("\"double\" BETWEEN 1.2 AND 4.5", 1.2...4.5 ~= double)
-        AssertSQL("\"doubleOptional\" BETWEEN 1.2 AND 4.5", 1.2...4.5 ~= doubleOptional)
+        assertSQL("\"double\" BETWEEN 1.2 AND 4.5", 1.2...4.5 ~= double)
+        assertSQL("\"doubleOptional\" BETWEEN 1.2 AND 4.5", 1.2...4.5 ~= doubleOptional)
     }
 
     func test_patternMatchingOperator_withComparableRange_buildsBooleanExpression() {
-        AssertSQL("\"double\" >= 1.2 AND \"double\" < 4.5", 1.2..<4.5 ~= double)
-        AssertSQL("\"doubleOptional\" >= 1.2 AND \"doubleOptional\" < 4.5", 1.2..<4.5 ~= doubleOptional)
+        assertSQL("\"double\" >= 1.2 AND \"double\" < 4.5", 1.2..<4.5 ~= double)
+        assertSQL("\"doubleOptional\" >= 1.2 AND \"doubleOptional\" < 4.5", 1.2..<4.5 ~= doubleOptional)
     }
 
     func test_patternMatchingOperator_withComparablePartialRangeThrough_buildsBooleanExpression() {
-        AssertSQL("\"double\" <= 4.5", ...4.5 ~= double)
-        AssertSQL("\"doubleOptional\" <= 4.5", ...4.5 ~= doubleOptional)
+        assertSQL("\"double\" <= 4.5", ...4.5 ~= double)
+        assertSQL("\"doubleOptional\" <= 4.5", ...4.5 ~= doubleOptional)
     }
 
     func test_patternMatchingOperator_withComparablePartialRangeUpTo_buildsBooleanExpression() {
-        AssertSQL("\"double\" < 4.5", ..<4.5 ~= double)
-        AssertSQL("\"doubleOptional\" < 4.5", ..<4.5 ~= doubleOptional)
+        assertSQL("\"double\" < 4.5", ..<4.5 ~= double)
+        assertSQL("\"doubleOptional\" < 4.5", ..<4.5 ~= doubleOptional)
     }
 
     func test_patternMatchingOperator_withComparablePartialRangeFrom_buildsBooleanExpression() {
-        AssertSQL("\"double\" >= 4.5", 4.5... ~= double)
-        AssertSQL("\"doubleOptional\" >= 4.5", 4.5... ~= doubleOptional)
+        assertSQL("\"double\" >= 4.5", 4.5... ~= double)
+        assertSQL("\"doubleOptional\" >= 4.5", 4.5... ~= doubleOptional)
     }
 
     func test_patternMatchingOperator_withComparableClosedRangeString_buildsBetweenBooleanExpression() {
-        AssertSQL("\"string\" BETWEEN 'a' AND 'b'", "a"..."b" ~= string)
-        AssertSQL("\"stringOptional\" BETWEEN 'a' AND 'b'", "a"..."b" ~= stringOptional)
+        assertSQL("\"string\" BETWEEN 'a' AND 'b'", "a"..."b" ~= string)
+        assertSQL("\"stringOptional\" BETWEEN 'a' AND 'b'", "a"..."b" ~= stringOptional)
     }
 
     func test_doubleAndOperator_withBooleanExpressions_buildsCompoundExpression() {
-        AssertSQL("(\"bool\" AND \"bool\")", bool && bool)
-        AssertSQL("(\"bool\" AND \"boolOptional\")", bool && boolOptional)
-        AssertSQL("(\"boolOptional\" AND \"bool\")", boolOptional && bool)
-        AssertSQL("(\"boolOptional\" AND \"boolOptional\")", boolOptional && boolOptional)
-        AssertSQL("(\"bool\" AND 1)", bool && true)
-        AssertSQL("(\"boolOptional\" AND 1)", boolOptional && true)
-        AssertSQL("(1 AND \"bool\")", true && bool)
-        AssertSQL("(1 AND \"boolOptional\")", true && boolOptional)
-    }
-    
+        assertSQL("(\"bool\" AND \"bool\")", bool && bool)
+        assertSQL("(\"bool\" AND \"boolOptional\")", bool && boolOptional)
+        assertSQL("(\"boolOptional\" AND \"bool\")", boolOptional && bool)
+        assertSQL("(\"boolOptional\" AND \"boolOptional\")", boolOptional && boolOptional)
+        assertSQL("(\"bool\" AND 1)", bool && true)
+        assertSQL("(\"boolOptional\" AND 1)", boolOptional && true)
+        assertSQL("(1 AND \"bool\")", true && bool)
+        assertSQL("(1 AND \"boolOptional\")", true && boolOptional)
+    }
+
     func test_andFunction_withBooleanExpressions_buildsCompoundExpression() {
-        AssertSQL("(\"bool\" AND \"bool\" AND \"bool\")", and([bool, bool, bool]))
-        AssertSQL("(\"bool\" AND \"bool\")", and([bool, bool]))
-        AssertSQL("(\"bool\")", and([bool]))
-        
-        AssertSQL("(\"bool\" AND \"bool\" AND \"bool\")", and(bool, bool, bool))
-        AssertSQL("(\"bool\" AND \"bool\")", and(bool, bool))
-        AssertSQL("(\"bool\")", and(bool))
+        assertSQL("(\"bool\" AND \"bool\" AND \"bool\")", and([bool, bool, bool]))
+        assertSQL("(\"bool\" AND \"bool\")", and([bool, bool]))
+        assertSQL("(\"bool\")", and([bool]))
+
+        assertSQL("(\"bool\" AND \"bool\" AND \"bool\")", and(bool, bool, bool))
+        assertSQL("(\"bool\" AND \"bool\")", and(bool, bool))
+        assertSQL("(\"bool\")", and(bool))
     }
 
     func test_doubleOrOperator_withBooleanExpressions_buildsCompoundExpression() {
-        AssertSQL("(\"bool\" OR \"bool\")", bool || bool)
-        AssertSQL("(\"bool\" OR \"boolOptional\")", bool || boolOptional)
-        AssertSQL("(\"boolOptional\" OR \"bool\")", boolOptional || bool)
-        AssertSQL("(\"boolOptional\" OR \"boolOptional\")", boolOptional || boolOptional)
-        AssertSQL("(\"bool\" OR 1)", bool || true)
-        AssertSQL("(\"boolOptional\" OR 1)", boolOptional || true)
-        AssertSQL("(1 OR \"bool\")", true || bool)
-        AssertSQL("(1 OR \"boolOptional\")", true || boolOptional)
-    }
-    
+        assertSQL("(\"bool\" OR \"bool\")", bool || bool)
+        assertSQL("(\"bool\" OR \"boolOptional\")", bool || boolOptional)
+        assertSQL("(\"boolOptional\" OR \"bool\")", boolOptional || bool)
+        assertSQL("(\"boolOptional\" OR \"boolOptional\")", boolOptional || boolOptional)
+        assertSQL("(\"bool\" OR 1)", bool || true)
+        assertSQL("(\"boolOptional\" OR 1)", boolOptional || true)
+        assertSQL("(1 OR \"bool\")", true || bool)
+        assertSQL("(1 OR \"boolOptional\")", true || boolOptional)
+    }
+
     func test_orFunction_withBooleanExpressions_buildsCompoundExpression() {
-        AssertSQL("(\"bool\" OR \"bool\" OR \"bool\")", or([bool, bool, bool]))
-        AssertSQL("(\"bool\" OR \"bool\")", or([bool, bool]))
-        AssertSQL("(\"bool\")", or([bool]))
-        
-        AssertSQL("(\"bool\" OR \"bool\" OR \"bool\")", or(bool, bool, bool))
-        AssertSQL("(\"bool\" OR \"bool\")", or(bool, bool))
-        AssertSQL("(\"bool\")", or(bool))
+        assertSQL("(\"bool\" OR \"bool\" OR \"bool\")", or([bool, bool, bool]))
+        assertSQL("(\"bool\" OR \"bool\")", or([bool, bool]))
+        assertSQL("(\"bool\")", or([bool]))
+
+        assertSQL("(\"bool\" OR \"bool\" OR \"bool\")", or(bool, bool, bool))
+        assertSQL("(\"bool\" OR \"bool\")", or(bool, bool))
+        assertSQL("(\"bool\")", or(bool))
     }
 
     func test_unaryNotOperator_withBooleanExpressions_buildsNotExpression() {
-        AssertSQL("NOT (\"bool\")", !bool)
-        AssertSQL("NOT (\"boolOptional\")", !boolOptional)
+        assertSQL("NOT (\"bool\")", !bool)
+        assertSQL("NOT (\"boolOptional\")", !boolOptional)
     }
 
     func test_precedencePreserved() {
         let n = Expression<Int>(value: 1)
-        AssertSQL("(((1 = 1) AND (1 = 1)) OR (1 = 1))", (n == n && n == n) || n == n)
-        AssertSQL("((1 = 1) AND ((1 = 1) OR (1 = 1)))", n == n && (n == n || n == n))
+        assertSQL("(((1 = 1) AND (1 = 1)) OR (1 = 1))", (n == n && n == n) || n == n)
+        assertSQL("((1 = 1) AND ((1 = 1) OR (1 = 1)))", n == n && (n == n || n == n))
     }
 
     func test_dateExpressionLessGreater() {
         let begin = Date(timeIntervalSince1970: 0)
-        AssertSQL("(\"date\" < '1970-01-01T00:00:00.000')", date < begin)
-        AssertSQL("(\"date\" > '1970-01-01T00:00:00.000')", date > begin)
-        AssertSQL("(\"date\" >= '1970-01-01T00:00:00.000')", date >= begin)
-        AssertSQL("(\"date\" <= '1970-01-01T00:00:00.000')", date <= begin)
+        assertSQL("(\"date\" < '1970-01-01T00:00:00.000')", date < begin)
+        assertSQL("(\"date\" > '1970-01-01T00:00:00.000')", date > begin)
+        assertSQL("(\"date\" >= '1970-01-01T00:00:00.000')", date >= begin)
+        assertSQL("(\"date\" <= '1970-01-01T00:00:00.000')", date <= begin)
     }
 
     func test_dateExpressionRange() {
         let begin = Date(timeIntervalSince1970: 0)
         let end = Date(timeIntervalSince1970: 5000)
-        AssertSQL(
+        assertSQL(
             "\"date\" >= '1970-01-01T00:00:00.000' AND \"date\" < '1970-01-01T01:23:20.000'",
             (begin..<end) ~= date
         )
@@ -381,7 +381,7 @@ class OperatorsTests : XCTestCase {
     func test_dateExpressionClosedRange() {
         let begin = Date(timeIntervalSince1970: 0)
         let end = Date(timeIntervalSince1970: 5000)
-        AssertSQL(
+        assertSQL(
             "\"date\" BETWEEN '1970-01-01T00:00:00.000' AND '1970-01-01T01:23:20.000'",
             (begin...end) ~= date
         )
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index 041b7d0c..3a58e2fc 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -10,7 +10,7 @@ import SQLite3
 #endif
 @testable import SQLite
 
-class QueryTests : XCTestCase {
+class QueryTests: XCTestCase {
 
     let users = Table("users")
     let id = Expression<Int64>("id")
@@ -28,65 +28,65 @@ class QueryTests : XCTestCase {
     let tag = Expression<String>("tag")
 
     func test_select_withExpression_compilesSelectClause() {
-        AssertSQL("SELECT \"email\" FROM \"users\"", users.select(email))
+        assertSQL("SELECT \"email\" FROM \"users\"", users.select(email))
     }
 
     func test_select_withStarExpression_compilesSelectClause() {
-        AssertSQL("SELECT * FROM \"users\"", users.select(*))
+        assertSQL("SELECT * FROM \"users\"", users.select(*))
     }
 
     func test_select_withNamespacedStarExpression_compilesSelectClause() {
-        AssertSQL("SELECT \"users\".* FROM \"users\"", users.select(users[*]))
+        assertSQL("SELECT \"users\".* FROM \"users\"", users.select(users[*]))
     }
 
     func test_select_withVariadicExpressions_compilesSelectClause() {
-        AssertSQL("SELECT \"email\", count(*) FROM \"users\"", users.select(email, count(*)))
+        assertSQL("SELECT \"email\", count(*) FROM \"users\"", users.select(email, count(*)))
     }
 
     func test_select_withExpressions_compilesSelectClause() {
-        AssertSQL("SELECT \"email\", count(*) FROM \"users\"", users.select([email, count(*)]))
+        assertSQL("SELECT \"email\", count(*) FROM \"users\"", users.select([email, count(*)]))
     }
 
     func test_selectDistinct_withExpression_compilesSelectClause() {
-        AssertSQL("SELECT DISTINCT \"age\" FROM \"users\"", users.select(distinct: age))
+        assertSQL("SELECT DISTINCT \"age\" FROM \"users\"", users.select(distinct: age))
     }
 
     func test_selectDistinct_withExpressions_compilesSelectClause() {
-        AssertSQL("SELECT DISTINCT \"age\", \"admin\" FROM \"users\"", users.select(distinct: [age, admin]))
+        assertSQL("SELECT DISTINCT \"age\", \"admin\" FROM \"users\"", users.select(distinct: [age, admin]))
     }
 
     func test_selectDistinct_withStar_compilesSelectClause() {
-        AssertSQL("SELECT DISTINCT * FROM \"users\"", users.select(distinct: *))
+        assertSQL("SELECT DISTINCT * FROM \"users\"", users.select(distinct: *))
     }
 
     func test_join_compilesJoinClause() {
-        AssertSQL(
+        assertSQL(
             "SELECT * FROM \"users\" INNER JOIN \"posts\" ON (\"posts\".\"user_id\" = \"users\".\"id\")",
             users.join(posts, on: posts[userId] == users[id])
         )
     }
 
     func test_join_withExplicitType_compilesJoinClauseWithType() {
-        AssertSQL(
+        assertSQL(
             "SELECT * FROM \"users\" LEFT OUTER JOIN \"posts\" ON (\"posts\".\"user_id\" = \"users\".\"id\")",
             users.join(.leftOuter, posts, on: posts[userId] == users[id])
         )
 
-        AssertSQL(
+        assertSQL(
             "SELECT * FROM \"users\" CROSS JOIN \"posts\" ON (\"posts\".\"user_id\" = \"users\".\"id\")",
             users.join(.cross, posts, on: posts[userId] == users[id])
         )
     }
 
     func test_join_withTableCondition_compilesJoinClauseWithTableCondition() {
-        AssertSQL(
+        assertSQL(
             "SELECT * FROM \"users\" INNER JOIN \"posts\" ON ((\"posts\".\"user_id\" = \"users\".\"id\") AND \"published\")",
             users.join(posts.filter(published), on: posts[userId] == users[id])
         )
     }
 
     func test_join_whenChained_compilesAggregateJoinClause() {
-        AssertSQL(
+        assertSQL(
             "SELECT * FROM \"users\" " +
             "INNER JOIN \"posts\" ON (\"posts\".\"user_id\" = \"users\".\"id\") " +
             "INNER JOIN \"categories\" ON (\"categories\".\"id\" = \"posts\".\"category_id\")",
@@ -95,79 +95,79 @@ class QueryTests : XCTestCase {
     }
 
     func test_filter_compilesWhereClause() {
-        AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 1)", users.filter(admin == true))
+        assertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 1)", users.filter(admin == true))
     }
 
     func test_filter_compilesWhereClause_false() {
-        AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 0)", users.filter(admin == false))
+        assertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 0)", users.filter(admin == false))
     }
 
     func test_filter_compilesWhereClause_optional() {
-        AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 1)", users.filter(optionalAdmin == true))
+        assertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 1)", users.filter(optionalAdmin == true))
     }
 
     func test_filter_compilesWhereClause_optional_false() {
-        AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 0)", users.filter(optionalAdmin == false))
+        assertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 0)", users.filter(optionalAdmin == false))
     }
 
     func test_where_compilesWhereClause() {
-        AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 1)", users.where(admin == true))
+        assertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 1)", users.where(admin == true))
     }
 
     func test_where_compilesWhereClause_false() {
-        AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 0)", users.where(admin == false))
+        assertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 0)", users.where(admin == false))
     }
 
     func test_where_compilesWhereClause_optional() {
-        AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 1)", users.where(optionalAdmin == true))
+        assertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 1)", users.where(optionalAdmin == true))
     }
 
     func test_where_compilesWhereClause_optional_false() {
-        AssertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 0)", users.where(optionalAdmin == false))
+        assertSQL("SELECT * FROM \"users\" WHERE (\"admin\" = 0)", users.where(optionalAdmin == false))
     }
 
     func test_filter_whenChained_compilesAggregateWhereClause() {
-        AssertSQL(
+        assertSQL(
             "SELECT * FROM \"users\" WHERE ((\"age\" >= 35) AND \"admin\")",
             users.filter(age >= 35).filter(admin)
         )
     }
 
     func test_group_withSingleExpressionName_compilesGroupClause() {
-        AssertSQL("SELECT * FROM \"users\" GROUP BY \"age\"",
+        assertSQL("SELECT * FROM \"users\" GROUP BY \"age\"",
             users.group(age))
     }
 
     func test_group_withVariadicExpressionNames_compilesGroupClause() {
-        AssertSQL("SELECT * FROM \"users\" GROUP BY \"age\", \"admin\"", users.group(age, admin))
+        assertSQL("SELECT * FROM \"users\" GROUP BY \"age\", \"admin\"", users.group(age, admin))
     }
 
     func test_group_withExpressionNameAndHavingBindings_compilesGroupClause() {
-        AssertSQL("SELECT * FROM \"users\" GROUP BY \"age\" HAVING \"admin\"", users.group(age, having: admin))
-        AssertSQL("SELECT * FROM \"users\" GROUP BY \"age\" HAVING (\"age\" >= 30)", users.group(age, having: age >= 30))
+        assertSQL("SELECT * FROM \"users\" GROUP BY \"age\" HAVING \"admin\"", users.group(age, having: admin))
+        assertSQL("SELECT * FROM \"users\" GROUP BY \"age\" HAVING (\"age\" >= 30)", users.group(age, having: age >= 30))
     }
 
     func test_group_withExpressionNamesAndHavingBindings_compilesGroupClause() {
-        AssertSQL(
+        assertSQL(
             "SELECT * FROM \"users\" GROUP BY \"age\", \"admin\" HAVING \"admin\"",
             users.group([age, admin], having: admin)
         )
-        AssertSQL(
+        assertSQL(
             "SELECT * FROM \"users\" GROUP BY \"age\", \"admin\" HAVING (\"age\" >= 30)",
             users.group([age, admin], having: age >= 30)
         )
     }
 
     func test_order_withSingleExpressionName_compilesOrderClause() {
-        AssertSQL("SELECT * FROM \"users\" ORDER BY \"age\"", users.order(age))
+        assertSQL("SELECT * FROM \"users\" ORDER BY \"age\"", users.order(age))
     }
 
     func test_order_withVariadicExpressionNames_compilesOrderClause() {
-        AssertSQL("SELECT * FROM \"users\" ORDER BY \"age\", \"email\"", users.order(age, email))
+        assertSQL("SELECT * FROM \"users\" ORDER BY \"age\", \"email\"", users.order(age, email))
     }
 
     func test_order_withArrayExpressionNames_compilesOrderClause() {
-        AssertSQL("SELECT * FROM \"users\" ORDER BY \"age\", \"email\"", users.order([age, email]))
+        assertSQL("SELECT * FROM \"users\" ORDER BY \"age\", \"email\"", users.order([age, email]))
     }
 
     func test_order_withExpressionAndSortDirection_compilesOrderClause() {
@@ -175,7 +175,7 @@ class QueryTests : XCTestCase {
     }
 
     func test_order_whenChained_resetsOrderClause() {
-        AssertSQL("SELECT * FROM \"users\" ORDER BY \"age\"", users.order(email).order(age))
+        assertSQL("SELECT * FROM \"users\" ORDER BY \"age\"", users.order(email).order(age))
     }
 
     func test_reverse_withoutOrder_ordersByRowIdDescending() {
@@ -187,25 +187,25 @@ class QueryTests : XCTestCase {
     }
 
     func test_limit_compilesLimitClause() {
-        AssertSQL("SELECT * FROM \"users\" LIMIT 5", users.limit(5))
+        assertSQL("SELECT * FROM \"users\" LIMIT 5", users.limit(5))
     }
 
     func test_limit_withOffset_compilesOffsetClause() {
-        AssertSQL("SELECT * FROM \"users\" LIMIT 5 OFFSET 5", users.limit(5, offset: 5))
+        assertSQL("SELECT * FROM \"users\" LIMIT 5 OFFSET 5", users.limit(5, offset: 5))
     }
 
     func test_limit_whenChained_overridesLimit() {
         let query = users.limit(5)
 
-        AssertSQL("SELECT * FROM \"users\" LIMIT 10", query.limit(10))
-        AssertSQL("SELECT * FROM \"users\"", query.limit(nil))
+        assertSQL("SELECT * FROM \"users\" LIMIT 10", query.limit(10))
+        assertSQL("SELECT * FROM \"users\"", query.limit(nil))
     }
 
     func test_limit_whenChained_withOffset_overridesOffset() {
         let query = users.limit(5, offset: 5)
 
-        AssertSQL("SELECT * FROM \"users\" LIMIT 10 OFFSET 20", query.limit(10, offset: 20))
-        AssertSQL("SELECT * FROM \"users\"", query.limit(nil))
+        assertSQL("SELECT * FROM \"users\" LIMIT 10 OFFSET 20", query.limit(10, offset: 20))
+        assertSQL("SELECT * FROM \"users\"", query.limit(nil))
     }
 
     func test_alias_aliasesTable() {
@@ -213,7 +213,7 @@ class QueryTests : XCTestCase {
 
         let managers = users.alias("managers")
 
-        AssertSQL(
+        assertSQL(
             "SELECT * FROM \"users\" " +
             "INNER JOIN \"users\" AS \"managers\" ON (\"managers\".\"id\" = \"users\".\"manager_id\")",
             users.join(managers, on: managers[id] == users[managerId])
@@ -221,78 +221,99 @@ class QueryTests : XCTestCase {
     }
 
     func test_insert_compilesInsertExpression() {
-        AssertSQL(
+        assertSQL(
             "INSERT INTO \"users\" (\"email\", \"age\") VALUES ('alice@example.com', 30)",
             users.insert(email <- "alice@example.com", age <- 30)
         )
     }
 
     func test_insert_withOnConflict_compilesInsertOrOnConflictExpression() {
-        AssertSQL(
+        assertSQL(
             "INSERT OR REPLACE INTO \"users\" (\"email\", \"age\") VALUES ('alice@example.com', 30)",
             users.insert(or: .replace, email <- "alice@example.com", age <- 30)
         )
     }
 
     func test_insert_compilesInsertExpressionWithDefaultValues() {
-        AssertSQL("INSERT INTO \"users\" DEFAULT VALUES", users.insert())
+        assertSQL("INSERT INTO \"users\" DEFAULT VALUES", users.insert())
     }
 
     func test_insert_withQuery_compilesInsertExpressionWithSelectStatement() {
         let emails = Table("emails")
 
-        AssertSQL(
+        assertSQL(
             "INSERT INTO \"emails\" SELECT \"email\" FROM \"users\" WHERE \"admin\"",
             emails.insert(users.select(email).filter(admin))
         )
     }
 
     func test_insert_many_compilesInsertManyExpression() {
-        AssertSQL(
-            "INSERT INTO \"users\" (\"email\", \"age\") VALUES ('alice@example.com', 30), ('geoff@example.com', 32), ('alex@example.com', 83)",
-            users.insertMany([[email <- "alice@example.com", age <- 30], [email <- "geoff@example.com", age <- 32], [email <- "alex@example.com", age <- 83]])
+        assertSQL(
+            """
+            INSERT INTO \"users\" (\"email\", \"age\") VALUES ('alice@example.com', 30), ('geoff@example.com', 32),
+             ('alex@example.com', 83)
+            """.replacingOccurrences(of: "\n", with: ""),
+            users.insertMany([[email <- "alice@example.com", age <- 30],
+                              [email <- "geoff@example.com", age <- 32], [email <- "alex@example.com", age <- 83]])
         )
     }
     func test_insert_many_compilesInsertManyNoneExpression() {
-        AssertSQL(
+        assertSQL(
             "INSERT INTO \"users\" DEFAULT VALUES",
             users.insertMany([])
         )
     }
 
     func test_insert_many_withOnConflict_compilesInsertManyOrOnConflictExpression() {
-        AssertSQL(
-            "INSERT OR REPLACE INTO \"users\" (\"email\", \"age\") VALUES ('alice@example.com', 30), ('geoff@example.com', 32), ('alex@example.com', 83)",
-            users.insertMany(or: .replace, [[email <- "alice@example.com", age <- 30], [email <- "geoff@example.com", age <- 32], [email <- "alex@example.com", age <- 83]])
+        assertSQL(
+            """
+            INSERT OR REPLACE INTO \"users\" (\"email\", \"age\") VALUES ('alice@example.com', 30),
+             ('geoff@example.com', 32), ('alex@example.com', 83)
+            """.replacingOccurrences(of: "\n", with: ""),
+            users.insertMany(or: .replace, [[email <- "alice@example.com", age <- 30],
+                                            [email <- "geoff@example.com", age <- 32],
+                                            [email <- "alex@example.com", age <- 83]])
         )
     }
 
     func test_insert_encodable() throws {
         let emails = Table("emails")
-        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
+                                date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
         let insert = try emails.insert(value)
-        AssertSQL(
-            "INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\") VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000')",
+        assertSQL(
+            """
+            INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\")
+             VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000')
+            """.replacingOccurrences(of: "\n", with: ""),
             insert
         )
     }
 
     func test_insert_encodable_with_nested_encodable() throws {
         let emails = Table("emails")
-        let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
-        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: "optional", sub: value1)
+        let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
+                                 date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
+                                date: Date(timeIntervalSince1970: 0), optional: "optional", sub: value1)
         let insert = try emails.insert(value)
         let encodedJSON = try JSONEncoder().encode(value1)
         let encodedJSONString = String(data: encodedJSON, encoding: .utf8)!
-        AssertSQL(
-            "INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\", \"optional\", \"sub\") VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000', 'optional', '\(encodedJSONString)')",
+        assertSQL(
+            """
+            INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\", \"optional\",
+             \"sub\") VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000', 'optional', '\(encodedJSONString)')
+            """.replacingOccurrences(of: "\n", with: ""),
             insert
         )
     }
 
     func test_upsert_withOnConflict_compilesInsertOrOnConflictExpression() {
-        AssertSQL(
-            "INSERT INTO \"users\" (\"email\", \"age\") VALUES ('alice@example.com', 30) ON CONFLICT (\"email\") DO UPDATE SET \"age\" = \"excluded\".\"age\"",
+        assertSQL(
+            """
+            INSERT INTO \"users\" (\"email\", \"age\") VALUES ('alice@example.com', 30) ON CONFLICT (\"email\")
+             DO UPDATE SET \"age\" = \"excluded\".\"age\"
+            """.replacingOccurrences(of: "\n", with: ""),
             users.upsert(email <- "alice@example.com", age <- 30, onConflictOf: email)
         )
     }
@@ -300,35 +321,48 @@ class QueryTests : XCTestCase {
     func test_upsert_encodable() throws {
         let emails = Table("emails")
         let string = Expression<String>("string")
-        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
+                                date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
         let insert = try emails.upsert(value, onConflictOf: string)
-        AssertSQL(
-            "INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\") VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000') ON CONFLICT (\"string\") DO UPDATE SET \"int\" = \"excluded\".\"int\", \"bool\" = \"excluded\".\"bool\", \"float\" = \"excluded\".\"float\", \"double\" = \"excluded\".\"double\", \"date\" = \"excluded\".\"date\"",
+        assertSQL(
+            """
+            INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\")
+             VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000') ON CONFLICT (\"string\")
+             DO UPDATE SET \"int\" = \"excluded\".\"int\", \"bool\" = \"excluded\".\"bool\",
+             \"float\" = \"excluded\".\"float\", \"double\" = \"excluded\".\"double\", \"date\" = \"excluded\".\"date\"
+            """.replacingOccurrences(of: "\n", with: ""),
             insert
         )
     }
 
     func test_insert_many_encodable() throws {
         let emails = Table("emails")
-        let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
-        let value2 = TestCodable(int: 2, string: "3", bool: true, float: 3, double: 5, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
-        let value3 = TestCodable(int: 3, string: "4", bool: true, float: 3, double: 6, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+        let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
+                                 date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+        let value2 = TestCodable(int: 2, string: "3", bool: true, float: 3, double: 5,
+                                 date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+        let value3 = TestCodable(int: 3, string: "4", bool: true, float: 3, double: 6,
+                                 date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
         let insert = try emails.insertMany([value1, value2, value3])
-        AssertSQL(
-            "INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\") VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000'), (2, '3', 1, 3.0, 5.0, '1970-01-01T00:00:00.000'), (3, '4', 1, 3.0, 6.0, '1970-01-01T00:00:00.000')",
+        assertSQL(
+            """
+            INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\")
+             VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000'), (2, '3', 1, 3.0, 5.0, '1970-01-01T00:00:00.000'),
+             (3, '4', 1, 3.0, 6.0, '1970-01-01T00:00:00.000')
+            """.replacingOccurrences(of: "\n", with: ""),
             insert
         )
     }
 
     func test_update_compilesUpdateExpression() {
-        AssertSQL(
+        assertSQL(
             "UPDATE \"users\" SET \"age\" = 30, \"admin\" = 1 WHERE (\"id\" = 1)",
             users.filter(id == 1).update(age <- 30, admin <- true)
         )
     }
 
     func test_update_compilesUpdateLimitOrderExpression() {
-        AssertSQL(
+        assertSQL(
             "UPDATE \"users\" SET \"age\" = 30 ORDER BY \"id\" LIMIT 1",
             users.order(id).limit(1).update(age <- 30)
         )
@@ -336,95 +370,104 @@ class QueryTests : XCTestCase {
 
     func test_update_encodable() throws {
         let emails = Table("emails")
-        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
+                                date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
         let update = try emails.update(value)
-        AssertSQL(
-            "UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0, \"date\" = '1970-01-01T00:00:00.000'",
+        assertSQL(
+            """
+            UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0,
+             \"date\" = '1970-01-01T00:00:00.000'
+            """.replacingOccurrences(of: "\n", with: ""),
             update
         )
     }
 
     func test_update_encodable_with_nested_encodable() throws {
         let emails = Table("emails")
-        let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
-        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: nil, sub: value1)
+        let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
+                                 date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+        let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
+                                date: Date(timeIntervalSince1970: 0), optional: nil, sub: value1)
         let update = try emails.update(value)
         let encodedJSON = try JSONEncoder().encode(value1)
         let encodedJSONString = String(data: encodedJSON, encoding: .utf8)!
-        AssertSQL(
-            "UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0, \"date\" = '1970-01-01T00:00:00.000', \"sub\" = '\(encodedJSONString)'",
+        assertSQL(
+            """
+            UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0,
+             \"date\" = '1970-01-01T00:00:00.000', \"sub\" = '\(encodedJSONString)'
+            """.replacingOccurrences(of: "\n", with: ""),
             update
         )
     }
 
     func test_delete_compilesDeleteExpression() {
-        AssertSQL(
+        assertSQL(
             "DELETE FROM \"users\" WHERE (\"id\" = 1)",
             users.filter(id == 1).delete()
         )
     }
 
     func test_delete_compilesDeleteLimitOrderExpression() {
-        AssertSQL(
+        assertSQL(
             "DELETE FROM \"users\" ORDER BY \"id\" LIMIT 1",
             users.order(id).limit(1).delete()
         )
     }
 
     func test_delete_compilesExistsExpression() {
-        AssertSQL(
+        assertSQL(
             "SELECT EXISTS (SELECT * FROM \"users\")",
             users.exists
         )
     }
 
     func test_count_returnsCountExpression() {
-        AssertSQL("SELECT count(*) FROM \"users\"", users.count)
+        assertSQL("SELECT count(*) FROM \"users\"", users.count)
     }
 
     func test_scalar_returnsScalarExpression() {
-        AssertSQL("SELECT \"int\" FROM \"table\"", table.select(int) as ScalarQuery<Int>)
-        AssertSQL("SELECT \"intOptional\" FROM \"table\"", table.select(intOptional) as ScalarQuery<Int?>)
-        AssertSQL("SELECT DISTINCT \"int\" FROM \"table\"", table.select(distinct: int) as ScalarQuery<Int>)
-        AssertSQL("SELECT DISTINCT \"intOptional\" FROM \"table\"", table.select(distinct: intOptional) as ScalarQuery<Int?>)
+        assertSQL("SELECT \"int\" FROM \"table\"", table.select(int) as ScalarQuery<Int>)
+        assertSQL("SELECT \"intOptional\" FROM \"table\"", table.select(intOptional) as ScalarQuery<Int?>)
+        assertSQL("SELECT DISTINCT \"int\" FROM \"table\"", table.select(distinct: int) as ScalarQuery<Int>)
+        assertSQL("SELECT DISTINCT \"intOptional\" FROM \"table\"", table.select(distinct: intOptional) as ScalarQuery<Int?>)
     }
 
     func test_subscript_withExpression_returnsNamespacedExpression() {
         let query = Table("query")
 
-        AssertSQL("\"query\".\"blob\"", query[data])
-        AssertSQL("\"query\".\"blobOptional\"", query[dataOptional])
+        assertSQL("\"query\".\"blob\"", query[data])
+        assertSQL("\"query\".\"blobOptional\"", query[dataOptional])
 
-        AssertSQL("\"query\".\"bool\"", query[bool])
-        AssertSQL("\"query\".\"boolOptional\"", query[boolOptional])
+        assertSQL("\"query\".\"bool\"", query[bool])
+        assertSQL("\"query\".\"boolOptional\"", query[boolOptional])
 
-        AssertSQL("\"query\".\"date\"", query[date])
-        AssertSQL("\"query\".\"dateOptional\"", query[dateOptional])
+        assertSQL("\"query\".\"date\"", query[date])
+        assertSQL("\"query\".\"dateOptional\"", query[dateOptional])
 
-        AssertSQL("\"query\".\"double\"", query[double])
-        AssertSQL("\"query\".\"doubleOptional\"", query[doubleOptional])
+        assertSQL("\"query\".\"double\"", query[double])
+        assertSQL("\"query\".\"doubleOptional\"", query[doubleOptional])
 
-        AssertSQL("\"query\".\"int\"", query[int])
-        AssertSQL("\"query\".\"intOptional\"", query[intOptional])
+        assertSQL("\"query\".\"int\"", query[int])
+        assertSQL("\"query\".\"intOptional\"", query[intOptional])
 
-        AssertSQL("\"query\".\"int64\"", query[int64])
-        AssertSQL("\"query\".\"int64Optional\"", query[int64Optional])
+        assertSQL("\"query\".\"int64\"", query[int64])
+        assertSQL("\"query\".\"int64Optional\"", query[int64Optional])
 
-        AssertSQL("\"query\".\"string\"", query[string])
-        AssertSQL("\"query\".\"stringOptional\"", query[stringOptional])
+        assertSQL("\"query\".\"string\"", query[string])
+        assertSQL("\"query\".\"stringOptional\"", query[stringOptional])
 
-        AssertSQL("\"query\".*", query[*])
+        assertSQL("\"query\".*", query[*])
     }
 
     func test_tableNamespacedByDatabase() {
         let table = Table("table", database: "attached")
 
-        AssertSQL("SELECT * FROM \"attached\".\"table\"", table)
+        assertSQL("SELECT * FROM \"attached\".\"table\"", table)
     }
 
 }
 
-class QueryIntegrationTests : SQLiteTestCase {
+class QueryIntegrationTests: SQLiteTestCase {
 
     let id = Expression<Int64>("id")
     let email = Expression<String>("email")
@@ -433,7 +476,7 @@ class QueryIntegrationTests : SQLiteTestCase {
     override func setUp() {
         super.setUp()
 
-        CreateUsersTable()
+        createUsersTable()
     }
 
     // MARK: -
@@ -452,7 +495,7 @@ class QueryIntegrationTests : SQLiteTestCase {
 
     func test_prepareRowIterator() {
         let names = ["a", "b", "c"]
-        try! InsertUsers(names)
+        try! insertUsers(names)
 
         let emailColumn = Expression<String>("email")
         let emails = try! db.prepareRowIterator(users).map { $0[emailColumn] }
@@ -462,7 +505,7 @@ class QueryIntegrationTests : SQLiteTestCase {
 
     func test_ambiguousMap() {
         let names = ["a", "b", "c"]
-        try! InsertUsers(names)
+        try! insertUsers(names)
 
         let emails = try! db.prepare("select email from users", []).map { $0[0] as! String  }
 
@@ -494,8 +537,10 @@ class QueryIntegrationTests : SQLiteTestCase {
             builder.column(Expression<Data>("sub"))
         })
 
-        let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4, date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
-        let value = TestCodable(int: 5, string: "6", bool: true, float: 7, double: 8, date: Date(timeIntervalSince1970: 5000), optional: "optional", sub: value1)
+        let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
+                                 date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+        let value = TestCodable(int: 5, string: "6", bool: true, float: 7, double: 8,
+                                date: Date(timeIntervalSince1970: 5000), optional: "optional", sub: value1)
 
         try db.run(table.insert(value))
 
@@ -523,7 +568,7 @@ class QueryIntegrationTests : SQLiteTestCase {
         XCTAssertEqual(0, try! db.scalar(users.count))
         XCTAssertEqual(false, try! db.scalar(users.exists))
 
-        try! InsertUsers("alice")
+        try! insertUsers("alice")
         XCTAssertEqual(1, try! db.scalar(users.select(id.average)))
     }
 
@@ -590,7 +635,7 @@ class QueryIntegrationTests : SQLiteTestCase {
 
     func test_no_such_column() throws {
         let doesNotExist = Expression<String>("doesNotExist")
-        try! InsertUser("alice")
+        try! insertUser("alice")
         let row = try! db.pluck(users.filter(email == "alice@example.com"))!
 
         XCTAssertThrowsError(try row.get(doesNotExist)) { error in
diff --git a/Tests/SQLiteTests/RTreeTests.swift b/Tests/SQLiteTests/RTreeTests.swift
index 7147533e..5525da26 100644
--- a/Tests/SQLiteTests/RTreeTests.swift
+++ b/Tests/SQLiteTests/RTreeTests.swift
@@ -1,7 +1,7 @@
 import XCTest
 import SQLite
 
-class RTreeTests : XCTestCase {
+class RTreeTests: XCTestCase {
 
     func test_create_onVirtualTable_withRTree_createVirtualTableExpression() {
         XCTAssertEqual(
@@ -14,4 +14,4 @@ class RTreeTests : XCTestCase {
         )
     }
 
-}
\ No newline at end of file
+}
diff --git a/Tests/SQLiteTests/RowTests.swift b/Tests/SQLiteTests/RowTests.swift
index 17873e71..36721f80 100644
--- a/Tests/SQLiteTests/RowTests.swift
+++ b/Tests/SQLiteTests/RowTests.swift
@@ -1,7 +1,7 @@
 import XCTest
 @testable import SQLite
 
-class RowTests : XCTestCase {
+class RowTests: XCTestCase {
 
     public func test_get_value() {
         let row = Row(["\"foo\"": 0], ["value"])
diff --git a/Tests/SQLiteTests/SchemaTests.swift b/Tests/SQLiteTests/SchemaTests.swift
index 30646b98..495a5e51 100644
--- a/Tests/SQLiteTests/SchemaTests.swift
+++ b/Tests/SQLiteTests/SchemaTests.swift
@@ -1,7 +1,7 @@
 import XCTest
 import SQLite
 
-class SchemaTests : XCTestCase {
+class SchemaTests: XCTestCase {
 
     func test_drop_compilesDropTableExpression() {
         XCTAssertEqual("DROP TABLE \"table\"", table.drop())
@@ -330,7 +330,10 @@ class SchemaTests : XCTestCase {
             table.create { t in t.column(int64, unique: true, check: int64 > 0, references: table, int64) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL UNIQUE CHECK (\"int64Optional\" > 0) REFERENCES \"table\" (\"int64\"))",
+            """
+            CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL UNIQUE CHECK (\"int64Optional\" > 0) REFERENCES
+             \"table\" (\"int64\"))
+            """.replacingOccurrences(of: "\n", with: ""),
             table.create { t in t.column(int64, unique: true, check: int64Optional > 0, references: table, int64) }
         )
 
@@ -487,48 +490,95 @@ class SchemaTests : XCTestCase {
             table.create { t in t.column(stringOptional, unique: true, check: string != "", defaultValue: string, collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"string\" != '') DEFAULT (\"stringOptional\") COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, unique: true, check: string != "", defaultValue: stringOptional, collate: .rtrim) }
+            """
+            CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"string\" != '')
+             DEFAULT (\"stringOptional\") COLLATE RTRIM)
+            """.replacingOccurrences(of: "\n", with: ""),
+            table.create { t in t.column(stringOptional,
+                                         unique: true,
+                                         check: string != "",
+                                         defaultValue: stringOptional,
+                                         collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"stringOptional\" != '') DEFAULT (\"string\") COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, unique: true, check: stringOptional != "", defaultValue: string, collate: .rtrim) }
+            """
+            CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"stringOptional\" != '')
+             DEFAULT (\"string\") COLLATE RTRIM)
+            """.replacingOccurrences(of: "\n", with: ""),
+            table.create { t in t.column(stringOptional, unique: true, check: stringOptional != "",
+                                         defaultValue: string, collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"stringOptional\" != '') DEFAULT (\"stringOptional\") COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, unique: true, check: stringOptional != "", defaultValue: stringOptional, collate: .rtrim) }
+            """
+            CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"stringOptional\" != '')
+             DEFAULT (\"stringOptional\") COLLATE RTRIM)
+            """.replacingOccurrences(of: "\n", with: ""),
+            table.create { t in t.column(stringOptional, unique: true, check: stringOptional != "",
+                                         defaultValue: stringOptional, collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"string\" != '') DEFAULT ('string') COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, unique: true, check: string != "", defaultValue: "string", collate: .rtrim) }
+            """
+            CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"string\" != '')
+             DEFAULT ('string') COLLATE RTRIM)
+            """.replacingOccurrences(of: "\n", with: ""),
+            table.create { t in t.column(stringOptional, unique: true, check: string != "",
+                                         defaultValue: "string", collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"stringOptional\" != '') DEFAULT ('string') COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, unique: true, check: stringOptional != "", defaultValue: "string", collate: .rtrim) }
+            """
+            CREATE TABLE \"table\" (\"stringOptional\" TEXT UNIQUE CHECK (\"stringOptional\" != '')
+             DEFAULT ('string') COLLATE RTRIM)
+            """.replacingOccurrences(of: "\n", with: ""),
+            table.create { t in t.column(stringOptional, unique: true, check: stringOptional != "",
+                                         defaultValue: "string", collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"string\" != '') DEFAULT (\"string\") COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, check: string != "", defaultValue: string, collate: .rtrim) }
+            """
+            CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"string\" != '')
+             DEFAULT (\"string\") COLLATE RTRIM)
+            """.replacingOccurrences(of: "\n", with: ""),
+            table.create { t in t.column(stringOptional, check: string != "",
+                                         defaultValue: string, collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"stringOptional\" != '') DEFAULT (\"string\") COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, check: stringOptional != "", defaultValue: string, collate: .rtrim) }
+            """
+            CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"stringOptional\" != '')
+             DEFAULT (\"string\") COLLATE RTRIM)
+            """.replacingOccurrences(of: "\n", with: ""),
+            table.create { t in t.column(stringOptional, check: stringOptional != "",
+                                         defaultValue: string, collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"string\" != '') DEFAULT (\"stringOptional\") COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, check: string != "", defaultValue: stringOptional, collate: .rtrim) }
+            """
+            CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"string\" != '')
+             DEFAULT (\"stringOptional\") COLLATE RTRIM)
+            """.replacingOccurrences(of: "\n", with: ""),
+            table.create { t in t.column(stringOptional, check: string != "",
+                                         defaultValue: stringOptional, collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"stringOptional\" != '') DEFAULT (\"stringOptional\") COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, check: stringOptional != "", defaultValue: stringOptional, collate: .rtrim) }
+            """
+            CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"stringOptional\" != '')
+             DEFAULT (\"stringOptional\") COLLATE RTRIM)
+            """.replacingOccurrences(of: "\n", with: ""),
+            table.create { t in t.column(stringOptional, check: stringOptional != "",
+                                         defaultValue: stringOptional, collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"string\" != '') DEFAULT ('string') COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, check: string != "", defaultValue: "string", collate: .rtrim) }
+            """
+            CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"string\" != '')
+             DEFAULT ('string') COLLATE RTRIM)
+            """.replacingOccurrences(of: "\n", with: ""),
+            table.create { t in t.column(stringOptional, check: string != "",
+                                         defaultValue: "string", collate: .rtrim) }
         )
         XCTAssertEqual(
-            "CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"stringOptional\" != '') DEFAULT ('string') COLLATE RTRIM)",
-            table.create { t in t.column(stringOptional, check: stringOptional != "", defaultValue: "string", collate: .rtrim) }
+            """
+            CREATE TABLE \"table\" (\"stringOptional\" TEXT CHECK (\"stringOptional\" != '')
+             DEFAULT ('string') COLLATE RTRIM)
+            """.replacingOccurrences(of: "\n", with: ""),
+            table.create { t in t.column(stringOptional, check: stringOptional != "",
+                                         defaultValue: "string", collate: .rtrim) }
         )
     }
 
diff --git a/Tests/SQLiteTests/SelectTests.swift b/Tests/SQLiteTests/SelectTests.swift
index bca01092..c66d401d 100644
--- a/Tests/SQLiteTests/SelectTests.swift
+++ b/Tests/SQLiteTests/SelectTests.swift
@@ -2,14 +2,14 @@ import XCTest
 @testable import SQLite
 
 class SelectTests: SQLiteTestCase {
-    
+
     override func setUp() {
         super.setUp()
-        CreateUsersTable()
-        CreateUsersDataTable()
+        createUsersTable()
+        createUsersDataTable()
     }
-    
-    func CreateUsersDataTable() {
+
+    func createUsersDataTable() {
         try! db.execute("""
             CREATE TABLE users_name (
                 id INTEGER,
@@ -19,27 +19,26 @@ class SelectTests: SQLiteTestCase {
             """
         )
     }
-    
+
     func test_select_columns_from_multiple_tables() {
         let usersData = Table("users_name")
         let users = Table("users")
-        
+
         let name = Expression<String>("name")
         let id = Expression<Int64>("id")
         let userID = Expression<Int64>("user_id")
         let email = Expression<String>("email")
-        
-        try! InsertUser("Joey")
+
+        try! insertUser("Joey")
         try! db.run(usersData.insert(
             id <- 1,
             userID <- 1,
             name <- "Joey"
         ))
-        
+
         try! db.prepare(users.select(name, email).join(usersData, on: userID == users[id])).forEach {
             XCTAssertEqual($0[name], "Joey")
             XCTAssertEqual($0[email], "Joey@example.com")
         }
     }
-    
 }
diff --git a/Tests/SQLiteTests/SetterTests.swift b/Tests/SQLiteTests/SetterTests.swift
index d4f189d7..938dd013 100644
--- a/Tests/SQLiteTests/SetterTests.swift
+++ b/Tests/SQLiteTests/SetterTests.swift
@@ -1,137 +1,137 @@
 import XCTest
 import SQLite
 
-class SetterTests : XCTestCase {
+class SetterTests: XCTestCase {
 
     func test_setterAssignmentOperator_buildsSetter() {
-        AssertSQL("\"int\" = \"int\"", int <- int)
-        AssertSQL("\"int\" = 1", int <- 1)
-        AssertSQL("\"intOptional\" = \"int\"", intOptional <- int)
-        AssertSQL("\"intOptional\" = \"intOptional\"", intOptional <- intOptional)
-        AssertSQL("\"intOptional\" = 1", intOptional <- 1)
-        AssertSQL("\"intOptional\" = NULL", intOptional <- nil)
+        assertSQL("\"int\" = \"int\"", int <- int)
+        assertSQL("\"int\" = 1", int <- 1)
+        assertSQL("\"intOptional\" = \"int\"", intOptional <- int)
+        assertSQL("\"intOptional\" = \"intOptional\"", intOptional <- intOptional)
+        assertSQL("\"intOptional\" = 1", intOptional <- 1)
+        assertSQL("\"intOptional\" = NULL", intOptional <- nil)
     }
 
     func test_plusEquals_withStringExpression_buildsSetter() {
-        AssertSQL("\"string\" = (\"string\" || \"string\")", string += string)
-        AssertSQL("\"string\" = (\"string\" || 'literal')", string += "literal")
-        AssertSQL("\"stringOptional\" = (\"stringOptional\" || \"string\")", stringOptional += string)
-        AssertSQL("\"stringOptional\" = (\"stringOptional\" || \"stringOptional\")", stringOptional += stringOptional)
-        AssertSQL("\"stringOptional\" = (\"stringOptional\" || 'literal')", stringOptional += "literal")
+        assertSQL("\"string\" = (\"string\" || \"string\")", string += string)
+        assertSQL("\"string\" = (\"string\" || 'literal')", string += "literal")
+        assertSQL("\"stringOptional\" = (\"stringOptional\" || \"string\")", stringOptional += string)
+        assertSQL("\"stringOptional\" = (\"stringOptional\" || \"stringOptional\")", stringOptional += stringOptional)
+        assertSQL("\"stringOptional\" = (\"stringOptional\" || 'literal')", stringOptional += "literal")
     }
 
     func test_plusEquals_withNumberExpression_buildsSetter() {
-        AssertSQL("\"int\" = (\"int\" + \"int\")", int += int)
-        AssertSQL("\"int\" = (\"int\" + 1)", int += 1)
-        AssertSQL("\"intOptional\" = (\"intOptional\" + \"int\")", intOptional += int)
-        AssertSQL("\"intOptional\" = (\"intOptional\" + \"intOptional\")", intOptional += intOptional)
-        AssertSQL("\"intOptional\" = (\"intOptional\" + 1)", intOptional += 1)
-
-        AssertSQL("\"double\" = (\"double\" + \"double\")", double += double)
-        AssertSQL("\"double\" = (\"double\" + 1.0)", double += 1)
-        AssertSQL("\"doubleOptional\" = (\"doubleOptional\" + \"double\")", doubleOptional += double)
-        AssertSQL("\"doubleOptional\" = (\"doubleOptional\" + \"doubleOptional\")", doubleOptional += doubleOptional)
-        AssertSQL("\"doubleOptional\" = (\"doubleOptional\" + 1.0)", doubleOptional += 1)
+        assertSQL("\"int\" = (\"int\" + \"int\")", int += int)
+        assertSQL("\"int\" = (\"int\" + 1)", int += 1)
+        assertSQL("\"intOptional\" = (\"intOptional\" + \"int\")", intOptional += int)
+        assertSQL("\"intOptional\" = (\"intOptional\" + \"intOptional\")", intOptional += intOptional)
+        assertSQL("\"intOptional\" = (\"intOptional\" + 1)", intOptional += 1)
+
+        assertSQL("\"double\" = (\"double\" + \"double\")", double += double)
+        assertSQL("\"double\" = (\"double\" + 1.0)", double += 1)
+        assertSQL("\"doubleOptional\" = (\"doubleOptional\" + \"double\")", doubleOptional += double)
+        assertSQL("\"doubleOptional\" = (\"doubleOptional\" + \"doubleOptional\")", doubleOptional += doubleOptional)
+        assertSQL("\"doubleOptional\" = (\"doubleOptional\" + 1.0)", doubleOptional += 1)
     }
 
     func test_minusEquals_withNumberExpression_buildsSetter() {
-        AssertSQL("\"int\" = (\"int\" - \"int\")", int -= int)
-        AssertSQL("\"int\" = (\"int\" - 1)", int -= 1)
-        AssertSQL("\"intOptional\" = (\"intOptional\" - \"int\")", intOptional -= int)
-        AssertSQL("\"intOptional\" = (\"intOptional\" - \"intOptional\")", intOptional -= intOptional)
-        AssertSQL("\"intOptional\" = (\"intOptional\" - 1)", intOptional -= 1)
-
-        AssertSQL("\"double\" = (\"double\" - \"double\")", double -= double)
-        AssertSQL("\"double\" = (\"double\" - 1.0)", double -= 1)
-        AssertSQL("\"doubleOptional\" = (\"doubleOptional\" - \"double\")", doubleOptional -= double)
-        AssertSQL("\"doubleOptional\" = (\"doubleOptional\" - \"doubleOptional\")", doubleOptional -= doubleOptional)
-        AssertSQL("\"doubleOptional\" = (\"doubleOptional\" - 1.0)", doubleOptional -= 1)
+        assertSQL("\"int\" = (\"int\" - \"int\")", int -= int)
+        assertSQL("\"int\" = (\"int\" - 1)", int -= 1)
+        assertSQL("\"intOptional\" = (\"intOptional\" - \"int\")", intOptional -= int)
+        assertSQL("\"intOptional\" = (\"intOptional\" - \"intOptional\")", intOptional -= intOptional)
+        assertSQL("\"intOptional\" = (\"intOptional\" - 1)", intOptional -= 1)
+
+        assertSQL("\"double\" = (\"double\" - \"double\")", double -= double)
+        assertSQL("\"double\" = (\"double\" - 1.0)", double -= 1)
+        assertSQL("\"doubleOptional\" = (\"doubleOptional\" - \"double\")", doubleOptional -= double)
+        assertSQL("\"doubleOptional\" = (\"doubleOptional\" - \"doubleOptional\")", doubleOptional -= doubleOptional)
+        assertSQL("\"doubleOptional\" = (\"doubleOptional\" - 1.0)", doubleOptional -= 1)
     }
 
     func test_timesEquals_withNumberExpression_buildsSetter() {
-        AssertSQL("\"int\" = (\"int\" * \"int\")", int *= int)
-        AssertSQL("\"int\" = (\"int\" * 1)", int *= 1)
-        AssertSQL("\"intOptional\" = (\"intOptional\" * \"int\")", intOptional *= int)
-        AssertSQL("\"intOptional\" = (\"intOptional\" * \"intOptional\")", intOptional *= intOptional)
-        AssertSQL("\"intOptional\" = (\"intOptional\" * 1)", intOptional *= 1)
-
-        AssertSQL("\"double\" = (\"double\" * \"double\")", double *= double)
-        AssertSQL("\"double\" = (\"double\" * 1.0)", double *= 1)
-        AssertSQL("\"doubleOptional\" = (\"doubleOptional\" * \"double\")", doubleOptional *= double)
-        AssertSQL("\"doubleOptional\" = (\"doubleOptional\" * \"doubleOptional\")", doubleOptional *= doubleOptional)
-        AssertSQL("\"doubleOptional\" = (\"doubleOptional\" * 1.0)", doubleOptional *= 1)
+        assertSQL("\"int\" = (\"int\" * \"int\")", int *= int)
+        assertSQL("\"int\" = (\"int\" * 1)", int *= 1)
+        assertSQL("\"intOptional\" = (\"intOptional\" * \"int\")", intOptional *= int)
+        assertSQL("\"intOptional\" = (\"intOptional\" * \"intOptional\")", intOptional *= intOptional)
+        assertSQL("\"intOptional\" = (\"intOptional\" * 1)", intOptional *= 1)
+
+        assertSQL("\"double\" = (\"double\" * \"double\")", double *= double)
+        assertSQL("\"double\" = (\"double\" * 1.0)", double *= 1)
+        assertSQL("\"doubleOptional\" = (\"doubleOptional\" * \"double\")", doubleOptional *= double)
+        assertSQL("\"doubleOptional\" = (\"doubleOptional\" * \"doubleOptional\")", doubleOptional *= doubleOptional)
+        assertSQL("\"doubleOptional\" = (\"doubleOptional\" * 1.0)", doubleOptional *= 1)
     }
 
     func test_dividedByEquals_withNumberExpression_buildsSetter() {
-        AssertSQL("\"int\" = (\"int\" / \"int\")", int /= int)
-        AssertSQL("\"int\" = (\"int\" / 1)", int /= 1)
-        AssertSQL("\"intOptional\" = (\"intOptional\" / \"int\")", intOptional /= int)
-        AssertSQL("\"intOptional\" = (\"intOptional\" / \"intOptional\")", intOptional /= intOptional)
-        AssertSQL("\"intOptional\" = (\"intOptional\" / 1)", intOptional /= 1)
-
-        AssertSQL("\"double\" = (\"double\" / \"double\")", double /= double)
-        AssertSQL("\"double\" = (\"double\" / 1.0)", double /= 1)
-        AssertSQL("\"doubleOptional\" = (\"doubleOptional\" / \"double\")", doubleOptional /= double)
-        AssertSQL("\"doubleOptional\" = (\"doubleOptional\" / \"doubleOptional\")", doubleOptional /= doubleOptional)
-        AssertSQL("\"doubleOptional\" = (\"doubleOptional\" / 1.0)", doubleOptional /= 1)
+        assertSQL("\"int\" = (\"int\" / \"int\")", int /= int)
+        assertSQL("\"int\" = (\"int\" / 1)", int /= 1)
+        assertSQL("\"intOptional\" = (\"intOptional\" / \"int\")", intOptional /= int)
+        assertSQL("\"intOptional\" = (\"intOptional\" / \"intOptional\")", intOptional /= intOptional)
+        assertSQL("\"intOptional\" = (\"intOptional\" / 1)", intOptional /= 1)
+
+        assertSQL("\"double\" = (\"double\" / \"double\")", double /= double)
+        assertSQL("\"double\" = (\"double\" / 1.0)", double /= 1)
+        assertSQL("\"doubleOptional\" = (\"doubleOptional\" / \"double\")", doubleOptional /= double)
+        assertSQL("\"doubleOptional\" = (\"doubleOptional\" / \"doubleOptional\")", doubleOptional /= doubleOptional)
+        assertSQL("\"doubleOptional\" = (\"doubleOptional\" / 1.0)", doubleOptional /= 1)
     }
 
     func test_moduloEquals_withIntegerExpression_buildsSetter() {
-        AssertSQL("\"int\" = (\"int\" % \"int\")", int %= int)
-        AssertSQL("\"int\" = (\"int\" % 1)", int %= 1)
-        AssertSQL("\"intOptional\" = (\"intOptional\" % \"int\")", intOptional %= int)
-        AssertSQL("\"intOptional\" = (\"intOptional\" % \"intOptional\")", intOptional %= intOptional)
-        AssertSQL("\"intOptional\" = (\"intOptional\" % 1)", intOptional %= 1)
+        assertSQL("\"int\" = (\"int\" % \"int\")", int %= int)
+        assertSQL("\"int\" = (\"int\" % 1)", int %= 1)
+        assertSQL("\"intOptional\" = (\"intOptional\" % \"int\")", intOptional %= int)
+        assertSQL("\"intOptional\" = (\"intOptional\" % \"intOptional\")", intOptional %= intOptional)
+        assertSQL("\"intOptional\" = (\"intOptional\" % 1)", intOptional %= 1)
     }
 
     func test_leftShiftEquals_withIntegerExpression_buildsSetter() {
-        AssertSQL("\"int\" = (\"int\" << \"int\")", int <<= int)
-        AssertSQL("\"int\" = (\"int\" << 1)", int <<= 1)
-        AssertSQL("\"intOptional\" = (\"intOptional\" << \"int\")", intOptional <<= int)
-        AssertSQL("\"intOptional\" = (\"intOptional\" << \"intOptional\")", intOptional <<= intOptional)
-        AssertSQL("\"intOptional\" = (\"intOptional\" << 1)", intOptional <<= 1)
+        assertSQL("\"int\" = (\"int\" << \"int\")", int <<= int)
+        assertSQL("\"int\" = (\"int\" << 1)", int <<= 1)
+        assertSQL("\"intOptional\" = (\"intOptional\" << \"int\")", intOptional <<= int)
+        assertSQL("\"intOptional\" = (\"intOptional\" << \"intOptional\")", intOptional <<= intOptional)
+        assertSQL("\"intOptional\" = (\"intOptional\" << 1)", intOptional <<= 1)
     }
 
     func test_rightShiftEquals_withIntegerExpression_buildsSetter() {
-        AssertSQL("\"int\" = (\"int\" >> \"int\")", int >>= int)
-        AssertSQL("\"int\" = (\"int\" >> 1)", int >>= 1)
-        AssertSQL("\"intOptional\" = (\"intOptional\" >> \"int\")", intOptional >>= int)
-        AssertSQL("\"intOptional\" = (\"intOptional\" >> \"intOptional\")", intOptional >>= intOptional)
-        AssertSQL("\"intOptional\" = (\"intOptional\" >> 1)", intOptional >>= 1)
+        assertSQL("\"int\" = (\"int\" >> \"int\")", int >>= int)
+        assertSQL("\"int\" = (\"int\" >> 1)", int >>= 1)
+        assertSQL("\"intOptional\" = (\"intOptional\" >> \"int\")", intOptional >>= int)
+        assertSQL("\"intOptional\" = (\"intOptional\" >> \"intOptional\")", intOptional >>= intOptional)
+        assertSQL("\"intOptional\" = (\"intOptional\" >> 1)", intOptional >>= 1)
     }
 
     func test_bitwiseAndEquals_withIntegerExpression_buildsSetter() {
-        AssertSQL("\"int\" = (\"int\" & \"int\")", int &= int)
-        AssertSQL("\"int\" = (\"int\" & 1)", int &= 1)
-        AssertSQL("\"intOptional\" = (\"intOptional\" & \"int\")", intOptional &= int)
-        AssertSQL("\"intOptional\" = (\"intOptional\" & \"intOptional\")", intOptional &= intOptional)
-        AssertSQL("\"intOptional\" = (\"intOptional\" & 1)", intOptional &= 1)
+        assertSQL("\"int\" = (\"int\" & \"int\")", int &= int)
+        assertSQL("\"int\" = (\"int\" & 1)", int &= 1)
+        assertSQL("\"intOptional\" = (\"intOptional\" & \"int\")", intOptional &= int)
+        assertSQL("\"intOptional\" = (\"intOptional\" & \"intOptional\")", intOptional &= intOptional)
+        assertSQL("\"intOptional\" = (\"intOptional\" & 1)", intOptional &= 1)
     }
 
     func test_bitwiseOrEquals_withIntegerExpression_buildsSetter() {
-        AssertSQL("\"int\" = (\"int\" | \"int\")", int |= int)
-        AssertSQL("\"int\" = (\"int\" | 1)", int |= 1)
-        AssertSQL("\"intOptional\" = (\"intOptional\" | \"int\")", intOptional |= int)
-        AssertSQL("\"intOptional\" = (\"intOptional\" | \"intOptional\")", intOptional |= intOptional)
-        AssertSQL("\"intOptional\" = (\"intOptional\" | 1)", intOptional |= 1)
+        assertSQL("\"int\" = (\"int\" | \"int\")", int |= int)
+        assertSQL("\"int\" = (\"int\" | 1)", int |= 1)
+        assertSQL("\"intOptional\" = (\"intOptional\" | \"int\")", intOptional |= int)
+        assertSQL("\"intOptional\" = (\"intOptional\" | \"intOptional\")", intOptional |= intOptional)
+        assertSQL("\"intOptional\" = (\"intOptional\" | 1)", intOptional |= 1)
     }
 
     func test_bitwiseExclusiveOrEquals_withIntegerExpression_buildsSetter() {
-        AssertSQL("\"int\" = (~((\"int\" & \"int\")) & (\"int\" | \"int\"))", int ^= int)
-        AssertSQL("\"int\" = (~((\"int\" & 1)) & (\"int\" | 1))", int ^= 1)
-        AssertSQL("\"intOptional\" = (~((\"intOptional\" & \"int\")) & (\"intOptional\" | \"int\"))", intOptional ^= int)
-        AssertSQL("\"intOptional\" = (~((\"intOptional\" & \"intOptional\")) & (\"intOptional\" | \"intOptional\"))", intOptional ^= intOptional)
-        AssertSQL("\"intOptional\" = (~((\"intOptional\" & 1)) & (\"intOptional\" | 1))", intOptional ^= 1)
+        assertSQL("\"int\" = (~((\"int\" & \"int\")) & (\"int\" | \"int\"))", int ^= int)
+        assertSQL("\"int\" = (~((\"int\" & 1)) & (\"int\" | 1))", int ^= 1)
+        assertSQL("\"intOptional\" = (~((\"intOptional\" & \"int\")) & (\"intOptional\" | \"int\"))", intOptional ^= int)
+        assertSQL("\"intOptional\" = (~((\"intOptional\" & \"intOptional\")) & (\"intOptional\" | \"intOptional\"))", intOptional ^= intOptional)
+        assertSQL("\"intOptional\" = (~((\"intOptional\" & 1)) & (\"intOptional\" | 1))", intOptional ^= 1)
     }
 
     func test_postfixPlus_withIntegerValue_buildsSetter() {
-        AssertSQL("\"int\" = (\"int\" + 1)", int++)
-        AssertSQL("\"intOptional\" = (\"intOptional\" + 1)", intOptional++)
+        assertSQL("\"int\" = (\"int\" + 1)", int++)
+        assertSQL("\"intOptional\" = (\"intOptional\" + 1)", intOptional++)
     }
 
     func test_postfixMinus_withIntegerValue_buildsSetter() {
-        AssertSQL("\"int\" = (\"int\" - 1)", int--)
-        AssertSQL("\"intOptional\" = (\"intOptional\" - 1)", intOptional--)
+        assertSQL("\"int\" = (\"int\" - 1)", int--)
+        assertSQL("\"intOptional\" = (\"intOptional\" - 1)", intOptional--)
     }
 
 }
diff --git a/Tests/SQLiteTests/StatementTests.swift b/Tests/SQLiteTests/StatementTests.swift
index 326259b2..5a05675d 100644
--- a/Tests/SQLiteTests/StatementTests.swift
+++ b/Tests/SQLiteTests/StatementTests.swift
@@ -1,14 +1,14 @@
 import XCTest
 import SQLite
 
-class StatementTests : SQLiteTestCase {
+class StatementTests: SQLiteTestCase {
     override func setUp() {
         super.setUp()
-        CreateUsersTable()
+        createUsersTable()
     }
 
     func test_cursor_to_blob() {
-        try! InsertUsers("alice")
+        try! insertUsers("alice")
         let statement = try! db.prepare("SELECT email FROM users")
         XCTAssert(try! statement.step())
         let blob = statement.row[0] as Blob
diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index 247013b4..0994dd97 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -1,15 +1,15 @@
 import XCTest
 @testable import SQLite
 
-class SQLiteTestCase : XCTestCase {
-    private var trace:[String: Int]!
-    var db:Connection!
+class SQLiteTestCase: XCTestCase {
+    private var trace: [String: Int]!
+    var db: Connection!
     let users = Table("users")
 
     override func setUp() {
         super.setUp()
         db = try! Connection()
-        trace = [String:Int]()
+        trace = [String: Int]()
 
         db.trace { SQL in
             print(SQL)
@@ -17,7 +17,7 @@ class SQLiteTestCase : XCTestCase {
         }
     }
 
-    func CreateUsersTable() {
+    func createUsersTable() {
         try! db.execute("""
             CREATE TABLE users (
                 id INTEGER PRIMARY KEY,
@@ -33,22 +33,22 @@ class SQLiteTestCase : XCTestCase {
         )
     }
 
-    func InsertUsers(_ names: String...) throws {
-        try InsertUsers(names)
+    func insertUsers(_ names: String...) throws {
+        try insertUsers(names)
     }
 
-    func InsertUsers(_ names: [String]) throws {
-        for name in names { try InsertUser(name) }
+    func insertUsers(_ names: [String]) throws {
+        for name in names { try insertUser(name) }
     }
 
-    @discardableResult func InsertUser(_ name: String, age: Int? = nil, admin: Bool = false) throws -> Statement {
+    @discardableResult func insertUser(_ name: String, age: Int? = nil, admin: Bool = false) throws -> Statement {
         return try db.run(
             "INSERT INTO \"users\" (email, age, admin) values (?, ?, ?)",
             "\(name)@example.com", age?.datatypeValue, admin.datatypeValue
         )
     }
 
-    func AssertSQL(_ SQL: String, _ executions: Int = 1, _ message: String? = nil, file: StaticString = #file, line: UInt = #line) {
+    func assertSQL(_ SQL: String, _ executions: Int = 1, _ message: String? = nil, file: StaticString = #file, line: UInt = #line) {
         XCTAssertEqual(
             executions, trace[SQL] ?? 0,
             message ?? SQL,
@@ -56,9 +56,9 @@ class SQLiteTestCase : XCTestCase {
         )
     }
 
-    func AssertSQL(_ SQL: String, _ statement: Statement, _ message: String? = nil, file: StaticString = #file, line: UInt = #line) {
+    func assertSQL(_ SQL: String, _ statement: Statement, _ message: String? = nil, file: StaticString = #file, line: UInt = #line) {
         try! statement.run()
-        AssertSQL(SQL, 1, message, file: file, line: line)
+        assertSQL(SQL, 1, message, file: file, line: line)
         if let count = trace[SQL] { trace[SQL] = count - 1 }
     }
 
@@ -97,7 +97,8 @@ let int64Optional = Expression<Int64?>("int64Optional")
 let string = Expression<String>("string")
 let stringOptional = Expression<String?>("stringOptional")
 
-func AssertSQL(_ expression1: @autoclosure () -> String, _ expression2: @autoclosure () -> Expressible, file: StaticString = #file, line: UInt = #line) {
+func assertSQL(_ expression1: @autoclosure () -> String, _ expression2: @autoclosure () -> Expressible,
+               file: StaticString = #file, line: UInt = #line) {
     XCTAssertEqual(expression1(), expression2().asSQL(), file: file, line: line)
 }
 
diff --git a/Tests/SQLiteTests/ValueTests.swift b/Tests/SQLiteTests/ValueTests.swift
index bda2b4b3..f880cb34 100644
--- a/Tests/SQLiteTests/ValueTests.swift
+++ b/Tests/SQLiteTests/ValueTests.swift
@@ -1,6 +1,6 @@
 import XCTest
 import SQLite
 
-class ValueTests : XCTestCase {
+class ValueTests: XCTestCase {
 
 }

From ae42398825c0e391dbbb8393dc8380979e3a9004 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 23 Aug 2021 01:20:49 +0200
Subject: [PATCH 405/685] brew

---
 .github/workflows/build.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 0b9d0cf1..1119284a 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -14,7 +14,7 @@ jobs:
         gem install xcpretty --no-document
         brew update
         brew outdated carthage || brew upgrade carthage
-        brew install swiftlint
+        brew outdated swiftlint || brew upgrade swiftlint
     - name: "Lint"
       run: make lint
     - name: "Run tests (BUILD_SCHEME: SQLite iOS)"

From a8f5079a2e0676b74baffe49a3226c65cb7af6e4 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 23 Aug 2021 01:38:03 +0200
Subject: [PATCH 406/685] Fix warnings

---
 .swiftlint.yml                           | 12 +++++++++---
 Makefile                                 |  2 +-
 Sources/SQLite/Core/Connection.swift     | 10 +++++-----
 Sources/SQLite/Extensions/FTS4.swift     |  1 +
 Sources/SQLite/Helpers.swift             | 10 +++++-----
 Sources/SQLite/Typed/CoreFunctions.swift |  2 +-
 Sources/SQLite/Typed/Query.swift         | 20 +++++++++++---------
 7 files changed, 33 insertions(+), 24 deletions(-)

diff --git a/.swiftlint.yml b/.swiftlint.yml
index e18c09a1..3bfc5fa5 100644
--- a/.swiftlint.yml
+++ b/.swiftlint.yml
@@ -11,6 +11,7 @@ excluded: # paths to ignore during linting. overridden by `included`.
 identifier_name:
   excluded:
     - db
+    - in
     - to
     - by
     - or
@@ -20,13 +21,18 @@ identifier_name:
     - fn
     - a
     - b
+    - q
+    - SQLITE_TRANSIENT
+
+type_body_length:
+  warning: 260
+  error: 260
 
 line_length:
   warning: 150
   error: 150
   ignores_comments: true
 
-
 file_length:
-  warning: 700
-  error: 700
+  warning: 760
+  error: 760
diff --git a/Makefile b/Makefile
index 5e4ff388..a9d29d58 100644
--- a/Makefile
+++ b/Makefile
@@ -19,7 +19,7 @@ build:
 	$(BUILD_TOOL) $(BUILD_ARGUMENTS)
 
 lint:
-	swiftlint
+	swiftlint --strict
 
 test:
 ifdef XCPRETTY
diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index a4dad4a6..61c5f94a 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -473,10 +473,10 @@ public final class Connection {
                  // The T argument is one of the SQLITE_TRACE constants to indicate why the
                  // callback was invoked. The C argument is a copy of the context pointer.
                  // The P and X arguments are pointers whose meanings depend on T.
-                 (_: UInt32, C: UnsafeMutableRawPointer?, P: UnsafeMutableRawPointer?, _: UnsafeMutableRawPointer?) in
-                 if let P = P,
-                    let expandedSQL = sqlite3_expanded_sql(OpaquePointer(P)) {
-                     unsafeBitCast(C, to: Trace.self)(expandedSQL)
+                 (_: UInt32, context: UnsafeMutableRawPointer?, pointer: UnsafeMutableRawPointer?, _: UnsafeMutableRawPointer?) in
+                 if let pointer = pointer,
+                    let expandedSQL = sqlite3_expanded_sql(OpaquePointer(pointer)) {
+                     unsafeBitCast(context, to: Trace.self)(expandedSQL)
                      sqlite3_free(expandedSQL)
                  }
                  return Int32(0) // currently ignored
@@ -585,7 +585,7 @@ public final class Connection {
     ///   - block: A block of code to run when the function is called. The block
     ///     is called with an array of raw SQL values mapped to the function’s
     ///     parameters and should return a raw SQL value (or nil).
-    // swiftlint:disable:next cyclomatic_complexity
+    // swiftlint:disable:next cyclomatic_complexity function_body_length
     public func createFunction(_ function: String, argumentCount: UInt? = nil, deterministic: Bool = false,
                                _ block: @escaping (_ args: [Binding?]) -> Binding?) {
         let argc = argumentCount.map { Int($0) } ?? -1
diff --git a/Sources/SQLite/Extensions/FTS4.swift b/Sources/SQLite/Extensions/FTS4.swift
index a3c253f2..bdb89e0e 100644
--- a/Sources/SQLite/Extensions/FTS4.swift
+++ b/Sources/SQLite/Extensions/FTS4.swift
@@ -91,6 +91,7 @@ extension VirtualTable {
 
 }
 
+// swiftlint:disable identifier_name
 public struct Tokenizer {
 
     public static let Simple = Tokenizer("simple")
diff --git a/Sources/SQLite/Helpers.swift b/Sources/SQLite/Helpers.swift
index 0e3385e3..f5c67e36 100644
--- a/Sources/SQLite/Helpers.swift
+++ b/Sources/SQLite/Helpers.swift
@@ -115,11 +115,11 @@ func transcode(_ literal: Binding?) -> String {
     }
 }
 
-//swiftlint:disable force_cast
-func value<A: Value>(_ v: Binding) -> A {
-    A.fromDatatypeValue(v as! A.Datatype) as! A
+// swiftlint:disable force_cast
+func value<A: Value>(_ binding: Binding) -> A {
+    A.fromDatatypeValue(binding as! A.Datatype) as! A
 }
 
-func value<A: Value>(_ v: Binding?) -> A {
-    value(v!)
+func value<A: Value>(_ binding: Binding?) -> A {
+    value(binding!)
 }
diff --git a/Sources/SQLite/Typed/CoreFunctions.swift b/Sources/SQLite/Typed/CoreFunctions.swift
index 053f17e5..42689578 100644
--- a/Sources/SQLite/Typed/CoreFunctions.swift
+++ b/Sources/SQLite/Typed/CoreFunctions.swift
@@ -21,7 +21,7 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 //
-
+// swiftlint:disable file_length
 import Foundation
 
 private enum Function: String {
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index 8d3ded52..6b1f6b8e 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -1015,13 +1015,13 @@ extension Connection {
             let column = names.removeLast()
             let namespace = names.joined(separator: ".")
 
-            func expandGlob(_ namespace: Bool) -> ((QueryType) throws -> Void) {
-                return { (query: QueryType) throws -> Void in
-                    var q = type(of: query).init(query.clauses.from.name, database: query.clauses.from.database)
-                    q.clauses.select = query.clauses.select
-                    let e = q.expression
-                    var names = try self.prepare(e.template, e.bindings).columnNames.map { $0.quote() }
-                    if namespace { names = names.map { "\(query.tableName().expression.template).\($0)" } }
+            func expandGlob(_ namespace: Bool) -> (QueryType) throws -> Void {
+                return { (queryType: QueryType) throws -> Void in
+                    var query = type(of: queryType).init(queryType.clauses.from.name, database: queryType.clauses.from.database)
+                    query.clauses.select = queryType.clauses.select
+                    let expression = query.expression
+                    var names = try self.prepare(expression.template, expression.bindings).columnNames.map { $0.quote() }
+                    if namespace { names = names.map { "\(queryType.tableName().expression.template).\($0)" } }
                     for name in names { columnNames[name] = idx; idx += 1 }
                 }
             }
@@ -1184,11 +1184,13 @@ public struct Row {
     }
 
     public subscript<T: Value>(column: Expression<T>) -> T {
-        return try! get(column)
+        // swiftlint:disable:next force_try
+        try! get(column)
     }
 
     public subscript<T: Value>(column: Expression<T?>) -> T? {
-        return try! get(column)
+        // swiftlint:disable:next force_try
+        try! get(column)
     }
 }
 

From 7a8269be26e128fe4731cc39a624470edcc11764 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 23 Aug 2021 10:41:51 +0200
Subject: [PATCH 407/685] Remove unnecessary self

---
 Sources/SQLite/Core/Connection.swift    |  4 +-
 Sources/SQLite/Core/Statement.swift     | 10 +--
 Sources/SQLite/Extensions/FTS4.swift    | 14 ++--
 Sources/SQLite/Extensions/FTS5.swift    |  4 +-
 Sources/SQLite/Foundation.swift         |  2 +-
 Sources/SQLite/Typed/Coding.swift       | 96 ++++++++++++-------------
 Sources/SQLite/Typed/Query.swift        |  8 +--
 Sources/SQLite/Typed/Setter.swift       |  2 +-
 Tests/SQLiteTests/ConnectionTests.swift | 14 ++--
 9 files changed, 77 insertions(+), 77 deletions(-)

diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 61c5f94a..2ba51d80 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -161,7 +161,7 @@ public final class Connection {
     ///
     /// - Throws: `Result.Error` if query execution fails.
     public func execute(_ SQL: String) throws {
-        _ = try sync { try self.check(sqlite3_exec(self.handle, SQL, nil, nil, nil)) }
+        _ = try sync { try check(sqlite3_exec(handle, SQL, nil, nil, nil)) }
     }
 
     // MARK: - Prepare
@@ -633,7 +633,7 @@ public final class Connection {
             let function = unsafeBitCast(sqlite3_user_data(context), to: Function.self)
             function(context, argc, value)
         }, nil, nil, nil)
-        if functions[function] == nil { self.functions[function] = [:] }
+        if functions[function] == nil { functions[function] = [:] }
         functions[function]?[argc] = box
     }
     
diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index dfb67d22..4332cb49 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -48,10 +48,10 @@ public final class Statement {
         sqlite3_finalize(handle)
     }
 
-    public lazy var columnCount: Int = Int(sqlite3_column_count(self.handle))
+    public lazy var columnCount: Int = Int(sqlite3_column_count(handle))
 
-    public lazy var columnNames: [String] = (0..<Int32(self.columnCount)).map {
-        String(cString: sqlite3_column_name(self.handle, $0))
+    public lazy var columnNames: [String] = (0..<Int32(columnCount)).map {
+        String(cString: sqlite3_column_name(handle, $0))
     }
 
     /// A cursor pointing to the current row.
@@ -182,7 +182,7 @@ public final class Statement {
     }
 
     public func step() throws -> Bool {
-        return try connection.sync { try self.connection.check(sqlite3_step(self.handle)) == SQLITE_ROW }
+        return try connection.sync { try connection.check(sqlite3_step(handle)) == SQLITE_ROW }
     }
 
     fileprivate func reset(clearBindings shouldClear: Bool = true) {
@@ -304,7 +304,7 @@ extension Cursor: Sequence {
     public func makeIterator() -> AnyIterator<Binding?> {
         var idx = 0
         return AnyIterator {
-            if idx >= self.columnCount {
+            if idx >= columnCount {
                 return Binding??.none
             } else {
                 idx += 1
diff --git a/Sources/SQLite/Extensions/FTS4.swift b/Sources/SQLite/Extensions/FTS4.swift
index bdb89e0e..1de03ff2 100644
--- a/Sources/SQLite/Extensions/FTS4.swift
+++ b/Sources/SQLite/Extensions/FTS4.swift
@@ -184,7 +184,7 @@ open class FTSConfig {
 
     /// Adds a column definition
     @discardableResult open func column(_ column: Expressible, _ options: [ColumnOption] = []) -> Self {
-        self.columnDefinitions.append((column, options))
+        columnDefinitions.append((column, options))
         return self
     }
 
@@ -203,19 +203,19 @@ open class FTSConfig {
 
     /// [The prefix= option](https://www.sqlite.org/fts3.html#section_6_6)
     @discardableResult open func prefix(_ prefix: [Int]) -> Self {
-        self.prefixes += prefix
+        prefixes += prefix
         return self
     }
 
     /// [The content= option](https://www.sqlite.org/fts3.html#section_6_2)
     @discardableResult open func externalContent(_ schema: SchemaType) -> Self {
-        self.externalContentSchema = schema
+        externalContentSchema = schema
         return self
     }
 
     /// [Contentless FTS4 Tables](https://www.sqlite.org/fts3.html#section_6_2_1)
     @discardableResult open func contentless() -> Self {
-        self.isContentless = true
+        isContentless = true
         return self
     }
 
@@ -311,19 +311,19 @@ open class FTS4Config: FTSConfig {
 
     /// [The compress= and uncompress= options](https://www.sqlite.org/fts3.html#section_6_1)
     @discardableResult open func compress(_ functionName: String) -> Self {
-        self.compressFunction = functionName
+        compressFunction = functionName
         return self
     }
 
     /// [The compress= and uncompress= options](https://www.sqlite.org/fts3.html#section_6_1)
     @discardableResult open func uncompress(_ functionName: String) -> Self {
-        self.uncompressFunction = functionName
+        uncompressFunction = functionName
         return self
     }
 
     /// [The languageid= option](https://www.sqlite.org/fts3.html#section_6_3)
     @discardableResult open func languageId(_ columnName: String) -> Self {
-        self.languageId = columnName
+        languageId = columnName
         return self
     }
 
diff --git a/Sources/SQLite/Extensions/FTS5.swift b/Sources/SQLite/Extensions/FTS5.swift
index 07f49ffc..a5d04dbf 100644
--- a/Sources/SQLite/Extensions/FTS5.swift
+++ b/Sources/SQLite/Extensions/FTS5.swift
@@ -59,13 +59,13 @@ open class FTS5Config: FTSConfig {
 
     /// [External Content Tables](https://www.sqlite.org/fts5.html#section_4_4_2)
     @discardableResult open func contentRowId(_ column: Expressible) -> Self {
-        self.contentRowId = column
+        contentRowId = column
         return self
     }
 
     /// [The Columnsize Option](https://www.sqlite.org/fts5.html#section_4_5)
     @discardableResult open func columnSize(_ size: Int) -> Self {
-        self.columnSize = size
+        columnSize = size
         return self
     }
 
diff --git a/Sources/SQLite/Foundation.swift b/Sources/SQLite/Foundation.swift
index d837d8ba..81e89d48 100644
--- a/Sources/SQLite/Foundation.swift
+++ b/Sources/SQLite/Foundation.swift
@@ -80,7 +80,7 @@ extension UUID: Value {
     }
 
     public var datatypeValue: String {
-        return self.uuidString
+        return uuidString
     }
 
 }
diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index 5a672883..d2df2fe6 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -149,7 +149,7 @@ extension Row {
     ///
     /// - Returns: a decoded object from this row
     public func decode<V: Decodable>(userInfo: [CodingUserInfoKey: Any] = [:]) throws -> V {
-        return try V(from: self.decoder(userInfo: userInfo))
+        return try V(from: decoder(userInfo: userInfo))
     }
 
     public func decoder(userInfo: [CodingUserInfoKey: Any] = [:]) -> Decoder {
@@ -179,82 +179,82 @@ private class SQLiteEncoder: Encoder {
         }
 
         func encodeNil(forKey key: SQLiteEncoder.SQLiteKeyedEncodingContainer<Key>.Key) throws {
-            self.encoder.setters.append(Expression<String?>(key.stringValue) <- nil)
+            encoder.setters.append(Expression<String?>(key.stringValue) <- nil)
         }
 
         func encode(_ value: Int, forKey key: SQLiteEncoder.SQLiteKeyedEncodingContainer<Key>.Key) throws {
-            self.encoder.setters.append(Expression(key.stringValue) <- value)
+            encoder.setters.append(Expression(key.stringValue) <- value)
         }
 
         func encode(_ value: Bool, forKey key: Key) throws {
-            self.encoder.setters.append(Expression(key.stringValue) <- value)
+            encoder.setters.append(Expression(key.stringValue) <- value)
         }
 
         func encode(_ value: Float, forKey key: Key) throws {
-            self.encoder.setters.append(Expression(key.stringValue) <- Double(value))
+            encoder.setters.append(Expression(key.stringValue) <- Double(value))
         }
 
         func encode(_ value: Double, forKey key: Key) throws {
-            self.encoder.setters.append(Expression(key.stringValue) <- value)
+            encoder.setters.append(Expression(key.stringValue) <- value)
         }
 
         func encode(_ value: String, forKey key: Key) throws {
-            self.encoder.setters.append(Expression(key.stringValue) <- value)
+            encoder.setters.append(Expression(key.stringValue) <- value)
         }
 
         func encode<T>(_ value: T, forKey key: Key) throws where T: Swift.Encodable {
             if let data = value as? Data {
-                self.encoder.setters.append(Expression(key.stringValue) <- data)
+                encoder.setters.append(Expression(key.stringValue) <- data)
             } else if let date = value as? Date {
-                self.encoder.setters.append(Expression(key.stringValue) <- date.datatypeValue)
+                encoder.setters.append(Expression(key.stringValue) <- date.datatypeValue)
             } else {
                 let encoded = try JSONEncoder().encode(value)
                 let string = String(data: encoded, encoding: .utf8)
-                self.encoder.setters.append(Expression(key.stringValue) <- string)
+                encoder.setters.append(Expression(key.stringValue) <- string)
             }
         }
 
         func encode(_ value: Int8, forKey key: Key) throws {
-            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath,
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an Int8 is not supported"))
         }
 
         func encode(_ value: Int16, forKey key: Key) throws {
-            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath,
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an Int16 is not supported"))
         }
 
         func encode(_ value: Int32, forKey key: Key) throws {
-            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath,
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an Int32 is not supported"))
         }
 
         func encode(_ value: Int64, forKey key: Key) throws {
-            self.encoder.setters.append(Expression(key.stringValue) <- value)
+            encoder.setters.append(Expression(key.stringValue) <- value)
         }
 
         func encode(_ value: UInt, forKey key: Key) throws {
-            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath,
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an UInt is not supported"))
         }
 
         func encode(_ value: UInt8, forKey key: Key) throws {
-            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath,
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an UInt8 is not supported"))
         }
 
         func encode(_ value: UInt16, forKey key: Key) throws {
-            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath,
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an UInt16 is not supported"))
         }
 
         func encode(_ value: UInt32, forKey key: Key) throws {
-            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath,
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an UInt32 is not supported"))
         }
 
         func encode(_ value: UInt64, forKey key: Key) throws {
-            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: self.codingPath,
+            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an UInt64 is not supported"))
         }
 
@@ -301,98 +301,98 @@ private class SQLiteDecoder: Decoder {
         }
 
         var allKeys: [Key] {
-            return self.row.columnNames.keys.compactMap({Key(stringValue: $0)})
+            return row.columnNames.keys.compactMap({Key(stringValue: $0)})
         }
 
         func contains(_ key: Key) -> Bool {
-            return self.row.hasValue(for: key.stringValue)
+            return row.hasValue(for: key.stringValue)
         }
 
         func decodeNil(forKey key: Key) throws -> Bool {
-            return !self.contains(key)
+            return !contains(key)
         }
 
         func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool {
-            return try self.row.get(Expression(key.stringValue))
+            return try row.get(Expression(key.stringValue))
         }
 
         func decode(_ type: Int.Type, forKey key: Key) throws -> Int {
-            return try self.row.get(Expression(key.stringValue))
+            return try row.get(Expression(key.stringValue))
         }
 
         func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 {
-            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath,
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an Int8 is not supported"))
         }
 
         func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 {
-            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath,
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an Int16 is not supported"))
         }
 
         func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 {
-            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath,
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an Int32 is not supported"))
         }
 
         func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
-            return try self.row.get(Expression(key.stringValue))
+            return try row.get(Expression(key.stringValue))
         }
 
         func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {
-            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath,
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an UInt is not supported"))
 
         }
 
         func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 {
-            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath,
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an UInt8 is not supported"))
         }
 
         func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 {
-            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath,
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an UInt16 is not supported"))
         }
 
         func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 {
-            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath,
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an UInt32 is not supported"))
         }
 
         func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 {
-            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath,
+            throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an UInt64 is not supported"))
         }
 
         func decode(_ type: Float.Type, forKey key: Key) throws -> Float {
-            return Float(try self.row.get(Expression<Double>(key.stringValue)))
+            return Float(try row.get(Expression<Double>(key.stringValue)))
         }
 
         func decode(_ type: Double.Type, forKey key: Key) throws -> Double {
-            return try self.row.get(Expression(key.stringValue))
+            return try row.get(Expression(key.stringValue))
         }
 
         func decode(_ type: String.Type, forKey key: Key) throws -> String {
-            return try self.row.get(Expression(key.stringValue))
+            return try row.get(Expression(key.stringValue))
         }
 
         func decode<T>(_ type: T.Type, forKey key: Key) throws -> T where T: Swift.Decodable {
             // swiftlint:disable force_cast
             if type == Data.self {
-                let data = try self.row.get(Expression<Data>(key.stringValue))
+                let data = try row.get(Expression<Data>(key.stringValue))
                 return data as! T
             } else if type == Date.self {
-                let date = try self.row.get(Expression<Date>(key.stringValue))
+                let date = try row.get(Expression<Date>(key.stringValue))
                 return date as! T
             }
             // swiftlint:enable force_cast
-            guard let JSONString = try self.row.get(Expression<String?>(key.stringValue)) else {
-                throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: self.codingPath,
+            guard let JSONString = try row.get(Expression<String?>(key.stringValue)) else {
+                throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                              debugDescription: "an unsupported type was found"))
             }
             guard let data = JSONString.data(using: .utf8) else {
-                throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath,
+                throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,
                                                                         debugDescription: "invalid utf8 data found"))
             }
             return try JSONDecoder().decode(type, from: data)
@@ -400,22 +400,22 @@ private class SQLiteDecoder: Decoder {
 
         func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws
                         -> KeyedDecodingContainer<NestedKey> where NestedKey: CodingKey {
-            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath,
+            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,
                                                                     debugDescription: "decoding nested containers is not supported"))
         }
 
         func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
-            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath,
+            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,
                                                                     debugDescription: "decoding unkeyed containers is not supported"))
         }
 
         func superDecoder() throws -> Swift.Decoder {
-            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath,
+            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,
                                                                     debugDescription: "decoding super encoders containers is not supported"))
         }
 
         func superDecoder(forKey key: Key) throws -> Swift.Decoder {
-            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath,
+            throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,
                                                                     debugDescription: "decoding super decoders is not supported"))
         }
     }
@@ -430,16 +430,16 @@ private class SQLiteDecoder: Decoder {
     }
 
     func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> where Key: CodingKey {
-        return KeyedDecodingContainer(SQLiteKeyedDecodingContainer(row: self.row))
+        return KeyedDecodingContainer(SQLiteKeyedDecodingContainer(row: row))
     }
 
     func unkeyedContainer() throws -> UnkeyedDecodingContainer {
-        throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath,
+        throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,
                                                                 debugDescription: "decoding an unkeyed container is not supported"))
     }
 
     func singleValueContainer() throws -> SingleValueDecodingContainer {
-        throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath,
+        throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,
                                                                 debugDescription: "decoding a single value container is not supported"))
     }
 }
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index 6b1f6b8e..22742809 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -1093,7 +1093,7 @@ extension Connection {
         let expression = query.expression
         return try sync {
             try self.run(expression.template, expression.bindings)
-            return self.lastInsertRowid
+            return lastInsertRowid
         }
     }
 
@@ -1109,7 +1109,7 @@ extension Connection {
         let expression = query.expression
         return try sync {
             try self.run(expression.template, expression.bindings)
-            return self.changes
+            return changes
         }
     }
 
@@ -1124,7 +1124,7 @@ extension Connection {
         let expression = query.expression
         return try sync {
             try self.run(expression.template, expression.bindings)
-            return self.changes
+            return changes
         }
     }
 
@@ -1244,7 +1244,7 @@ public struct QueryClauses {
     var union = [QueryType]()
 
     fileprivate init(_ name: String, alias: String?, database: String?) {
-        self.from = (name, alias, database)
+        from = (name, alias, database)
     }
 
 }
diff --git a/Sources/SQLite/Typed/Setter.swift b/Sources/SQLite/Typed/Setter.swift
index 25e88342..08fb1748 100644
--- a/Sources/SQLite/Typed/Setter.swift
+++ b/Sources/SQLite/Typed/Setter.swift
@@ -63,7 +63,7 @@ public struct Setter {
     init(excluded column: Expressible) {
         let excluded = Expression<Void>("excluded")
         self.column = column
-        self.value = ".".join([excluded, column.expression])
+        value = ".".join([excluded, column.expression])
     }
 }
 
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index 00fe4f6b..44c2c302 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -217,7 +217,7 @@ class ConnectionTests: SQLiteTestCase {
     }
 
     func test_savepoint_beginsAndCommitsSavepoints() {
-        let db: Connection = self.db
+        let db: Connection = db
 
         try! db.savepoint("1") {
             try db.savepoint("2") {
@@ -235,7 +235,7 @@ class ConnectionTests: SQLiteTestCase {
     }
 
     func test_savepoint_beginsAndRollsSavepointsBack() {
-        let db: Connection = self.db
+        let db: Connection = db
         let stmt = try! db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com")
 
         do {
@@ -310,7 +310,7 @@ class ConnectionTests: SQLiteTestCase {
                 done()
             }
             try! db.transaction {
-                try self.insertUser("alice")
+                try insertUser("alice")
             }
             XCTAssertEqual(1, try! db.scalar("SELECT count(*) FROM users") as? Int64)
         }
@@ -321,8 +321,8 @@ class ConnectionTests: SQLiteTestCase {
             db.rollbackHook(done)
             do {
                 try db.transaction {
-                    try self.insertUser("alice")
-                    try self.insertUser("alice") // throw
+                    try insertUser("alice")
+                    try insertUser("alice") // throw
                 }
             } catch {
             }
@@ -338,7 +338,7 @@ class ConnectionTests: SQLiteTestCase {
             db.rollbackHook(done)
             do {
                 try db.transaction {
-                    try self.insertUser("alice")
+                    try insertUser("alice")
                 }
             } catch {
             }
@@ -437,7 +437,7 @@ class ResultTests: XCTestCase {
             XCTAssertEqual("not an error", message)
             XCTAssertEqual(SQLITE_MISUSE, code)
             XCTAssertNil(statement)
-            XCTAssert(self.connection === connection)
+            XCTAssert(connection === connection)
         } else {
             XCTFail("no error")
         }

From e2afa8b6bf00728ab275af6be155a4f7b3b16a6e Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 23 Aug 2021 10:48:13 +0200
Subject: [PATCH 408/685] Simplify

---
 Sources/SQLite/Core/Statement.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index 4332cb49..1f9afbc6 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -305,7 +305,7 @@ extension Cursor: Sequence {
         var idx = 0
         return AnyIterator {
             if idx >= columnCount {
-                return Binding??.none
+                return .none
             } else {
                 idx += 1
                 return self[idx - 1]

From aebb9c590a469f714b334a9fd2ce84c45475f464 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 23 Aug 2021 11:01:21 +0200
Subject: [PATCH 409/685] Remove unnecessary returns

---
 Sources/SQLite/Core/Blob.swift                |   6 +-
 Sources/SQLite/Core/Connection.swift          |  30 +-
 Sources/SQLite/Core/Statement.swift           |  28 +-
 Sources/SQLite/Core/Value.swift               |  24 +-
 Sources/SQLite/Extensions/Cipher.swift        |   2 +-
 Sources/SQLite/Extensions/FTS4.swift          |  32 +-
 Sources/SQLite/Extensions/FTS5.swift          |   4 +-
 Sources/SQLite/Foundation.swift               |  20 +-
 Sources/SQLite/Helpers.swift                  |  12 +-
 Sources/SQLite/Typed/AggregateFunctions.swift |  34 +-
 Sources/SQLite/Typed/Coding.swift             |  26 +-
 Sources/SQLite/Typed/Collation.swift          |   2 +-
 Sources/SQLite/Typed/CoreFunctions.swift      |  62 +--
 .../SQLite/Typed/DateAndTimeFunctions.swift   |  24 +-
 Sources/SQLite/Typed/Expression.swift         |  14 +-
 Sources/SQLite/Typed/Operators.swift          | 368 +++++++++---------
 Sources/SQLite/Typed/Query.swift              | 110 +++---
 Sources/SQLite/Typed/Schema.swift             |  42 +-
 Sources/SQLite/Typed/Setter.swift             | 130 +++----
 Tests/SQLiteTests/ConnectionTests.swift       |   4 +-
 Tests/SQLiteTests/CustomFunctionsTests.swift  |  28 +-
 Tests/SQLiteTests/FTS4Tests.swift             |   2 +-
 Tests/SQLiteTests/FTS5Tests.swift             |   2 +-
 Tests/SQLiteTests/TestHelpers.swift           |   6 +-
 24 files changed, 506 insertions(+), 506 deletions(-)

diff --git a/Sources/SQLite/Core/Blob.swift b/Sources/SQLite/Core/Blob.swift
index a49ef23b..cd31483b 100644
--- a/Sources/SQLite/Core/Blob.swift
+++ b/Sources/SQLite/Core/Blob.swift
@@ -36,7 +36,7 @@ public struct Blob {
     }
 
     public func toHex() -> String {
-        return bytes.map {
+        bytes.map {
             ($0 < 16 ? "0" : "") + String($0, radix: 16, uppercase: false)
         }.joined(separator: "")
     }
@@ -46,7 +46,7 @@ public struct Blob {
 extension Blob: CustomStringConvertible {
 
     public var description: String {
-        return "x'\(toHex())'"
+        "x'\(toHex())'"
     }
 
 }
@@ -56,5 +56,5 @@ extension Blob: Equatable {
 }
 
 public func ==(lhs: Blob, rhs: Blob) -> Bool {
-    return lhs.bytes == rhs.bytes
+    lhs.bytes == rhs.bytes
 }
diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 2ba51d80..07c85373 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -84,7 +84,7 @@ public final class Connection {
         }
     }
 
-    public var handle: OpaquePointer { return _handle! }
+    public var handle: OpaquePointer { _handle! }
 
     fileprivate var _handle: OpaquePointer?
 
@@ -133,23 +133,23 @@ public final class Connection {
     // MARK: -
 
     /// Whether or not the database was opened in a read-only state.
-    public var readonly: Bool { return sqlite3_db_readonly(handle, nil) == 1 }
+    public var readonly: Bool { sqlite3_db_readonly(handle, nil) == 1 }
 
     /// The last rowid inserted into the database via this connection.
     public var lastInsertRowid: Int64 {
-        return sqlite3_last_insert_rowid(handle)
+        sqlite3_last_insert_rowid(handle)
     }
 
     /// The last number of changes (inserts, updates, or deletes) made to the
     /// database via this connection.
     public var changes: Int {
-        return Int(sqlite3_changes(handle))
+        Int(sqlite3_changes(handle))
     }
 
     /// The total number of changes (inserts, updates, or deletes) made to the
     /// database via this connection.
     public var totalChanges: Int {
-        return Int(sqlite3_total_changes(handle))
+        Int(sqlite3_total_changes(handle))
     }
 
     // MARK: - Execute
@@ -190,7 +190,7 @@ public final class Connection {
     ///
     /// - Returns: A prepared statement.
     public func prepare(_ statement: String, _ bindings: [Binding?]) throws -> Statement {
-        return try prepare(statement).bind(bindings)
+        try prepare(statement).bind(bindings)
     }
 
     /// Prepares a single SQL statement and binds parameters to it.
@@ -203,7 +203,7 @@ public final class Connection {
     ///
     /// - Returns: A prepared statement.
     public func prepare(_ statement: String, _ bindings: [String: Binding?]) throws -> Statement {
-        return try prepare(statement).bind(bindings)
+        try prepare(statement).bind(bindings)
     }
 
     // MARK: - Run
@@ -220,7 +220,7 @@ public final class Connection {
     ///
     /// - Returns: The statement.
     @discardableResult public func run(_ statement: String, _ bindings: Binding?...) throws -> Statement {
-        return try run(statement, bindings)
+        try run(statement, bindings)
     }
 
     /// Prepares, binds, and runs a single SQL statement.
@@ -235,7 +235,7 @@ public final class Connection {
     ///
     /// - Returns: The statement.
     @discardableResult public func run(_ statement: String, _ bindings: [Binding?]) throws -> Statement {
-        return try prepare(statement).run(bindings)
+        try prepare(statement).run(bindings)
     }
 
     /// Prepares, binds, and runs a single SQL statement.
@@ -250,7 +250,7 @@ public final class Connection {
     ///
     /// - Returns: The statement.
     @discardableResult public func run(_ statement: String, _ bindings: [String: Binding?]) throws -> Statement {
-        return try prepare(statement).run(bindings)
+        try prepare(statement).run(bindings)
     }
 
     // MARK: - VACUUM
@@ -261,7 +261,7 @@ public final class Connection {
     ///
     /// - Returns: The statement.
     @discardableResult public func vacuum() throws -> Statement {
-        return try run("VACUUM")
+        try run("VACUUM")
     }
 
     // MARK: - Scalar
@@ -277,7 +277,7 @@ public final class Connection {
     ///
     /// - Returns: The first value of the first row returned.
     public func scalar(_ statement: String, _ bindings: Binding?...) throws -> Binding? {
-        return try scalar(statement, bindings)
+        try scalar(statement, bindings)
     }
 
     /// Runs a single SQL statement (with optional parameter bindings),
@@ -291,7 +291,7 @@ public final class Connection {
     ///
     /// - Returns: The first value of the first row returned.
     public func scalar(_ statement: String, _ bindings: [Binding?]) throws -> Binding? {
-        return try prepare(statement).scalar(bindings)
+        try prepare(statement).scalar(bindings)
     }
 
     /// Runs a single SQL statement (with optional parameter bindings),
@@ -305,7 +305,7 @@ public final class Connection {
     ///
     /// - Returns: The first value of the first row returned.
     public func scalar(_ statement: String, _ bindings: [String: Binding?]) throws -> Binding? {
-        return try prepare(statement).scalar(bindings)
+        try prepare(statement).scalar(bindings)
     }
 
     // MARK: - Transactions
@@ -810,7 +810,7 @@ public final class Connection {
 extension Connection: CustomStringConvertible {
 
     public var description: String {
-        return String(cString: sqlite3_db_filename(handle, nil))
+        String(cString: sqlite3_db_filename(handle, nil))
     }
 
 }
diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index 1f9afbc6..48347c31 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -63,7 +63,7 @@ public final class Statement {
     ///
     /// - Returns: The statement object (useful for chaining).
     public func bind(_ values: Binding?...) -> Statement {
-        return bind(values)
+        bind(values)
     }
 
     /// Binds a list of parameters to a statement.
@@ -140,7 +140,7 @@ public final class Statement {
     ///
     /// - Returns: The statement object (useful for chaining).
     @discardableResult public func run(_ bindings: [Binding?]) throws -> Statement {
-        return try bind(bindings).run()
+        try bind(bindings).run()
     }
 
     /// - Parameter bindings: A dictionary of named parameters to bind to the
@@ -150,7 +150,7 @@ public final class Statement {
     ///
     /// - Returns: The statement object (useful for chaining).
     @discardableResult public func run(_ bindings: [String: Binding?]) throws -> Statement {
-        return try bind(bindings).run()
+        try bind(bindings).run()
     }
 
     /// - Parameter bindings: A list of parameters to bind to the statement.
@@ -170,7 +170,7 @@ public final class Statement {
     ///
     /// - Returns: The first value of the first row returned.
     public func scalar(_ bindings: [Binding?]) throws -> Binding? {
-        return try bind(bindings).scalar()
+        try bind(bindings).scalar()
     }
 
     /// - Parameter bindings: A dictionary of named parameters to bind to the
@@ -178,11 +178,11 @@ public final class Statement {
     ///
     /// - Returns: The first value of the first row returned.
     public func scalar(_ bindings: [String: Binding?]) throws -> Binding? {
-        return try bind(bindings).scalar()
+        try bind(bindings).scalar()
     }
 
     public func step() throws -> Bool {
-        return try connection.sync { try connection.check(sqlite3_step(handle)) == SQLITE_ROW }
+        try connection.sync { try connection.check(sqlite3_step(handle)) == SQLITE_ROW }
     }
 
     fileprivate func reset(clearBindings shouldClear: Bool = true) {
@@ -207,7 +207,7 @@ public protocol FailableIterator: IteratorProtocol {
 
 extension FailableIterator {
     public func next() -> Element? {
-        return try? failableNext()
+        try? failableNext()
     }
 }
 
@@ -223,14 +223,14 @@ extension Array {
 extension Statement: FailableIterator {
     public typealias Element = [Binding?]
     public func failableNext() throws -> [Binding?]? {
-        return try step() ? Array(row) : nil
+        try step() ? Array(row) : nil
     }
 }
 
 extension Statement: CustomStringConvertible {
 
     public var description: String {
-        return String(cString: sqlite3_sql(handle))
+        String(cString: sqlite3_sql(handle))
     }
 
 }
@@ -247,15 +247,15 @@ public struct Cursor {
     }
 
     public subscript(idx: Int) -> Double {
-        return sqlite3_column_double(handle, Int32(idx))
+        sqlite3_column_double(handle, Int32(idx))
     }
 
     public subscript(idx: Int) -> Int64 {
-        return sqlite3_column_int64(handle, Int32(idx))
+        sqlite3_column_int64(handle, Int32(idx))
     }
 
     public subscript(idx: Int) -> String {
-        return String(cString: UnsafePointer(sqlite3_column_text(handle, Int32(idx))))
+        String(cString: UnsafePointer(sqlite3_column_text(handle, Int32(idx))))
     }
 
     public subscript(idx: Int) -> Blob {
@@ -272,11 +272,11 @@ public struct Cursor {
     // MARK: -
 
     public subscript(idx: Int) -> Bool {
-        return Bool.fromDatatypeValue(self[idx])
+        Bool.fromDatatypeValue(self[idx])
     }
 
     public subscript(idx: Int) -> Int {
-        return Int.fromDatatypeValue(self[idx])
+        Int.fromDatatypeValue(self[idx])
     }
 
 }
diff --git a/Sources/SQLite/Core/Value.swift b/Sources/SQLite/Core/Value.swift
index b8686eab..9c463f0c 100644
--- a/Sources/SQLite/Core/Value.swift
+++ b/Sources/SQLite/Core/Value.swift
@@ -50,11 +50,11 @@ extension Double: Number, Value {
     public static let declaredDatatype = "REAL"
 
     public static func fromDatatypeValue(_ datatypeValue: Double) -> Double {
-        return datatypeValue
+        datatypeValue
     }
 
     public var datatypeValue: Double {
-        return self
+        self
     }
 
 }
@@ -64,11 +64,11 @@ extension Int64: Number, Value {
     public static let declaredDatatype = "INTEGER"
 
     public static func fromDatatypeValue(_ datatypeValue: Int64) -> Int64 {
-        return datatypeValue
+        datatypeValue
     }
 
     public var datatypeValue: Int64 {
-        return self
+        self
     }
 
 }
@@ -78,11 +78,11 @@ extension String: Binding, Value {
     public static let declaredDatatype = "TEXT"
 
     public static func fromDatatypeValue(_ datatypeValue: String) -> String {
-        return datatypeValue
+        datatypeValue
     }
 
     public var datatypeValue: String {
-        return self
+        self
     }
 
 }
@@ -92,11 +92,11 @@ extension Blob: Binding, Value {
     public static let declaredDatatype = "BLOB"
 
     public static func fromDatatypeValue(_ datatypeValue: Blob) -> Blob {
-        return datatypeValue
+        datatypeValue
     }
 
     public var datatypeValue: Blob {
-        return self
+        self
     }
 
 }
@@ -108,11 +108,11 @@ extension Bool: Binding, Value {
     public static var declaredDatatype = Int64.declaredDatatype
 
     public static func fromDatatypeValue(_ datatypeValue: Int64) -> Bool {
-        return datatypeValue != 0
+        datatypeValue != 0
     }
 
     public var datatypeValue: Int64 {
-        return self ? 1 : 0
+        self ? 1 : 0
     }
 
 }
@@ -122,11 +122,11 @@ extension Int: Number, Value {
     public static var declaredDatatype = Int64.declaredDatatype
 
     public static func fromDatatypeValue(_ datatypeValue: Int64) -> Int {
-        return Int(datatypeValue)
+        Int(datatypeValue)
     }
 
     public var datatypeValue: Int64 {
-        return Int64(self)
+        Int64(self)
     }
 
 }
diff --git a/Sources/SQLite/Extensions/Cipher.swift b/Sources/SQLite/Extensions/Cipher.swift
index 9fce42f7..25d20158 100644
--- a/Sources/SQLite/Extensions/Cipher.swift
+++ b/Sources/SQLite/Extensions/Cipher.swift
@@ -7,7 +7,7 @@ extension Connection {
 
     /// - Returns: the SQLCipher version
     public var cipherVersion: String? {
-        return (try? scalar("PRAGMA cipher_version")) as? String
+        (try? scalar("PRAGMA cipher_version")) as? String
     }
 
     /// Specify the key for an encrypted database.  This routine should be
diff --git a/Sources/SQLite/Extensions/FTS4.swift b/Sources/SQLite/Extensions/FTS4.swift
index 1de03ff2..115b146a 100644
--- a/Sources/SQLite/Extensions/FTS4.swift
+++ b/Sources/SQLite/Extensions/FTS4.swift
@@ -29,15 +29,15 @@ import SQLiteObjc
 extension Module {
 
     public static func FTS4(_ column: Expressible, _ more: Expressible...) -> Module {
-        return FTS4([column] + more)
+        FTS4([column] + more)
     }
 
     public static func FTS4(_ columns: [Expressible] = [], tokenize tokenizer: Tokenizer? = nil) -> Module {
-        return FTS4(FTS4Config().columns(columns).tokenizer(tokenizer))
+        FTS4(FTS4Config().columns(columns).tokenizer(tokenizer))
     }
 
     public static func FTS4(_ config: FTS4Config) -> Module {
-        return Module(name: "fts4", arguments: config.arguments())
+        Module(name: "fts4", arguments: config.arguments())
     }
 }
 
@@ -56,15 +56,15 @@ extension VirtualTable {
     /// - Returns: An expression appended with a `MATCH` query against the given
     ///   pattern.
     public func match(_ pattern: String) -> Expression<Bool> {
-        return "MATCH".infix(tableName(), pattern)
+        "MATCH".infix(tableName(), pattern)
     }
 
     public func match(_ pattern: Expression<String>) -> Expression<Bool> {
-        return "MATCH".infix(tableName(), pattern)
+        "MATCH".infix(tableName(), pattern)
     }
 
     public func match(_ pattern: Expression<String?>) -> Expression<Bool?> {
-        return "MATCH".infix(tableName(), pattern)
+        "MATCH".infix(tableName(), pattern)
     }
 
     /// Builds a copy of the query with a `WHERE … MATCH` clause.
@@ -78,15 +78,15 @@ extension VirtualTable {
     ///
     /// - Returns: A query with the given `WHERE … MATCH` clause applied.
     public func match(_ pattern: String) -> QueryType {
-        return filter(match(pattern))
+        filter(match(pattern))
     }
 
     public func match(_ pattern: Expression<String>) -> QueryType {
-        return filter(match(pattern))
+        filter(match(pattern))
     }
 
     public func match(_ pattern: Expression<String?>) -> QueryType {
-        return filter(match(pattern))
+        filter(match(pattern))
     }
 
 }
@@ -120,7 +120,7 @@ public struct Tokenizer {
     }
 
     public static func Custom(_ name: String) -> Tokenizer {
-        return Tokenizer(Tokenizer.moduleName.quote(), [name.quote()])
+        Tokenizer(Tokenizer.moduleName.quote(), [name.quote()])
     }
 
     public let name: String
@@ -139,7 +139,7 @@ public struct Tokenizer {
 extension Tokenizer: CustomStringConvertible {
 
     public var description: String {
-        return ([name] + arguments).joined(separator: " ")
+        ([name] + arguments).joined(separator: " ")
     }
 
 }
@@ -220,11 +220,11 @@ open class FTSConfig {
     }
 
     func formatColumnDefinitions() -> [Expressible] {
-        return columnDefinitions.map { $0.0 }
+        columnDefinitions.map { $0.0 }
     }
 
     func arguments() -> [Expressible] {
-        return options().arguments
+        options().arguments
     }
 
     func options() -> Options {
@@ -259,11 +259,11 @@ open class FTSConfig {
         }
 
         @discardableResult mutating func append(_ key: String, value: CustomStringConvertible?) -> Options {
-            return append(key, value: value?.description)
+            append(key, value: value?.description)
         }
 
         @discardableResult mutating func append(_ key: String, value: String?) -> Options {
-            return append(key, value: value.map { Expression<String>($0) })
+            append(key, value: value.map { Expression<String>($0) })
         }
 
         @discardableResult mutating func append(_ key: String, value: Expressible?) -> Options {
@@ -281,7 +281,7 @@ open class FTS4Config: FTSConfig {
     public enum MatchInfo: CustomStringConvertible {
         case fts3
         public var description: String {
-            return "fts3"
+            "fts3"
         }
     }
 
diff --git a/Sources/SQLite/Extensions/FTS5.swift b/Sources/SQLite/Extensions/FTS5.swift
index a5d04dbf..f108bbec 100644
--- a/Sources/SQLite/Extensions/FTS5.swift
+++ b/Sources/SQLite/Extensions/FTS5.swift
@@ -24,7 +24,7 @@
 
 extension Module {
     public static func FTS5(_ config: FTS5Config) -> Module {
-        return Module(name: "fts5", arguments: config.arguments())
+        Module(name: "fts5", arguments: config.arguments())
     }
 }
 
@@ -86,7 +86,7 @@ open class FTS5Config: FTSConfig {
     }
 
     override func formatColumnDefinitions() -> [Expressible] {
-        return columnDefinitions.map { definition in
+        columnDefinitions.map { definition in
             if definition.options.contains(.unindexed) {
                 return " ".join([definition.0, Expression<Void>(literal: "UNINDEXED")])
             } else {
diff --git a/Sources/SQLite/Foundation.swift b/Sources/SQLite/Foundation.swift
index 81e89d48..2acbc00e 100644
--- a/Sources/SQLite/Foundation.swift
+++ b/Sources/SQLite/Foundation.swift
@@ -27,16 +27,16 @@ import Foundation
 extension Data: Value {
 
     public static var declaredDatatype: String {
-        return Blob.declaredDatatype
+        Blob.declaredDatatype
     }
 
     public static func fromDatatypeValue(_ dataValue: Blob) -> Data {
-        return Data(dataValue.bytes)
+        Data(dataValue.bytes)
     }
 
     public var datatypeValue: Blob {
-        return withUnsafeBytes { (pointer: UnsafeRawBufferPointer) -> Blob in
-            return Blob(bytes: pointer.baseAddress!, length: count)
+        withUnsafeBytes { (pointer: UnsafeRawBufferPointer) -> Blob in
+            Blob(bytes: pointer.baseAddress!, length: count)
         }
     }
 
@@ -45,15 +45,15 @@ extension Data: Value {
 extension Date: Value {
 
     public static var declaredDatatype: String {
-        return String.declaredDatatype
+        String.declaredDatatype
     }
 
     public static func fromDatatypeValue(_ stringValue: String) -> Date {
-        return dateFormatter.date(from: stringValue)!
+        dateFormatter.date(from: stringValue)!
     }
 
     public var datatypeValue: String {
-        return dateFormatter.string(from: self)
+        dateFormatter.string(from: self)
     }
 
 }
@@ -72,15 +72,15 @@ public var dateFormatter: DateFormatter = {
 extension UUID: Value {
 
     public static var declaredDatatype: String {
-        return String.declaredDatatype
+        String.declaredDatatype
     }
 
     public static func fromDatatypeValue(_ stringValue: String) -> UUID {
-        return UUID(uuidString: stringValue)!
+        UUID(uuidString: stringValue)!
     }
 
     public var datatypeValue: String {
-        return uuidString
+        uuidString
     }
 
 }
diff --git a/Sources/SQLite/Helpers.swift b/Sources/SQLite/Helpers.swift
index f5c67e36..d4c6828e 100644
--- a/Sources/SQLite/Helpers.swift
+++ b/Sources/SQLite/Helpers.swift
@@ -35,7 +35,7 @@ import SQLite3
 public typealias Star = (Expression<Binding>?, Expression<Binding>?) -> Expression<Void>
 
 public func *(_: Expression<Binding>?, _: Expression<Binding>?) -> Expression<Void> {
-    return Expression(literal: "*")
+    Expression(literal: "*")
 }
 
 public protocol _OptionalType {
@@ -73,7 +73,7 @@ extension String {
     }
 
     func infix<T>(_ lhs: Expressible, _ rhs: Expressible, wrap: Bool = true) -> Expression<T> {
-        return infix([lhs, rhs], wrap: wrap)
+        infix([lhs, rhs], wrap: wrap)
     }
 
     func infix<T>(_ terms: [Expressible], wrap: Bool = true) -> Expression<T> {
@@ -85,19 +85,19 @@ extension String {
     }
 
     func prefix(_ expressions: Expressible) -> Expressible {
-        return "\(self) ".wrap(expressions) as Expression<Void>
+        "\(self) ".wrap(expressions) as Expression<Void>
     }
 
     func prefix(_ expressions: [Expressible]) -> Expressible {
-        return "\(self) ".wrap(expressions) as Expression<Void>
+        "\(self) ".wrap(expressions) as Expression<Void>
     }
 
     func wrap<T>(_ expression: Expressible) -> Expression<T> {
-        return Expression("\(self)(\(expression.expression.template))", expression.expression.bindings)
+        Expression("\(self)(\(expression.expression.template))", expression.expression.bindings)
     }
 
     func wrap<T>(_ expressions: [Expressible]) -> Expression<T> {
-        return wrap(", ".join(expressions))
+        wrap(", ".join(expressions))
     }
 
 }
diff --git a/Sources/SQLite/Typed/AggregateFunctions.swift b/Sources/SQLite/Typed/AggregateFunctions.swift
index 325b0277..bf4fb8fc 100644
--- a/Sources/SQLite/Typed/AggregateFunctions.swift
+++ b/Sources/SQLite/Typed/AggregateFunctions.swift
@@ -31,7 +31,7 @@ private enum Function: String {
     case total
 
     func wrap<T>(_ expression: Expressible) -> Expression<T> {
-        return self.rawValue.wrap(expression)
+        self.rawValue.wrap(expression)
     }
 }
 
@@ -46,7 +46,7 @@ extension ExpressionType where UnderlyingType: Value {
     /// - Returns: A copy of the expression prefixed with the `DISTINCT`
     ///   keyword.
     public var distinct: Expression<UnderlyingType> {
-        return Expression("DISTINCT \(template)", bindings)
+        Expression("DISTINCT \(template)", bindings)
     }
 
     /// Builds a copy of the expression wrapped with the `count` aggregate
@@ -61,7 +61,7 @@ extension ExpressionType where UnderlyingType: Value {
     /// - Returns: A copy of the expression wrapped with the `count` aggregate
     ///   function.
     public var count: Expression<Int> {
-        return Function.count.wrap(self)
+        Function.count.wrap(self)
     }
 
 }
@@ -77,7 +77,7 @@ extension ExpressionType where UnderlyingType: _OptionalType, UnderlyingType.Wra
     /// - Returns: A copy of the expression prefixed with the `DISTINCT`
     ///   keyword.
     public var distinct: Expression<UnderlyingType> {
-        return Expression("DISTINCT \(template)", bindings)
+        Expression("DISTINCT \(template)", bindings)
     }
 
     /// Builds a copy of the expression wrapped with the `count` aggregate
@@ -92,7 +92,7 @@ extension ExpressionType where UnderlyingType: _OptionalType, UnderlyingType.Wra
     /// - Returns: A copy of the expression wrapped with the `count` aggregate
     ///   function.
     public var count: Expression<Int> {
-        return Function.count.wrap(self)
+        Function.count.wrap(self)
     }
 
 }
@@ -109,7 +109,7 @@ extension ExpressionType where UnderlyingType: Value, UnderlyingType.Datatype: C
     /// - Returns: A copy of the expression wrapped with the `max` aggregate
     ///   function.
     public var max: Expression<UnderlyingType?> {
-        return Function.max.wrap(self)
+        Function.max.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `min` aggregate
@@ -122,7 +122,7 @@ extension ExpressionType where UnderlyingType: Value, UnderlyingType.Datatype: C
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var min: Expression<UnderlyingType?> {
-        return Function.min.wrap(self)
+        Function.min.wrap(self)
     }
 
 }
@@ -139,7 +139,7 @@ extension ExpressionType where UnderlyingType: _OptionalType, UnderlyingType.Wra
     /// - Returns: A copy of the expression wrapped with the `max` aggregate
     ///   function.
     public var max: Expression<UnderlyingType> {
-        return Function.max.wrap(self)
+        Function.max.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `min` aggregate
@@ -152,7 +152,7 @@ extension ExpressionType where UnderlyingType: _OptionalType, UnderlyingType.Wra
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var min: Expression<UnderlyingType> {
-        return Function.min.wrap(self)
+        Function.min.wrap(self)
     }
 
 }
@@ -169,7 +169,7 @@ extension ExpressionType where UnderlyingType: Value, UnderlyingType.Datatype: N
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var average: Expression<Double?> {
-        return Function.avg.wrap(self)
+        Function.avg.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `sum` aggregate
@@ -182,7 +182,7 @@ extension ExpressionType where UnderlyingType: Value, UnderlyingType.Datatype: N
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var sum: Expression<UnderlyingType?> {
-        return Function.sum.wrap(self)
+        Function.sum.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `total` aggregate
@@ -195,7 +195,7 @@ extension ExpressionType where UnderlyingType: Value, UnderlyingType.Datatype: N
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var total: Expression<Double> {
-        return Function.total.wrap(self)
+        Function.total.wrap(self)
     }
 
 }
@@ -212,7 +212,7 @@ extension ExpressionType where UnderlyingType: _OptionalType, UnderlyingType.Wra
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var average: Expression<Double?> {
-        return Function.avg.wrap(self)
+        Function.avg.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `sum` aggregate
@@ -225,7 +225,7 @@ extension ExpressionType where UnderlyingType: _OptionalType, UnderlyingType.Wra
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var sum: Expression<UnderlyingType> {
-        return Function.sum.wrap(self)
+        Function.sum.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `total` aggregate
@@ -238,7 +238,7 @@ extension ExpressionType where UnderlyingType: _OptionalType, UnderlyingType.Wra
     /// - Returns: A copy of the expression wrapped with the `min` aggregate
     ///   function.
     public var total: Expression<Double> {
-        return Function.total.wrap(self)
+        Function.total.wrap(self)
     }
 
 }
@@ -246,7 +246,7 @@ extension ExpressionType where UnderlyingType: _OptionalType, UnderlyingType.Wra
 extension ExpressionType where UnderlyingType == Int {
 
     static func count(_ star: Star) -> Expression<UnderlyingType> {
-        return Function.count.wrap(star(nil, nil))
+        Function.count.wrap(star(nil, nil))
     }
 
 }
@@ -260,5 +260,5 @@ extension ExpressionType where UnderlyingType == Int {
 /// - Returns: An expression returning `count(*)` (when called with the `*`
 ///   function literal).
 public func count(_ star: Star) -> Expression<Int> {
-    return Expression.count(star)
+    Expression.count(star)
 }
diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index d2df2fe6..3dc1e6cf 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -149,11 +149,11 @@ extension Row {
     ///
     /// - Returns: a decoded object from this row
     public func decode<V: Decodable>(userInfo: [CodingUserInfoKey: Any] = [:]) throws -> V {
-        return try V(from: decoder(userInfo: userInfo))
+        try V(from: decoder(userInfo: userInfo))
     }
 
     public func decoder(userInfo: [CodingUserInfoKey: Any] = [:]) -> Decoder {
-        return SQLiteDecoder(row: self, userInfo: userInfo)
+        SQLiteDecoder(row: self, userInfo: userInfo)
     }
 }
 
@@ -285,7 +285,7 @@ private class SQLiteEncoder: Encoder {
     }
 
     func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key: CodingKey {
-        return KeyedEncodingContainer(SQLiteKeyedEncodingContainer(encoder: self))
+        KeyedEncodingContainer(SQLiteKeyedEncodingContainer(encoder: self))
     }
 }
 
@@ -301,23 +301,23 @@ private class SQLiteDecoder: Decoder {
         }
 
         var allKeys: [Key] {
-            return row.columnNames.keys.compactMap({Key(stringValue: $0)})
+            row.columnNames.keys.compactMap({ Key(stringValue: $0) })
         }
 
         func contains(_ key: Key) -> Bool {
-            return row.hasValue(for: key.stringValue)
+            row.hasValue(for: key.stringValue)
         }
 
         func decodeNil(forKey key: Key) throws -> Bool {
-            return !contains(key)
+            !contains(key)
         }
 
         func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool {
-            return try row.get(Expression(key.stringValue))
+            try row.get(Expression(key.stringValue))
         }
 
         func decode(_ type: Int.Type, forKey key: Key) throws -> Int {
-            return try row.get(Expression(key.stringValue))
+            try row.get(Expression(key.stringValue))
         }
 
         func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 {
@@ -336,7 +336,7 @@ private class SQLiteDecoder: Decoder {
         }
 
         func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
-            return try row.get(Expression(key.stringValue))
+            try row.get(Expression(key.stringValue))
         }
 
         func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {
@@ -366,15 +366,15 @@ private class SQLiteDecoder: Decoder {
         }
 
         func decode(_ type: Float.Type, forKey key: Key) throws -> Float {
-            return Float(try row.get(Expression<Double>(key.stringValue)))
+            Float(try row.get(Expression<Double>(key.stringValue)))
         }
 
         func decode(_ type: Double.Type, forKey key: Key) throws -> Double {
-            return try row.get(Expression(key.stringValue))
+            try row.get(Expression(key.stringValue))
         }
 
         func decode(_ type: String.Type, forKey key: Key) throws -> String {
-            return try row.get(Expression(key.stringValue))
+            try row.get(Expression(key.stringValue))
         }
 
         func decode<T>(_ type: T.Type, forKey key: Key) throws -> T where T: Swift.Decodable {
@@ -430,7 +430,7 @@ private class SQLiteDecoder: Decoder {
     }
 
     func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> where Key: CodingKey {
-        return KeyedDecodingContainer(SQLiteKeyedDecodingContainer(row: row))
+        KeyedDecodingContainer(SQLiteKeyedDecodingContainer(row: row))
     }
 
     func unkeyedContainer() throws -> UnkeyedDecodingContainer {
diff --git a/Sources/SQLite/Typed/Collation.swift b/Sources/SQLite/Typed/Collation.swift
index 3b268ce0..fec66129 100644
--- a/Sources/SQLite/Typed/Collation.swift
+++ b/Sources/SQLite/Typed/Collation.swift
@@ -46,7 +46,7 @@ public enum Collation {
 extension Collation: Expressible {
 
     public var expression: Expression<Void> {
-        return Expression(literal: description)
+        Expression(literal: description)
     }
 
 }
diff --git a/Sources/SQLite/Typed/CoreFunctions.swift b/Sources/SQLite/Typed/CoreFunctions.swift
index 42689578..be38d97e 100644
--- a/Sources/SQLite/Typed/CoreFunctions.swift
+++ b/Sources/SQLite/Typed/CoreFunctions.swift
@@ -47,15 +47,15 @@ private enum Function: String {
     case ifnull
 
     func infix<T>(_ lhs: Expressible, _ rhs: Expressible, wrap: Bool = true) -> Expression<T> {
-        return self.rawValue.infix(lhs, rhs, wrap: wrap)
+        self.rawValue.infix(lhs, rhs, wrap: wrap)
     }
 
     func wrap<T>(_ expression: Expressible) -> Expression<T> {
-        return self.rawValue.wrap(expression)
+        self.rawValue.wrap(expression)
     }
 
     func wrap<T>(_ expressions: [Expressible]) -> Expression<T> {
-        return self.rawValue.wrap(", ".join(expressions))
+        self.rawValue.wrap(", ".join(expressions))
     }
 }
 
@@ -69,7 +69,7 @@ extension ExpressionType where UnderlyingType: Number {
     ///
     /// - Returns: A copy of the expression wrapped with the `abs` function.
     public var absoluteValue: Expression<UnderlyingType> {
-        return Function.abs.wrap(self)
+        Function.abs.wrap(self)
     }
 
 }
@@ -84,7 +84,7 @@ extension ExpressionType where UnderlyingType: _OptionalType, UnderlyingType.Wra
     ///
     /// - Returns: A copy of the expression wrapped with the `abs` function.
     public var absoluteValue: Expression<UnderlyingType> {
-        return Function.abs.wrap(self)
+        Function.abs.wrap(self)
     }
 
 }
@@ -138,7 +138,7 @@ extension ExpressionType where UnderlyingType: Value, UnderlyingType.Datatype ==
     ///
     /// - Returns: An expression calling the `random` function.
     public static func random() -> Expression<UnderlyingType> {
-        return Function.random.wrap([])
+        Function.random.wrap([])
     }
 
 }
@@ -154,7 +154,7 @@ extension ExpressionType where UnderlyingType == Data {
     ///
     /// - Returns: An expression calling the `randomblob` function.
     public static func random(_ length: Int) -> Expression<UnderlyingType> {
-        return Function.randomblob.wrap([])
+        Function.randomblob.wrap([])
     }
 
     /// Builds an expression representing the `zeroblob` function.
@@ -166,7 +166,7 @@ extension ExpressionType where UnderlyingType == Data {
     ///
     /// - Returns: An expression calling the `zeroblob` function.
     public static func allZeros(_ length: Int) -> Expression<UnderlyingType> {
-        return Function.zeroblob.wrap([])
+        Function.zeroblob.wrap([])
     }
 
     /// Builds a copy of the expression wrapped with the `length` function.
@@ -177,7 +177,7 @@ extension ExpressionType where UnderlyingType == Data {
     ///
     /// - Returns: A copy of the expression wrapped with the `length` function.
     public var length: Expression<Int> {
-        return Function.length.wrap(self)
+        Function.length.wrap(self)
     }
 
 }
@@ -192,7 +192,7 @@ extension ExpressionType where UnderlyingType == Data? {
     ///
     /// - Returns: A copy of the expression wrapped with the `length` function.
     public var length: Expression<Int?> {
-        return Function.length.wrap(self)
+        Function.length.wrap(self)
     }
 
 }
@@ -207,7 +207,7 @@ extension ExpressionType where UnderlyingType == String {
     ///
     /// - Returns: A copy of the expression wrapped with the `length` function.
     public var length: Expression<Int> {
-        return Function.length.wrap(self)
+        Function.length.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `lower` function.
@@ -218,7 +218,7 @@ extension ExpressionType where UnderlyingType == String {
     ///
     /// - Returns: A copy of the expression wrapped with the `lower` function.
     public var lowercaseString: Expression<UnderlyingType> {
-        return Function.lower.wrap(self)
+        Function.lower.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `upper` function.
@@ -229,7 +229,7 @@ extension ExpressionType where UnderlyingType == String {
     ///
     /// - Returns: A copy of the expression wrapped with the `upper` function.
     public var uppercaseString: Expression<UnderlyingType> {
-        return Function.upper.wrap(self)
+        Function.upper.wrap(self)
     }
 
     /// Builds a copy of the expression appended with a `LIKE` query against the
@@ -294,7 +294,7 @@ extension ExpressionType where UnderlyingType == String {
     /// - Returns: A copy of the expression appended with a `GLOB` query against
     ///   the given pattern.
     public func glob(_ pattern: String) -> Expression<Bool> {
-        return Function.glob.infix(self, pattern)
+        Function.glob.infix(self, pattern)
     }
 
     /// Builds a copy of the expression appended with a `MATCH` query against
@@ -309,7 +309,7 @@ extension ExpressionType where UnderlyingType == String {
     /// - Returns: A copy of the expression appended with a `MATCH` query
     ///   against the given pattern.
     public func match(_ pattern: String) -> Expression<Bool> {
-        return Function.match.infix(self, pattern)
+        Function.match.infix(self, pattern)
     }
 
     /// Builds a copy of the expression appended with a `REGEXP` query against
@@ -320,7 +320,7 @@ extension ExpressionType where UnderlyingType == String {
     /// - Returns: A copy of the expression appended with a `REGEXP` query
     ///   against the given pattern.
     public func regexp(_ pattern: String) -> Expression<Bool> {
-        return Function.regexp.infix(self, pattern)
+        Function.regexp.infix(self, pattern)
     }
 
     /// Builds a copy of the expression appended with a `COLLATE` clause with
@@ -335,7 +335,7 @@ extension ExpressionType where UnderlyingType == String {
     /// - Returns: A copy of the expression appended with a `COLLATE` clause
     ///   with the given sequence.
     public func collate(_ collation: Collation) -> Expression<UnderlyingType> {
-        return Function.collate.infix(self, collation)
+        Function.collate.infix(self, collation)
     }
 
     /// Builds a copy of the expression wrapped with the `ltrim` function.
@@ -406,7 +406,7 @@ extension ExpressionType where UnderlyingType == String {
     ///
     /// - Returns: A copy of the expression wrapped with the `replace` function.
     public func replace(_ pattern: String, with replacement: String) -> Expression<UnderlyingType> {
-        return Function.replace.wrap([self, pattern, replacement])
+        Function.replace.wrap([self, pattern, replacement])
     }
 
     public func substring(_ location: Int, length: Int? = nil) -> Expression<UnderlyingType> {
@@ -417,7 +417,7 @@ extension ExpressionType where UnderlyingType == String {
     }
 
     public subscript(range: Range<Int>) -> Expression<UnderlyingType> {
-        return substring(range.lowerBound, length: range.upperBound - range.lowerBound)
+        substring(range.lowerBound, length: range.upperBound - range.lowerBound)
     }
 
 }
@@ -432,7 +432,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression wrapped with the `length` function.
     public var length: Expression<Int?> {
-        return Function.length.wrap(self)
+        Function.length.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `lower` function.
@@ -443,7 +443,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression wrapped with the `lower` function.
     public var lowercaseString: Expression<UnderlyingType> {
-        return Function.lower.wrap(self)
+        Function.lower.wrap(self)
     }
 
     /// Builds a copy of the expression wrapped with the `upper` function.
@@ -454,7 +454,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression wrapped with the `upper` function.
     public var uppercaseString: Expression<UnderlyingType> {
-        return Function.upper.wrap(self)
+        Function.upper.wrap(self)
     }
 
     /// Builds a copy of the expression appended with a `LIKE` query against the
@@ -519,7 +519,7 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression appended with a `GLOB` query against
     ///   the given pattern.
     public func glob(_ pattern: String) -> Expression<Bool?> {
-        return Function.glob.infix(self, pattern)
+        Function.glob.infix(self, pattern)
     }
 
     /// Builds a copy of the expression appended with a `MATCH` query against
@@ -534,7 +534,7 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression appended with a `MATCH` query
     ///   against the given pattern.
     public func match(_ pattern: String) -> Expression<Bool> {
-        return Function.match.infix(self, pattern)
+        Function.match.infix(self, pattern)
     }
 
     /// Builds a copy of the expression appended with a `REGEXP` query against
@@ -545,7 +545,7 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression appended with a `REGEXP` query
     ///   against the given pattern.
     public func regexp(_ pattern: String) -> Expression<Bool?> {
-        return Function.regexp.infix(self, pattern)
+        Function.regexp.infix(self, pattern)
     }
 
     /// Builds a copy of the expression appended with a `COLLATE` clause with
@@ -560,7 +560,7 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression appended with a `COLLATE` clause
     ///   with the given sequence.
     public func collate(_ collation: Collation) -> Expression<UnderlyingType> {
-        return Function.collate.infix(self, collation)
+        Function.collate.infix(self, collation)
     }
 
     /// Builds a copy of the expression wrapped with the `ltrim` function.
@@ -631,7 +631,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression wrapped with the `replace` function.
     public func replace(_ pattern: String, with replacement: String) -> Expression<UnderlyingType> {
-        return Function.replace.wrap([self, pattern, replacement])
+        Function.replace.wrap([self, pattern, replacement])
     }
 
     /// Builds a copy of the expression wrapped with the `substr` function.
@@ -666,7 +666,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression wrapped with the `substr` function.
     public subscript(range: Range<Int>) -> Expression<UnderlyingType> {
-        return substring(range.lowerBound, length: range.upperBound - range.lowerBound)
+        substring(range.lowerBound, length: range.upperBound - range.lowerBound)
     }
 
 }
@@ -752,7 +752,7 @@ extension String {
 /// - Returns: A copy of the given expressions wrapped with the `ifnull`
 ///   function.
 public func ??<V: Value>(optional: Expression<V?>, defaultValue: V) -> Expression<V> {
-    return Function.ifnull.wrap([optional, defaultValue])
+    Function.ifnull.wrap([optional, defaultValue])
 }
 
 /// Builds a copy of the given expressions wrapped with the `ifnull` function.
@@ -772,7 +772,7 @@ public func ??<V: Value>(optional: Expression<V?>, defaultValue: V) -> Expressio
 /// - Returns: A copy of the given expressions wrapped with the `ifnull`
 ///   function.
 public func ??<V: Value>(optional: Expression<V?>, defaultValue: Expression<V>) -> Expression<V> {
-    return Function.ifnull.wrap([optional, defaultValue])
+    Function.ifnull.wrap([optional, defaultValue])
 }
 
 /// Builds a copy of the given expressions wrapped with the `ifnull` function.
@@ -792,5 +792,5 @@ public func ??<V: Value>(optional: Expression<V?>, defaultValue: Expression<V>)
 /// - Returns: A copy of the given expressions wrapped with the `ifnull`
 ///   function.
 public func ??<V: Value>(optional: Expression<V?>, defaultValue: Expression<V?>) -> Expression<V> {
-    return Function.ifnull.wrap([optional, defaultValue])
+    Function.ifnull.wrap([optional, defaultValue])
 }
diff --git a/Sources/SQLite/Typed/DateAndTimeFunctions.swift b/Sources/SQLite/Typed/DateAndTimeFunctions.swift
index 0b9a497f..b4382194 100644
--- a/Sources/SQLite/Typed/DateAndTimeFunctions.swift
+++ b/Sources/SQLite/Typed/DateAndTimeFunctions.swift
@@ -32,23 +32,23 @@ import Foundation
 public class DateFunctions {
     /// The date() function returns the date in this format: YYYY-MM-DD.
     public static func date(_ timestring: String, _ modifiers: String...) -> Expression<Date?> {
-        return timefunction("date", timestring: timestring, modifiers: modifiers)
+        timefunction("date", timestring: timestring, modifiers: modifiers)
     }
 
     /// The time() function returns the time as HH:MM:SS.
     public static func time(_ timestring: String, _ modifiers: String...) -> Expression<Date?> {
-        return timefunction("time", timestring: timestring, modifiers: modifiers)
+        timefunction("time", timestring: timestring, modifiers: modifiers)
     }
 
     /// The datetime() function returns "YYYY-MM-DD HH:MM:SS".
     public static func datetime(_ timestring: String, _ modifiers: String...) -> Expression<Date?> {
-        return timefunction("datetime", timestring: timestring, modifiers: modifiers)
+        timefunction("datetime", timestring: timestring, modifiers: modifiers)
     }
 
     /// The julianday() function returns the Julian day -
     /// the number of days since noon in Greenwich on November 24, 4714 B.C.
     public static func julianday(_ timestring: String, _ modifiers: String...) -> Expression<Date?> {
-        return timefunction("julianday", timestring: timestring, modifiers: modifiers)
+        timefunction("julianday", timestring: timestring, modifiers: modifiers)
     }
 
     ///  The strftime() routine returns the date formatted according to the format string specified as the first argument.
@@ -71,36 +71,36 @@ public class DateFunctions {
 
 extension Date {
     public var date: Expression<Date?> {
-        return DateFunctions.date(dateFormatter.string(from: self))
+        DateFunctions.date(dateFormatter.string(from: self))
     }
 
     public var time: Expression<Date?> {
-        return DateFunctions.time(dateFormatter.string(from: self))
+        DateFunctions.time(dateFormatter.string(from: self))
     }
 
     public var datetime: Expression<Date?> {
-        return DateFunctions.datetime(dateFormatter.string(from: self))
+        DateFunctions.datetime(dateFormatter.string(from: self))
     }
 
     public var julianday: Expression<Date?> {
-        return DateFunctions.julianday(dateFormatter.string(from: self))
+        DateFunctions.julianday(dateFormatter.string(from: self))
     }
 }
 
 extension Expression where UnderlyingType == Date {
     public var date: Expression<Date> {
-        return Expression<Date>("date(\(template))", bindings)
+        Expression<Date>("date(\(template))", bindings)
     }
 
     public var time: Expression<Date> {
-        return Expression<Date>("time(\(template))", bindings)
+        Expression<Date>("time(\(template))", bindings)
     }
 
     public var datetime: Expression<Date> {
-        return Expression<Date>("datetime(\(template))", bindings)
+        Expression<Date>("datetime(\(template))", bindings)
     }
 
     public var julianday: Expression<Date> {
-        return Expression<Date>("julianday(\(template))", bindings)
+        Expression<Date>("julianday(\(template))", bindings)
     }
 }
diff --git a/Sources/SQLite/Typed/Expression.swift b/Sources/SQLite/Typed/Expression.swift
index 39a3c62f..95cdd3b9 100644
--- a/Sources/SQLite/Typed/Expression.swift
+++ b/Sources/SQLite/Typed/Expression.swift
@@ -95,15 +95,15 @@ extension Expressible {
 extension ExpressionType {
 
     public var expression: Expression<Void> {
-        return Expression(template, bindings)
+        Expression(template, bindings)
     }
 
     public var asc: Expressible {
-        return " ".join([self, Expression<Void>(literal: "ASC")])
+        " ".join([self, Expression<Void>(literal: "ASC")])
     }
 
     public var desc: Expressible {
-        return " ".join([self, Expression<Void>(literal: "DESC")])
+        " ".join([self, Expression<Void>(literal: "DESC")])
     }
 
 }
@@ -119,7 +119,7 @@ extension ExpressionType where UnderlyingType: Value {
 extension ExpressionType where UnderlyingType: _OptionalType, UnderlyingType.WrappedType: Value {
 
     public static var null: Self {
-        return self.init(value: nil)
+        self.init(value: nil)
     }
 
     public init(value: UnderlyingType.WrappedType?) {
@@ -131,7 +131,7 @@ extension ExpressionType where UnderlyingType: _OptionalType, UnderlyingType.Wra
 extension Value {
 
     public var expression: Expression<Void> {
-        return Expression(value: self).expression
+        Expression(value: self).expression
     }
 
 }
@@ -139,9 +139,9 @@ extension Value {
 public let rowid = Expression<Int64>("ROWID")
 
 public func cast<T: Value, U: Value>(_ expression: Expression<T>) -> Expression<U> {
-    return Expression("CAST (\(expression.template) AS \(U.declaredDatatype))", expression.bindings)
+    Expression("CAST (\(expression.template) AS \(U.declaredDatatype))", expression.bindings)
 }
 
 public func cast<T: Value, U: Value>(_ expression: Expression<T?>) -> Expression<U?> {
-    return Expression("CAST (\(expression.template) AS \(U.declaredDatatype))", expression.bindings)
+    Expression("CAST (\(expression.template) AS \(U.declaredDatatype))", expression.bindings)
 }
diff --git a/Sources/SQLite/Typed/Operators.swift b/Sources/SQLite/Typed/Operators.swift
index 32d39fa7..5ffbbceb 100644
--- a/Sources/SQLite/Typed/Operators.swift
+++ b/Sources/SQLite/Typed/Operators.swift
@@ -47,331 +47,331 @@ private enum Operator: String {
     case concatenate = "||"
 
     func infix<T>(_ lhs: Expressible, _ rhs: Expressible, wrap: Bool = true) -> Expression<T> {
-        return self.rawValue.infix(lhs, rhs, wrap: wrap)
+        self.rawValue.infix(lhs, rhs, wrap: wrap)
     }
 
     func wrap<T>(_ expression: Expressible) -> Expression<T> {
-        return self.rawValue.wrap(expression)
+        self.rawValue.wrap(expression)
     }
 }
 
 public func +(lhs: Expression<String>, rhs: Expression<String>) -> Expression<String> {
-    return Operator.concatenate.infix(lhs, rhs)
+    Operator.concatenate.infix(lhs, rhs)
 }
 
 public func +(lhs: Expression<String>, rhs: Expression<String?>) -> Expression<String?> {
-    return Operator.concatenate.infix(lhs, rhs)
+    Operator.concatenate.infix(lhs, rhs)
 }
 public func +(lhs: Expression<String?>, rhs: Expression<String>) -> Expression<String?> {
-    return Operator.concatenate.infix(lhs, rhs)
+    Operator.concatenate.infix(lhs, rhs)
 }
 public func +(lhs: Expression<String?>, rhs: Expression<String?>) -> Expression<String?> {
-    return Operator.concatenate.infix(lhs, rhs)
+    Operator.concatenate.infix(lhs, rhs)
 }
 public func +(lhs: Expression<String>, rhs: String) -> Expression<String> {
-    return Operator.concatenate.infix(lhs, rhs)
+    Operator.concatenate.infix(lhs, rhs)
 }
 public func +(lhs: Expression<String?>, rhs: String) -> Expression<String?> {
-    return Operator.concatenate.infix(lhs, rhs)
+    Operator.concatenate.infix(lhs, rhs)
 }
 public func +(lhs: String, rhs: Expression<String>) -> Expression<String> {
-    return Operator.concatenate.infix(lhs, rhs)
+    Operator.concatenate.infix(lhs, rhs)
 }
 public func +(lhs: String, rhs: Expression<String?>) -> Expression<String?> {
-    return Operator.concatenate.infix(lhs, rhs)
+    Operator.concatenate.infix(lhs, rhs)
 }
 
 // MARK: -
 
 public func +<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype: Number {
-    return Operator.plus.infix(lhs, rhs)
+    Operator.plus.infix(lhs, rhs)
 }
 public func +<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
-    return Operator.plus.infix(lhs, rhs)
+    Operator.plus.infix(lhs, rhs)
 }
 public func +<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype: Number {
-    return Operator.plus.infix(lhs, rhs)
+    Operator.plus.infix(lhs, rhs)
 }
 public func +<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
-    return Operator.plus.infix(lhs, rhs)
+    Operator.plus.infix(lhs, rhs)
 }
 public func +<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype: Number {
-    return Operator.plus.infix(lhs, rhs)
+    Operator.plus.infix(lhs, rhs)
 }
 public func +<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype: Number {
-    return Operator.plus.infix(lhs, rhs)
+    Operator.plus.infix(lhs, rhs)
 }
 public func +<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype: Number {
-    return Operator.plus.infix(lhs, rhs)
+    Operator.plus.infix(lhs, rhs)
 }
 public func +<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
-    return Operator.plus.infix(lhs, rhs)
+    Operator.plus.infix(lhs, rhs)
 }
 
 public func -<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype: Number {
-    return Operator.minus.infix(lhs, rhs)
+    Operator.minus.infix(lhs, rhs)
 }
 public func -<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
-    return Operator.minus.infix(lhs, rhs)
+    Operator.minus.infix(lhs, rhs)
 }
 public func -<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype: Number {
-    return Operator.minus.infix(lhs, rhs)
+    Operator.minus.infix(lhs, rhs)
 }
 public func -<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
-    return Operator.minus.infix(lhs, rhs)
+    Operator.minus.infix(lhs, rhs)
 }
 public func -<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype: Number {
-    return Operator.minus.infix(lhs, rhs)
+    Operator.minus.infix(lhs, rhs)
 }
 public func -<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype: Number {
-    return Operator.minus.infix(lhs, rhs)
+    Operator.minus.infix(lhs, rhs)
 }
 public func -<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype: Number {
-    return Operator.minus.infix(lhs, rhs)
+    Operator.minus.infix(lhs, rhs)
 }
 public func -<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
-    return Operator.minus.infix(lhs, rhs)
+    Operator.minus.infix(lhs, rhs)
 }
 
 public func *<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype: Number {
-    return Operator.mul.infix(lhs, rhs)
+    Operator.mul.infix(lhs, rhs)
 }
 public func *<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
-    return Operator.mul.infix(lhs, rhs)
+    Operator.mul.infix(lhs, rhs)
 }
 public func *<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype: Number {
-    return Operator.mul.infix(lhs, rhs)
+    Operator.mul.infix(lhs, rhs)
 }
 public func *<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
-    return Operator.mul.infix(lhs, rhs)
+    Operator.mul.infix(lhs, rhs)
 }
 public func *<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype: Number {
-    return Operator.mul.infix(lhs, rhs)
+    Operator.mul.infix(lhs, rhs)
 }
 public func *<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype: Number {
-    return Operator.mul.infix(lhs, rhs)
+    Operator.mul.infix(lhs, rhs)
 }
 public func *<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype: Number {
-    return Operator.mul.infix(lhs, rhs)
+    Operator.mul.infix(lhs, rhs)
 }
 public func *<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
-    return Operator.mul.infix(lhs, rhs)
+    Operator.mul.infix(lhs, rhs)
 }
 
 public func /<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype: Number {
-    return Operator.div.infix(lhs, rhs)
+    Operator.div.infix(lhs, rhs)
 }
 public func /<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
-    return Operator.div.infix(lhs, rhs)
+    Operator.div.infix(lhs, rhs)
 }
 public func /<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype: Number {
-    return Operator.div.infix(lhs, rhs)
+    Operator.div.infix(lhs, rhs)
 }
 public func /<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
-    return Operator.div.infix(lhs, rhs)
+    Operator.div.infix(lhs, rhs)
 }
 public func /<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype: Number {
-    return Operator.div.infix(lhs, rhs)
+    Operator.div.infix(lhs, rhs)
 }
 public func /<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype: Number {
-    return Operator.div.infix(lhs, rhs)
+    Operator.div.infix(lhs, rhs)
 }
 public func /<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype: Number {
-    return Operator.div.infix(lhs, rhs)
+    Operator.div.infix(lhs, rhs)
 }
 public func /<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
-    return Operator.div.infix(lhs, rhs)
+    Operator.div.infix(lhs, rhs)
 }
 
 public prefix func -<V: Value>(rhs: Expression<V>) -> Expression<V> where V.Datatype: Number {
-    return Operator.minus.wrap(rhs)
+    Operator.minus.wrap(rhs)
 }
 public prefix func -<V: Value>(rhs: Expression<V?>) -> Expression<V?> where V.Datatype: Number {
-    return Operator.minus.wrap(rhs)
+    Operator.minus.wrap(rhs)
 }
 
 // MARK: -
 
 public func %<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return Operator.mod.infix(lhs, rhs)
+    Operator.mod.infix(lhs, rhs)
 }
 public func %<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.mod.infix(lhs, rhs)
+    Operator.mod.infix(lhs, rhs)
 }
 public func %<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.mod.infix(lhs, rhs)
+    Operator.mod.infix(lhs, rhs)
 }
 public func %<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.mod.infix(lhs, rhs)
+    Operator.mod.infix(lhs, rhs)
 }
 public func %<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
-    return Operator.mod.infix(lhs, rhs)
+    Operator.mod.infix(lhs, rhs)
 }
 public func %<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.mod.infix(lhs, rhs)
+    Operator.mod.infix(lhs, rhs)
 }
 public func %<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return Operator.mod.infix(lhs, rhs)
+    Operator.mod.infix(lhs, rhs)
 }
 public func %<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.mod.infix(lhs, rhs)
+    Operator.mod.infix(lhs, rhs)
 }
 
 public func <<<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return Operator.bitwiseLeft.infix(lhs, rhs)
+    Operator.bitwiseLeft.infix(lhs, rhs)
 }
 public func <<<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.bitwiseLeft.infix(lhs, rhs)
+    Operator.bitwiseLeft.infix(lhs, rhs)
 }
 public func <<<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.bitwiseLeft.infix(lhs, rhs)
+    Operator.bitwiseLeft.infix(lhs, rhs)
 }
 public func <<<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.bitwiseLeft.infix(lhs, rhs)
+    Operator.bitwiseLeft.infix(lhs, rhs)
 }
 public func <<<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
-    return Operator.bitwiseLeft.infix(lhs, rhs)
+    Operator.bitwiseLeft.infix(lhs, rhs)
 }
 public func <<<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.bitwiseLeft.infix(lhs, rhs)
+    Operator.bitwiseLeft.infix(lhs, rhs)
 }
 public func <<<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return Operator.bitwiseLeft.infix(lhs, rhs)
+    Operator.bitwiseLeft.infix(lhs, rhs)
 }
 public func <<<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.bitwiseLeft.infix(lhs, rhs)
+    Operator.bitwiseLeft.infix(lhs, rhs)
 }
 
 public func >><V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return Operator.bitwiseRight.infix(lhs, rhs)
+    Operator.bitwiseRight.infix(lhs, rhs)
 }
 public func >><V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.bitwiseRight.infix(lhs, rhs)
+    Operator.bitwiseRight.infix(lhs, rhs)
 }
 public func >><V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.bitwiseRight.infix(lhs, rhs)
+    Operator.bitwiseRight.infix(lhs, rhs)
 }
 public func >><V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.bitwiseRight.infix(lhs, rhs)
+    Operator.bitwiseRight.infix(lhs, rhs)
 }
 public func >><V: Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
-    return Operator.bitwiseRight.infix(lhs, rhs)
+    Operator.bitwiseRight.infix(lhs, rhs)
 }
 public func >><V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.bitwiseRight.infix(lhs, rhs)
+    Operator.bitwiseRight.infix(lhs, rhs)
 }
 public func >><V: Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return Operator.bitwiseRight.infix(lhs, rhs)
+    Operator.bitwiseRight.infix(lhs, rhs)
 }
 public func >><V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.bitwiseRight.infix(lhs, rhs)
+    Operator.bitwiseRight.infix(lhs, rhs)
 }
 
 public func &<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return Operator.bitwiseAnd.infix(lhs, rhs)
+    Operator.bitwiseAnd.infix(lhs, rhs)
 }
 public func &<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.bitwiseAnd.infix(lhs, rhs)
+    Operator.bitwiseAnd.infix(lhs, rhs)
 }
 public func &<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.bitwiseAnd.infix(lhs, rhs)
+    Operator.bitwiseAnd.infix(lhs, rhs)
 }
 public func &<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.bitwiseAnd.infix(lhs, rhs)
+    Operator.bitwiseAnd.infix(lhs, rhs)
 }
 public func &<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
-    return Operator.bitwiseAnd.infix(lhs, rhs)
+    Operator.bitwiseAnd.infix(lhs, rhs)
 }
 public func &<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.bitwiseAnd.infix(lhs, rhs)
+    Operator.bitwiseAnd.infix(lhs, rhs)
 }
 public func &<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return Operator.bitwiseAnd.infix(lhs, rhs)
+    Operator.bitwiseAnd.infix(lhs, rhs)
 }
 public func &<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.bitwiseAnd.infix(lhs, rhs)
+    Operator.bitwiseAnd.infix(lhs, rhs)
 }
 
 public func |<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return Operator.bitwiseOr.infix(lhs, rhs)
+    Operator.bitwiseOr.infix(lhs, rhs)
 }
 public func |<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.bitwiseOr.infix(lhs, rhs)
+    Operator.bitwiseOr.infix(lhs, rhs)
 }
 public func |<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.bitwiseOr.infix(lhs, rhs)
+    Operator.bitwiseOr.infix(lhs, rhs)
 }
 public func |<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.bitwiseOr.infix(lhs, rhs)
+    Operator.bitwiseOr.infix(lhs, rhs)
 }
 public func |<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
-    return Operator.bitwiseOr.infix(lhs, rhs)
+    Operator.bitwiseOr.infix(lhs, rhs)
 }
 public func |<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.bitwiseOr.infix(lhs, rhs)
+    Operator.bitwiseOr.infix(lhs, rhs)
 }
 public func |<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return Operator.bitwiseOr.infix(lhs, rhs)
+    Operator.bitwiseOr.infix(lhs, rhs)
 }
 public func |<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.bitwiseOr.infix(lhs, rhs)
+    Operator.bitwiseOr.infix(lhs, rhs)
 }
 
 public func ^<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return (~(lhs & rhs)) & (lhs | rhs)
+    (~(lhs & rhs)) & (lhs | rhs)
 }
 public func ^<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return (~(lhs & rhs)) & (lhs | rhs)
+    (~(lhs & rhs)) & (lhs | rhs)
 }
 public func ^<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<V?> where V.Datatype == Int64 {
-    return (~(lhs & rhs)) & (lhs | rhs)
+    (~(lhs & rhs)) & (lhs | rhs)
 }
 public func ^<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return (~(lhs & rhs)) & (lhs | rhs)
+    (~(lhs & rhs)) & (lhs | rhs)
 }
 public func ^<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<V> where V.Datatype == Int64 {
-    return (~(lhs & rhs)) & (lhs | rhs)
+    (~(lhs & rhs)) & (lhs | rhs)
 }
 public func ^<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<V?> where V.Datatype == Int64 {
-    return (~(lhs & rhs)) & (lhs | rhs)
+    (~(lhs & rhs)) & (lhs | rhs)
 }
 public func ^<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return (~(lhs & rhs)) & (lhs | rhs)
+    (~(lhs & rhs)) & (lhs | rhs)
 }
 public func ^<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return (~(lhs & rhs)) & (lhs | rhs)
+    (~(lhs & rhs)) & (lhs | rhs)
 }
 
 public prefix func ~<V: Value>(rhs: Expression<V>) -> Expression<V> where V.Datatype == Int64 {
-    return Operator.bitwiseXor.wrap(rhs)
+    Operator.bitwiseXor.wrap(rhs)
 }
 public prefix func ~<V: Value>(rhs: Expression<V?>) -> Expression<V?> where V.Datatype == Int64 {
-    return Operator.bitwiseXor.wrap(rhs)
+    Operator.bitwiseXor.wrap(rhs)
 }
 
 // MARK: -
 
 public func ==<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Equatable {
-    return Operator.eq.infix(lhs, rhs)
+    Operator.eq.infix(lhs, rhs)
 }
 public func ==<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
-    return Operator.eq.infix(lhs, rhs)
+    Operator.eq.infix(lhs, rhs)
 }
 public func ==<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype: Equatable {
-    return Operator.eq.infix(lhs, rhs)
+    Operator.eq.infix(lhs, rhs)
 }
 public func ==<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
-    return Operator.eq.infix(lhs, rhs)
+    Operator.eq.infix(lhs, rhs)
 }
 public func ==<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype: Equatable {
-    return Operator.eq.infix(lhs, rhs)
+    Operator.eq.infix(lhs, rhs)
 }
 public func ==<V: Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype: Equatable {
     guard let rhs = rhs else { return "IS".infix(lhs, Expression<V?>(value: nil)) }
     return Operator.eq.infix(lhs, rhs)
 }
 public func ==<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Equatable {
-    return Operator.eq.infix(lhs, rhs)
+    Operator.eq.infix(lhs, rhs)
 }
 public func ==<V: Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
     guard let lhs = lhs else { return "IS".infix(Expression<V?>(value: nil), rhs) }
@@ -379,26 +379,26 @@ public func ==<V: Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> wher
 }
 
 public func ===<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Equatable {
-    return "IS".infix(lhs, rhs)
+    "IS".infix(lhs, rhs)
 }
 public func ===<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
-    return "IS".infix(lhs, rhs)
+    "IS".infix(lhs, rhs)
 }
 public func ===<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype: Equatable {
-    return "IS".infix(lhs, rhs)
+    "IS".infix(lhs, rhs)
 }
 public func ===<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
-    return "IS".infix(lhs, rhs)
+    "IS".infix(lhs, rhs)
 }
 public func ===<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype: Equatable {
-    return "IS".infix(lhs, rhs)
+    "IS".infix(lhs, rhs)
 }
 public func ===<V: Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype: Equatable {
     guard let rhs = rhs else { return "IS".infix(lhs, Expression<V?>(value: nil)) }
     return "IS".infix(lhs, rhs)
 }
 public func ===<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Equatable {
-    return "IS".infix(lhs, rhs)
+    "IS".infix(lhs, rhs)
 }
 public func ===<V: Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
     guard let lhs = lhs else { return "IS".infix(Expression<V?>(value: nil), rhs) }
@@ -406,26 +406,26 @@ public func ===<V: Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> whe
 }
 
 public func !=<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Equatable {
-    return Operator.neq.infix(lhs, rhs)
+    Operator.neq.infix(lhs, rhs)
 }
 public func !=<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
-    return Operator.neq.infix(lhs, rhs)
+    Operator.neq.infix(lhs, rhs)
 }
 public func !=<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype: Equatable {
-    return Operator.neq.infix(lhs, rhs)
+    Operator.neq.infix(lhs, rhs)
 }
 public func !=<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
-    return Operator.neq.infix(lhs, rhs)
+    Operator.neq.infix(lhs, rhs)
 }
 public func !=<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype: Equatable {
-    return Operator.neq.infix(lhs, rhs)
+    Operator.neq.infix(lhs, rhs)
 }
 public func !=<V: Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype: Equatable {
     guard let rhs = rhs else { return "IS NOT".infix(lhs, Expression<V?>(value: nil)) }
     return Operator.neq.infix(lhs, rhs)
 }
 public func !=<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Equatable {
-    return Operator.neq.infix(lhs, rhs)
+    Operator.neq.infix(lhs, rhs)
 }
 public func !=<V: Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
     guard let lhs = lhs else { return "IS NOT".infix(Expression<V?>(value: nil), rhs) }
@@ -433,26 +433,26 @@ public func !=<V: Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> wher
 }
 
 public func !==<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Equatable {
-    return "IS NOT".infix(lhs, rhs)
+    "IS NOT".infix(lhs, rhs)
 }
 public func !==<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
-    return "IS NOT".infix(lhs, rhs)
+    "IS NOT".infix(lhs, rhs)
 }
 public func !==<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype: Equatable {
-    return "IS NOT".infix(lhs, rhs)
+    "IS NOT".infix(lhs, rhs)
 }
 public func !==<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
-    return "IS NOT".infix(lhs, rhs)
+    "IS NOT".infix(lhs, rhs)
 }
 public func !==<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype: Equatable {
-    return "IS NOT".infix(lhs, rhs)
+    "IS NOT".infix(lhs, rhs)
 }
 public func !==<V: Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype: Equatable {
     guard let rhs = rhs else { return "IS NOT".infix(lhs, Expression<V?>(value: nil)) }
     return "IS NOT".infix(lhs, rhs)
 }
 public func !==<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Equatable {
-    return "IS NOT".infix(lhs, rhs)
+    "IS NOT".infix(lhs, rhs)
 }
 public func !==<V: Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
     guard let lhs = lhs else { return "IS NOT".infix(Expression<V?>(value: nil), rhs) }
@@ -460,215 +460,215 @@ public func !==<V: Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> whe
 }
 
 public func ><V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable {
-    return Operator.gt.infix(lhs, rhs)
+    Operator.gt.infix(lhs, rhs)
 }
 public func ><V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
-    return Operator.gt.infix(lhs, rhs)
+    Operator.gt.infix(lhs, rhs)
 }
 public func ><V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype: Comparable {
-    return Operator.gt.infix(lhs, rhs)
+    Operator.gt.infix(lhs, rhs)
 }
 public func ><V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
-    return Operator.gt.infix(lhs, rhs)
+    Operator.gt.infix(lhs, rhs)
 }
 public func ><V: Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype: Comparable {
-    return Operator.gt.infix(lhs, rhs)
+    Operator.gt.infix(lhs, rhs)
 }
 public func ><V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype: Comparable {
-    return Operator.gt.infix(lhs, rhs)
+    Operator.gt.infix(lhs, rhs)
 }
 public func ><V: Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable {
-    return Operator.gt.infix(lhs, rhs)
+    Operator.gt.infix(lhs, rhs)
 }
 public func ><V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
-    return Operator.gt.infix(lhs, rhs)
+    Operator.gt.infix(lhs, rhs)
 }
 
 public func >=<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable {
-    return Operator.gte.infix(lhs, rhs)
+    Operator.gte.infix(lhs, rhs)
 }
 public func >=<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
-    return Operator.gte.infix(lhs, rhs)
+    Operator.gte.infix(lhs, rhs)
 }
 public func >=<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype: Comparable {
-    return Operator.gte.infix(lhs, rhs)
+    Operator.gte.infix(lhs, rhs)
 }
 public func >=<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
-    return Operator.gte.infix(lhs, rhs)
+    Operator.gte.infix(lhs, rhs)
 }
 public func >=<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype: Comparable {
-    return Operator.gte.infix(lhs, rhs)
+    Operator.gte.infix(lhs, rhs)
 }
 public func >=<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype: Comparable {
-    return Operator.gte.infix(lhs, rhs)
+    Operator.gte.infix(lhs, rhs)
 }
 public func >=<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable {
-    return Operator.gte.infix(lhs, rhs)
+    Operator.gte.infix(lhs, rhs)
 }
 public func >=<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
-    return Operator.gte.infix(lhs, rhs)
+    Operator.gte.infix(lhs, rhs)
 }
 
 public func <<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable {
-    return Operator.lt.infix(lhs, rhs)
+    Operator.lt.infix(lhs, rhs)
 }
 public func <<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
-    return Operator.lt.infix(lhs, rhs)
+    Operator.lt.infix(lhs, rhs)
 }
 public func <<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype: Comparable {
-    return Operator.lt.infix(lhs, rhs)
+    Operator.lt.infix(lhs, rhs)
 }
 public func <<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
-    return Operator.lt.infix(lhs, rhs)
+    Operator.lt.infix(lhs, rhs)
 }
 public func <<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype: Comparable {
-    return Operator.lt.infix(lhs, rhs)
+    Operator.lt.infix(lhs, rhs)
 }
 public func <<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype: Comparable {
-    return Operator.lt.infix(lhs, rhs)
+    Operator.lt.infix(lhs, rhs)
 }
 public func <<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable {
-    return Operator.lt.infix(lhs, rhs)
+    Operator.lt.infix(lhs, rhs)
 }
 public func <<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
-    return Operator.lt.infix(lhs, rhs)
+    Operator.lt.infix(lhs, rhs)
 }
 
 public func <=<V: Value>(lhs: Expression<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable {
-    return Operator.lte.infix(lhs, rhs)
+    Operator.lte.infix(lhs, rhs)
 }
 public func <=<V: Value>(lhs: Expression<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
-    return Operator.lte.infix(lhs, rhs)
+    Operator.lte.infix(lhs, rhs)
 }
 public func <=<V: Value>(lhs: Expression<V?>, rhs: Expression<V>) -> Expression<Bool?> where V.Datatype: Comparable {
-    return Operator.lte.infix(lhs, rhs)
+    Operator.lte.infix(lhs, rhs)
 }
 public func <=<V: Value>(lhs: Expression<V?>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
-    return Operator.lte.infix(lhs, rhs)
+    Operator.lte.infix(lhs, rhs)
 }
 public func <=<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V.Datatype: Comparable {
-    return Operator.lte.infix(lhs, rhs)
+    Operator.lte.infix(lhs, rhs)
 }
 public func <=<V: Value>(lhs: Expression<V?>, rhs: V) -> Expression<Bool?> where V.Datatype: Comparable {
-    return Operator.lte.infix(lhs, rhs)
+    Operator.lte.infix(lhs, rhs)
 }
 public func <=<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable {
-    return Operator.lte.infix(lhs, rhs)
+    Operator.lte.infix(lhs, rhs)
 }
 public func <=<V: Value>(lhs: V, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable {
-    return Operator.lte.infix(lhs, rhs)
+    Operator.lte.infix(lhs, rhs)
 }
 
 public func ~=<V: Value>(lhs: ClosedRange<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable & Value {
-    return Expression("\(rhs.template) BETWEEN ? AND ?", rhs.bindings + [lhs.lowerBound.datatypeValue, lhs.upperBound.datatypeValue])
+    Expression("\(rhs.template) BETWEEN ? AND ?", rhs.bindings + [lhs.lowerBound.datatypeValue, lhs.upperBound.datatypeValue])
 }
 
 public func ~=<V: Value>(lhs: ClosedRange<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable & Value {
-    return Expression("\(rhs.template) BETWEEN ? AND ?", rhs.bindings + [lhs.lowerBound.datatypeValue, lhs.upperBound.datatypeValue])
+    Expression("\(rhs.template) BETWEEN ? AND ?", rhs.bindings + [lhs.lowerBound.datatypeValue, lhs.upperBound.datatypeValue])
 }
 
 public func ~=<V: Value>(lhs: Range<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable & Value {
-    return Expression("\(rhs.template) >= ? AND \(rhs.template) < ?", rhs.bindings + [lhs.lowerBound.datatypeValue] +
-            rhs.bindings + [lhs.upperBound.datatypeValue])
+    Expression("\(rhs.template) >= ? AND \(rhs.template) < ?",
+               rhs.bindings + [lhs.lowerBound.datatypeValue] + rhs.bindings + [lhs.upperBound.datatypeValue])
 }
 
 public func ~=<V: Value>(lhs: Range<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable & Value {
-    return Expression("\(rhs.template) >= ? AND \(rhs.template) < ?", rhs.bindings + [lhs.lowerBound.datatypeValue] +
-            rhs.bindings + [lhs.upperBound.datatypeValue])
+    Expression("\(rhs.template) >= ? AND \(rhs.template) < ?",
+               rhs.bindings + [lhs.lowerBound.datatypeValue] + rhs.bindings + [lhs.upperBound.datatypeValue])
 }
 
 public func ~=<V: Value>(lhs: PartialRangeThrough<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable & Value {
-    return Expression("\(rhs.template) <= ?", rhs.bindings + [lhs.upperBound.datatypeValue])
+    Expression("\(rhs.template) <= ?", rhs.bindings + [lhs.upperBound.datatypeValue])
 }
 
 public func ~=<V: Value>(lhs: PartialRangeThrough<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable & Value {
-    return Expression("\(rhs.template) <= ?", rhs.bindings + [lhs.upperBound.datatypeValue])
+    Expression("\(rhs.template) <= ?", rhs.bindings + [lhs.upperBound.datatypeValue])
 }
 
 public func ~=<V: Value>(lhs: PartialRangeUpTo<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable & Value {
-    return Expression("\(rhs.template) < ?", rhs.bindings + [lhs.upperBound.datatypeValue])
+    Expression("\(rhs.template) < ?", rhs.bindings + [lhs.upperBound.datatypeValue])
 }
 
 public func ~=<V: Value>(lhs: PartialRangeUpTo<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable & Value {
-    return Expression("\(rhs.template) < ?", rhs.bindings + [lhs.upperBound.datatypeValue])
+    Expression("\(rhs.template) < ?", rhs.bindings + [lhs.upperBound.datatypeValue])
 }
 
 public func ~=<V: Value>(lhs: PartialRangeFrom<V>, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Comparable & Value {
-    return Expression("\(rhs.template) >= ?", rhs.bindings + [lhs.lowerBound.datatypeValue])
+    Expression("\(rhs.template) >= ?", rhs.bindings + [lhs.lowerBound.datatypeValue])
 }
 
 public func ~=<V: Value>(lhs: PartialRangeFrom<V>, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Comparable & Value {
-    return Expression("\(rhs.template) >= ?", rhs.bindings + [lhs.lowerBound.datatypeValue])
+    Expression("\(rhs.template) >= ?", rhs.bindings + [lhs.lowerBound.datatypeValue])
 }
 
 // MARK: -
 
 public func and(_ terms: Expression<Bool>...) -> Expression<Bool> {
-    return "AND".infix(terms)
+    "AND".infix(terms)
 }
 public func and(_ terms: [Expression<Bool>]) -> Expression<Bool> {
-    return "AND".infix(terms)
+    "AND".infix(terms)
 }
 public func &&(lhs: Expression<Bool>, rhs: Expression<Bool>) -> Expression<Bool> {
-    return Operator.and.infix(lhs, rhs)
+    Operator.and.infix(lhs, rhs)
 }
 public func &&(lhs: Expression<Bool>, rhs: Expression<Bool?>) -> Expression<Bool?> {
-    return Operator.and.infix(lhs, rhs)
+    Operator.and.infix(lhs, rhs)
 }
 public func &&(lhs: Expression<Bool?>, rhs: Expression<Bool>) -> Expression<Bool?> {
-    return Operator.and.infix(lhs, rhs)
+    Operator.and.infix(lhs, rhs)
 }
 public func &&(lhs: Expression<Bool?>, rhs: Expression<Bool?>) -> Expression<Bool?> {
-    return Operator.and.infix(lhs, rhs)
+    Operator.and.infix(lhs, rhs)
 }
 public func &&(lhs: Expression<Bool>, rhs: Bool) -> Expression<Bool> {
-    return Operator.and.infix(lhs, rhs)
+    Operator.and.infix(lhs, rhs)
 }
 public func &&(lhs: Expression<Bool?>, rhs: Bool) -> Expression<Bool?> {
-    return Operator.and.infix(lhs, rhs)
+    Operator.and.infix(lhs, rhs)
 }
 public func &&(lhs: Bool, rhs: Expression<Bool>) -> Expression<Bool> {
-    return Operator.and.infix(lhs, rhs)
+    Operator.and.infix(lhs, rhs)
 }
 public func &&(lhs: Bool, rhs: Expression<Bool?>) -> Expression<Bool?> {
-    return Operator.and.infix(lhs, rhs)
+    Operator.and.infix(lhs, rhs)
 }
 
 public func or(_ terms: Expression<Bool>...) -> Expression<Bool> {
-    return "OR".infix(terms)
+    "OR".infix(terms)
 }
 public func or(_ terms: [Expression<Bool>]) -> Expression<Bool> {
-    return "OR".infix(terms)
+    "OR".infix(terms)
 }
 public func ||(lhs: Expression<Bool>, rhs: Expression<Bool>) -> Expression<Bool> {
-    return Operator.or.infix(lhs, rhs)
+    Operator.or.infix(lhs, rhs)
 }
 public func ||(lhs: Expression<Bool>, rhs: Expression<Bool?>) -> Expression<Bool?> {
-    return Operator.or.infix(lhs, rhs)
+    Operator.or.infix(lhs, rhs)
 }
 public func ||(lhs: Expression<Bool?>, rhs: Expression<Bool>) -> Expression<Bool?> {
-    return Operator.or.infix(lhs, rhs)
+    Operator.or.infix(lhs, rhs)
 }
 public func ||(lhs: Expression<Bool?>, rhs: Expression<Bool?>) -> Expression<Bool?> {
-    return Operator.or.infix(lhs, rhs)
+    Operator.or.infix(lhs, rhs)
 }
 public func ||(lhs: Expression<Bool>, rhs: Bool) -> Expression<Bool> {
-    return Operator.or.infix(lhs, rhs)
+    Operator.or.infix(lhs, rhs)
 }
 public func ||(lhs: Expression<Bool?>, rhs: Bool) -> Expression<Bool?> {
-    return Operator.or.infix(lhs, rhs)
+    Operator.or.infix(lhs, rhs)
 }
 public func ||(lhs: Bool, rhs: Expression<Bool>) -> Expression<Bool> {
-    return Operator.or.infix(lhs, rhs)
+    Operator.or.infix(lhs, rhs)
 }
 public func ||(lhs: Bool, rhs: Expression<Bool?>) -> Expression<Bool?> {
-    return Operator.or.infix(lhs, rhs)
+    Operator.or.infix(lhs, rhs)
 }
 
 public prefix func !(rhs: Expression<Bool>) -> Expression<Bool> {
-    return Operator.not.wrap(rhs)
+    Operator.not.wrap(rhs)
 }
 
 public prefix func !(rhs: Expression<Bool?>) -> Expression<Bool?> {
-    return Operator.not.wrap(rhs)
+    Operator.not.wrap(rhs)
 }
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index 22742809..59b24a8d 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -53,7 +53,7 @@ extension SchemaType {
     ///
     /// - Returns: A query with the given `SELECT` clause applied.
     public func select(_ column1: Expressible, _ more: Expressible...) -> Self {
-        return select(false, [column1] + more)
+        select(false, [column1] + more)
     }
 
     /// Builds a copy of the query with the `SELECT DISTINCT` clause applied.
@@ -68,7 +68,7 @@ extension SchemaType {
     ///
     /// - Returns: A query with the given `SELECT DISTINCT` clause applied.
     public func select(distinct column1: Expressible, _ more: Expressible...) -> Self {
-        return select(true, [column1] + more)
+        select(true, [column1] + more)
     }
 
     /// Builds a copy of the query with the `SELECT` clause applied.
@@ -84,7 +84,7 @@ extension SchemaType {
     ///
     /// - Returns: A query with the given `SELECT` clause applied.
     public func select(_ all: [Expressible]) -> Self {
-        return select(false, all)
+        select(false, all)
     }
 
     /// Builds a copy of the query with the `SELECT DISTINCT` clause applied.
@@ -99,7 +99,7 @@ extension SchemaType {
     ///
     /// - Returns: A query with the given `SELECT DISTINCT` clause applied.
     public func select(distinct columns: [Expressible]) -> Self {
-        return select(true, columns)
+        select(true, columns)
     }
 
     /// Builds a copy of the query with the `SELECT *` clause applied.
@@ -113,7 +113,7 @@ extension SchemaType {
     ///
     /// - Returns: A query with the given `SELECT *` clause applied.
     public func select(_ star: Star) -> Self {
-        return select([star(nil, nil)])
+        select([star(nil, nil)])
     }
 
     /// Builds a copy of the query with the `SELECT DISTINCT *` clause applied.
@@ -127,7 +127,7 @@ extension SchemaType {
     ///
     /// - Returns: A query with the given `SELECT DISTINCT *` clause applied.
     public func select(distinct star: Star) -> Self {
-        return select(distinct: [star(nil, nil)])
+        select(distinct: [star(nil, nil)])
     }
 
     /// Builds a scalar copy of the query with the `SELECT` clause applied.
@@ -142,10 +142,10 @@ extension SchemaType {
     ///
     /// - Returns: A query with the given `SELECT` clause applied.
     public func select<V: Value>(_ column: Expression<V>) -> ScalarQuery<V> {
-        return select(false, [column])
+        select(false, [column])
     }
     public func select<V: Value>(_ column: Expression<V?>) -> ScalarQuery<V?> {
-        return select(false, [column])
+        select(false, [column])
     }
 
     /// Builds a scalar copy of the query with the `SELECT DISTINCT` clause
@@ -161,14 +161,14 @@ extension SchemaType {
     ///
     /// - Returns: A query with the given `SELECT DISTINCT` clause applied.
     public func select<V: Value>(distinct column: Expression<V>) -> ScalarQuery<V> {
-        return select(true, [column])
+        select(true, [column])
     }
     public func select<V: Value>(distinct column: Expression<V?>) -> ScalarQuery<V?> {
-        return select(true, [column])
+        select(true, [column])
     }
 
     public var count: ScalarQuery<Int> {
-        return select(Expression.count(*))
+        select(Expression.count(*))
     }
 
 }
@@ -223,7 +223,7 @@ extension QueryType {
     ///
     /// - Returns: A query with the given `JOIN` clause applied.
     public func join(_ table: QueryType, on condition: Expression<Bool>) -> Self {
-        return join(table, on: Expression<Bool?>(condition))
+        join(table, on: Expression<Bool?>(condition))
     }
 
     /// Adds a `JOIN` clause to the query.
@@ -244,7 +244,7 @@ extension QueryType {
     ///
     /// - Returns: A query with the given `JOIN` clause applied.
     public func join(_ table: QueryType, on condition: Expression<Bool?>) -> Self {
-        return join(.inner, table, on: condition)
+        join(.inner, table, on: condition)
     }
 
     /// Adds a `JOIN` clause to the query.
@@ -267,7 +267,7 @@ extension QueryType {
     ///
     /// - Returns: A query with the given `JOIN` clause applied.
     public func join(_ type: JoinType, _ table: QueryType, on condition: Expression<Bool>) -> Self {
-        return join(type, table, on: Expression<Bool?>(condition))
+        join(type, table, on: Expression<Bool?>(condition))
     }
 
     /// Adds a `JOIN` clause to the query.
@@ -291,7 +291,8 @@ extension QueryType {
     /// - Returns: A query with the given `JOIN` clause applied.
     public func join(_ type: JoinType, _ table: QueryType, on condition: Expression<Bool?>) -> Self {
         var query = self
-        query.clauses.join.append((type: type, query: table, condition: table.clauses.filters.map { condition && $0 } ?? condition as Expressible))
+        query.clauses.join.append((type: type, query: table,
+                                          condition: table.clauses.filters.map { condition && $0 } ?? condition as Expressible))
         return query
     }
 
@@ -309,7 +310,7 @@ extension QueryType {
     ///
     /// - Returns: A query with the given `WHERE` clause applied.
     public func filter(_ predicate: Expression<Bool>) -> Self {
-        return filter(Expression<Bool?>(predicate))
+        filter(Expression<Bool?>(predicate))
     }
 
     /// Adds a condition to the query’s `WHERE` clause.
@@ -332,13 +333,13 @@ extension QueryType {
     /// Adds a condition to the query’s `WHERE` clause.
     /// This is an alias for `filter(predicate)`
     public func `where`(_ predicate: Expression<Bool>) -> Self {
-        return `where`(Expression<Bool?>(predicate))
+        `where`(Expression<Bool?>(predicate))
     }
 
     /// Adds a condition to the query’s `WHERE` clause.
     /// This is an alias for `filter(predicate)`
     public func `where`(_ predicate: Expression<Bool?>) -> Self {
-        return filter(predicate)
+        filter(predicate)
     }
 
     // MARK: GROUP BY
@@ -349,7 +350,7 @@ extension QueryType {
     ///
     /// - Returns: A query with the given `GROUP BY` clause applied.
     public func group(_ by: Expressible...) -> Self {
-        return group(by)
+        group(by)
     }
 
     /// Sets a `GROUP BY` clause on the query.
@@ -358,7 +359,7 @@ extension QueryType {
     ///
     /// - Returns: A query with the given `GROUP BY` clause applied.
     public func group(_ by: [Expressible]) -> Self {
-        return group(by, nil)
+        group(by, nil)
     }
 
     /// Sets a `GROUP BY`-`HAVING` clause on the query.
@@ -371,7 +372,7 @@ extension QueryType {
     ///
     /// - Returns: A query with the given `GROUP BY`–`HAVING` clause applied.
     public func group(_ by: Expressible, having: Expression<Bool>) -> Self {
-        return group([by], having: having)
+        group([by], having: having)
     }
 
     /// Sets a `GROUP BY`-`HAVING` clause on the query.
@@ -384,7 +385,7 @@ extension QueryType {
     ///
     /// - Returns: A query with the given `GROUP BY`–`HAVING` clause applied.
     public func group(_ by: Expressible, having: Expression<Bool?>) -> Self {
-        return group([by], having: having)
+        group([by], having: having)
     }
 
     /// Sets a `GROUP BY`-`HAVING` clause on the query.
@@ -397,7 +398,7 @@ extension QueryType {
     ///
     /// - Returns: A query with the given `GROUP BY`–`HAVING` clause applied.
     public func group(_ by: [Expressible], having: Expression<Bool>) -> Self {
-        return group(by, Expression<Bool?>(having))
+        group(by, Expression<Bool?>(having))
     }
 
     /// Sets a `GROUP BY`-`HAVING` clause on the query.
@@ -410,7 +411,7 @@ extension QueryType {
     ///
     /// - Returns: A query with the given `GROUP BY`–`HAVING` clause applied.
     public func group(_ by: [Expressible], having: Expression<Bool?>) -> Self {
-        return group(by, having)
+        group(by, having)
     }
 
     fileprivate func group(_ by: [Expressible], _ having: Expression<Bool?>?) -> Self {
@@ -434,7 +435,7 @@ extension QueryType {
     ///
     /// - Returns: A query with the given `ORDER BY` clause applied.
     public func order(_ by: Expressible...) -> Self {
-        return order(by)
+        order(by)
     }
 
     /// Sets an `ORDER BY` clause on the query.
@@ -469,7 +470,7 @@ extension QueryType {
     ///
     /// - Returns: A query with the given LIMIT clause applied.
     public func limit(_ length: Int?) -> Self {
-        return limit(length, nil)
+        limit(length, nil)
     }
 
     /// Sets LIMIT and OFFSET clauses on the query.
@@ -487,7 +488,7 @@ extension QueryType {
     ///
     /// - Returns: A query with the given LIMIT and OFFSET clauses applied.
     public func limit(_ length: Int, offset: Int) -> Self {
-        return limit(length, offset)
+        limit(length, offset)
     }
 
     // prevents limit(nil, offset: 5)
@@ -504,12 +505,13 @@ extension QueryType {
     // MARK: -
 
     fileprivate var selectClause: Expressible {
-        return " ".join([
-            Expression<Void>(literal: clauses.select.distinct ? "SELECT DISTINCT" : "SELECT"),
-            ", ".join(clauses.select.columns),
-            Expression<Void>(literal: "FROM"),
-            tableName(alias: true)
-        ])
+        " ".join([
+           Expression<Void>(literal:
+                            clauses.select.distinct ? "SELECT DISTINCT" : "SELECT"),
+           ", ".join(clauses.select.columns),
+           Expression<Void>(literal: "FROM"),
+           tableName(alias: true)
+       ])
     }
 
     fileprivate var joinClause: Expressible? {
@@ -616,31 +618,31 @@ extension QueryType {
     // MARK: INSERT
 
     public func insert(_ value: Setter, _ more: Setter...) -> Insert {
-        return insert([value] + more)
+        insert([value] + more)
     }
 
     public func insert(_ values: [Setter]) -> Insert {
-        return insert(nil, values)
+        insert(nil, values)
     }
 
     public func insert(or onConflict: OnConflict, _ values: Setter...) -> Insert {
-        return insert(or: onConflict, values)
+        insert(or: onConflict, values)
     }
 
     public func insert(or onConflict: OnConflict, _ values: [Setter]) -> Insert {
-        return insert(onConflict, values)
+        insert(onConflict, values)
     }
 
     public func insertMany( _ values: [[Setter]]) -> Insert {
-        return insertMany(nil, values)
+        insertMany(nil, values)
     }
 
     public func insertMany(or onConflict: OnConflict, _ values: [[Setter]]) -> Insert {
-        return insertMany(onConflict, values)
+        insertMany(onConflict, values)
     }
 
     public func insertMany(or onConflict: OnConflict, _ values: [Setter]...) -> Insert {
-        return insertMany(onConflict, values)
+        insertMany(onConflict, values)
     }
 
     fileprivate func insert(_ or: OnConflict?, _ values: [Setter]) -> Insert {
@@ -689,7 +691,7 @@ extension QueryType {
 
     /// Runs an `INSERT` statement against the query with `DEFAULT VALUES`.
     public func insert() -> Insert {
-        return Insert(" ".join([
+        Insert(" ".join([
             Expression<Void>(literal: "INSERT INTO"),
             tableName(),
             Expression<Void>(literal: "DEFAULT VALUES")
@@ -703,17 +705,17 @@ extension QueryType {
     ///
     /// - Returns: The number of updated rows and statement.
     public func insert(_ query: QueryType) -> Update {
-        return Update(" ".join([
+        Update(" ".join([
             Expression<Void>(literal: "INSERT INTO"),
             tableName(),
             query.expression
-        ]).expression)
+       ]).expression)
     }
 
     // MARK: UPSERT
 
     public func upsert(_ insertValues: Setter..., onConflictOf conflicting: Expressible) -> Insert {
-        return upsert(insertValues, onConflictOf: conflicting)
+        upsert(insertValues, onConflictOf: conflicting)
     }
 
     public func upsert(_ insertValues: [Setter], onConflictOf conflicting: Expressible) -> Insert {
@@ -723,7 +725,7 @@ extension QueryType {
     }
 
     public func upsert(_ insertValues: Setter..., onConflictOf conflicting: Expressible, set setValues: [Setter]) -> Insert {
-        return upsert(insertValues, onConflictOf: conflicting, set: setValues)
+        upsert(insertValues, onConflictOf: conflicting, set: setValues)
     }
 
     public func upsert(_ insertValues: [Setter], onConflictOf conflicting: Expressible, set setValues: [Setter]) -> Insert {
@@ -751,7 +753,7 @@ extension QueryType {
     // MARK: UPDATE
 
     public func update(_ values: Setter...) -> Update {
-        return update(values)
+        update(values)
     }
 
     public func update(_ values: [Setter]) -> Update {
@@ -785,7 +787,7 @@ extension QueryType {
     // MARK: EXISTS
 
     public var exists: Select<Bool> {
-        return Select(" ".join([
+        Select(" ".join([
             Expression<Void>(literal: "SELECT EXISTS"),
             "".wrap(expression) as Expression<Void>
         ]).expression)
@@ -800,15 +802,15 @@ extension QueryType {
     /// - Returns: A column expression namespaced with the query’s table name or
     ///   alias.
     public func namespace<V>(_ column: Expression<V>) -> Expression<V> {
-        return Expression(".".join([tableName(), column]).expression)
+        Expression(".".join([tableName(), column]).expression)
     }
 
     public subscript<T>(column: Expression<T>) -> Expression<T> {
-        return namespace(column)
+        namespace(column)
     }
 
     public subscript<T>(column: Expression<T?>) -> Expression<T?> {
-        return namespace(column)
+        namespace(column)
     }
 
     /// Prefixes a star with the query’s table name or alias.
@@ -818,7 +820,7 @@ extension QueryType {
     /// - Returns: A `*` expression namespaced with the query’s table name or
     ///   alias.
     public subscript(star: Star) -> Expression<Void> {
-        return namespace(star(nil, nil))
+        namespace(star(nil, nil))
     }
 
     // MARK: -
@@ -977,7 +979,7 @@ public struct RowIterator: FailableIterator {
     let columnNames: [String: Int]
 
     public func failableNext() throws -> Row? {
-        return try statement.failableNext().flatMap { Row(columnNames, $0) }
+        try statement.failableNext().flatMap { Row(columnNames, $0) }
     }
 
     public func map<T>(_ transform: (Element) throws -> T) throws -> [T] {
@@ -1016,7 +1018,7 @@ extension Connection {
             let namespace = names.joined(separator: ".")
 
             func expandGlob(_ namespace: Bool) -> (QueryType) throws -> Void {
-                return { (queryType: QueryType) throws -> Void in
+                { (queryType: QueryType) throws -> Void in
                     var query = type(of: queryType).init(queryType.clauses.from.name, database: queryType.clauses.from.database)
                     query.clauses.select = queryType.clauses.select
                     let expression = query.expression
@@ -1074,7 +1076,7 @@ extension Connection {
     }
 
     public func pluck(_ query: QueryType) throws -> Row? {
-        return try prepareRowIterator(query.limit(1, query.clauses.limit?.offset)).failableNext()
+        try prepareRowIterator(query.limit(1, query.clauses.limit?.offset)).failableNext()
     }
 
     /// Runs an `Insert` query.
diff --git a/Sources/SQLite/Typed/Schema.swift b/Sources/SQLite/Typed/Schema.swift
index d8d45e41..726f3e27 100644
--- a/Sources/SQLite/Typed/Schema.swift
+++ b/Sources/SQLite/Typed/Schema.swift
@@ -27,7 +27,7 @@ extension SchemaType {
     // MARK: - DROP TABLE / VIEW / VIRTUAL TABLE
 
     public func drop(ifExists: Bool = false) -> String {
-        return drop("TABLE", tableName(), ifExists)
+        drop("TABLE", tableName(), ifExists)
     }
 
 }
@@ -64,63 +64,63 @@ extension Table {
     // MARK: - ALTER TABLE … ADD COLUMN
 
     public func addColumn<V: Value>(_ name: Expression<V>, check: Expression<Bool>? = nil, defaultValue: V) -> String {
-        return addColumn(definition(name, V.declaredDatatype, nil, false, false, check, defaultValue, nil, nil))
+        addColumn(definition(name, V.declaredDatatype, nil, false, false, check, defaultValue, nil, nil))
     }
 
     public func addColumn<V: Value>(_ name: Expression<V>, check: Expression<Bool?>, defaultValue: V) -> String {
-        return addColumn(definition(name, V.declaredDatatype, nil, false, false, check, defaultValue, nil, nil))
+        addColumn(definition(name, V.declaredDatatype, nil, false, false, check, defaultValue, nil, nil))
     }
 
     public func addColumn<V: Value>(_ name: Expression<V?>, check: Expression<Bool>? = nil, defaultValue: V? = nil) -> String {
-        return addColumn(definition(name, V.declaredDatatype, nil, true, false, check, defaultValue, nil, nil))
+        addColumn(definition(name, V.declaredDatatype, nil, true, false, check, defaultValue, nil, nil))
     }
 
     public func addColumn<V: Value>(_ name: Expression<V?>, check: Expression<Bool?>, defaultValue: V? = nil) -> String {
-        return addColumn(definition(name, V.declaredDatatype, nil, true, false, check, defaultValue, nil, nil))
+        addColumn(definition(name, V.declaredDatatype, nil, true, false, check, defaultValue, nil, nil))
     }
 
     public func addColumn<V: Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil,
                                     references table: QueryType, _ other: Expression<V>) -> String where V.Datatype == Int64 {
-        return addColumn(definition(name, V.declaredDatatype, nil, false, unique, check, nil, (table, other), nil))
+        addColumn(definition(name, V.declaredDatatype, nil, false, unique, check, nil, (table, other), nil))
     }
 
     public func addColumn<V: Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool?>,
                                     references table: QueryType, _ other: Expression<V>) -> String where V.Datatype == Int64 {
-        return addColumn(definition(name, V.declaredDatatype, nil, false, unique, check, nil, (table, other), nil))
+        addColumn(definition(name, V.declaredDatatype, nil, false, unique, check, nil, (table, other), nil))
     }
 
     public func addColumn<V: Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool>? = nil,
                                     references table: QueryType, _ other: Expression<V>) -> String where V.Datatype == Int64 {
-        return addColumn(definition(name, V.declaredDatatype, nil, true, unique, check, nil, (table, other), nil))
+        addColumn(definition(name, V.declaredDatatype, nil, true, unique, check, nil, (table, other), nil))
     }
 
     public func addColumn<V: Value>(_ name: Expression<V?>, unique: Bool = false, check: Expression<Bool?>,
                                     references table: QueryType, _ other: Expression<V>) -> String where V.Datatype == Int64 {
-        return addColumn(definition(name, V.declaredDatatype, nil, true, unique, check, nil, (table, other), nil))
+        addColumn(definition(name, V.declaredDatatype, nil, true, unique, check, nil, (table, other), nil))
     }
 
     public func addColumn<V: Value>(_ name: Expression<V>, check: Expression<Bool>? = nil, defaultValue: V,
                                     collate: Collation) -> String where V.Datatype == String {
-        return addColumn(definition(name, V.declaredDatatype, nil, false, false, check, defaultValue, nil, collate))
+        addColumn(definition(name, V.declaredDatatype, nil, false, false, check, defaultValue, nil, collate))
     }
 
     public func addColumn<V: Value>(_ name: Expression<V>, check: Expression<Bool?>, defaultValue: V,
                                     collate: Collation) -> String where V.Datatype == String {
-        return addColumn(definition(name, V.declaredDatatype, nil, false, false, check, defaultValue, nil, collate))
+        addColumn(definition(name, V.declaredDatatype, nil, false, false, check, defaultValue, nil, collate))
     }
 
     public func addColumn<V: Value>(_ name: Expression<V?>, check: Expression<Bool>? = nil, defaultValue: V? = nil,
                                     collate: Collation) -> String where V.Datatype == String {
-        return addColumn(definition(name, V.declaredDatatype, nil, true, false, check, defaultValue, nil, collate))
+        addColumn(definition(name, V.declaredDatatype, nil, true, false, check, defaultValue, nil, collate))
     }
 
     public func addColumn<V: Value>(_ name: Expression<V?>, check: Expression<Bool?>, defaultValue: V? = nil,
                                     collate: Collation) -> String where V.Datatype == String {
-        return addColumn(definition(name, V.declaredDatatype, nil, true, false, check, defaultValue, nil, collate))
+        addColumn(definition(name, V.declaredDatatype, nil, true, false, check, defaultValue, nil, collate))
     }
 
     fileprivate func addColumn(_ expression: Expressible) -> String {
-        return " ".join([
+        " ".join([
             Expression<Void>(literal: "ALTER TABLE"),
             tableName(),
             Expression<Void>(literal: "ADD COLUMN"),
@@ -131,7 +131,7 @@ extension Table {
     // MARK: - ALTER TABLE … RENAME TO
 
     public func rename(_ to: Table) -> String {
-        return rename(to: to)
+        rename(to: to)
     }
 
     // MARK: - CREATE INDEX
@@ -150,7 +150,7 @@ extension Table {
     // MARK: - DROP INDEX
 
     public func dropIndex(_ columns: Expressible..., ifExists: Bool = false) -> String {
-        return drop("INDEX", indexName(columns), ifExists)
+        drop("INDEX", indexName(columns), ifExists)
     }
 
     fileprivate func indexName(_ columns: [Expressible]) -> Expressible {
@@ -188,7 +188,7 @@ extension View {
     // MARK: - DROP VIEW
 
     public func drop(ifExists: Bool = false) -> String {
-        return drop("VIEW", tableName(), ifExists)
+        drop("VIEW", tableName(), ifExists)
     }
 
 }
@@ -210,7 +210,7 @@ extension VirtualTable {
     // MARK: - ALTER TABLE … RENAME TO
 
     public func rename(_ to: VirtualTable) -> String {
-        return rename(to: to)
+        rename(to: to)
     }
 
 }
@@ -495,7 +495,7 @@ public struct Module {
 extension Module: Expressible {
 
     public var expression: Expression<Void> {
-        return name.wrap(arguments)
+        name.wrap(arguments)
     }
 
 }
@@ -517,7 +517,7 @@ private extension QueryType {
     }
 
     func rename(to: Self) -> String {
-        return " ".join([
+        " ".join([
             Expression<Void>(literal: "ALTER TABLE"),
             tableName(),
             Expression<Void>(literal: "RENAME TO"),
@@ -557,7 +557,7 @@ private func definition(_ column: Expressible, _ datatype: String, _ primaryKey:
 }
 
 private func reference(_ primary: (QueryType, Expressible)) -> Expressible {
-    return " ".join([
+    " ".join([
         Expression<Void>(literal: "REFERENCES"),
         primary.0.tableName(qualified: false),
         "".wrap(primary.1) as Expression<Void>
diff --git a/Sources/SQLite/Typed/Setter.swift b/Sources/SQLite/Typed/Setter.swift
index 08fb1748..7910cab8 100644
--- a/Sources/SQLite/Typed/Setter.swift
+++ b/Sources/SQLite/Typed/Setter.swift
@@ -70,213 +70,213 @@ public struct Setter {
 extension Setter: Expressible {
 
     public var expression: Expression<Void> {
-        return "=".infix(column, value, wrap: false)
+        "=".infix(column, value, wrap: false)
     }
 
 }
 
 public func <-<V: Value>(column: Expression<V>, value: Expression<V>) -> Setter {
-    return Setter(column: column, value: value)
+    Setter(column: column, value: value)
 }
 public func <-<V: Value>(column: Expression<V>, value: V) -> Setter {
-    return Setter(column: column, value: value)
+    Setter(column: column, value: value)
 }
 public func <-<V: Value>(column: Expression<V?>, value: Expression<V>) -> Setter {
-    return Setter(column: column, value: value)
+    Setter(column: column, value: value)
 }
 public func <-<V: Value>(column: Expression<V?>, value: Expression<V?>) -> Setter {
-    return Setter(column: column, value: value)
+    Setter(column: column, value: value)
 }
 public func <-<V: Value>(column: Expression<V?>, value: V?) -> Setter {
-    return Setter(column: column, value: value)
+    Setter(column: column, value: value)
 }
 
 public func +=(column: Expression<String>, value: Expression<String>) -> Setter {
-    return column <- column + value
+    column <- column + value
 }
 public func +=(column: Expression<String>, value: String) -> Setter {
-    return column <- column + value
+    column <- column + value
 }
 public func +=(column: Expression<String?>, value: Expression<String>) -> Setter {
-    return column <- column + value
+    column <- column + value
 }
 public func +=(column: Expression<String?>, value: Expression<String?>) -> Setter {
-    return column <- column + value
+    column <- column + value
 }
 public func +=(column: Expression<String?>, value: String) -> Setter {
-    return column <- column + value
+    column <- column + value
 }
 
 public func +=<V: Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype: Number {
-    return column <- column + value
+    column <- column + value
 }
 public func +=<V: Value>(column: Expression<V>, value: V) -> Setter where V.Datatype: Number {
-    return column <- column + value
+    column <- column + value
 }
 public func +=<V: Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype: Number {
-    return column <- column + value
+    column <- column + value
 }
 public func +=<V: Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype: Number {
-    return column <- column + value
+    column <- column + value
 }
 public func +=<V: Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype: Number {
-    return column <- column + value
+    column <- column + value
 }
 
 public func -=<V: Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype: Number {
-    return column <- column - value
+    column <- column - value
 }
 public func -=<V: Value>(column: Expression<V>, value: V) -> Setter where V.Datatype: Number {
-    return column <- column - value
+    column <- column - value
 }
 public func -=<V: Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype: Number {
-    return column <- column - value
+    column <- column - value
 }
 public func -=<V: Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype: Number {
-    return column <- column - value
+    column <- column - value
 }
 public func -=<V: Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype: Number {
-    return column <- column - value
+    column <- column - value
 }
 
 public func *=<V: Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype: Number {
-    return column <- column * value
+    column <- column * value
 }
 public func *=<V: Value>(column: Expression<V>, value: V) -> Setter where V.Datatype: Number {
-    return column <- column * value
+    column <- column * value
 }
 public func *=<V: Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype: Number {
-    return column <- column * value
+    column <- column * value
 }
 public func *=<V: Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype: Number {
-    return column <- column * value
+    column <- column * value
 }
 public func *=<V: Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype: Number {
-    return column <- column * value
+    column <- column * value
 }
 
 public func /=<V: Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype: Number {
-    return column <- column / value
+    column <- column / value
 }
 public func /=<V: Value>(column: Expression<V>, value: V) -> Setter where V.Datatype: Number {
-    return column <- column / value
+    column <- column / value
 }
 public func /=<V: Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype: Number {
-    return column <- column / value
+    column <- column / value
 }
 public func /=<V: Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype: Number {
-    return column <- column / value
+    column <- column / value
 }
 public func /=<V: Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype: Number {
-    return column <- column / value
+    column <- column / value
 }
 
 public func %=<V: Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
-    return column <- column % value
+    column <- column % value
 }
 public func %=<V: Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
-    return column <- column % value
+    column <- column % value
 }
 public func %=<V: Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
-    return column <- column % value
+    column <- column % value
 }
 public func %=<V: Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
-    return column <- column % value
+    column <- column % value
 }
 public func %=<V: Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
-    return column <- column % value
+    column <- column % value
 }
 
 public func <<=<V: Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
-    return column <- column << value
+    column <- column << value
 }
 public func <<=<V: Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
-    return column <- column << value
+    column <- column << value
 }
 public func <<=<V: Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
-    return column <- column << value
+    column <- column << value
 }
 public func <<=<V: Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
-    return column <- column << value
+    column <- column << value
 }
 public func <<=<V: Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
-    return column <- column << value
+    column <- column << value
 }
 
 public func >>=<V: Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
-    return column <- column >> value
+    column <- column >> value
 }
 public func >>=<V: Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
-    return column <- column >> value
+    column <- column >> value
 }
 public func >>=<V: Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
-    return column <- column >> value
+    column <- column >> value
 }
 public func >>=<V: Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
-    return column <- column >> value
+    column <- column >> value
 }
 public func >>=<V: Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
-    return column <- column >> value
+    column <- column >> value
 }
 
 public func &=<V: Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
-    return column <- column & value
+    column <- column & value
 }
 public func &=<V: Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
-    return column <- column & value
+    column <- column & value
 }
 public func &=<V: Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
-    return column <- column & value
+    column <- column & value
 }
 public func &=<V: Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
-    return column <- column & value
+    column <- column & value
 }
 public func &=<V: Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
-    return column <- column & value
+    column <- column & value
 }
 
 public func |=<V: Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
-    return column <- column | value
+    column <- column | value
 }
 public func |=<V: Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
-    return column <- column | value
+    column <- column | value
 }
 public func |=<V: Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
-    return column <- column | value
+    column <- column | value
 }
 public func |=<V: Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
-    return column <- column | value
+    column <- column | value
 }
 public func |=<V: Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
-    return column <- column | value
+    column <- column | value
 }
 
 public func ^=<V: Value>(column: Expression<V>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
-    return column <- column ^ value
+    column <- column ^ value
 }
 public func ^=<V: Value>(column: Expression<V>, value: V) -> Setter where V.Datatype == Int64 {
-    return column <- column ^ value
+    column <- column ^ value
 }
 public func ^=<V: Value>(column: Expression<V?>, value: Expression<V>) -> Setter where V.Datatype == Int64 {
-    return column <- column ^ value
+    column <- column ^ value
 }
 public func ^=<V: Value>(column: Expression<V?>, value: Expression<V?>) -> Setter where V.Datatype == Int64 {
-    return column <- column ^ value
+    column <- column ^ value
 }
 public func ^=<V: Value>(column: Expression<V?>, value: V) -> Setter where V.Datatype == Int64 {
-    return column <- column ^ value
+    column <- column ^ value
 }
 
 public postfix func ++<V: Value>(column: Expression<V>) -> Setter where V.Datatype == Int64 {
-    return Expression<Int>(column) += 1
+    Expression<Int>(column) += 1
 }
 public postfix func ++<V: Value>(column: Expression<V?>) -> Setter where V.Datatype == Int64 {
-    return Expression<Int>(column) += 1
+    Expression<Int>(column) += 1
 }
 
 public postfix func --<V: Value>(column: Expression<V>) -> Setter where V.Datatype == Int64 {
-    return Expression<Int>(column) -= 1
+    Expression<Int>(column) -= 1
 }
 public postfix func --<V: Value>(column: Expression<V?>) -> Setter where V.Datatype == Int64 {
-    return Expression<Int>(column) -= 1
+    Expression<Int>(column) -= 1
 }
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index 44c2c302..045a8274 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -362,14 +362,14 @@ class ConnectionTests: SQLiteTestCase {
 
     func test_createCollation_createsCollation() {
         try! db.createCollation("NODIACRITIC") { lhs, rhs in
-            return lhs.compare(rhs, options: .diacriticInsensitive)
+            lhs.compare(rhs, options: .diacriticInsensitive)
         }
         XCTAssertEqual(1, try! db.scalar("SELECT ? = ? COLLATE NODIACRITIC", "cafe", "café") as? Int64)
     }
 
     func test_createCollation_createsQuotableCollation() {
         try! db.createCollation("NO DIACRITIC") { lhs, rhs in
-            return lhs.compare(rhs, options: .diacriticInsensitive)
+            lhs.compare(rhs, options: .diacriticInsensitive)
         }
         XCTAssertEqual(1, try! db.scalar("SELECT ? = ? COLLATE \"NO DIACRITIC\"", "cafe", "café") as? Int64)
     }
diff --git a/Tests/SQLiteTests/CustomFunctionsTests.swift b/Tests/SQLiteTests/CustomFunctionsTests.swift
index 0ebcd13c..af1ef110 100644
--- a/Tests/SQLiteTests/CustomFunctionsTests.swift
+++ b/Tests/SQLiteTests/CustomFunctionsTests.swift
@@ -7,7 +7,7 @@ class CustomFunctionNoArgsTests: SQLiteTestCase {
 
     func testFunctionNoOptional() {
         let _: FunctionNoOptional = try! db.createFunction("test", deterministic: true) {
-            return "a"
+            "a"
         }
         let result = try! db.prepare("SELECT test()").scalar() as! String
         XCTAssertEqual("a", result)
@@ -15,7 +15,7 @@ class CustomFunctionNoArgsTests: SQLiteTestCase {
 
     func testFunctionResultOptional() {
         let _: FunctionResultOptional = try! db.createFunction("test", deterministic: true) {
-            return "a"
+            "a"
         }
         let result = try! db.prepare("SELECT test()").scalar() as! String?
         XCTAssertEqual("a", result)
@@ -30,7 +30,7 @@ class CustomFunctionWithOneArgTests: SQLiteTestCase {
 
     func testFunctionNoOptional() {
         let _: FunctionNoOptional = try! db.createFunction("test", deterministic: true) { a in
-            return "b"+a
+            "b" + a
         }
         let result = try! db.prepare("SELECT test(?)").scalar("a") as! String
         XCTAssertEqual("ba", result)
@@ -38,7 +38,7 @@ class CustomFunctionWithOneArgTests: SQLiteTestCase {
 
     func testFunctionLeftOptional() {
         let _: FunctionLeftOptional = try! db.createFunction("test", deterministic: true) { a in
-            return "b"+a!
+            "b" + a!
         }
         let result = try! db.prepare("SELECT test(?)").scalar("a") as! String
         XCTAssertEqual("ba", result)
@@ -46,7 +46,7 @@ class CustomFunctionWithOneArgTests: SQLiteTestCase {
 
     func testFunctionResultOptional() {
         let _: FunctionResultOptional = try! db.createFunction("test", deterministic: true) { a in
-            return "b"+a
+            "b" + a
         }
         let result = try! db.prepare("SELECT test(?)").scalar("a") as! String
         XCTAssertEqual("ba", result)
@@ -54,7 +54,7 @@ class CustomFunctionWithOneArgTests: SQLiteTestCase {
 
     func testFunctionLeftResultOptional() {
         let _: FunctionLeftResultOptional = try! db.createFunction("test", deterministic: true) { (a: String?) -> String? in
-            return "b"+a!
+            "b" + a!
         }
         let result = try! db.prepare("SELECT test(?)").scalar("a") as! String
         XCTAssertEqual("ba", result)
@@ -73,7 +73,7 @@ class CustomFunctionWithTwoArgsTests: SQLiteTestCase {
 
     func testNoOptional() {
         let _: FunctionNoOptional = try! db.createFunction("test", deterministic: true) { a, b in
-            return a+b
+            a + b
         }
         let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String
         XCTAssertEqual("ab", result)
@@ -81,7 +81,7 @@ class CustomFunctionWithTwoArgsTests: SQLiteTestCase {
 
     func testLeftOptional() {
         let _: FunctionLeftOptional = try! db.createFunction("test", deterministic: true) { a, b in
-            return a!+b
+            a! + b
         }
         let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String
         XCTAssertEqual("ab", result)
@@ -89,7 +89,7 @@ class CustomFunctionWithTwoArgsTests: SQLiteTestCase {
 
     func testRightOptional() {
         let _: FunctionRightOptional = try! db.createFunction("test", deterministic: true) { a, b in
-            return a+b!
+            a + b!
         }
         let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String
         XCTAssertEqual("ab", result)
@@ -97,7 +97,7 @@ class CustomFunctionWithTwoArgsTests: SQLiteTestCase {
 
     func testResultOptional() {
         let _: FunctionResultOptional = try! db.createFunction("test", deterministic: true) { a, b in
-            return a+b
+            a + b
         }
         let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String?
         XCTAssertEqual("ab", result)
@@ -105,7 +105,7 @@ class CustomFunctionWithTwoArgsTests: SQLiteTestCase {
 
     func testFunctionLeftRightOptional() {
         let _: FunctionLeftRightOptional = try! db.createFunction("test", deterministic: true) { a, b in
-            return a!+b!
+            a! + b!
         }
         let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String
         XCTAssertEqual("ab", result)
@@ -113,7 +113,7 @@ class CustomFunctionWithTwoArgsTests: SQLiteTestCase {
 
     func testFunctionLeftResultOptional() {
         let _: FunctionLeftResultOptional = try! db.createFunction("test", deterministic: true) { a, b in
-            return a!+b
+            a! + b
         }
         let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String?
         XCTAssertEqual("ab", result)
@@ -121,7 +121,7 @@ class CustomFunctionWithTwoArgsTests: SQLiteTestCase {
 
     func testFunctionRightResultOptional() {
         let _: FunctionRightResultOptional = try! db.createFunction("test", deterministic: true) { a, b in
-            return a+b!
+            a + b!
         }
         let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String?
         XCTAssertEqual("ab", result)
@@ -129,7 +129,7 @@ class CustomFunctionWithTwoArgsTests: SQLiteTestCase {
 
     func testFunctionLeftRightResultOptional() {
         let _: FunctionLeftRightResultOptional = try! db.createFunction("test", deterministic: true) { a, b in
-            return a!+b!
+            a! + b!
         }
         let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String?
         XCTAssertEqual("ab", result)
diff --git a/Tests/SQLiteTests/FTS4Tests.swift b/Tests/SQLiteTests/FTS4Tests.swift
index b637955b..33be422c 100644
--- a/Tests/SQLiteTests/FTS4Tests.swift
+++ b/Tests/SQLiteTests/FTS4Tests.swift
@@ -185,7 +185,7 @@ class FTS4ConfigTests: XCTestCase {
     }
 
     func sql(_ config: FTS4Config) -> String {
-        return virtualTable.create(.FTS4(config))
+        virtualTable.create(.FTS4(config))
     }
 }
 
diff --git a/Tests/SQLiteTests/FTS5Tests.swift b/Tests/SQLiteTests/FTS5Tests.swift
index 8079b28c..4cce4523 100644
--- a/Tests/SQLiteTests/FTS5Tests.swift
+++ b/Tests/SQLiteTests/FTS5Tests.swift
@@ -122,6 +122,6 @@ class FTS5Tests: XCTestCase {
     }
 
     func sql(_ config: FTS5Config) -> String {
-        return virtualTable.create(.FTS5(config))
+        virtualTable.create(.FTS5(config))
     }
 }
diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index 0994dd97..0aa918f0 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -42,10 +42,8 @@ class SQLiteTestCase: XCTestCase {
     }
 
     @discardableResult func insertUser(_ name: String, age: Int? = nil, admin: Bool = false) throws -> Statement {
-        return try db.run(
-            "INSERT INTO \"users\" (email, age, admin) values (?, ?, ?)",
-            "\(name)@example.com", age?.datatypeValue, admin.datatypeValue
-        )
+        try db.run("INSERT INTO \"users\" (email, age, admin) values (?, ?, ?)",
+                   "\(name)@example.com", age?.datatypeValue, admin.datatypeValue)
     }
 
     func assertSQL(_ SQL: String, _ executions: Int = 1, _ message: String? = nil, file: StaticString = #file, line: UInt = #line) {

From 9b3781c66197ed1d30894fbc831112b54786f21e Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 23 Aug 2021 11:06:05 +0200
Subject: [PATCH 410/685] Unneeded

---
 Tests/SQLiteTests/ConnectionTests.swift | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index 045a8274..37b765ab 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -217,8 +217,6 @@ class ConnectionTests: SQLiteTestCase {
     }
 
     func test_savepoint_beginsAndCommitsSavepoints() {
-        let db: Connection = db
-
         try! db.savepoint("1") {
             try db.savepoint("2") {
                 try db.run("INSERT INTO users (email) VALUES (?)", "alice@example.com")
@@ -235,7 +233,6 @@ class ConnectionTests: SQLiteTestCase {
     }
 
     func test_savepoint_beginsAndRollsSavepointsBack() {
-        let db: Connection = db
         let stmt = try! db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com")
 
         do {

From 6a1b8f355a808255a850c58d65ca56b1b68df9bf Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 23 Aug 2021 11:32:10 +0200
Subject: [PATCH 411/685] Add a release checklist

---
 .cocoadocs.yml                                |  2 --
 Documentation/Release.md                      | 10 ++++++
 SQLite.xcodeproj/project.pbxproj              |  2 ++
 Sources/SQLite/Typed/CustomFunctions.swift    | 24 ++++++-------
 .../SQLiteTests/CustomAggregationTests.swift  | 34 +++++++++----------
 5 files changed, 41 insertions(+), 31 deletions(-)
 delete mode 100644 .cocoadocs.yml
 create mode 100644 Documentation/Release.md

diff --git a/.cocoadocs.yml b/.cocoadocs.yml
deleted file mode 100644
index 27840032..00000000
--- a/.cocoadocs.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-additional_guides:
-  - Documentation/Index.md
diff --git a/Documentation/Release.md b/Documentation/Release.md
new file mode 100644
index 00000000..ef174683
--- /dev/null
+++ b/Documentation/Release.md
@@ -0,0 +1,10 @@
+# SQLite.swift Release checklist
+
+* [ ] Make sure current master branch has a green build
+* [ ] Make sure `CHANGELOG.md` is up-to-date
+* [ ] Run `pod lib lint` locally
+* [ ] Update the version numbers mentioned in `README.md`, `Documentation/Index.md`
+* [ ] Update `MARKETING_VERSION` in `SQLite.xcodeproj/project.pbxproj`
+* [ ] Create a tag with the version number (`x.y.z`)
+* [ ] Publish to CocoaPods: `pod trunk push`
+* [ ] Update the release information on GitHub
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 03d8b326..3b5428d0 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -232,6 +232,7 @@
 		19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAndTimeFunctions.swift; sourceTree = "<group>"; };
 		19A17E2695737FAB5D6086E3 /* fixtures */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = folder; path = fixtures; sourceTree = "<group>"; };
 		3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomAggregationTests.swift; sourceTree = "<group>"; };
+		19A17EA3A313F129011B3FA0 /* Release.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Release.md; sourceTree = "<group>"; };
 		3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.0.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
 		3DDC112E26CDBA0200CE369F /* SQLiteObjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SQLiteObjc.h; path = ../SQLiteObjc/include/SQLiteObjc.h; sourceTree = "<group>"; };
 		49EB68C31F7B3CB400D89D40 /* Coding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coding.swift; sourceTree = "<group>"; };
@@ -496,6 +497,7 @@
 			children = (
 				EE247B8F1C3F822500AE3E12 /* Index.md */,
 				EE247B901C3F822500AE3E12 /* Resources */,
+				19A17EA3A313F129011B3FA0 /* Release.md */,
 			);
 			path = Documentation;
 			sourceTree = "<group>";
diff --git a/Sources/SQLite/Typed/CustomFunctions.swift b/Sources/SQLite/Typed/CustomFunctions.swift
index 88fb5aaa..f2d90b0f 100644
--- a/Sources/SQLite/Typed/CustomFunctions.swift
+++ b/Sources/SQLite/Typed/CustomFunctions.swift
@@ -160,8 +160,8 @@ public extension Connection {
     }
 
     // MARK: -
-    
-    public func createAggregation<T: AnyObject>(
+
+    func createAggregation<T: AnyObject>(
         _ aggregate: String,
         argumentCount: UInt? = nil,
         deterministic: Bool = false,
@@ -169,14 +169,14 @@ public extension Connection {
         reduce: @escaping (T, [Binding?]) -> T,
         result: @escaping (T) -> Binding?
         ) {
-        
+
         let step: ([Binding?], UnsafeMutablePointer<UnsafeMutableRawPointer>) -> () = { (bindings, ptr) in
             let p = ptr.pointee.assumingMemoryBound(to: T.self)
             let current = Unmanaged<T>.fromOpaque(p).takeRetainedValue()
             let next = reduce(current, bindings)
             ptr.pointee = Unmanaged.passRetained(next).toOpaque()
         }
-        
+
         let final: (UnsafeMutablePointer<UnsafeMutableRawPointer>) -> Binding? = { (ptr) in
             let p = ptr.pointee.assumingMemoryBound(to: T.self)
             let obj = Unmanaged<T>.fromOpaque(p).takeRetainedValue()
@@ -184,17 +184,17 @@ public extension Connection {
             ptr.deallocate()
             return value
         }
-        
+
         let state: () -> UnsafeMutablePointer<UnsafeMutableRawPointer> = {
             let p = UnsafeMutablePointer<UnsafeMutableRawPointer>.allocate(capacity: 1)
             p.pointee = Unmanaged.passRetained(initialValue).toOpaque()
             return p
         }
-        
+
         createAggregation(aggregate, step: step, final: final, state: state)
     }
-    
-    public func createAggregation<T>(
+
+    func createAggregation<T>(
         _ aggregate: String,
         argumentCount: UInt? = nil,
         deterministic: Bool = false,
@@ -202,25 +202,25 @@ public extension Connection {
         reduce: @escaping (T, [Binding?]) -> T,
         result: @escaping (T) -> Binding?
         ) {
-        
+
         let step: ([Binding?], UnsafeMutablePointer<T>) -> () = { (bindings, p) in
             let current = p.pointee
             let next = reduce(current, bindings)
             p.pointee = next
         }
-        
+
         let final: (UnsafeMutablePointer<T>) -> Binding? = { (p) in
             let v = result(p.pointee)
             p.deallocate()
             return v
         }
-        
+
         let state: () -> UnsafeMutablePointer<T> = {
             let p = UnsafeMutablePointer<T>.allocate(capacity: 1)
             p.pointee = initialValue
             return p
         }
-        
+
         createAggregation(aggregate, step: step, final: final, state: state)
     }
 
diff --git a/Tests/SQLiteTests/CustomAggregationTests.swift b/Tests/SQLiteTests/CustomAggregationTests.swift
index f8efc7e4..05ed619a 100644
--- a/Tests/SQLiteTests/CustomAggregationTests.swift
+++ b/Tests/SQLiteTests/CustomAggregationTests.swift
@@ -16,19 +16,19 @@ import SQLite3
 class CustomAggregationTests : SQLiteTestCase {
     override func setUp() {
         super.setUp()
-        CreateUsersTable()
-        try! InsertUser("Alice", age: 30, admin: true)
-        try! InsertUser("Bob", age: 25, admin: true)
-        try! InsertUser("Eve", age: 28, admin: false)
+        createUsersTable()
+        try! insertUser("Alice", age: 30, admin: true)
+        try! insertUser("Bob", age: 25, admin: true)
+        try! insertUser("Eve", age: 28, admin: false)
     }
-    
+
     func testUnsafeCustomSum() {
         let step = { (bindings: [Binding?], state: UnsafeMutablePointer<Int64>) in
             if let v = bindings[0] as? Int64 {
                 state.pointee += v
             }
         }
-        
+
         let final = { (state: UnsafeMutablePointer<Int64>) -> Binding? in
             let v = state.pointee
             let p = UnsafeMutableBufferPointer(start: state, count: 1)
@@ -41,13 +41,13 @@ class CustomAggregationTests : SQLiteTestCase {
             return v.baseAddress!
         }
         let result = try! db.prepare("SELECT mySUM1(age) AS s FROM users")
-        let i = result.columnNames.index(of: "s")!
+        let i = result.columnNames.firstIndex(of: "s")!
         for row in result {
             let value = row[i] as? Int64
             XCTAssertEqual(83, value)
         }
     }
-    
+
     func testUnsafeCustomSumGrouping() {
         let step = { (bindings: [Binding?], state: UnsafeMutablePointer<Int64>) in
             if let v = bindings[0] as? Int64 {
@@ -66,11 +66,11 @@ class CustomAggregationTests : SQLiteTestCase {
             return v.baseAddress!
         }
         let result = try! db.prepare("SELECT mySUM2(age) AS s FROM users GROUP BY admin ORDER BY s")
-        let i = result.columnNames.index(of: "s")!
+        let i = result.columnNames.firstIndex(of: "s")!
         let values = result.compactMap { $0[i] as? Int64 }
         XCTAssertTrue(values.elementsEqual([28, 55]))
     }
-    
+
     func testCustomSum() {
         let reduce : (Int64, [Binding?]) -> Int64 = { (last, bindings) in
             let v = (bindings[0] as? Int64) ?? 0
@@ -78,7 +78,7 @@ class CustomAggregationTests : SQLiteTestCase {
         }
         let _ = db.createAggregation("myReduceSUM1", initialValue: Int64(2000), reduce: reduce, result: { $0 })
         let result = try! db.prepare("SELECT myReduceSUM1(age) AS s FROM users")
-        let i = result.columnNames.index(of: "s")!
+        let i = result.columnNames.firstIndex(of: "s")!
         for row in result {
             let value = row[i] as? Int64
             XCTAssertEqual(2083, value)
@@ -92,11 +92,11 @@ class CustomAggregationTests : SQLiteTestCase {
         }
         let _ = db.createAggregation("myReduceSUM2", initialValue: Int64(3000), reduce: reduce, result: { $0 })
         let result = try! db.prepare("SELECT myReduceSUM2(age) AS s FROM users GROUP BY admin ORDER BY s")
-        let i = result.columnNames.index(of: "s")!
+        let i = result.columnNames.firstIndex(of: "s")!
         let values = result.compactMap { $0[i] as? Int64 }
         XCTAssertTrue(values.elementsEqual([3028, 3055]))
     }
-    
+
     func testCustomStringAgg() {
         let initial = String(repeating: " ", count: 64)
         let reduce : (String, [Binding?]) -> String = { (last, bindings) in
@@ -105,13 +105,13 @@ class CustomAggregationTests : SQLiteTestCase {
         }
         let _ = db.createAggregation("myReduceSUM3", initialValue: initial, reduce: reduce, result: { $0 })
         let result = try! db.prepare("SELECT myReduceSUM3(email) AS s FROM users")
-        let i = result.columnNames.index(of: "s")!
+        let i = result.columnNames.firstIndex(of: "s")!
         for row in result {
             let value = row[i] as? String
             XCTAssertEqual("\(initial)Alice@example.comBob@example.comEve@example.com", value)
         }
     }
-    
+
     func testCustomObjectSum() {
         {
             let initial = TestObject(value: 1000)
@@ -126,7 +126,7 @@ class CustomAggregationTests : SQLiteTestCase {
         {
             XCTAssertEqual(TestObject.inits, 1)
             let result = try! db.prepare("SELECT myReduceSUMX(age) AS s FROM users")
-            let i = result.columnNames.index(of: "s")!
+            let i = result.columnNames.firstIndex(of: "s")!
             for row in result {
                 let value = row[i] as? Int64
                 XCTAssertEqual(1083, value)
@@ -143,7 +143,7 @@ class CustomAggregationTests : SQLiteTestCase {
 class TestObject {
     static var inits = 0
     static var deinits = 0
-    
+
     var value: Int64
     init(value: Int64) {
         self.value = value

From 75ef800901784da018a4d9eed1942e49e0a82ae1 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 23 Aug 2021 11:37:02 +0200
Subject: [PATCH 412/685] Need to update podspec

---
 Documentation/Release.md | 1 +
 SQLite.swift.podspec     | 7 +++----
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/Documentation/Release.md b/Documentation/Release.md
index ef174683..0177fc8f 100644
--- a/Documentation/Release.md
+++ b/Documentation/Release.md
@@ -2,6 +2,7 @@
 
 * [ ] Make sure current master branch has a green build
 * [ ] Make sure `CHANGELOG.md` is up-to-date
+* [ ] Update the version number in `SQLite.swift.podspec`
 * [ ] Run `pod lib lint` locally
 * [ ] Update the version numbers mentioned in `README.md`, `Documentation/Index.md`
 * [ ] Update `MARKETING_VERSION` in `SQLite.xcodeproj/project.pbxproj`
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 499012c1..f273ffd8 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,7 +1,7 @@
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
   s.version          = "0.13.0"
-  s.summary          = "A type-safe, Swift-language layer over SQLite3 for iOS and macOS."
+  s.summary          = "A type-safe, Swift-language layer over SQLite3."
 
   s.description      = <<-DESC
     SQLite.swift provides compile-time confidence in SQL statement syntax and
@@ -17,13 +17,12 @@ Pod::Spec.new do |s|
   s.module_name      = 'SQLite'
   s.default_subspec  = 'standard'
   s.swift_versions = ['5']
-  
-  
+
   ios_deployment_target = '9.0'
   tvos_deployment_target = '9.1'
   osx_deployment_target = '10.15'
   watchos_deployment_target = '3.0'
-  
+
   s.ios.deployment_target = ios_deployment_target
   s.tvos.deployment_target = tvos_deployment_target
   s.osx.deployment_target = osx_deployment_target

From 8ba6c0e6ea34e3b85f71a47511420fe2ad34bddd Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 23 Aug 2021 11:45:50 +0200
Subject: [PATCH 413/685] https links, cocoadocs is dead

---
 CONTRIBUTING.md |  2 +-
 README.md       | 14 +++++++-------
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6c367b95..6969a705 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -19,7 +19,7 @@ addresses everything. If it doesn’t, continue the conversation there.
 If your searches return empty, see the [bug](#bugs) or [feature
 request](#feature-requests) guidelines below.
 
-[Ask on Stack Overflow]: http://stackoverflow.com/questions/tagged/sqlite.swift
+[Ask on Stack Overflow]: https://stackoverflow.com/questions/tagged/sqlite.swift
 [Search]: https://github.com/stephencelis/SQLite.swift/search?type=Issues
 
 
diff --git a/README.md b/README.md
index 98a625c4..ac044dc0 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ syntax _and_ intent.
  - Extensively tested
  - [SQLCipher][] support via CocoaPods
  - Active support at
-   [StackOverflow](http://stackoverflow.com/questions/tagged/sqlite.swift),
+   [StackOverflow](https://stackoverflow.com/questions/tagged/sqlite.swift),
    and [Gitter Chat Room](https://gitter.im/stephencelis/SQLite.swift)
    (_experimental_)
 
@@ -119,7 +119,7 @@ For a more comprehensive example, see
 and the [companion repository][SQLiteDataAccessLayer2].
 
 
-[Create a Data Access Layer with SQLite.swift and Swift 2]: http://masteringswift.blogspot.com/2015/09/create-data-access-layer-with.html
+[Create a Data Access Layer with SQLite.swift and Swift 2]: https://masteringswift.blogspot.com/2015/09/create-data-access-layer-with.html
 [SQLiteDataAccessLayer2]: https://github.com/hoffmanjon/SQLiteDataAccessLayer2/tree/master
 
 ## Installation
@@ -226,7 +226,7 @@ device:
 
 
 [Xcode]: https://developer.apple.com/xcode/downloads/
-[Submodule]: http://git-scm.com/book/en/Git-Tools-Submodules
+[Submodule]: https://git-scm.com/book/en/Git-Tools-Submodules
 [download]: https://github.com/stephencelis/SQLite.swift/archive/master.zip
 
 
@@ -243,7 +243,7 @@ device:
 
 [See the planning document]: /Documentation/Planning.md
 [Read the contributing guidelines]: ./CONTRIBUTING.md#contributing
-[Ask on Stack Overflow]: http://stackoverflow.com/questions/tagged/sqlite.swift
+[Ask on Stack Overflow]: https://stackoverflow.com/questions/tagged/sqlite.swift
 [Open an issue]: https://github.com/stephencelis/SQLite.swift/issues/new
 [Submit a pull request]: https://github.com/stephencelis/SQLite.swift/fork
 
@@ -280,16 +280,16 @@ Looking for something else? Try another Swift wrapper (or [FMDB][]):
  - [SwiftSQLite](https://github.com/chrismsimpson/SwiftSQLite)
 
 [Swift]: https://swift.org/
-[SQLite3]: http://www.sqlite.org
+[SQLite3]: https://www.sqlite.org
 [SQLite.swift]: https://github.com/stephencelis/SQLite.swift
 
 [GitHubActionBadge]: https://img.shields.io/github/workflow/status/stephencelis/SQLite.swift/Build%20and%20test
 
 [CocoaPodsVersionBadge]: https://cocoapod-badges.herokuapp.com/v/SQLite.swift/badge.png
-[CocoaPodsVersionLink]: http://cocoadocs.org/docsets/SQLite.swift
+[CocoaPodsVersionLink]: https://cocoapods.org/pods/SQLite.swift
 
 [PlatformBadge]: https://cocoapod-badges.herokuapp.com/p/SQLite.swift/badge.png
-[PlatformLink]: http://cocoadocs.org/docsets/SQLite.swift
+[PlatformLink]: https://cocoapods.org/pods/SQLite.swift
 
 [CartagheBadge]: https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat
 [CarthageLink]: https://github.com/Carthage/Carthage

From 66e01e2191707158dff6127ce1055fb084f8f2b5 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 23 Aug 2021 12:03:19 +0200
Subject: [PATCH 414/685] Fix lint post merge

---
 .swiftlint.yml                                |  8 +++--
 Sources/SQLite/Core/Connection.swift          | 32 ++++++++---------
 Sources/SQLite/Typed/CoreFunctions.swift      |  1 -
 Sources/SQLite/Typed/CustomFunctions.swift    | 36 +++++++++----------
 .../SQLiteTests/CustomAggregationTests.swift  | 24 +++++++------
 5 files changed, 53 insertions(+), 48 deletions(-)

diff --git a/.swiftlint.yml b/.swiftlint.yml
index 3bfc5fa5..b5e53d56 100644
--- a/.swiftlint.yml
+++ b/.swiftlint.yml
@@ -28,11 +28,15 @@ type_body_length:
   warning: 260
   error: 260
 
+function_body_length:
+  warning: 60
+  error: 60
+
 line_length:
   warning: 150
   error: 150
   ignores_comments: true
 
 file_length:
-  warning: 760
-  error: 760
+  warning: 900
+  error: 900
diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 07c85373..2bea05c8 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -35,6 +35,7 @@ import SQLite3
 #endif
 
 /// A connection to SQLite.
+// swiftlint:disable:next type_body_length
 public final class Connection {
 
     /// The location of a SQLite database.
@@ -585,7 +586,7 @@ public final class Connection {
     ///   - block: A block of code to run when the function is called. The block
     ///     is called with an array of raw SQL values mapped to the function’s
     ///     parameters and should return a raw SQL value (or nil).
-    // swiftlint:disable:next cyclomatic_complexity function_body_length
+    // swiftlint:disable:next cyclomatic_complexity
     public func createFunction(_ function: String, argumentCount: UInt? = nil, deterministic: Bool = false,
                                _ block: @escaping (_ args: [Binding?]) -> Binding?) {
         let argc = argumentCount.map { Int($0) } ?? -1
@@ -636,7 +637,7 @@ public final class Connection {
         if functions[function] == nil { functions[function] = [:] }
         functions[function]?[argc] = box
     }
-    
+
     /// Creates or redefines a custom SQL aggregate.
     ///
     /// - Parameters:
@@ -665,19 +666,19 @@ public final class Connection {
     ///   - state: A block of code to run to produce a fresh state variable for
     ///     each aggregation group. The block should return an
     ///     UnsafeMutablePointer to the fresh state variable.
+    // swiftlint:disable:next cyclomatic_complexity
     public func createAggregation<T>(
         _ aggregate: String,
         argumentCount: UInt? = nil,
         deterministic: Bool = false,
-        step: @escaping ([Binding?], UnsafeMutablePointer<T>) -> (),
+        step: @escaping ([Binding?], UnsafeMutablePointer<T>) -> Void,
         final: @escaping (UnsafeMutablePointer<T>) -> Binding?,
         state: @escaping () -> UnsafeMutablePointer<T>) {
-        
-        
+
         let argc = argumentCount.map { Int($0) } ?? -1
-        let box : Aggregate = { (stepFlag: Int, context: OpaquePointer?, argc: Int32, argv: UnsafeMutablePointer<OpaquePointer?>?) in
+        let box: Aggregate = { (stepFlag: Int, context: OpaquePointer?, argc: Int32, argv: UnsafeMutablePointer<OpaquePointer?>?) in
             let ptr = sqlite3_aggregate_context(context, 64)! // needs to be at least as large as uintptr_t; better way to do this?
-            let p = ptr.assumingMemoryBound(to: UnsafeMutableRawPointer.self)
+            let mutablePointer = ptr.assumingMemoryBound(to: UnsafeMutableRawPointer.self)
             if stepFlag > 0 {
                 let arguments: [Binding?] = (0..<Int(argc)).map { idx in
                     let value = argv![idx]
@@ -696,14 +697,14 @@ public final class Connection {
                         fatalError("unsupported value type: \(type)")
                     }
                 }
-                
+
                 if ptr.assumingMemoryBound(to: Int64.self).pointee == 0 {
-                    let v = state()
-                    p.pointee = UnsafeMutableRawPointer(mutating: v)
+                    let value = state()
+                    mutablePointer.pointee = UnsafeMutableRawPointer(mutating: value)
                 }
-                step(arguments, p.pointee.assumingMemoryBound(to: T.self))
+                step(arguments, mutablePointer.pointee.assumingMemoryBound(to: T.self))
             } else {
-                let result = final(p.pointee.assumingMemoryBound(to: T.self))
+                let result = final(mutablePointer.pointee.assumingMemoryBound(to: T.self))
                 if let result = result as? Blob {
                     sqlite3_result_blob(context, result.bytes, Int32(result.bytes.count), nil)
                 } else if let result = result as? Double {
@@ -719,14 +720,14 @@ public final class Connection {
                 }
             }
         }
-        
+
         var flags = SQLITE_UTF8
         #if !os(Linux)
         if deterministic {
             flags |= SQLITE_DETERMINISTIC
         }
         #endif
-        
+
         sqlite3_create_function_v2(
             handle,
             aggregate,
@@ -737,8 +738,7 @@ public final class Connection {
             { context, argc, value in
                 let function = unsafeBitCast(sqlite3_user_data(context), to: Aggregate.self)
                 function(1, context, argc, value)
-        },
-            { context in
+        }, { context in
                 let function = unsafeBitCast(sqlite3_user_data(context), to: Aggregate.self)
                 function(0, context, 0, nil)
         },
diff --git a/Sources/SQLite/Typed/CoreFunctions.swift b/Sources/SQLite/Typed/CoreFunctions.swift
index be38d97e..dc6a1044 100644
--- a/Sources/SQLite/Typed/CoreFunctions.swift
+++ b/Sources/SQLite/Typed/CoreFunctions.swift
@@ -21,7 +21,6 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 //
-// swiftlint:disable file_length
 import Foundation
 
 private enum Function: String {
diff --git a/Sources/SQLite/Typed/CustomFunctions.swift b/Sources/SQLite/Typed/CustomFunctions.swift
index f2d90b0f..1d66d075 100644
--- a/Sources/SQLite/Typed/CustomFunctions.swift
+++ b/Sources/SQLite/Typed/CustomFunctions.swift
@@ -170,25 +170,25 @@ public extension Connection {
         result: @escaping (T) -> Binding?
         ) {
 
-        let step: ([Binding?], UnsafeMutablePointer<UnsafeMutableRawPointer>) -> () = { (bindings, ptr) in
-            let p = ptr.pointee.assumingMemoryBound(to: T.self)
-            let current = Unmanaged<T>.fromOpaque(p).takeRetainedValue()
+        let step: ([Binding?], UnsafeMutablePointer<UnsafeMutableRawPointer>) -> Void = { (bindings, ptr) in
+            let pointer = ptr.pointee.assumingMemoryBound(to: T.self)
+            let current = Unmanaged<T>.fromOpaque(pointer).takeRetainedValue()
             let next = reduce(current, bindings)
             ptr.pointee = Unmanaged.passRetained(next).toOpaque()
         }
 
         let final: (UnsafeMutablePointer<UnsafeMutableRawPointer>) -> Binding? = { (ptr) in
-            let p = ptr.pointee.assumingMemoryBound(to: T.self)
-            let obj = Unmanaged<T>.fromOpaque(p).takeRetainedValue()
+            let pointer = ptr.pointee.assumingMemoryBound(to: T.self)
+            let obj = Unmanaged<T>.fromOpaque(pointer).takeRetainedValue()
             let value = result(obj)
             ptr.deallocate()
             return value
         }
 
         let state: () -> UnsafeMutablePointer<UnsafeMutableRawPointer> = {
-            let p = UnsafeMutablePointer<UnsafeMutableRawPointer>.allocate(capacity: 1)
-            p.pointee = Unmanaged.passRetained(initialValue).toOpaque()
-            return p
+            let pointer = UnsafeMutablePointer<UnsafeMutableRawPointer>.allocate(capacity: 1)
+            pointer.pointee = Unmanaged.passRetained(initialValue).toOpaque()
+            return pointer
         }
 
         createAggregation(aggregate, step: step, final: final, state: state)
@@ -203,22 +203,22 @@ public extension Connection {
         result: @escaping (T) -> Binding?
         ) {
 
-        let step: ([Binding?], UnsafeMutablePointer<T>) -> () = { (bindings, p) in
-            let current = p.pointee
+        let step: ([Binding?], UnsafeMutablePointer<T>) -> Void = { (bindings, pointer) in
+            let current = pointer.pointee
             let next = reduce(current, bindings)
-            p.pointee = next
+            pointer.pointee = next
         }
 
-        let final: (UnsafeMutablePointer<T>) -> Binding? = { (p) in
-            let v = result(p.pointee)
-            p.deallocate()
-            return v
+        let final: (UnsafeMutablePointer<T>) -> Binding? = { pointer in
+            let value = result(pointer.pointee)
+            pointer.deallocate()
+            return value
         }
 
         let state: () -> UnsafeMutablePointer<T> = {
-            let p = UnsafeMutablePointer<T>.allocate(capacity: 1)
-            p.pointee = initialValue
-            return p
+            let pointer = UnsafeMutablePointer<T>.allocate(capacity: 1)
+            pointer.pointee = initialValue
+            return pointer
         }
 
         createAggregation(aggregate, step: step, final: final, state: state)
diff --git a/Tests/SQLiteTests/CustomAggregationTests.swift b/Tests/SQLiteTests/CustomAggregationTests.swift
index 05ed619a..99cbb00d 100644
--- a/Tests/SQLiteTests/CustomAggregationTests.swift
+++ b/Tests/SQLiteTests/CustomAggregationTests.swift
@@ -13,7 +13,7 @@ import CSQLite
 import SQLite3
 #endif
 
-class CustomAggregationTests : SQLiteTestCase {
+class CustomAggregationTests: SQLiteTestCase {
     override func setUp() {
         super.setUp()
         createUsersTable()
@@ -35,7 +35,7 @@ class CustomAggregationTests : SQLiteTestCase {
             p.deallocate()
             return v
         }
-        let _ = db.createAggregation("mySUM1", step: step, final: final) {
+        _ = db.createAggregation("mySUM1", step: step, final: final) {
             let v = UnsafeMutableBufferPointer<Int64>.allocate(capacity: 1)
             v[0] = 0
             return v.baseAddress!
@@ -60,7 +60,7 @@ class CustomAggregationTests : SQLiteTestCase {
             p.deallocate()
             return v
         }
-        let _ = db.createAggregation("mySUM2", step: step, final: final) {
+        _ = db.createAggregation("mySUM2", step: step, final: final) {
             let v = UnsafeMutableBufferPointer<Int64>.allocate(capacity: 1)
             v[0] = 0
             return v.baseAddress!
@@ -72,11 +72,11 @@ class CustomAggregationTests : SQLiteTestCase {
     }
 
     func testCustomSum() {
-        let reduce : (Int64, [Binding?]) -> Int64 = { (last, bindings) in
+        let reduce: (Int64, [Binding?]) -> Int64 = { (last, bindings) in
             let v = (bindings[0] as? Int64) ?? 0
             return last + v
         }
-        let _ = db.createAggregation("myReduceSUM1", initialValue: Int64(2000), reduce: reduce, result: { $0 })
+        _ = db.createAggregation("myReduceSUM1", initialValue: Int64(2000), reduce: reduce, result: { $0 })
         let result = try! db.prepare("SELECT myReduceSUM1(age) AS s FROM users")
         let i = result.columnNames.firstIndex(of: "s")!
         for row in result {
@@ -86,11 +86,11 @@ class CustomAggregationTests : SQLiteTestCase {
     }
 
     func testCustomSumGrouping() {
-        let reduce : (Int64, [Binding?]) -> Int64 = { (last, bindings) in
+        let reduce: (Int64, [Binding?]) -> Int64 = { (last, bindings) in
             let v = (bindings[0] as? Int64) ?? 0
             return last + v
         }
-        let _ = db.createAggregation("myReduceSUM2", initialValue: Int64(3000), reduce: reduce, result: { $0 })
+        _ = db.createAggregation("myReduceSUM2", initialValue: Int64(3000), reduce: reduce, result: { $0 })
         let result = try! db.prepare("SELECT myReduceSUM2(age) AS s FROM users GROUP BY admin ORDER BY s")
         let i = result.columnNames.firstIndex(of: "s")!
         let values = result.compactMap { $0[i] as? Int64 }
@@ -99,11 +99,11 @@ class CustomAggregationTests : SQLiteTestCase {
 
     func testCustomStringAgg() {
         let initial = String(repeating: " ", count: 64)
-        let reduce : (String, [Binding?]) -> String = { (last, bindings) in
+        let reduce: (String, [Binding?]) -> String = { (last, bindings) in
             let v = (bindings[0] as? String) ?? ""
             return last + v
         }
-        let _ = db.createAggregation("myReduceSUM3", initialValue: initial, reduce: reduce, result: { $0 })
+        _ = db.createAggregation("myReduceSUM3", initialValue: initial, reduce: reduce, result: { $0 })
         let result = try! db.prepare("SELECT myReduceSUM3(email) AS s FROM users")
         let i = result.columnNames.firstIndex(of: "s")!
         for row in result {
@@ -115,14 +115,16 @@ class CustomAggregationTests : SQLiteTestCase {
     func testCustomObjectSum() {
         {
             let initial = TestObject(value: 1000)
-            let reduce : (TestObject, [Binding?]) -> TestObject = { (last, bindings) in
+            let reduce: (TestObject, [Binding?]) -> TestObject = { (last, bindings) in
                 let v = (bindings[0] as? Int64) ?? 0
                 return TestObject(value: last.value + v)
             }
-            let _ = db.createAggregation("myReduceSUMX", initialValue: initial, reduce: reduce, result: { $0.value })
+            db.createAggregation("myReduceSUMX", initialValue: initial, reduce: reduce, result: { $0.value })
             // end this scope to ensure that the initial value is retained
             // by the createAggregation call.
+            // swiftlint:disable:next trailing_semicolon
         }();
+
         {
             XCTAssertEqual(TestObject.inits, 1)
             let result = try! db.prepare("SELECT myReduceSUMX(age) AS s FROM users")

From 985b2e4d8c21f94879a084c5d5becafee4821dfe Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 23 Aug 2021 12:04:41 +0200
Subject: [PATCH 415/685] Fix warnings

---
 Tests/SQLiteTests/CustomAggregationTests.swift | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/Tests/SQLiteTests/CustomAggregationTests.swift b/Tests/SQLiteTests/CustomAggregationTests.swift
index 99cbb00d..337a5aa8 100644
--- a/Tests/SQLiteTests/CustomAggregationTests.swift
+++ b/Tests/SQLiteTests/CustomAggregationTests.swift
@@ -35,7 +35,7 @@ class CustomAggregationTests: SQLiteTestCase {
             p.deallocate()
             return v
         }
-        _ = db.createAggregation("mySUM1", step: step, final: final) {
+        db.createAggregation("mySUM1", step: step, final: final) {
             let v = UnsafeMutableBufferPointer<Int64>.allocate(capacity: 1)
             v[0] = 0
             return v.baseAddress!
@@ -60,7 +60,7 @@ class CustomAggregationTests: SQLiteTestCase {
             p.deallocate()
             return v
         }
-        _ = db.createAggregation("mySUM2", step: step, final: final) {
+        db.createAggregation("mySUM2", step: step, final: final) {
             let v = UnsafeMutableBufferPointer<Int64>.allocate(capacity: 1)
             v[0] = 0
             return v.baseAddress!
@@ -76,7 +76,7 @@ class CustomAggregationTests: SQLiteTestCase {
             let v = (bindings[0] as? Int64) ?? 0
             return last + v
         }
-        _ = db.createAggregation("myReduceSUM1", initialValue: Int64(2000), reduce: reduce, result: { $0 })
+        db.createAggregation("myReduceSUM1", initialValue: Int64(2000), reduce: reduce, result: { $0 })
         let result = try! db.prepare("SELECT myReduceSUM1(age) AS s FROM users")
         let i = result.columnNames.firstIndex(of: "s")!
         for row in result {
@@ -90,7 +90,7 @@ class CustomAggregationTests: SQLiteTestCase {
             let v = (bindings[0] as? Int64) ?? 0
             return last + v
         }
-        _ = db.createAggregation("myReduceSUM2", initialValue: Int64(3000), reduce: reduce, result: { $0 })
+        db.createAggregation("myReduceSUM2", initialValue: Int64(3000), reduce: reduce, result: { $0 })
         let result = try! db.prepare("SELECT myReduceSUM2(age) AS s FROM users GROUP BY admin ORDER BY s")
         let i = result.columnNames.firstIndex(of: "s")!
         let values = result.compactMap { $0[i] as? Int64 }
@@ -103,7 +103,7 @@ class CustomAggregationTests: SQLiteTestCase {
             let v = (bindings[0] as? String) ?? ""
             return last + v
         }
-        _ = db.createAggregation("myReduceSUM3", initialValue: initial, reduce: reduce, result: { $0 })
+        db.createAggregation("myReduceSUM3", initialValue: initial, reduce: reduce, result: { $0 })
         let result = try! db.prepare("SELECT myReduceSUM3(email) AS s FROM users")
         let i = result.columnNames.firstIndex(of: "s")!
         for row in result {

From 896d2978548a336bcade3c8e1b3076f7b2205c55 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 23 Aug 2021 13:16:20 +0200
Subject: [PATCH 416/685] Fail build if there are compiler warnings

Closes #1065
---
 .github/workflows/build.yml          | 8 ++++----
 Sources/SQLite/Core/Connection.swift | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 1119284a..af6666ba 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -17,6 +17,10 @@ jobs:
         brew outdated swiftlint || brew upgrade swiftlint
     - name: "Lint"
       run: make lint
+    - name: "Run tests (PACKAGE_MANAGER_COMMAND: test)"
+      env:
+        PACKAGE_MANAGER_COMMAND: test -Xswiftc -warnings-as-errors
+      run: ./run-tests.sh
     - name: "Run tests (BUILD_SCHEME: SQLite iOS)"
       env:
         BUILD_SCHEME: SQLite iOS
@@ -57,7 +61,3 @@ jobs:
       env:
         CARTHAGE_PLATFORM: tvOS
       run: ./run-tests.sh
-    - name: "Run tests (PACKAGE_MANAGER_COMMAND: test)"
-      env:
-        PACKAGE_MANAGER_COMMAND: test
-      run: ./run-tests.sh
diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 2bea05c8..fa086181 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -434,7 +434,7 @@ public final class Connection {
         }
     }
 
-    @available(OSX, deprecated: 10.2)
+    @available(OSX, deprecated: 10.12)
     @available(iOS, deprecated: 10.0)
     @available(watchOS, deprecated: 3.0)
     @available(tvOS, deprecated: 10.0)

From 559b796187ab1b71148ac68f37c4b2e23db3b49a Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 23 Aug 2021 13:42:34 +0200
Subject: [PATCH 417/685] Simplify CocoaPods linting

Closes #1066
---
 Tests/CocoaPods/.gitignore          |  1 -
 Tests/CocoaPods/Gemfile             |  4 --
 Tests/CocoaPods/Gemfile.lock        | 96 -----------------------------
 Tests/CocoaPods/Makefile            | 15 -----
 Tests/CocoaPods/integration_test.rb | 35 -----------
 run-tests.sh                        |  8 ++-
 6 files changed, 6 insertions(+), 153 deletions(-)
 delete mode 100644 Tests/CocoaPods/.gitignore
 delete mode 100644 Tests/CocoaPods/Gemfile
 delete mode 100644 Tests/CocoaPods/Gemfile.lock
 delete mode 100644 Tests/CocoaPods/Makefile
 delete mode 100755 Tests/CocoaPods/integration_test.rb

diff --git a/Tests/CocoaPods/.gitignore b/Tests/CocoaPods/.gitignore
deleted file mode 100644
index 4cf24de2..00000000
--- a/Tests/CocoaPods/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-gems/
diff --git a/Tests/CocoaPods/Gemfile b/Tests/CocoaPods/Gemfile
deleted file mode 100644
index da52ec89..00000000
--- a/Tests/CocoaPods/Gemfile
+++ /dev/null
@@ -1,4 +0,0 @@
-source 'https://rubygems.org'
-
-gem 'cocoapods', '~> 1.10.2'
-gem 'minitest'
diff --git a/Tests/CocoaPods/Gemfile.lock b/Tests/CocoaPods/Gemfile.lock
deleted file mode 100644
index e0383a67..00000000
--- a/Tests/CocoaPods/Gemfile.lock
+++ /dev/null
@@ -1,96 +0,0 @@
-GEM
-  remote: https://rubygems.org/
-  specs:
-    CFPropertyList (3.0.3)
-    activesupport (5.2.6)
-      concurrent-ruby (~> 1.0, >= 1.0.2)
-      i18n (>= 0.7, < 2)
-      minitest (~> 5.1)
-      tzinfo (~> 1.1)
-    addressable (2.8.0)
-      public_suffix (>= 2.0.2, < 5.0)
-    algoliasearch (1.27.5)
-      httpclient (~> 2.8, >= 2.8.3)
-      json (>= 1.5.1)
-    atomos (0.1.3)
-    claide (1.0.3)
-    cocoapods (1.10.2)
-      addressable (~> 2.6)
-      claide (>= 1.0.2, < 2.0)
-      cocoapods-core (= 1.10.2)
-      cocoapods-deintegrate (>= 1.0.3, < 2.0)
-      cocoapods-downloader (>= 1.4.0, < 2.0)
-      cocoapods-plugins (>= 1.0.0, < 2.0)
-      cocoapods-search (>= 1.0.0, < 2.0)
-      cocoapods-trunk (>= 1.4.0, < 2.0)
-      cocoapods-try (>= 1.1.0, < 2.0)
-      colored2 (~> 3.1)
-      escape (~> 0.0.4)
-      fourflusher (>= 2.3.0, < 3.0)
-      gh_inspector (~> 1.0)
-      molinillo (~> 0.6.6)
-      nap (~> 1.0)
-      ruby-macho (~> 1.4)
-      xcodeproj (>= 1.19.0, < 2.0)
-    cocoapods-core (1.10.2)
-      activesupport (> 5.0, < 6)
-      addressable (~> 2.6)
-      algoliasearch (~> 1.0)
-      concurrent-ruby (~> 1.1)
-      fuzzy_match (~> 2.0.4)
-      nap (~> 1.0)
-      netrc (~> 0.11)
-      public_suffix
-      typhoeus (~> 1.0)
-    cocoapods-deintegrate (1.0.5)
-    cocoapods-downloader (1.4.0)
-    cocoapods-plugins (1.0.0)
-      nap
-    cocoapods-search (1.0.1)
-    cocoapods-trunk (1.5.0)
-      nap (>= 0.8, < 2.0)
-      netrc (~> 0.11)
-    cocoapods-try (1.2.0)
-    colored2 (3.1.2)
-    concurrent-ruby (1.1.9)
-    escape (0.0.4)
-    ethon (0.14.0)
-      ffi (>= 1.15.0)
-    ffi (1.15.3)
-    fourflusher (2.3.1)
-    fuzzy_match (2.0.4)
-    gh_inspector (1.1.3)
-    httpclient (2.8.3)
-    i18n (1.8.10)
-      concurrent-ruby (~> 1.0)
-    json (2.5.1)
-    minitest (5.11.3)
-    molinillo (0.6.6)
-    nanaimo (0.3.0)
-    nap (1.1.0)
-    netrc (0.11.0)
-    public_suffix (4.0.6)
-    rexml (3.2.5)
-    ruby-macho (1.4.0)
-    thread_safe (0.3.6)
-    typhoeus (1.4.0)
-      ethon (>= 0.9.0)
-    tzinfo (1.2.9)
-      thread_safe (~> 0.1)
-    xcodeproj (1.21.0)
-      CFPropertyList (>= 2.3.3, < 4.0)
-      atomos (~> 0.1.3)
-      claide (>= 1.0.2, < 2.0)
-      colored2 (~> 3.1)
-      nanaimo (~> 0.3.0)
-      rexml (~> 3.2.4)
-
-PLATFORMS
-  ruby
-
-DEPENDENCIES
-  cocoapods (~> 1.10.2)
-  minitest
-
-BUNDLED WITH
-   2.2.22
diff --git a/Tests/CocoaPods/Makefile b/Tests/CocoaPods/Makefile
deleted file mode 100644
index 532dcbff..00000000
--- a/Tests/CocoaPods/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-XCPRETTY := $(shell command -v xcpretty)
-
-test: install repo_update
-	@set -e; \
-	for test in *_test.rb; do \
-		bundle exec ./$$test | $(XCPRETTY) -c; \
-	done
-
-repo_update:
-	@bundle exec pod repo update --silent
-
-install:
-	@bundle install --path gems
-
-.PHONY: test install
diff --git a/Tests/CocoaPods/integration_test.rb b/Tests/CocoaPods/integration_test.rb
deleted file mode 100755
index 67b13385..00000000
--- a/Tests/CocoaPods/integration_test.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/usr/bin/env ruby
-
-require 'cocoapods'
-require 'cocoapods/validator'
-require 'minitest/autorun'
-
-class IntegrationTest < Minitest::Test
-
-  def test_validate_project
-    assert validator.validate, "validation failed: #{validator.failure_reason}"
-  end
-
-  private
-
-  def validator
-    @validator ||= Pod::Validator.new(podspec, ['https://github.com/CocoaPods/Specs.git']).tap do |validator|
-        validator.config.verbose = true
-        validator.no_clean = true
-        validator.use_frameworks = true
-        validator.fail_fast = true
-        validator.local = true
-        validator.allow_warnings = true
-        subspec = ENV['VALIDATOR_SUBSPEC']
-        if subspec == 'none'
-          validator.no_subspecs = true
-        else
-          validator.only_subspec = subspec
-        end
-    end
-  end
-
-  def podspec
-    File.expand_path(File.dirname(__FILE__) + '/../../SQLite.swift.podspec')
-  end
-end
diff --git a/run-tests.sh b/run-tests.sh
index 0a105c41..edc60987 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -7,9 +7,13 @@ if [ -n "$BUILD_SCHEME" ]; then
         make test BUILD_SCHEME="$BUILD_SCHEME"
     fi
 elif [ -n "$VALIDATOR_SUBSPEC" ]; then
-    cd Tests/CocoaPods && make test
+    if [ "$VALIDATOR_SUBSPEC" == "none" ]; then
+      pod lib lint --no-subspecs
+    else
+      pod lib lint --subspec="${VALIDATOR_SUBSPEC}"
+    fi
 elif [ -n "$CARTHAGE_PLATFORM" ]; then
     cd Tests/Carthage && make test CARTHAGE_PLATFORM="$CARTHAGE_PLATFORM"
 elif [ -n "${PACKAGE_MANAGER_COMMAND}" ]; then
-    swift ${PACKAGE_MANAGER_COMMAND}
+    swift "${PACKAGE_MANAGER_COMMAND}"
 fi

From 00b7d3f2eea7a5d98941f88f05c4f9c38eb04654 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 23 Aug 2021 13:51:00 +0200
Subject: [PATCH 418/685] rm obsolete swiftcov

---
 Makefile | 28 ++--------------------------
 1 file changed, 2 insertions(+), 26 deletions(-)

diff --git a/Makefile b/Makefile
index a9d29d58..0b9a1606 100644
--- a/Makefile
+++ b/Makefile
@@ -9,8 +9,6 @@ else
 endif
 
 XCPRETTY := $(shell command -v xcpretty)
-SWIFTCOV := $(shell command -v swiftcov)
-GCOVR := $(shell command -v gcovr)
 TEST_ACTIONS := clean build build-for-testing test-without-building
 
 default: test
@@ -28,36 +26,14 @@ else
 	$(BUILD_TOOL) $(BUILD_ARGUMENTS) $(TEST_ACTIONS)
 endif
 
-coverage:
-ifdef SWIFTCOV
-	$(SWIFTCOV) generate --output coverage \
-		$(BUILD_TOOL) $(BUILD_ARGUMENTS) -configuration Release test \
-		-- ./SQLite/*.swift
-ifdef GCOVR
-	$(GCOVR) \
-		--root . \
-		--use-gcov-files \
-		--html \
-		--html-details \
-		--output coverage/index.html \
-		--keep
-else
-	@echo gcovr must be installed for HTML output: https://github.com/gcovr/gcovr
-endif
-else
-	@echo swiftcov must be installed for coverage: https://github.com/realm/SwiftCov
-	@exit 1
-endif
-
 clean:
 	$(BUILD_TOOL) $(BUILD_ARGUMENTS) clean
-	rm -r coverage
 
 repl:
 	@$(BUILD_TOOL) $(BUILD_ARGUMENTS) -derivedDataPath $(TMPDIR)/SQLite.swift > /dev/null && \
 		swift -F '$(TMPDIR)/SQLite.swift/Build/Products/Debug'
 
 sloc:
-	@zsh -c "grep -vE '^ *//|^$$' SQLite/*/*.{swift,h,m} | wc -l"
+	@zsh -c "grep -vE '^ *//|^$$' Sources/**/*.{swift,h,m} | wc -l"
 
-.PHONY: test coverage clean repl sloc
+.PHONY: test clean repl sloc

From 325cfd9480f59a280f4bfe64eb05b1b9288a6402 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 23 Aug 2021 14:00:42 +0200
Subject: [PATCH 419/685] Unquote

---
 run-tests.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/run-tests.sh b/run-tests.sh
index edc60987..1ae7a5ca 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -15,5 +15,5 @@ elif [ -n "$VALIDATOR_SUBSPEC" ]; then
 elif [ -n "$CARTHAGE_PLATFORM" ]; then
     cd Tests/Carthage && make test CARTHAGE_PLATFORM="$CARTHAGE_PLATFORM"
 elif [ -n "${PACKAGE_MANAGER_COMMAND}" ]; then
-    swift "${PACKAGE_MANAGER_COMMAND}"
+    swift ${PACKAGE_MANAGER_COMMAND}
 fi

From 05c84149a49ff2c41b3f15c1f971b736985c9553 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 23 Aug 2021 14:12:21 +0200
Subject: [PATCH 420/685] Treat warnings as errors

---
 SQLite.xcodeproj/project.pbxproj | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 3b5428d0..ea7ab871 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -231,8 +231,8 @@
 		19A17B93B48B5560E6E51791 /* Fixtures.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Fixtures.swift; sourceTree = "<group>"; };
 		19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAndTimeFunctions.swift; sourceTree = "<group>"; };
 		19A17E2695737FAB5D6086E3 /* fixtures */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = folder; path = fixtures; sourceTree = "<group>"; };
-		3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomAggregationTests.swift; sourceTree = "<group>"; };
 		19A17EA3A313F129011B3FA0 /* Release.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Release.md; sourceTree = "<group>"; };
+		3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomAggregationTests.swift; sourceTree = "<group>"; };
 		3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.0.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
 		3DDC112E26CDBA0200CE369F /* SQLiteObjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SQLiteObjc.h; path = ../SQLiteObjc/include/SQLiteObjc.h; sourceTree = "<group>"; };
 		49EB68C31F7B3CB400D89D40 /* Coding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coding.swift; sourceTree = "<group>"; };
@@ -1042,6 +1042,7 @@
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@@ -1049,6 +1050,7 @@
 				PRODUCT_NAME = SQLite;
 				SDKROOT = appletvos;
 				SKIP_INSTALL = YES;
+				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
 				TVOS_DEPLOYMENT_TARGET = 12.0;
 			};
 			name = Debug;
@@ -1062,6 +1064,7 @@
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@@ -1069,6 +1072,7 @@
 				PRODUCT_NAME = SQLite;
 				SDKROOT = appletvos;
 				SKIP_INSTALL = YES;
+				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
 				TVOS_DEPLOYMENT_TARGET = 12.0;
 			};
 			name = Release;
@@ -1076,11 +1080,13 @@
 		03A65E6D1C6BB0F60062603F /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = appletvos;
+				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
 				TVOS_DEPLOYMENT_TARGET = 12.0;
 			};
 			name = Debug;
@@ -1088,11 +1094,13 @@
 		03A65E6E1C6BB0F60062603F /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = appletvos;
+				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
 				TVOS_DEPLOYMENT_TARGET = 12.0;
 			};
 			name = Release;
@@ -1107,6 +1115,7 @@
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@@ -1114,6 +1123,7 @@
 				PRODUCT_NAME = SQLite;
 				SDKROOT = watchos;
 				SKIP_INSTALL = YES;
+				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
 				TARGETED_DEVICE_FAMILY = 4;
 				WATCHOS_DEPLOYMENT_TARGET = 3.0;
 			};
@@ -1129,6 +1139,7 @@
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@@ -1136,6 +1147,7 @@
 				PRODUCT_NAME = SQLite;
 				SDKROOT = watchos;
 				SKIP_INSTALL = YES;
+				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
 				TARGETED_DEVICE_FAMILY = 4;
 				WATCHOS_DEPLOYMENT_TARGET = 3.0;
 			};
@@ -1271,6 +1283,7 @@
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
@@ -1280,6 +1293,7 @@
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
 			};
 			name = Debug;
 		};
@@ -1293,6 +1307,7 @@
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
@@ -1301,26 +1316,31 @@
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
+				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
 			};
 			name = Release;
 		};
 		EE247AEB1C3F04ED00AE3E12 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
 			};
 			name = Debug;
 		};
 		EE247AEC1C3F04ED00AE3E12 /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
 			};
 			name = Release;
 		};
@@ -1335,6 +1355,7 @@
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				FRAMEWORK_VERSION = A;
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
@@ -1343,6 +1364,7 @@
 				SDKROOT = macosx;
 				SKIP_INSTALL = YES;
 				SWIFT_INCLUDE_PATHS = "";
+				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
 			};
 			name = Debug;
 		};
@@ -1357,6 +1379,7 @@
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				FRAMEWORK_VERSION = A;
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
@@ -1365,6 +1388,7 @@
 				SDKROOT = macosx;
 				SKIP_INSTALL = YES;
 				SWIFT_INCLUDE_PATHS = "";
+				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
 			};
 			name = Release;
 		};
@@ -1373,11 +1397,13 @@
 			buildSettings = {
 				CODE_SIGN_IDENTITY = "-";
 				COMBINE_HIDPI_IMAGES = YES;
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = macosx;
+				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
 			};
 			name = Debug;
 		};
@@ -1386,11 +1412,13 @@
 			buildSettings = {
 				CODE_SIGN_IDENTITY = "-";
 				COMBINE_HIDPI_IMAGES = YES;
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = macosx;
+				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
 			};
 			name = Release;
 		};

From fdac6551b06350181904eab08a0be0a4be4a2160 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 23 Aug 2021 14:13:58 +0200
Subject: [PATCH 421/685] fail fast

---
 run-tests.sh | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/run-tests.sh b/run-tests.sh
index 1ae7a5ca..32465388 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -8,9 +8,9 @@ if [ -n "$BUILD_SCHEME" ]; then
     fi
 elif [ -n "$VALIDATOR_SUBSPEC" ]; then
     if [ "$VALIDATOR_SUBSPEC" == "none" ]; then
-      pod lib lint --no-subspecs
+      pod lib lint --no-subspecs --fail-fast
     else
-      pod lib lint --subspec="${VALIDATOR_SUBSPEC}"
+      pod lib lint --subspec="${VALIDATOR_SUBSPEC}" --fail-fast
     fi
 elif [ -n "$CARTHAGE_PLATFORM" ]; then
     cd Tests/Carthage && make test CARTHAGE_PLATFORM="$CARTHAGE_PLATFORM"

From 6d5bb0ca1d561589cbcf5ffbacd154e5c05659cf Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 23 Aug 2021 14:52:47 +0200
Subject: [PATCH 422/685] Initialize pointer

---
 Sources/SQLite/Typed/CustomFunctions.swift     | 2 +-
 Tests/SQLiteTests/CustomAggregationTests.swift | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/Sources/SQLite/Typed/CustomFunctions.swift b/Sources/SQLite/Typed/CustomFunctions.swift
index 1d66d075..c38113d1 100644
--- a/Sources/SQLite/Typed/CustomFunctions.swift
+++ b/Sources/SQLite/Typed/CustomFunctions.swift
@@ -217,7 +217,7 @@ public extension Connection {
 
         let state: () -> UnsafeMutablePointer<T> = {
             let pointer = UnsafeMutablePointer<T>.allocate(capacity: 1)
-            pointer.pointee = initialValue
+            pointer.initialize(to: initialValue)
             return pointer
         }
 
diff --git a/Tests/SQLiteTests/CustomAggregationTests.swift b/Tests/SQLiteTests/CustomAggregationTests.swift
index 337a5aa8..d4569eef 100644
--- a/Tests/SQLiteTests/CustomAggregationTests.swift
+++ b/Tests/SQLiteTests/CustomAggregationTests.swift
@@ -105,6 +105,7 @@ class CustomAggregationTests: SQLiteTestCase {
         }
         db.createAggregation("myReduceSUM3", initialValue: initial, reduce: reduce, result: { $0 })
         let result = try! db.prepare("SELECT myReduceSUM3(email) AS s FROM users")
+
         let i = result.columnNames.firstIndex(of: "s")!
         for row in result {
             let value = row[i] as? String

From 9bfc767ce660df89eaacd35e2ff23c8465c3ac3b Mon Sep 17 00:00:00 2001
From: Nathan <contact@nathanfallet.me>
Date: Tue, 24 Aug 2021 10:36:16 +0200
Subject: [PATCH 423/685] Triggering GitHub Actions workflow


From 7ec7a266bf3cc071db3a6dbdb2c1628ebf3e212c Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 24 Aug 2021 17:49:52 +0200
Subject: [PATCH 424/685] Fix truncated strings in function

Closes #468
---
 Sources/SQLite/Core/Connection.swift         | 2 +-
 Tests/SQLiteTests/CustomFunctionsTests.swift | 9 +++++++++
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index fa086181..b2bc2cbd 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -616,7 +616,7 @@ public final class Connection {
             } else if let result = result as? Int64 {
                 sqlite3_result_int64(context, result)
             } else if let result = result as? String {
-                sqlite3_result_text(context, result, Int32(result.count), SQLITE_TRANSIENT)
+                sqlite3_result_text(context, result, Int32(result.lengthOfBytes(using: .utf8)), SQLITE_TRANSIENT)
             } else if result == nil {
                 sqlite3_result_null(context)
             } else {
diff --git a/Tests/SQLiteTests/CustomFunctionsTests.swift b/Tests/SQLiteTests/CustomFunctionsTests.swift
index af1ef110..8e702e9c 100644
--- a/Tests/SQLiteTests/CustomFunctionsTests.swift
+++ b/Tests/SQLiteTests/CustomFunctionsTests.swift
@@ -135,3 +135,12 @@ class CustomFunctionWithTwoArgsTests: SQLiteTestCase {
         XCTAssertEqual("ab", result)
     }
 }
+
+class CustomFunctionTruncation: SQLiteTestCase {
+    // https://github.com/stephencelis/SQLite.swift/issues/468
+    func testStringTruncation() {
+        _ = try! db.createFunction("customLower") { (value: String) in value.lowercased() }
+        let result = try! db.prepare("SELECT customLower(?)").scalar("TÖL-AA 12") as? String
+        XCTAssertEqual("töl-aa 12", result)
+    }
+}

From 4b4dc65997c1fce4735178c7563285b988133c6a Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 25 Aug 2021 10:53:04 +0200
Subject: [PATCH 425/685] Make reference to libsqlite3.tbd non-version specific
 on macOS

https://github.com/stephencelis/SQLite.swift/pull/846
---
 SQLite.xcodeproj/project.pbxproj | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index ea7ab871..fcdb521c 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -286,7 +286,7 @@
 		EE247B911C3F822500AE3E12 /* installation@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "installation@2x.png"; sourceTree = "<group>"; };
 		EE247B921C3F822600AE3E12 /* playground@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "playground@2x.png"; sourceTree = "<group>"; };
 		EE247B931C3F826100AE3E12 /* SQLite.swift.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; path = SQLite.swift.podspec; sourceTree = "<group>"; };
-		EE9180911C46E9D30038162A /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
+		EE9180911C46E9D30038162A /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
 		EE9180931C46EA210038162A /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; };
 /* End PBXFileReference section */
 

From be6bed351703b1e4c054e7ef403a50ca8de53e91 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 25 Aug 2021 11:06:07 +0200
Subject: [PATCH 426/685] Renamed

---
 Documentation/Index.md | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 5cc678a6..fce068a2 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -262,10 +262,8 @@ If you have bundled it in your application, you can use FileManager to copy it t
 
 ```swift
 func copyDatabaseIfNeeded(sourcePath: String) -> Bool {
-    let path = NSSearchPathForDirectoriesInDomains(
-        .documentDirectory, .userDomainMask, true
-    ).first!
-    let destinationPath = destinationPath + "/db.sqlite3"
+    let documents = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
+    let destinationPath = documents + "/db.sqlite3"
     let exists = FileManager.default.fileExists(atPath: destinationPath)
     guard !exists else { return false }
     do {

From 03823fb0ccf57628db29d8644b1e09d0bb6cc2f8 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 25 Aug 2021 12:44:22 +0200
Subject: [PATCH 427/685] Add Linux tests

Closes #1064
---
 .github/workflows/build.yml                   | 10 ++++++++
 Documentation/Linux.md                        | 24 +++++++++++++++++++
 SQLite.xcodeproj/project.pbxproj              |  2 ++
 Sources/SQLite/Core/Connection.swift          | 16 ++++++++++---
 Tests/LinuxMain.swift                         |  6 -----
 Tests/SQLiteTests/ConnectionTests.swift       |  3 +++
 .../SQLiteTests/CustomAggregationTests.swift  |  4 ++++
 Tests/SQLiteTests/CustomFunctionsTests.swift  |  5 ++++
 Tests/SQLiteTests/QueryTests.swift            |  2 ++
 9 files changed, 63 insertions(+), 9 deletions(-)
 create mode 100644 Documentation/Linux.md
 delete mode 100644 Tests/LinuxMain.swift

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index af6666ba..51654fba 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -61,3 +61,13 @@ jobs:
       env:
         CARTHAGE_PLATFORM: tvOS
       run: ./run-tests.sh
+  build-linux:
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v2
+    - name: Install
+      run: |
+        sudo apt-get update -qq
+        sudo apt-get install -y libsqlite3-dev
+    - name: Test
+      run: swift test
diff --git a/Documentation/Linux.md b/Documentation/Linux.md
new file mode 100644
index 00000000..19189c53
--- /dev/null
+++ b/Documentation/Linux.md
@@ -0,0 +1,24 @@
+# Linux
+
+## Debugging
+
+### Create and launch docker container
+
+```shell
+$ docker container create swift:focal
+$ docker run --cap-add=SYS_PTRACE \
+  --security-opt seccomp=unconfined \
+  --security-opt apparmor=unconfined \
+  -i -t swift:focal bash
+```
+
+### Compile and run tests in debugger
+
+```shell
+$ apt-get update && apt-get install libsqlite3-dev
+$ git clone https://github.com/stephencelis/SQLite.swift.git
+$ swift test
+$ lldb .build/x86_64-unknown-linux-gnu/debug/SQLite.swiftPackageTests.xctest
+(lldb) target create ".build/x86_64-unknown-linux-gnu/debug/SQLite.swiftPackageTests.xctest"
+(lldb) run
+```
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index fcdb521c..6aff8045 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -227,6 +227,7 @@
 		19A17399EA9E61235D5D77BF /* CipherTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CipherTests.swift; sourceTree = "<group>"; };
 		19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RowTests.swift; sourceTree = "<group>"; };
 		19A178A39ACA9667A62663CC /* Cipher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cipher.swift; sourceTree = "<group>"; };
+		19A1794B7972D14330A65BBD /* Linux.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Linux.md; sourceTree = "<group>"; };
 		19A1794CC4D7827E997E32A7 /* FoundationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationTests.swift; sourceTree = "<group>"; };
 		19A17B93B48B5560E6E51791 /* Fixtures.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Fixtures.swift; sourceTree = "<group>"; };
 		19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAndTimeFunctions.swift; sourceTree = "<group>"; };
@@ -498,6 +499,7 @@
 				EE247B8F1C3F822500AE3E12 /* Index.md */,
 				EE247B901C3F822500AE3E12 /* Resources */,
 				19A17EA3A313F129011B3FA0 /* Release.md */,
+				19A1794B7972D14330A65BBD /* Linux.md */,
 			);
 			path = Documentation;
 			sourceTree = "<group>";
diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index b2bc2cbd..39f19a5c 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -629,12 +629,22 @@ public final class Connection {
             flags |= SQLITE_DETERMINISTIC
         }
         #endif
-        sqlite3_create_function_v2(handle, function, Int32(argc), flags,
-                                   unsafeBitCast(box, to: UnsafeMutableRawPointer.self), { context, argc, value in
+        let resultCode = sqlite3_create_function_v2(handle,
+                                                    function,
+                                                    Int32(argc),
+                                                    flags,
+                                                    unsafeBitCast(box, to: UnsafeMutableRawPointer.self), { context, argc, value in
             let function = unsafeBitCast(sqlite3_user_data(context), to: Function.self)
             function(context, argc, value)
         }, nil, nil, nil)
-        if functions[function] == nil { functions[function] = [:] }
+
+        if let result = Result(errorCode: resultCode, connection: self, statement: nil) {
+            fatalError("Error creating function: \(result)")
+        }
+
+        if functions[function] == nil {
+            functions[function] = [:] // fails on Linux, https://bugs.swift.org/browse/SR-4429
+        }
         functions[function]?[argc] = box
     }
 
diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift
deleted file mode 100644
index 59796fde..00000000
--- a/Tests/LinuxMain.swift
+++ /dev/null
@@ -1,6 +0,0 @@
-import XCTest
-@testable import SQLiteTests
-
-XCTMain([
-testCase([
-])])
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index 37b765ab..6c4d170a 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -343,6 +343,8 @@ class ConnectionTests: SQLiteTestCase {
         }
     }
 
+    // https://bugs.swift.org/browse/SR-4429
+    #if !os(Linux)
     func test_createFunction_withArrayArguments() {
         db.createFunction("hello") { $0[0].map { "Hello, \($0)!" } }
 
@@ -390,6 +392,7 @@ class ConnectionTests: SQLiteTestCase {
             }
         }
     }
+    #endif
 
     func test_concurrent_access_single_connection() {
         // test can fail on iOS/tvOS 9.x: SQLite compile-time differences?
diff --git a/Tests/SQLiteTests/CustomAggregationTests.swift b/Tests/SQLiteTests/CustomAggregationTests.swift
index d4569eef..142d5d6e 100644
--- a/Tests/SQLiteTests/CustomAggregationTests.swift
+++ b/Tests/SQLiteTests/CustomAggregationTests.swift
@@ -13,6 +13,9 @@ import CSQLite
 import SQLite3
 #endif
 
+// https://bugs.swift.org/browse/SR-4429
+#if !os(Linux)
+
 class CustomAggregationTests: SQLiteTestCase {
     override func setUp() {
         super.setUp()
@@ -139,6 +142,7 @@ class CustomAggregationTests: SQLiteTestCase {
         XCTAssertEqual(TestObject.deinits, 3) // the initial value is still retained by the aggregate's state block, so deinits is one less than inits
     }
 }
+#endif
 
 /// This class is used to test that aggregation state variables
 /// can be reference types and are properly memory managed when
diff --git a/Tests/SQLiteTests/CustomFunctionsTests.swift b/Tests/SQLiteTests/CustomFunctionsTests.swift
index 8e702e9c..caa48acd 100644
--- a/Tests/SQLiteTests/CustomFunctionsTests.swift
+++ b/Tests/SQLiteTests/CustomFunctionsTests.swift
@@ -1,6 +1,9 @@
 import XCTest
 import SQLite
 
+// https://bugs.swift.org/browse/SR-4429
+#if !os(Linux)
+
 class CustomFunctionNoArgsTests: SQLiteTestCase {
     typealias FunctionNoOptional              = ()  -> Expression<String>
     typealias FunctionResultOptional          = ()  -> Expression<String?>
@@ -144,3 +147,5 @@ class CustomFunctionTruncation: SQLiteTestCase {
         XCTAssertEqual("töl-aa 12", result)
     }
 }
+
+#endif
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index 3a58e2fc..c80dd0c7 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -290,6 +290,7 @@ class QueryTests: XCTestCase {
         )
     }
 
+    #if !os(Linux) // depends on exact JSON serialization
     func test_insert_encodable_with_nested_encodable() throws {
         let emails = Table("emails")
         let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
@@ -307,6 +308,7 @@ class QueryTests: XCTestCase {
             insert
         )
     }
+    #endif
 
     func test_upsert_withOnConflict_compilesInsertOrOnConflictExpression() {
         assertSQL(

From 7d95523caa831ac0c59c98dd5cbe49675dc74a25 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 25 Aug 2021 15:50:03 +0200
Subject: [PATCH 428/685] Link to GH issue

---
 Sources/SQLite/Core/Connection.swift           | 2 +-
 Tests/SQLiteTests/ConnectionTests.swift        | 2 +-
 Tests/SQLiteTests/CustomAggregationTests.swift | 2 +-
 Tests/SQLiteTests/CustomFunctionsTests.swift   | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 39f19a5c..2c8c408c 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -643,7 +643,7 @@ public final class Connection {
         }
 
         if functions[function] == nil {
-            functions[function] = [:] // fails on Linux, https://bugs.swift.org/browse/SR-4429
+            functions[function] = [:] // fails on Linux, https://github.com/stephencelis/SQLite.swift/issues/1071
         }
         functions[function]?[argc] = box
     }
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index 6c4d170a..5bc4d42f 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -343,7 +343,7 @@ class ConnectionTests: SQLiteTestCase {
         }
     }
 
-    // https://bugs.swift.org/browse/SR-4429
+    // https://github.com/stephencelis/SQLite.swift/issues/1071
     #if !os(Linux)
     func test_createFunction_withArrayArguments() {
         db.createFunction("hello") { $0[0].map { "Hello, \($0)!" } }
diff --git a/Tests/SQLiteTests/CustomAggregationTests.swift b/Tests/SQLiteTests/CustomAggregationTests.swift
index 142d5d6e..d5232260 100644
--- a/Tests/SQLiteTests/CustomAggregationTests.swift
+++ b/Tests/SQLiteTests/CustomAggregationTests.swift
@@ -13,7 +13,7 @@ import CSQLite
 import SQLite3
 #endif
 
-// https://bugs.swift.org/browse/SR-4429
+// https://github.com/stephencelis/SQLite.swift/issues/1071
 #if !os(Linux)
 
 class CustomAggregationTests: SQLiteTestCase {
diff --git a/Tests/SQLiteTests/CustomFunctionsTests.swift b/Tests/SQLiteTests/CustomFunctionsTests.swift
index caa48acd..3d897f8e 100644
--- a/Tests/SQLiteTests/CustomFunctionsTests.swift
+++ b/Tests/SQLiteTests/CustomFunctionsTests.swift
@@ -1,7 +1,7 @@
 import XCTest
 import SQLite
 
-// https://bugs.swift.org/browse/SR-4429
+// https://github.com/stephencelis/SQLite.swift/issues/1071
 #if !os(Linux)
 
 class CustomFunctionNoArgsTests: SQLiteTestCase {

From 5e5ba530c064f93cff583923ae2455f0aaa67d15 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 25 Aug 2021 16:00:59 +0200
Subject: [PATCH 429/685] Link to Linux doc

---
 Documentation/Linux.md | 5 +++++
 README.md              | 1 +
 2 files changed, 6 insertions(+)

diff --git a/Documentation/Linux.md b/Documentation/Linux.md
index 19189c53..c9e85254 100644
--- a/Documentation/Linux.md
+++ b/Documentation/Linux.md
@@ -1,5 +1,10 @@
 # Linux
 
+## Limitations
+
+* Custom functions are currently not supported and crash, caused by a bug in Swift.
+See [#1071](https://github.com/stephencelis/SQLite.swift/issues/1071).
+
 ## Debugging
 
 ### Create and launch docker container
diff --git a/README.md b/README.md
index ac044dc0..9242b200 100644
--- a/README.md
+++ b/README.md
@@ -19,6 +19,7 @@ syntax _and_ intent.
  - [Well-documented][See Documentation]
  - Extensively tested
  - [SQLCipher][] support via CocoaPods
+ - Works on [Linux](Documentation/Linux.md) (with some limitations)
  - Active support at
    [StackOverflow](https://stackoverflow.com/questions/tagged/sqlite.swift),
    and [Gitter Chat Room](https://gitter.im/stephencelis/SQLite.swift)

From 0dd440cfefa79f9088547a0b5ee440736de87bf7 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 25 Aug 2021 16:04:47 +0200
Subject: [PATCH 430/685] FTS5

---
 Documentation/Linux.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/Linux.md b/Documentation/Linux.md
index c9e85254..640ced6f 100644
--- a/Documentation/Linux.md
+++ b/Documentation/Linux.md
@@ -4,6 +4,7 @@
 
 * Custom functions are currently not supported and crash, caused by a bug in Swift.
 See [#1071](https://github.com/stephencelis/SQLite.swift/issues/1071).
+* FTS5 might not work, see [#1007](https://github.com/stephencelis/SQLite.swift/issues/1007)
 
 ## Debugging
 

From 8583eb66469d69cc8e003d18ac5d8a5391bc14c6 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 25 Aug 2021 18:37:19 +0200
Subject: [PATCH 431/685] Closes #285

---
 SQLite.xcodeproj/project.pbxproj              |   8 +
 Tests/SQLiteTests/QueryIntegrationTests.swift | 222 ++++++++++++++++++
 Tests/SQLiteTests/QueryTests.swift            | 203 ----------------
 3 files changed, 230 insertions(+), 203 deletions(-)
 create mode 100644 Tests/SQLiteTests/QueryIntegrationTests.swift

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 6aff8045..6efd3a47 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -52,6 +52,7 @@
 		19A171F12AB8B07F2FD7201A /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
 		19A1720B67ED13E6150C6A3D /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */; };
 		19A17254FBA7894891F7297B /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
+		19A172A9B536D02D4A98AAAD /* QueryIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */; };
 		19A172EB202970561E5C4245 /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */; };
 		19A173668D948AD4DF1F5352 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
 		19A1737286A74F3CF7412906 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
@@ -60,6 +61,7 @@
 		19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
 		19A1750CEE9B05267995CF3D /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
 		19A175DFF47B84757E547C62 /* fixtures in Resources */ = {isa = PBXBuildFile; fileRef = 19A17E2695737FAB5D6086E3 /* fixtures */; };
+		19A176406BDE9D9C80CC9FA3 /* QueryIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */; };
 		19A1769C1F3A7542BECF50FF /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */; };
 		19A177CC33F2E6A24AF90B02 /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
 		19A178072B371489E6A1E839 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
@@ -71,6 +73,7 @@
 		19A179E76EA6207669B60C1B /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
 		19A17C4B951CB054EE48AB1C /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
 		19A17C80076860CF7751A056 /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */; };
+		19A17CB808ACF606726E77A8 /* QueryIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */; };
 		19A17DC282E36C4F41AA440B /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
 		19A17E04C4C0956715C5676A /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
 		19A17E29278A12BC4F542506 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
@@ -231,6 +234,7 @@
 		19A1794CC4D7827E997E32A7 /* FoundationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationTests.swift; sourceTree = "<group>"; };
 		19A17B93B48B5560E6E51791 /* Fixtures.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Fixtures.swift; sourceTree = "<group>"; };
 		19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAndTimeFunctions.swift; sourceTree = "<group>"; };
+		19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryIntegrationTests.swift; sourceTree = "<group>"; };
 		19A17E2695737FAB5D6086E3 /* fixtures */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = folder; path = fixtures; sourceTree = "<group>"; };
 		19A17EA3A313F129011B3FA0 /* Release.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Release.md; sourceTree = "<group>"; };
 		3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomAggregationTests.swift; sourceTree = "<group>"; };
@@ -430,6 +434,7 @@
 				19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */,
 				19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */,
 				D4DB368A20C09C9B00D5A58E /* SelectTests.swift */,
+				19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */,
 			);
 			name = SQLiteTests;
 			path = Tests/SQLiteTests;
@@ -861,6 +866,7 @@
 				19A1785195182AF8731A8BDA /* RowTests.swift in Sources */,
 				19A1769C1F3A7542BECF50FF /* DateAndTimeFunctionTests.swift in Sources */,
 				D4DB368E20C09CFD00D5A58E /* SelectTests.swift in Sources */,
+				19A17CB808ACF606726E77A8 /* QueryIntegrationTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -951,6 +957,7 @@
 				19A1720B67ED13E6150C6A3D /* RowTests.swift in Sources */,
 				19A17C80076860CF7751A056 /* DateAndTimeFunctionTests.swift in Sources */,
 				D4DB368C20C09CFB00D5A58E /* SelectTests.swift in Sources */,
+				19A172A9B536D02D4A98AAAD /* QueryIntegrationTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1011,6 +1018,7 @@
 				19A171967CC511C4F6F773C9 /* RowTests.swift in Sources */,
 				19A172EB202970561E5C4245 /* DateAndTimeFunctionTests.swift in Sources */,
 				D4DB368D20C09CFC00D5A58E /* SelectTests.swift in Sources */,
+				19A176406BDE9D9C80CC9FA3 /* QueryIntegrationTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/Tests/SQLiteTests/QueryIntegrationTests.swift b/Tests/SQLiteTests/QueryIntegrationTests.swift
new file mode 100644
index 00000000..9f5dc5aa
--- /dev/null
+++ b/Tests/SQLiteTests/QueryIntegrationTests.swift
@@ -0,0 +1,222 @@
+import XCTest
+#if SQLITE_SWIFT_STANDALONE
+import sqlite3
+#elseif SQLITE_SWIFT_SQLCIPHER
+import SQLCipher
+#elseif os(Linux)
+import CSQLite
+#else
+import SQLite3
+#endif
+@testable import SQLite
+
+class QueryIntegrationTests: SQLiteTestCase {
+
+    let id = Expression<Int64>("id")
+    let email = Expression<String>("email")
+    let age = Expression<Int>("age")
+
+    override func setUp() {
+        super.setUp()
+
+        createUsersTable()
+    }
+
+    // MARK: -
+
+    func test_select() {
+        let managerId = Expression<Int64>("manager_id")
+        let managers = users.alias("managers")
+
+        let alice = try! db.run(users.insert(email <- "alice@example.com"))
+        _ = try! db.run(users.insert(email <- "betsy@example.com", managerId <- alice))
+
+        for user in try! db.prepare(users.join(managers, on: managers[id] == users[managerId])) {
+            _ = user[users[managerId]]
+        }
+    }
+
+    func test_prepareRowIterator() {
+        let names = ["a", "b", "c"]
+        try! insertUsers(names)
+
+        let emailColumn = Expression<String>("email")
+        let emails = try! db.prepareRowIterator(users).map { $0[emailColumn] }
+
+        XCTAssertEqual(names.map({ "\($0)@example.com" }), emails.sorted())
+    }
+
+    func test_ambiguousMap() {
+        let names = ["a", "b", "c"]
+        try! insertUsers(names)
+
+        let emails = try! db.prepare("select email from users", []).map { $0[0] as! String  }
+
+        XCTAssertEqual(names.map({ "\($0)@example.com" }), emails.sorted())
+    }
+
+    func test_select_optional() {
+        let managerId = Expression<Int64?>("manager_id")
+        let managers = users.alias("managers")
+
+        let alice = try! db.run(users.insert(email <- "alice@example.com"))
+        _ = try! db.run(users.insert(email <- "betsy@example.com", managerId <- alice))
+
+        for user in try! db.prepare(users.join(managers, on: managers[id] == users[managerId])) {
+            _ = user[users[managerId]]
+        }
+    }
+
+    func test_select_codable() throws {
+        let table = Table("codable")
+        try db.run(table.create { builder in
+            builder.column(Expression<Int>("int"))
+            builder.column(Expression<String>("string"))
+            builder.column(Expression<Bool>("bool"))
+            builder.column(Expression<Double>("float"))
+            builder.column(Expression<Double>("double"))
+            builder.column(Expression<Date>("date"))
+            builder.column(Expression<String?>("optional"))
+            builder.column(Expression<Data>("sub"))
+        })
+
+        let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
+                                 date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+        let value = TestCodable(int: 5, string: "6", bool: true, float: 7, double: 8,
+                                date: Date(timeIntervalSince1970: 5000), optional: "optional", sub: value1)
+
+        try db.run(table.insert(value))
+
+        let rows = try db.prepare(table)
+        let values: [TestCodable] = try rows.map({ try $0.decode() })
+        XCTAssertEqual(values.count, 1)
+        XCTAssertEqual(values[0].int, 5)
+        XCTAssertEqual(values[0].string, "6")
+        XCTAssertEqual(values[0].bool, true)
+        XCTAssertEqual(values[0].float, 7)
+        XCTAssertEqual(values[0].double, 8)
+        XCTAssertEqual(values[0].date, Date(timeIntervalSince1970: 5000))
+        XCTAssertEqual(values[0].optional, "optional")
+        XCTAssertEqual(values[0].sub?.int, 1)
+        XCTAssertEqual(values[0].sub?.string, "2")
+        XCTAssertEqual(values[0].sub?.bool, true)
+        XCTAssertEqual(values[0].sub?.float, 3)
+        XCTAssertEqual(values[0].sub?.double, 4)
+        XCTAssertEqual(values[0].sub?.date, Date(timeIntervalSince1970: 0))
+        XCTAssertNil(values[0].sub?.optional)
+        XCTAssertNil(values[0].sub?.sub)
+    }
+
+    func test_scalar() {
+        XCTAssertEqual(0, try! db.scalar(users.count))
+        XCTAssertEqual(false, try! db.scalar(users.exists))
+
+        try! insertUsers("alice")
+        XCTAssertEqual(1, try! db.scalar(users.select(id.average)))
+    }
+
+    func test_pluck() {
+        let rowid = try! db.run(users.insert(email <- "alice@example.com"))
+        XCTAssertEqual(rowid, try! db.pluck(users)![id])
+    }
+
+    func test_insert() {
+        let id = try! db.run(users.insert(email <- "alice@example.com"))
+        XCTAssertEqual(1, id)
+    }
+
+    func test_insert_many() {
+        let id = try! db.run(users.insertMany([[email <- "alice@example.com"], [email <- "geoff@example.com"]]))
+        XCTAssertEqual(2, id)
+    }
+
+    func test_upsert() throws {
+        guard db.satisfiesMinimumVersion(minor: 24) else { return }
+        let fetchAge = { () throws -> Int? in
+            try self.db.pluck(self.users.filter(self.email == "alice@example.com")).flatMap { $0[self.age] }
+        }
+
+        let id = try db.run(users.upsert(email <- "alice@example.com", age <- 30, onConflictOf: email))
+        XCTAssertEqual(1, id)
+        XCTAssertEqual(30, try fetchAge())
+
+        let nextId = try db.run(users.upsert(email <- "alice@example.com", age <- 42, onConflictOf: email))
+        XCTAssertEqual(1, nextId)
+        XCTAssertEqual(42, try fetchAge())
+    }
+
+    func test_update() {
+        let changes = try! db.run(users.update(email <- "alice@example.com"))
+        XCTAssertEqual(0, changes)
+    }
+
+    func test_delete() {
+        let changes = try! db.run(users.delete())
+        XCTAssertEqual(0, changes)
+    }
+
+    func test_union() throws {
+        let expectedIDs = [
+            try db.run(users.insert(email <- "alice@example.com")),
+            try db.run(users.insert(email <- "sally@example.com"))
+        ]
+
+        let query1 = users.filter(email == "alice@example.com")
+        let query2 = users.filter(email == "sally@example.com")
+
+        let actualIDs = try db.prepare(query1.union(query2)).map { $0[id] }
+        XCTAssertEqual(expectedIDs, actualIDs)
+
+        let query3 = users.select(users[*], Expression<Int>(literal: "1 AS weight")).filter(email == "sally@example.com")
+        let query4 = users.select(users[*], Expression<Int>(literal: "2 AS weight")).filter(email == "alice@example.com")
+
+        print(query3.union(query4).order(Expression<Int>(literal: "weight")).asSQL())
+
+        let orderedIDs = try db.prepare(query3.union(query4).order(Expression<Int>(literal: "weight"), email)).map { $0[id] }
+        XCTAssertEqual(Array(expectedIDs.reversed()), orderedIDs)
+    }
+
+    func test_no_such_column() throws {
+        let doesNotExist = Expression<String>("doesNotExist")
+        try! insertUser("alice")
+        let row = try! db.pluck(users.filter(email == "alice@example.com"))!
+
+        XCTAssertThrowsError(try row.get(doesNotExist)) { error in
+            if case QueryError.noSuchColumn(let name, _) = error {
+                XCTAssertEqual("\"doesNotExist\"", name)
+            } else {
+                XCTFail("unexpected error: \(error)")
+            }
+        }
+    }
+
+    func test_catchConstraintError() {
+        try! db.run(users.insert(email <- "alice@example.com"))
+        do {
+            try db.run(users.insert(email <- "alice@example.com"))
+            XCTFail("expected error")
+        } catch let Result.error(_, code, _) where code == SQLITE_CONSTRAINT {
+            // expected
+        } catch let error {
+            XCTFail("unexpected error: \(error)")
+        }
+    }
+
+    // https://github.com/stephencelis/SQLite.swift/issues/285
+    func test_order_by_random() throws {
+        try insertUsers(["a", "b", "c'"])
+        let result = Array(try db.prepare(users.select(email).order(Expression<Int>.random()).limit(1)))
+        XCTAssertEqual(1, result.count)
+    }
+}
+
+
+private extension Connection {
+    func satisfiesMinimumVersion(minor: Int, patch: Int = 0) -> Bool {
+        guard let version = try? scalar("SELECT sqlite_version()") as? String else { return false }
+        let components = version.split(separator: ".", maxSplits: 3).compactMap { Int($0) }
+        guard components.count == 3 else { return false }
+
+        return components[1] >= minor && components[2] >= patch
+    }
+}
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index c80dd0c7..e0749f2c 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -468,206 +468,3 @@ class QueryTests: XCTestCase {
     }
 
 }
-
-class QueryIntegrationTests: SQLiteTestCase {
-
-    let id = Expression<Int64>("id")
-    let email = Expression<String>("email")
-    let age = Expression<Int>("age")
-
-    override func setUp() {
-        super.setUp()
-
-        createUsersTable()
-    }
-
-    // MARK: -
-
-    func test_select() {
-        let managerId = Expression<Int64>("manager_id")
-        let managers = users.alias("managers")
-
-        let alice = try! db.run(users.insert(email <- "alice@example.com"))
-        _ = try! db.run(users.insert(email <- "betsy@example.com", managerId <- alice))
-
-        for user in try! db.prepare(users.join(managers, on: managers[id] == users[managerId])) {
-            _ = user[users[managerId]]
-        }
-    }
-
-    func test_prepareRowIterator() {
-        let names = ["a", "b", "c"]
-        try! insertUsers(names)
-
-        let emailColumn = Expression<String>("email")
-        let emails = try! db.prepareRowIterator(users).map { $0[emailColumn] }
-
-        XCTAssertEqual(names.map({ "\($0)@example.com" }), emails.sorted())
-    }
-
-    func test_ambiguousMap() {
-        let names = ["a", "b", "c"]
-        try! insertUsers(names)
-
-        let emails = try! db.prepare("select email from users", []).map { $0[0] as! String  }
-
-        XCTAssertEqual(names.map({ "\($0)@example.com" }), emails.sorted())
-    }
-
-    func test_select_optional() {
-        let managerId = Expression<Int64?>("manager_id")
-        let managers = users.alias("managers")
-
-        let alice = try! db.run(users.insert(email <- "alice@example.com"))
-        _ = try! db.run(users.insert(email <- "betsy@example.com", managerId <- alice))
-
-        for user in try! db.prepare(users.join(managers, on: managers[id] == users[managerId])) {
-            _ = user[users[managerId]]
-        }
-    }
-
-    func test_select_codable() throws {
-        let table = Table("codable")
-        try db.run(table.create { builder in
-            builder.column(Expression<Int>("int"))
-            builder.column(Expression<String>("string"))
-            builder.column(Expression<Bool>("bool"))
-            builder.column(Expression<Double>("float"))
-            builder.column(Expression<Double>("double"))
-            builder.column(Expression<Date>("date"))
-            builder.column(Expression<String?>("optional"))
-            builder.column(Expression<Data>("sub"))
-        })
-
-        let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
-                                 date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
-        let value = TestCodable(int: 5, string: "6", bool: true, float: 7, double: 8,
-                                date: Date(timeIntervalSince1970: 5000), optional: "optional", sub: value1)
-
-        try db.run(table.insert(value))
-
-        let rows = try db.prepare(table)
-        let values: [TestCodable] = try rows.map({ try $0.decode() })
-        XCTAssertEqual(values.count, 1)
-        XCTAssertEqual(values[0].int, 5)
-        XCTAssertEqual(values[0].string, "6")
-        XCTAssertEqual(values[0].bool, true)
-        XCTAssertEqual(values[0].float, 7)
-        XCTAssertEqual(values[0].double, 8)
-        XCTAssertEqual(values[0].date, Date(timeIntervalSince1970: 5000))
-        XCTAssertEqual(values[0].optional, "optional")
-        XCTAssertEqual(values[0].sub?.int, 1)
-        XCTAssertEqual(values[0].sub?.string, "2")
-        XCTAssertEqual(values[0].sub?.bool, true)
-        XCTAssertEqual(values[0].sub?.float, 3)
-        XCTAssertEqual(values[0].sub?.double, 4)
-        XCTAssertEqual(values[0].sub?.date, Date(timeIntervalSince1970: 0))
-        XCTAssertNil(values[0].sub?.optional)
-        XCTAssertNil(values[0].sub?.sub)
-    }
-
-    func test_scalar() {
-        XCTAssertEqual(0, try! db.scalar(users.count))
-        XCTAssertEqual(false, try! db.scalar(users.exists))
-
-        try! insertUsers("alice")
-        XCTAssertEqual(1, try! db.scalar(users.select(id.average)))
-    }
-
-    func test_pluck() {
-        let rowid = try! db.run(users.insert(email <- "alice@example.com"))
-        XCTAssertEqual(rowid, try! db.pluck(users)![id])
-    }
-
-    func test_insert() {
-        let id = try! db.run(users.insert(email <- "alice@example.com"))
-        XCTAssertEqual(1, id)
-    }
-
-    func test_insert_many() {
-        let id = try! db.run(users.insertMany([[email <- "alice@example.com"], [email <- "geoff@example.com"]]))
-        XCTAssertEqual(2, id)
-    }
-
-    func test_upsert() throws {
-        guard db.satisfiesMinimumVersion(minor: 24) else { return }
-        let fetchAge = { () throws -> Int? in
-            try self.db.pluck(self.users.filter(self.email == "alice@example.com")).flatMap { $0[self.age] }
-        }
-
-        let id = try db.run(users.upsert(email <- "alice@example.com", age <- 30, onConflictOf: email))
-        XCTAssertEqual(1, id)
-        XCTAssertEqual(30, try fetchAge())
-
-        let nextId = try db.run(users.upsert(email <- "alice@example.com", age <- 42, onConflictOf: email))
-        XCTAssertEqual(1, nextId)
-        XCTAssertEqual(42, try fetchAge())
-    }
-
-    func test_update() {
-        let changes = try! db.run(users.update(email <- "alice@example.com"))
-        XCTAssertEqual(0, changes)
-    }
-
-    func test_delete() {
-        let changes = try! db.run(users.delete())
-        XCTAssertEqual(0, changes)
-    }
-
-    func test_union() throws {
-        let expectedIDs = [
-            try db.run(users.insert(email <- "alice@example.com")),
-            try db.run(users.insert(email <- "sally@example.com"))
-        ]
-
-        let query1 = users.filter(email == "alice@example.com")
-        let query2 = users.filter(email == "sally@example.com")
-
-        let actualIDs = try db.prepare(query1.union(query2)).map { $0[id] }
-        XCTAssertEqual(expectedIDs, actualIDs)
-
-        let query3 = users.select(users[*], Expression<Int>(literal: "1 AS weight")).filter(email == "sally@example.com")
-        let query4 = users.select(users[*], Expression<Int>(literal: "2 AS weight")).filter(email == "alice@example.com")
-
-        print(query3.union(query4).order(Expression<Int>(literal: "weight")).asSQL())
-
-        let orderedIDs = try db.prepare(query3.union(query4).order(Expression<Int>(literal: "weight"), email)).map { $0[id] }
-        XCTAssertEqual(Array(expectedIDs.reversed()), orderedIDs)
-    }
-
-    func test_no_such_column() throws {
-        let doesNotExist = Expression<String>("doesNotExist")
-        try! insertUser("alice")
-        let row = try! db.pluck(users.filter(email == "alice@example.com"))!
-
-        XCTAssertThrowsError(try row.get(doesNotExist)) { error in
-            if case QueryError.noSuchColumn(let name, _) = error {
-                XCTAssertEqual("\"doesNotExist\"", name)
-            } else {
-                XCTFail("unexpected error: \(error)")
-            }
-        }
-    }
-
-    func test_catchConstraintError() {
-        try! db.run(users.insert(email <- "alice@example.com"))
-        do {
-            try db.run(users.insert(email <- "alice@example.com"))
-            XCTFail("expected error")
-        } catch let Result.error(_, code, _) where code == SQLITE_CONSTRAINT {
-            // expected
-        } catch let error {
-            XCTFail("unexpected error: \(error)")
-        }
-    }
-}
-
-private extension Connection {
-    func satisfiesMinimumVersion(minor: Int, patch: Int = 0) -> Bool {
-        guard let version = try? scalar("SELECT sqlite_version()") as? String else { return false }
-        let components = version.split(separator: ".", maxSplits: 3).compactMap { Int($0) }
-        guard components.count == 3 else { return false }
-
-        return components[1] >= minor && components[2] >= patch
-    }
-}

From b94e7a9e453b07c8eea8486d266744e3a8c6751d Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 25 Aug 2021 18:42:45 +0200
Subject: [PATCH 432/685] Lint

---
 Tests/SQLiteTests/QueryIntegrationTests.swift | 1 -
 1 file changed, 1 deletion(-)

diff --git a/Tests/SQLiteTests/QueryIntegrationTests.swift b/Tests/SQLiteTests/QueryIntegrationTests.swift
index 9f5dc5aa..c98b1601 100644
--- a/Tests/SQLiteTests/QueryIntegrationTests.swift
+++ b/Tests/SQLiteTests/QueryIntegrationTests.swift
@@ -210,7 +210,6 @@ class QueryIntegrationTests: SQLiteTestCase {
     }
 }
 
-
 private extension Connection {
     func satisfiesMinimumVersion(minor: Int, patch: Int = 0) -> Bool {
         guard let version = try? scalar("SELECT sqlite_version()") as? String else { return false }

From 723cdc8456cc87ce5dadbc6a25b3f4bbf46275c9 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 25 Aug 2021 18:52:21 +0200
Subject: [PATCH 433/685] Lint fixes, swap param order

---
 SQLite.xcodeproj/project.pbxproj        |  8 +++
 Sources/SQLite/Core/Backup.swift        | 69 ++++++++++++-------------
 Sources/SQLite/Core/Connection.swift    | 50 +++---------------
 Sources/SQLite/Core/Result.swift        | 45 ++++++++++++++++
 Tests/SQLiteTests/ConnectionTests.swift | 10 ++--
 5 files changed, 97 insertions(+), 85 deletions(-)
 create mode 100644 Sources/SQLite/Core/Result.swift

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index fb40791a..b5929023 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -48,6 +48,7 @@
 		03A65E941C6BB3030062603F /* ValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B331C3F142E00AE3E12 /* ValueTests.swift */; };
 		03A65E951C6BB3030062603F /* TestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B161C3F127200AE3E12 /* TestHelpers.swift */; };
 		03A65E971C6BB3210062603F /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 03A65E961C6BB3210062603F /* libsqlite3.tbd */; };
+		19A17073552293CA063BEA66 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17E723300E5ED3771DCB5 /* Result.swift */; };
 		19A1709C3E7A406E62293B2A /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; };
 		19A17152E32A9585831E3FE0 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
 		19A1717B10CC941ACB5533D6 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
@@ -60,6 +61,7 @@
 		19A172EB202970561E5C4245 /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */; };
 		19A173668D948AD4DF1F5352 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
 		19A1737286A74F3CF7412906 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
+		19A173EFEF0B3BD0B3ED406C /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17E723300E5ED3771DCB5 /* Result.swift */; };
 		19A17408007B182F884E3A53 /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; };
 		19A17490543609FCED53CACC /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
 		19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
@@ -82,6 +84,7 @@
 		19A17E04C4C0956715C5676A /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
 		19A17E29278A12BC4F542506 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
 		19A17EC0D68BA8C03288ADF7 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
+		19A17F1B3F0A3C96B5ED6D64 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17E723300E5ED3771DCB5 /* Result.swift */; };
 		19A17F3E1F7ACA33BD43E138 /* fixtures in Resources */ = {isa = PBXBuildFile; fileRef = 19A17E2695737FAB5D6086E3 /* fixtures */; };
 		19A17F60B685636D1F83C2DD /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; };
 		19A17FB80B94E882050AA908 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
@@ -241,6 +244,7 @@
 		19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAndTimeFunctions.swift; sourceTree = "<group>"; };
 		19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryIntegrationTests.swift; sourceTree = "<group>"; };
 		19A17E2695737FAB5D6086E3 /* fixtures */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = folder; path = fixtures; sourceTree = "<group>"; };
+		19A17E723300E5ED3771DCB5 /* Result.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Result.swift; sourceTree = "<group>"; };
 		19A17EA3A313F129011B3FA0 /* Release.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Release.md; sourceTree = "<group>"; };
 		3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomAggregationTests.swift; sourceTree = "<group>"; };
 		3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.0.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
@@ -456,6 +460,7 @@
 				EE247AF31C3F06E900AE3E12 /* Value.swift */,
 				19A1710E73A46D5AC721CDA9 /* Errors.swift */,
 				02A43A9722738CF100FEC494 /* Backup.swift */,
+				19A17E723300E5ED3771DCB5 /* Result.swift */,
 			);
 			path = Core;
 			sourceTree = "<group>";
@@ -843,6 +848,7 @@
 				02A43A9A22738CF100FEC494 /* Backup.swift in Sources */,
 				19A17FF4A10B44D3937C8CAC /* Errors.swift in Sources */,
 				19A1737286A74F3CF7412906 /* DateAndTimeFunctions.swift in Sources */,
+				19A17073552293CA063BEA66 /* Result.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -936,6 +942,7 @@
 				02A43A9822738CF100FEC494 /* Backup.swift in Sources */,
 				19A1792C0520D4E83C2EB075 /* Errors.swift in Sources */,
 				19A17E29278A12BC4F542506 /* DateAndTimeFunctions.swift in Sources */,
+				19A173EFEF0B3BD0B3ED406C /* Result.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -998,6 +1005,7 @@
 				02A43A9922738CF100FEC494 /* Backup.swift in Sources */,
 				19A17490543609FCED53CACC /* Errors.swift in Sources */,
 				19A17152E32A9585831E3FE0 /* DateAndTimeFunctions.swift in Sources */,
+				19A17F1B3F0A3C96B5ED6D64 /* Result.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/Sources/SQLite/Core/Backup.swift b/Sources/SQLite/Core/Backup.swift
index 1ea9637d..84ebf1e0 100644
--- a/Sources/SQLite/Core/Backup.swift
+++ b/Sources/SQLite/Core/Backup.swift
@@ -38,19 +38,19 @@ import SQLite3
 ///
 /// See: <https://www.sqlite.org/backup.html>
 public final class Backup {
-    
+
     /// The name of the database to backup
     public enum DatabaseName {
-        
+
         /// The main database
         case main
-        
+
         /// The temporary database
         case temp
-        
+
         /// A database added to the connection with ATTACH statement
         case attached(name: String)
-        
+
         var name: String {
             switch self {
             case .main:
@@ -62,16 +62,16 @@ public final class Backup {
             }
         }
     }
-    
+
     /// Number of pages to copy while performing a backup step
     public enum Pages {
-        
+
         /// Indicates all remaining pages should be copied
         case all
-        
+
         /// Indicates the maximal number of pages to be copied in single step
         case limited(number: Int32)
-        
+
         var number: Int32 {
             switch self {
             case .all:
@@ -81,63 +81,60 @@ public final class Backup {
             }
         }
     }
-    
+
     /// Total number of pages to copy
     ///
     /// See: <https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backuppagecount>
     public var pageCount: Int32 {
         return handle.map { sqlite3_backup_pagecount($0) } ?? 0
     }
-    
+
     /// Number of remaining pages to copy.
     ///
     /// See: <https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupremaining>
     public var remainingPages: Int32 {
         return handle.map { sqlite3_backup_remaining($0) } ?? 0
     }
-    
+
     private let targetConnection: Connection
     private let sourceConnection: Connection
-    
+
     private var handle: OpaquePointer?
-    
+
     /// Initializes a new SQLite backup.
     ///
     /// - Parameters:
     ///
-    ///   - targetConnection: The connection to the database to save backup into.
-    ///
-    ///   - targetName: The name of the database to save backup into.
-    ///
-    ///     Default: `.main`.
-    ///
     ///   - sourceConnection: The connection to the database to backup.
-    ///
     ///   - sourceName: The name of the database to backup.
-    /// 
+    ///     Default: `.main`.
+    ///
+    ///   - targetConnection: The connection to the database to save backup into.
+    ///   - targetName: The name of the database to save backup into.
     ///     Default: `.main`.
     ///
     /// - Returns: A new database backup.
     ///
     /// See: <https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupinit>
-    public init(targetConnection: Connection,
-                targetName: DatabaseName = .main,
-                sourceConnection: Connection,
-                sourceName: DatabaseName = .main) throws {
-        
+    public init(sourceConnection: Connection,
+                sourceName: DatabaseName = .main,
+                targetConnection: Connection,
+                targetName: DatabaseName = .main) throws {
+
         self.targetConnection = targetConnection
         self.sourceConnection = sourceConnection
-        
+
         self.handle = sqlite3_backup_init(targetConnection.handle,
                                           targetName.name,
                                           sourceConnection.handle,
                                           sourceName.name)
-        
-        if self.handle == nil, let error = Result(errorCode: sqlite3_errcode(targetConnection.handle), connection: targetConnection) {
+
+        if handle == nil, let error = Result(errorCode: sqlite3_errcode(targetConnection.handle),
+                                             connection: targetConnection) {
             throw error
         }
     }
-    
+
     /// Performs a backup step.
     ///
     /// - Parameter pagesToCopy: The maximal number of pages to copy in one step
@@ -147,17 +144,17 @@ public final class Backup {
     /// See: <https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupstep>
     public func step(pagesToCopy pages: Pages = .all) throws {
         let status = sqlite3_backup_step(handle, pages.number)
-        
+
         guard status != SQLITE_DONE else {
             finish()
             return
         }
-        
+
         if let error = Result(errorCode: status, connection: targetConnection) {
             throw error
         }
     }
-    
+
     /// Finalizes backup.
     ///
     /// See: <https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupfinish>
@@ -165,11 +162,11 @@ public final class Backup {
         guard let handle = self.handle else {
             return
         }
-        
+
         sqlite3_backup_finish(handle)
         self.handle = nil
     }
-    
+
     deinit {
         finish()
     }
diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 5e34457c..a9012462 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -790,9 +790,9 @@ public final class Connection {
     }
     fileprivate typealias Collation = @convention(block) (UnsafeRawPointer, UnsafeRawPointer) -> Int32
     fileprivate var collations = [String: Collation]()
-    
+
     // MARK: - Backup
-    
+
     /// Prepares a new backup for current connection.
     ///
     /// - Parameters:
@@ -808,16 +808,14 @@ public final class Connection {
     ///     Default: `.main`.
     ///
     /// - Returns: A new database backup.
-    
+
     public func backup(databaseName: Backup.DatabaseName = .main,
                        usingConnection targetConnection: Connection,
                        andDatabaseName targetDatabaseName: Backup.DatabaseName = .main) throws -> Backup {
-        return try Backup(targetConnection: targetConnection,
-                          targetName: targetDatabaseName,
-                          sourceConnection: self,
-                          sourceName: databaseName)
+        try Backup(sourceConnection: self, sourceName: databaseName, targetConnection: targetConnection,
+                   targetName: targetDatabaseName)
     }
-    
+
     // MARK: - Error Handling
 
     func sync<T>(_ block: () throws -> T) rethrows -> T {
@@ -866,39 +864,3 @@ extension Connection.Location: CustomStringConvertible {
     }
 
 }
-
-public enum Result: Error {
-
-    fileprivate static let successCodes: Set = [SQLITE_OK, SQLITE_ROW, SQLITE_DONE]
-
-    /// Represents a SQLite specific [error code](https://sqlite.org/rescode.html)
-    ///
-    /// - message: English-language text that describes the error
-    ///
-    /// - code: SQLite [error code](https://sqlite.org/rescode.html#primary_result_code_list)
-    ///
-    /// - statement: the statement which produced the error
-    case error(message: String, code: Int32, statement: Statement?)
-
-    init?(errorCode: Int32, connection: Connection, statement: Statement? = nil) {
-        guard !Result.successCodes.contains(errorCode) else { return nil }
-
-        let message = String(cString: sqlite3_errmsg(connection.handle))
-        self = .error(message: message, code: errorCode, statement: statement)
-    }
-
-}
-
-extension Result: CustomStringConvertible {
-
-    public var description: String {
-        switch self {
-        case let .error(message, errorCode, statement):
-            if let statement = statement {
-                return "\(message) (\(statement)) (code: \(errorCode))"
-            } else {
-                return "\(message) (code: \(errorCode))"
-            }
-        }
-    }
-}
diff --git a/Sources/SQLite/Core/Result.swift b/Sources/SQLite/Core/Result.swift
new file mode 100644
index 00000000..3de4d25d
--- /dev/null
+++ b/Sources/SQLite/Core/Result.swift
@@ -0,0 +1,45 @@
+#if SQLITE_SWIFT_STANDALONE
+import sqlite3
+#elseif SQLITE_SWIFT_SQLCIPHER
+import SQLCipher
+#elseif os(Linux)
+import CSQLite
+#else
+import SQLite3
+#endif
+
+public enum Result: Error {
+
+    fileprivate static let successCodes: Set = [SQLITE_OK, SQLITE_ROW, SQLITE_DONE]
+
+    /// Represents a SQLite specific [error code](https://sqlite.org/rescode.html)
+    ///
+    /// - message: English-language text that describes the error
+    ///
+    /// - code: SQLite [error code](https://sqlite.org/rescode.html#primary_result_code_list)
+    ///
+    /// - statement: the statement which produced the error
+    case error(message: String, code: Int32, statement: Statement?)
+
+    init?(errorCode: Int32, connection: Connection, statement: Statement? = nil) {
+        guard !Result.successCodes.contains(errorCode) else { return nil }
+
+        let message = String(cString: sqlite3_errmsg(connection.handle))
+        self = .error(message: message, code: errorCode, statement: statement)
+    }
+
+}
+
+extension Result: CustomStringConvertible {
+
+    public var description: String {
+        switch self {
+        case let .error(message, errorCode, statement):
+            if let statement = statement {
+                return "\(message) (\(statement)) (code: \(errorCode))"
+            } else {
+                return "\(message) (code: \(errorCode))"
+            }
+        }
+    }
+}
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index 1cb70732..ae881289 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -147,15 +147,15 @@ class ConnectionTests: SQLiteTestCase {
 
         assertSQL("BEGIN EXCLUSIVE TRANSACTION")
     }
-    
+
     func test_backup_copiesDatabase() throws {
         let target = try Connection()
-        
-        try InsertUsers("alice", "betsy")
-        
+
+        try insertUsers("alice", "betsy")
+
         let backup = try db.backup(usingConnection: target)
         try backup.step()
-        
+
         let users = try target.prepare("SELECT email FROM users ORDER BY email")
         XCTAssertEqual(users.map { $0[0] as? String }, ["alice@example.com", "betsy@example.com"])
     }

From bcbfe980c789f73de1fe8486d78f82fda67b95b5 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 25 Aug 2021 18:56:02 +0200
Subject: [PATCH 434/685] Update changelog

---
 CHANGELOG.md | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 465438bc..fc09fa40 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+0.13.1 (tba)
+========================================
+
+* Support for database backup ([#919][])
+* Support for custom SQL aggregates ([#881][])
+
 0.13.0 (22-08-2021), [diff][diff-0.13.0]
 ========================================
 
@@ -116,3 +122,5 @@
 [#726]: https://github.com/stephencelis/SQLite.swift/pull/726
 [#797]: https://github.com/stephencelis/SQLite.swift/pull/797
 [#866]: https://github.com/stephencelis/SQLite.swift/pull/866
+[#881]: https://github.com/stephencelis/SQLite.swift/pull/881
+[#919]: https://github.com/stephencelis/SQLite.swift/pull/919

From 2ae7b9b61dfdc7e593108f8048ba19da5b51d656 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 25 Aug 2021 19:46:58 +0200
Subject: [PATCH 435/685] Missing target

---
 SQLite.xcodeproj/project.pbxproj | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index b5929023..b30c18d2 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -81,6 +81,7 @@
 		19A17C80076860CF7751A056 /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */; };
 		19A17CB808ACF606726E77A8 /* QueryIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */; };
 		19A17DC282E36C4F41AA440B /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
+		19A17DF8D4F13A20F5D2269E /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17E723300E5ED3771DCB5 /* Result.swift */; };
 		19A17E04C4C0956715C5676A /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
 		19A17E29278A12BC4F542506 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
 		19A17EC0D68BA8C03288ADF7 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
@@ -911,6 +912,7 @@
 				02A43A9B22738CF100FEC494 /* Backup.swift in Sources */,
 				19A17DC282E36C4F41AA440B /* Errors.swift in Sources */,
 				19A173668D948AD4DF1F5352 /* DateAndTimeFunctions.swift in Sources */,
+				19A17DF8D4F13A20F5D2269E /* Result.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

From 5e64bb587b8b45a478634eed54df5f26d84b0b5e Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 25 Aug 2021 19:25:53 +0200
Subject: [PATCH 436/685] Split and simplify code, remove duplication

---
 .swiftlint.yml                                |   5 +-
 SQLite.xcodeproj/project.pbxproj              |   8 +
 .../SQLite/Core/Connection+Aggregation.swift  | 155 ++++++++++++
 Sources/SQLite/Core/Connection.swift          | 225 +++++-------------
 Sources/SQLite/Typed/CustomFunctions.swift    |  65 -----
 Sources/SQLite/Typed/Query.swift              |   1 -
 6 files changed, 226 insertions(+), 233 deletions(-)
 create mode 100644 Sources/SQLite/Core/Connection+Aggregation.swift

diff --git a/.swiftlint.yml b/.swiftlint.yml
index b5e53d56..34bb253b 100644
--- a/.swiftlint.yml
+++ b/.swiftlint.yml
@@ -38,5 +38,6 @@ line_length:
   ignores_comments: true
 
 file_length:
-  warning: 900
-  error: 900
+  warning: 500
+  error: 500
+  ignore_comment_only_lines: true
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index b30c18d2..5bb52f4e 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -50,6 +50,7 @@
 		03A65E971C6BB3210062603F /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 03A65E961C6BB3210062603F /* libsqlite3.tbd */; };
 		19A17073552293CA063BEA66 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17E723300E5ED3771DCB5 /* Result.swift */; };
 		19A1709C3E7A406E62293B2A /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; };
+		19A170ACC97B19730FB7BA4D /* Connection+Aggregation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */; };
 		19A17152E32A9585831E3FE0 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
 		19A1717B10CC941ACB5533D6 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
 		19A171967CC511C4F6F773C9 /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */; };
@@ -67,6 +68,7 @@
 		19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
 		19A1750CEE9B05267995CF3D /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
 		19A175DFF47B84757E547C62 /* fixtures in Resources */ = {isa = PBXBuildFile; fileRef = 19A17E2695737FAB5D6086E3 /* fixtures */; };
+		19A176376CB6A94759F7980A /* Connection+Aggregation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */; };
 		19A176406BDE9D9C80CC9FA3 /* QueryIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */; };
 		19A1769C1F3A7542BECF50FF /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */; };
 		19A177CC33F2E6A24AF90B02 /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
@@ -75,6 +77,7 @@
 		19A1785195182AF8731A8BDA /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */; };
 		19A1792C0520D4E83C2EB075 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
 		19A179A0C45377CB09BB358C /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
+		19A179B59450FE7C4811AB8A /* Connection+Aggregation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */; };
 		19A179CCF9671E345E5A9811 /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
 		19A179E76EA6207669B60C1B /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
 		19A17C4B951CB054EE48AB1C /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
@@ -237,6 +240,7 @@
 		19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAndTimeFunctionTests.swift; sourceTree = "<group>"; };
 		19A1730E4390C775C25677D1 /* FTS5.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5.swift; sourceTree = "<group>"; };
 		19A17399EA9E61235D5D77BF /* CipherTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CipherTests.swift; sourceTree = "<group>"; };
+		19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Connection+Aggregation.swift"; sourceTree = "<group>"; };
 		19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RowTests.swift; sourceTree = "<group>"; };
 		19A178A39ACA9667A62663CC /* Cipher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cipher.swift; sourceTree = "<group>"; };
 		19A1794B7972D14330A65BBD /* Linux.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Linux.md; sourceTree = "<group>"; };
@@ -462,6 +466,7 @@
 				19A1710E73A46D5AC721CDA9 /* Errors.swift */,
 				02A43A9722738CF100FEC494 /* Backup.swift */,
 				19A17E723300E5ED3771DCB5 /* Result.swift */,
+				19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */,
 			);
 			path = Core;
 			sourceTree = "<group>";
@@ -850,6 +855,7 @@
 				19A17FF4A10B44D3937C8CAC /* Errors.swift in Sources */,
 				19A1737286A74F3CF7412906 /* DateAndTimeFunctions.swift in Sources */,
 				19A17073552293CA063BEA66 /* Result.swift in Sources */,
+				19A179B59450FE7C4811AB8A /* Connection+Aggregation.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -945,6 +951,7 @@
 				19A1792C0520D4E83C2EB075 /* Errors.swift in Sources */,
 				19A17E29278A12BC4F542506 /* DateAndTimeFunctions.swift in Sources */,
 				19A173EFEF0B3BD0B3ED406C /* Result.swift in Sources */,
+				19A176376CB6A94759F7980A /* Connection+Aggregation.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1008,6 +1015,7 @@
 				19A17490543609FCED53CACC /* Errors.swift in Sources */,
 				19A17152E32A9585831E3FE0 /* DateAndTimeFunctions.swift in Sources */,
 				19A17F1B3F0A3C96B5ED6D64 /* Result.swift in Sources */,
+				19A170ACC97B19730FB7BA4D /* Connection+Aggregation.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/Sources/SQLite/Core/Connection+Aggregation.swift b/Sources/SQLite/Core/Connection+Aggregation.swift
new file mode 100644
index 00000000..257d48ed
--- /dev/null
+++ b/Sources/SQLite/Core/Connection+Aggregation.swift
@@ -0,0 +1,155 @@
+import Foundation
+#if SQLITE_SWIFT_STANDALONE
+import sqlite3
+#elseif SQLITE_SWIFT_SQLCIPHER
+import SQLCipher
+#elseif os(Linux)
+import CSQLite
+#else
+import SQLite3
+#endif
+
+extension Connection {
+    private typealias Aggregate = @convention(block) (Int, OpaquePointer?, Int32, UnsafeMutablePointer<OpaquePointer?>?) -> Void
+
+    /// Creates or redefines a custom SQL aggregate.
+    ///
+    /// - Parameters:
+    ///
+    ///   - aggregate: The name of the aggregate to create or redefine.
+    ///
+    ///   - argumentCount: The number of arguments that the aggregate takes. If
+    ///     `nil`, the aggregate may take any number of arguments.
+    ///
+    ///     Default: `nil`
+    ///
+    ///   - deterministic: Whether or not the aggregate is deterministic (_i.e._
+    ///     the aggregate always returns the same result for a given input).
+    ///
+    ///     Default: `false`
+    ///
+    ///   - step: A block of code to run for each row of an aggregation group.
+    ///     The block is called with an array of raw SQL values mapped to the
+    ///     aggregate’s parameters, and an UnsafeMutablePointer to a state
+    ///     variable.
+    ///
+    ///   - final: A block of code to run after each row of an aggregation group
+    ///     is processed. The block is called with an UnsafeMutablePointer to a
+    ///     state variable, and should return a raw SQL value (or nil).
+    ///
+    ///   - state: A block of code to run to produce a fresh state variable for
+    ///     each aggregation group. The block should return an
+    ///     UnsafeMutablePointer to the fresh state variable.
+    public func createAggregation<T>(
+            _ functionName: String,
+            argumentCount: UInt? = nil,
+            deterministic: Bool = false,
+            step: @escaping ([Binding?], UnsafeMutablePointer<T>) -> Void,
+            final: @escaping (UnsafeMutablePointer<T>) -> Binding?,
+            state: @escaping () -> UnsafeMutablePointer<T>) {
+
+        let argc = argumentCount.map { Int($0) } ?? -1
+        let box: Aggregate = { (stepFlag: Int, context: OpaquePointer?, argc: Int32, argv: UnsafeMutablePointer<OpaquePointer?>?) in
+            let nBytes = Int32(MemoryLayout<UnsafeMutablePointer<Int64>>.size)
+            guard let aggregateContext = sqlite3_aggregate_context(context, nBytes) else {
+                fatalError("Could not get aggregate context")
+            }
+            let mutablePointer = aggregateContext.assumingMemoryBound(to: UnsafeMutableRawPointer.self)
+            if stepFlag > 0 {
+                let arguments = getArguments(argc: argc, argv: argv)
+                if aggregateContext.assumingMemoryBound(to: Int64.self).pointee == 0 {
+                    mutablePointer.pointee = UnsafeMutableRawPointer(mutating: state())
+                }
+                step(arguments, mutablePointer.pointee.assumingMemoryBound(to: T.self))
+            } else {
+                let result = final(mutablePointer.pointee.assumingMemoryBound(to: T.self))
+                set(result: result, on: context)
+            }
+        }
+
+        func xStep(context: OpaquePointer?, argc: Int32, value: UnsafeMutablePointer<OpaquePointer?>?) {
+            unsafeBitCast(sqlite3_user_data(context), to: Aggregate.self)(1, context, argc, value)
+        }
+
+        func xFinal(context: OpaquePointer?) {
+            unsafeBitCast(sqlite3_user_data(context), to: Aggregate.self)(0, context, 0, nil)
+        }
+
+        let flags = SQLITE_UTF8 | (deterministic ? SQLITE_DETERMINISTIC : 0)
+        let resultCode = sqlite3_create_function_v2(
+            handle,
+            functionName,
+            Int32(argc),
+            flags,
+            /* pApp */ unsafeBitCast(box, to: UnsafeMutableRawPointer.self),
+            /* xFunc */ nil, xStep, xFinal, /* xDestroy */ nil
+        )
+        if let result = Result(errorCode: resultCode, connection: self) {
+            fatalError("Error creating function: \(result)")
+        }
+        register(functionName, argc: argc, value: box)
+    }
+
+    func createAggregation<T: AnyObject>(
+            _ aggregate: String,
+            argumentCount: UInt? = nil,
+            deterministic: Bool = false,
+            initialValue: T,
+            reduce: @escaping (T, [Binding?]) -> T,
+            result: @escaping (T) -> Binding?
+    ) {
+        let step: ([Binding?], UnsafeMutablePointer<UnsafeMutableRawPointer>) -> Void = { (bindings, ptr) in
+            let pointer = ptr.pointee.assumingMemoryBound(to: T.self)
+            let current = Unmanaged<T>.fromOpaque(pointer).takeRetainedValue()
+            let next = reduce(current, bindings)
+            ptr.pointee = Unmanaged.passRetained(next).toOpaque()
+        }
+
+        let final: (UnsafeMutablePointer<UnsafeMutableRawPointer>) -> Binding? = { ptr in
+            let pointer = ptr.pointee.assumingMemoryBound(to: T.self)
+            let obj = Unmanaged<T>.fromOpaque(pointer).takeRetainedValue()
+            let value = result(obj)
+            ptr.deallocate()
+            return value
+        }
+
+        let state: () -> UnsafeMutablePointer<UnsafeMutableRawPointer> = {
+            let pointer = UnsafeMutablePointer<UnsafeMutableRawPointer>.allocate(capacity: 1)
+            pointer.pointee = Unmanaged.passRetained(initialValue).toOpaque()
+            return pointer
+        }
+
+        createAggregation(aggregate, step: step, final: final, state: state)
+    }
+
+    func createAggregation<T>(
+            _ aggregate: String,
+            argumentCount: UInt? = nil,
+            deterministic: Bool = false,
+            initialValue: T,
+            reduce: @escaping (T, [Binding?]) -> T,
+            result: @escaping (T) -> Binding?
+    ) {
+
+        let step: ([Binding?], UnsafeMutablePointer<T>) -> Void = { (bindings, pointer) in
+            let current = pointer.pointee
+            let next = reduce(current, bindings)
+            pointer.pointee = next
+        }
+
+        let final: (UnsafeMutablePointer<T>) -> Binding? = { pointer in
+            let value = result(pointer.pointee)
+            pointer.deallocate()
+            return value
+        }
+
+        let state: () -> UnsafeMutablePointer<T> = {
+            let pointer = UnsafeMutablePointer<T>.allocate(capacity: 1)
+            pointer.initialize(to: initialValue)
+            return pointer
+        }
+
+        createAggregation(aggregate, step: step, final: final, state: state)
+    }
+
+}
diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index a9012462..35996b29 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -35,7 +35,6 @@ import SQLite3
 #endif
 
 /// A connection to SQLite.
-// swiftlint:disable:next type_body_length
 public final class Connection {
 
     /// The location of a SQLite database.
@@ -586,182 +585,42 @@ public final class Connection {
     ///   - block: A block of code to run when the function is called. The block
     ///     is called with an array of raw SQL values mapped to the function’s
     ///     parameters and should return a raw SQL value (or nil).
-    // swiftlint:disable:next cyclomatic_complexity
-    public func createFunction(_ function: String, argumentCount: UInt? = nil, deterministic: Bool = false,
+    public func createFunction(_ functionName: String,
+                               argumentCount: UInt? = nil,
+                               deterministic: Bool = false,
                                _ block: @escaping (_ args: [Binding?]) -> Binding?) {
         let argc = argumentCount.map { Int($0) } ?? -1
         let box: Function = { context, argc, argv in
-            let arguments: [Binding?] = (0..<Int(argc)).map { idx in
-                let value = argv![idx]
-                switch sqlite3_value_type(value) {
-                case SQLITE_BLOB:
-                    return Blob(bytes: sqlite3_value_blob(value), length: Int(sqlite3_value_bytes(value)))
-                case SQLITE_FLOAT:
-                    return sqlite3_value_double(value)
-                case SQLITE_INTEGER:
-                    return sqlite3_value_int64(value)
-                case SQLITE_NULL:
-                    return nil
-                case SQLITE_TEXT:
-                    return String(cString: UnsafePointer(sqlite3_value_text(value)))
-                case let type:
-                    fatalError("unsupported value type: \(type)")
-                }
-            }
-            let result = block(arguments)
-            if let result = result as? Blob {
-                sqlite3_result_blob(context, result.bytes, Int32(result.bytes.count), nil)
-            } else if let result = result as? Double {
-                sqlite3_result_double(context, result)
-            } else if let result = result as? Int64 {
-                sqlite3_result_int64(context, result)
-            } else if let result = result as? String {
-                sqlite3_result_text(context, result, Int32(result.lengthOfBytes(using: .utf8)), SQLITE_TRANSIENT)
-            } else if result == nil {
-                sqlite3_result_null(context)
-            } else {
-                fatalError("unsupported result type: \(String(describing: result))")
-            }
+            set(result: block(getArguments(argc: argc, argv: argv)), on: context)
         }
-        var flags = SQLITE_UTF8
-        #if !os(Linux)
-        if deterministic {
-            flags |= SQLITE_DETERMINISTIC
-        }
-        #endif
-        let resultCode = sqlite3_create_function_v2(handle,
-                                                    function,
-                                                    Int32(argc),
-                                                    flags,
-                                                    unsafeBitCast(box, to: UnsafeMutableRawPointer.self), { context, argc, value in
-            let function = unsafeBitCast(sqlite3_user_data(context), to: Function.self)
-            function(context, argc, value)
-        }, nil, nil, nil)
-
-        if let result = Result(errorCode: resultCode, connection: self, statement: nil) {
-            fatalError("Error creating function: \(result)")
+        func xFunc(context: OpaquePointer?, argc: Int32, value: UnsafeMutablePointer<OpaquePointer?>?) {
+            unsafeBitCast(sqlite3_user_data(context), to: Function.self)(context, argc, value)
         }
+        let flags = SQLITE_UTF8 | (deterministic ? SQLITE_DETERMINISTIC : 0)
+        let resultCode = sqlite3_create_function_v2(
+            handle,
+            functionName,
+            Int32(argc),
+            flags,
+            /* pApp */ unsafeBitCast(box, to: UnsafeMutableRawPointer.self),
+            xFunc, /*xStep*/ nil, /*xFinal*/ nil, /*xDestroy*/ nil
+        )
 
-        if functions[function] == nil {
-            functions[function] = [:] // fails on Linux, https://github.com/stephencelis/SQLite.swift/issues/1071
+        if let result = Result(errorCode: resultCode, connection: self) {
+            fatalError("Error creating function: \(result)")
         }
-        functions[function]?[argc] = box
+        register(functionName, argc: argc, value: box)
     }
 
-    /// Creates or redefines a custom SQL aggregate.
-    ///
-    /// - Parameters:
-    ///
-    ///   - aggregate: The name of the aggregate to create or redefine.
-    ///
-    ///   - argumentCount: The number of arguments that the aggregate takes. If
-    ///     `nil`, the aggregate may take any number of arguments.
-    ///
-    ///     Default: `nil`
-    ///
-    ///   - deterministic: Whether or not the aggregate is deterministic (_i.e._
-    ///     the aggregate always returns the same result for a given input).
-    ///
-    ///     Default: `false`
-    ///
-    ///   - step: A block of code to run for each row of an aggregation group.
-    ///     The block is called with an array of raw SQL values mapped to the
-    ///     aggregate’s parameters, and an UnsafeMutablePointer to a state
-    ///     variable.
-    ///
-    ///   - final: A block of code to run after each row of an aggregation group
-    ///     is processed. The block is called with an UnsafeMutablePointer to a
-    ///     state variable, and should return a raw SQL value (or nil).
-    ///
-    ///   - state: A block of code to run to produce a fresh state variable for
-    ///     each aggregation group. The block should return an
-    ///     UnsafeMutablePointer to the fresh state variable.
-    // swiftlint:disable:next cyclomatic_complexity
-    public func createAggregation<T>(
-        _ aggregate: String,
-        argumentCount: UInt? = nil,
-        deterministic: Bool = false,
-        step: @escaping ([Binding?], UnsafeMutablePointer<T>) -> Void,
-        final: @escaping (UnsafeMutablePointer<T>) -> Binding?,
-        state: @escaping () -> UnsafeMutablePointer<T>) {
-
-        let argc = argumentCount.map { Int($0) } ?? -1
-        let box: Aggregate = { (stepFlag: Int, context: OpaquePointer?, argc: Int32, argv: UnsafeMutablePointer<OpaquePointer?>?) in
-            let ptr = sqlite3_aggregate_context(context, 64)! // needs to be at least as large as uintptr_t; better way to do this?
-            let mutablePointer = ptr.assumingMemoryBound(to: UnsafeMutableRawPointer.self)
-            if stepFlag > 0 {
-                let arguments: [Binding?] = (0..<Int(argc)).map { idx in
-                    let value = argv![idx]
-                    switch sqlite3_value_type(value) {
-                    case SQLITE_BLOB:
-                        return Blob(bytes: sqlite3_value_blob(value), length: Int(sqlite3_value_bytes(value)))
-                    case SQLITE_FLOAT:
-                        return sqlite3_value_double(value)
-                    case SQLITE_INTEGER:
-                        return sqlite3_value_int64(value)
-                    case SQLITE_NULL:
-                        return nil
-                    case SQLITE_TEXT:
-                        return String(cString: UnsafePointer(sqlite3_value_text(value)))
-                    case let type:
-                        fatalError("unsupported value type: \(type)")
-                    }
-                }
-
-                if ptr.assumingMemoryBound(to: Int64.self).pointee == 0 {
-                    let value = state()
-                    mutablePointer.pointee = UnsafeMutableRawPointer(mutating: value)
-                }
-                step(arguments, mutablePointer.pointee.assumingMemoryBound(to: T.self))
-            } else {
-                let result = final(mutablePointer.pointee.assumingMemoryBound(to: T.self))
-                if let result = result as? Blob {
-                    sqlite3_result_blob(context, result.bytes, Int32(result.bytes.count), nil)
-                } else if let result = result as? Double {
-                    sqlite3_result_double(context, result)
-                } else if let result = result as? Int64 {
-                    sqlite3_result_int64(context, result)
-                } else if let result = result as? String {
-                    sqlite3_result_text(context, result, Int32(result.count), SQLITE_TRANSIENT)
-                } else if result == nil {
-                    sqlite3_result_null(context)
-                } else {
-                    fatalError("unsupported result type: \(String(describing: result))")
-                }
-            }
+    func register(_ functionName: String, argc: Int, value: Any) {
+        if functions[functionName] == nil {
+            functions[functionName] = [:] // fails on Linux, https://github.com/stephencelis/SQLite.swift/issues/1071
         }
-
-        var flags = SQLITE_UTF8
-        #if !os(Linux)
-        if deterministic {
-            flags |= SQLITE_DETERMINISTIC
-        }
-        #endif
-
-        sqlite3_create_function_v2(
-            handle,
-            aggregate,
-            Int32(argc),
-            flags,
-            unsafeBitCast(box, to: UnsafeMutableRawPointer.self),
-            nil,
-            { context, argc, value in
-                let function = unsafeBitCast(sqlite3_user_data(context), to: Aggregate.self)
-                function(1, context, argc, value)
-        }, { context in
-                let function = unsafeBitCast(sqlite3_user_data(context), to: Aggregate.self)
-                function(0, context, 0, nil)
-        },
-            nil
-        )
-        if aggregations[aggregate] == nil { self.aggregations[aggregate] = [:] }
-        aggregations[aggregate]?[argc] = box
+        functions[functionName]?[argc] = value
     }
 
-    fileprivate typealias Aggregate = @convention(block) (Int, OpaquePointer?, Int32, UnsafeMutablePointer<OpaquePointer?>?) -> Void
     fileprivate typealias Function = @convention(block) (OpaquePointer?, Int32, UnsafeMutablePointer<OpaquePointer?>?) -> Void
-    fileprivate var functions = [String: [Int: Function]]()
-    fileprivate var aggregations = [String: [Int: Aggregate]]()
+    fileprivate var functions = [String: [Int: Any]]()
 
     /// Defines a new collating sequence.
     ///
@@ -808,7 +667,6 @@ public final class Connection {
     ///     Default: `.main`.
     ///
     /// - Returns: A new database backup.
-
     public func backup(databaseName: Backup.DatabaseName = .main,
                        usingConnection targetConnection: Connection,
                        andDatabaseName targetDatabaseName: Backup.DatabaseName = .main) throws -> Backup {
@@ -864,3 +722,40 @@ extension Connection.Location: CustomStringConvertible {
     }
 
 }
+
+func getArguments(argc: Int32, argv: UnsafeMutablePointer<OpaquePointer?>?) -> [Binding?] {
+    (0..<Int(argc)).map { idx in
+        let value = argv![idx]
+        switch sqlite3_value_type(value) {
+        case SQLITE_BLOB:
+            return Blob(bytes: sqlite3_value_blob(value), length: Int(sqlite3_value_bytes(value)))
+        case SQLITE_FLOAT:
+            return sqlite3_value_double(value)
+        case SQLITE_INTEGER:
+            return sqlite3_value_int64(value)
+        case SQLITE_NULL:
+            return nil
+        case SQLITE_TEXT:
+            return String(cString: UnsafePointer(sqlite3_value_text(value)))
+        case let type:
+            fatalError("unsupported value type: \(type)")
+        }
+    }
+}
+
+func set(result: Binding?, on context: OpaquePointer?) {
+    switch result {
+    case let blob as Blob:
+        sqlite3_result_blob(context, blob.bytes, Int32(blob.bytes.count), nil)
+    case let double as Double:
+        sqlite3_result_double(context, double)
+    case let int as Int64:
+        sqlite3_result_int64(context, int)
+    case let string as String:
+        sqlite3_result_text(context, string, Int32(string.lengthOfBytes(using: .utf8)), SQLITE_TRANSIENT)
+    case .none:
+        sqlite3_result_null(context)
+    default:
+        fatalError("unsupported result type: \(String(describing: result))")
+    }
+}
diff --git a/Sources/SQLite/Typed/CustomFunctions.swift b/Sources/SQLite/Typed/CustomFunctions.swift
index c38113d1..0eaa8cf3 100644
--- a/Sources/SQLite/Typed/CustomFunctions.swift
+++ b/Sources/SQLite/Typed/CustomFunctions.swift
@@ -159,69 +159,4 @@ public extension Connection {
         }
     }
 
-    // MARK: -
-
-    func createAggregation<T: AnyObject>(
-        _ aggregate: String,
-        argumentCount: UInt? = nil,
-        deterministic: Bool = false,
-        initialValue: T,
-        reduce: @escaping (T, [Binding?]) -> T,
-        result: @escaping (T) -> Binding?
-        ) {
-
-        let step: ([Binding?], UnsafeMutablePointer<UnsafeMutableRawPointer>) -> Void = { (bindings, ptr) in
-            let pointer = ptr.pointee.assumingMemoryBound(to: T.self)
-            let current = Unmanaged<T>.fromOpaque(pointer).takeRetainedValue()
-            let next = reduce(current, bindings)
-            ptr.pointee = Unmanaged.passRetained(next).toOpaque()
-        }
-
-        let final: (UnsafeMutablePointer<UnsafeMutableRawPointer>) -> Binding? = { (ptr) in
-            let pointer = ptr.pointee.assumingMemoryBound(to: T.self)
-            let obj = Unmanaged<T>.fromOpaque(pointer).takeRetainedValue()
-            let value = result(obj)
-            ptr.deallocate()
-            return value
-        }
-
-        let state: () -> UnsafeMutablePointer<UnsafeMutableRawPointer> = {
-            let pointer = UnsafeMutablePointer<UnsafeMutableRawPointer>.allocate(capacity: 1)
-            pointer.pointee = Unmanaged.passRetained(initialValue).toOpaque()
-            return pointer
-        }
-
-        createAggregation(aggregate, step: step, final: final, state: state)
-    }
-
-    func createAggregation<T>(
-        _ aggregate: String,
-        argumentCount: UInt? = nil,
-        deterministic: Bool = false,
-        initialValue: T,
-        reduce: @escaping (T, [Binding?]) -> T,
-        result: @escaping (T) -> Binding?
-        ) {
-
-        let step: ([Binding?], UnsafeMutablePointer<T>) -> Void = { (bindings, pointer) in
-            let current = pointer.pointee
-            let next = reduce(current, bindings)
-            pointer.pointee = next
-        }
-
-        let final: (UnsafeMutablePointer<T>) -> Binding? = { pointer in
-            let value = result(pointer.pointee)
-            pointer.deallocate()
-            return value
-        }
-
-        let state: () -> UnsafeMutablePointer<T> = {
-            let pointer = UnsafeMutablePointer<T>.allocate(capacity: 1)
-            pointer.initialize(to: initialValue)
-            return pointer
-        }
-
-        createAggregation(aggregate, step: step, final: final, state: state)
-    }
-
 }
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index 59b24a8d..2d88db63 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -21,7 +21,6 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 //
-// swiftlint:disable file_length
 import Foundation
 
 public protocol QueryType: Expressible {

From e5a10f5bcad9f9c25f948a9c90c5861e1bb83163 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 25 Aug 2021 22:23:36 +0200
Subject: [PATCH 437/685] Use typealiases

---
 .../SQLite/Core/Connection+Aggregation.swift  | 12 +--
 Sources/SQLite/Core/Connection.swift          | 74 ++++++++++---------
 2 files changed, 46 insertions(+), 40 deletions(-)

diff --git a/Sources/SQLite/Core/Connection+Aggregation.swift b/Sources/SQLite/Core/Connection+Aggregation.swift
index 257d48ed..106f292c 100644
--- a/Sources/SQLite/Core/Connection+Aggregation.swift
+++ b/Sources/SQLite/Core/Connection+Aggregation.swift
@@ -10,7 +10,7 @@ import SQLite3
 #endif
 
 extension Connection {
-    private typealias Aggregate = @convention(block) (Int, OpaquePointer?, Int32, UnsafeMutablePointer<OpaquePointer?>?) -> Void
+    private typealias Aggregate = @convention(block) (Int, Context, Int32, Argv) -> Void
 
     /// Creates or redefines a custom SQL aggregate.
     ///
@@ -49,29 +49,29 @@ extension Connection {
             state: @escaping () -> UnsafeMutablePointer<T>) {
 
         let argc = argumentCount.map { Int($0) } ?? -1
-        let box: Aggregate = { (stepFlag: Int, context: OpaquePointer?, argc: Int32, argv: UnsafeMutablePointer<OpaquePointer?>?) in
+        let box: Aggregate = { (stepFlag: Int, context: Context, argc: Int32, argv: Argv) in
             let nBytes = Int32(MemoryLayout<UnsafeMutablePointer<Int64>>.size)
             guard let aggregateContext = sqlite3_aggregate_context(context, nBytes) else {
                 fatalError("Could not get aggregate context")
             }
             let mutablePointer = aggregateContext.assumingMemoryBound(to: UnsafeMutableRawPointer.self)
             if stepFlag > 0 {
-                let arguments = getArguments(argc: argc, argv: argv)
+                let arguments = argv.getBindings(argc: argc)
                 if aggregateContext.assumingMemoryBound(to: Int64.self).pointee == 0 {
                     mutablePointer.pointee = UnsafeMutableRawPointer(mutating: state())
                 }
                 step(arguments, mutablePointer.pointee.assumingMemoryBound(to: T.self))
             } else {
                 let result = final(mutablePointer.pointee.assumingMemoryBound(to: T.self))
-                set(result: result, on: context)
+                context.set(result: result)
             }
         }
 
-        func xStep(context: OpaquePointer?, argc: Int32, value: UnsafeMutablePointer<OpaquePointer?>?) {
+        func xStep(context: Context, argc: Int32, value: Argv) {
             unsafeBitCast(sqlite3_user_data(context), to: Aggregate.self)(1, context, argc, value)
         }
 
-        func xFinal(context: OpaquePointer?) {
+        func xFinal(context: Context) {
             unsafeBitCast(sqlite3_user_data(context), to: Aggregate.self)(0, context, 0, nil)
         }
 
diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 35996b29..6b5481e3 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -590,10 +590,10 @@ public final class Connection {
                                deterministic: Bool = false,
                                _ block: @escaping (_ args: [Binding?]) -> Binding?) {
         let argc = argumentCount.map { Int($0) } ?? -1
-        let box: Function = { context, argc, argv in
-            set(result: block(getArguments(argc: argc, argv: argv)), on: context)
+        let box: Function = { (context: Context, argc, argv: Argv) in
+            context.set(result: block(argv.getBindings(argc: argc)))
         }
-        func xFunc(context: OpaquePointer?, argc: Int32, value: UnsafeMutablePointer<OpaquePointer?>?) {
+        func xFunc(context: Context, argc: Int32, value: Argv) {
             unsafeBitCast(sqlite3_user_data(context), to: Function.self)(context, argc, value)
         }
         let flags = SQLITE_UTF8 | (deterministic ? SQLITE_DETERMINISTIC : 0)
@@ -619,7 +619,7 @@ public final class Connection {
         functions[functionName]?[argc] = value
     }
 
-    fileprivate typealias Function = @convention(block) (OpaquePointer?, Int32, UnsafeMutablePointer<OpaquePointer?>?) -> Void
+    fileprivate typealias Function = @convention(block) (Context, Int32, Argv) -> Void
     fileprivate var functions = [String: [Int: Any]]()
 
     /// Defines a new collating sequence.
@@ -723,39 +723,45 @@ extension Connection.Location: CustomStringConvertible {
 
 }
 
-func getArguments(argc: Int32, argv: UnsafeMutablePointer<OpaquePointer?>?) -> [Binding?] {
-    (0..<Int(argc)).map { idx in
-        let value = argv![idx]
-        switch sqlite3_value_type(value) {
-        case SQLITE_BLOB:
-            return Blob(bytes: sqlite3_value_blob(value), length: Int(sqlite3_value_bytes(value)))
-        case SQLITE_FLOAT:
-            return sqlite3_value_double(value)
-        case SQLITE_INTEGER:
-            return sqlite3_value_int64(value)
-        case SQLITE_NULL:
-            return nil
-        case SQLITE_TEXT:
-            return String(cString: UnsafePointer(sqlite3_value_text(value)))
-        case let type:
-            fatalError("unsupported value type: \(type)")
+typealias Context = OpaquePointer?
+extension Context {
+    func set(result: Binding?) {
+        switch result {
+        case let blob as Blob:
+            sqlite3_result_blob(self, blob.bytes, Int32(blob.bytes.count), nil)
+        case let double as Double:
+            sqlite3_result_double(self, double)
+        case let int as Int64:
+            sqlite3_result_int64(self, int)
+        case let string as String:
+            sqlite3_result_text(self, string, Int32(string.lengthOfBytes(using: .utf8)), SQLITE_TRANSIENT)
+        case .none:
+            sqlite3_result_null(self)
+        default:
+            fatalError("unsupported result type: \(String(describing: result))")
         }
     }
 }
 
-func set(result: Binding?, on context: OpaquePointer?) {
-    switch result {
-    case let blob as Blob:
-        sqlite3_result_blob(context, blob.bytes, Int32(blob.bytes.count), nil)
-    case let double as Double:
-        sqlite3_result_double(context, double)
-    case let int as Int64:
-        sqlite3_result_int64(context, int)
-    case let string as String:
-        sqlite3_result_text(context, string, Int32(string.lengthOfBytes(using: .utf8)), SQLITE_TRANSIENT)
-    case .none:
-        sqlite3_result_null(context)
-    default:
-        fatalError("unsupported result type: \(String(describing: result))")
+typealias Argv = UnsafeMutablePointer<OpaquePointer?>?
+extension Argv {
+    func getBindings(argc: Int32) -> [Binding?] {
+        (0..<Int(argc)).map { idx in
+            let value = self![idx]
+            switch sqlite3_value_type(value) {
+            case SQLITE_BLOB:
+                return Blob(bytes: sqlite3_value_blob(value), length: Int(sqlite3_value_bytes(value)))
+            case SQLITE_FLOAT:
+                return sqlite3_value_double(value)
+            case SQLITE_INTEGER:
+                return sqlite3_value_int64(value)
+            case SQLITE_NULL:
+                return nil
+            case SQLITE_TEXT:
+                return String(cString: UnsafePointer(sqlite3_value_text(value)))
+            case let type:
+                fatalError("unsupported value type: \(type)")
+            }
+        }
     }
 }

From 7d12428fd912be63c072bea5b1670dd2d54d4089 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 23 Aug 2021 00:14:23 +0200
Subject: [PATCH 438/685] Add trigram tokenizer

---
 Sources/SQLite/Extensions/FTS4.swift |  9 +++++++--
 Tests/SQLiteTests/FTS5Tests.swift    | 10 ++++++++++
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/Sources/SQLite/Extensions/FTS4.swift b/Sources/SQLite/Extensions/FTS4.swift
index 115b146a..0e48943a 100644
--- a/Sources/SQLite/Extensions/FTS4.swift
+++ b/Sources/SQLite/Extensions/FTS4.swift
@@ -95,10 +95,10 @@ extension VirtualTable {
 public struct Tokenizer {
 
     public static let Simple = Tokenizer("simple")
-
     public static let Porter = Tokenizer("porter")
 
-    public static func Unicode61(removeDiacritics: Bool? = nil, tokenchars: Set<Character> = [],
+    public static func Unicode61(removeDiacritics: Bool? = nil,
+                                 tokenchars: Set<Character> = [],
                                  separators: Set<Character> = []) -> Tokenizer {
         var arguments = [String]()
 
@@ -119,6 +119,11 @@ public struct Tokenizer {
         return Tokenizer("unicode61", arguments)
     }
 
+    // https://sqlite.org/fts5.html#the_experimental_trigram_tokenizer
+    public static func Trigram(caseSensitive: Bool = false) -> Tokenizer {
+        return Tokenizer("trigram", ["case_sensitive", caseSensitive ? "1" : "0"])
+    }
+
     public static func Custom(_ name: String) -> Tokenizer {
         Tokenizer(Tokenizer.moduleName.quote(), [name.quote()])
     }
diff --git a/Tests/SQLiteTests/FTS5Tests.swift b/Tests/SQLiteTests/FTS5Tests.swift
index 4cce4523..c271be9d 100644
--- a/Tests/SQLiteTests/FTS5Tests.swift
+++ b/Tests/SQLiteTests/FTS5Tests.swift
@@ -81,6 +81,16 @@ class FTS5Tests: XCTestCase {
             sql(config.tokenizer(.Unicode61(removeDiacritics: true, tokenchars: ["."], separators: ["X"]))))
     }
 
+    func test_tokenizer_trigram() {
+        XCTAssertEqual(
+                "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(tokenize=trigram case_sensitive 0)",
+                sql(config.tokenizer(.Trigram())))
+
+        XCTAssertEqual(
+                "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(tokenize=trigram case_sensitive 1)",
+                sql(config.tokenizer(.Trigram(caseSensitive: true))))
+    }
+
     func test_column_size() {
         XCTAssertEqual(
             "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(columnsize=1)",

From 3dc24496883090888fdbd658a766eb622b815aec Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 26 Aug 2021 00:19:07 +0200
Subject: [PATCH 439/685] Add integration tests

---
 SQLite.xcodeproj/project.pbxproj              |  8 +++
 Tests/SQLiteTests/CipherTests.swift           | 16 ++---
 Tests/SQLiteTests/ConnectionTests.swift       |  7 +-
 .../SQLiteTests/CustomAggregationTests.swift  | 12 ++--
 Tests/SQLiteTests/FTSIntegrationTests.swift   | 64 +++++++++++++++++++
 Tests/SQLiteTests/QueryIntegrationTests.swift | 11 ++--
 Tests/SQLiteTests/SelectTests.swift           | 12 ++--
 Tests/SQLiteTests/StatementTests.swift        |  6 +-
 Tests/SQLiteTests/TestHelpers.swift           | 10 +--
 9 files changed, 108 insertions(+), 38 deletions(-)
 create mode 100644 Tests/SQLiteTests/FTSIntegrationTests.swift

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 5bb52f4e..92400180 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -54,6 +54,7 @@
 		19A17152E32A9585831E3FE0 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
 		19A1717B10CC941ACB5533D6 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
 		19A171967CC511C4F6F773C9 /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */; };
+		19A171BE056457F13BFBC4C3 /* FTSIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171FDE4D67879B14ACBDF /* FTSIntegrationTests.swift */; };
 		19A171E6FA242F72A308C594 /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
 		19A171F12AB8B07F2FD7201A /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
 		19A1720B67ED13E6150C6A3D /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */; };
@@ -80,8 +81,10 @@
 		19A179B59450FE7C4811AB8A /* Connection+Aggregation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */; };
 		19A179CCF9671E345E5A9811 /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
 		19A179E76EA6207669B60C1B /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
+		19A17C013B00682B70D53DB8 /* FTSIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171FDE4D67879B14ACBDF /* FTSIntegrationTests.swift */; };
 		19A17C4B951CB054EE48AB1C /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
 		19A17C80076860CF7751A056 /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */; };
+		19A17C9407AC0EE104E5CC85 /* FTSIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171FDE4D67879B14ACBDF /* FTSIntegrationTests.swift */; };
 		19A17CB808ACF606726E77A8 /* QueryIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */; };
 		19A17DC282E36C4F41AA440B /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
 		19A17DF8D4F13A20F5D2269E /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17E723300E5ED3771DCB5 /* Result.swift */; };
@@ -236,6 +239,7 @@
 		03A65E631C6BB0F60062603F /* SQLiteTests tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SQLiteTests tvOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
 		03A65E961C6BB3210062603F /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
 		19A1710E73A46D5AC721CDA9 /* Errors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = "<group>"; };
+		19A171FDE4D67879B14ACBDF /* FTSIntegrationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTSIntegrationTests.swift; sourceTree = "<group>"; };
 		19A1721B8984686B9963B45D /* FTS5Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5Tests.swift; sourceTree = "<group>"; };
 		19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAndTimeFunctionTests.swift; sourceTree = "<group>"; };
 		19A1730E4390C775C25677D1 /* FTS5.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5.swift; sourceTree = "<group>"; };
@@ -449,6 +453,7 @@
 				19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */,
 				D4DB368A20C09C9B00D5A58E /* SelectTests.swift */,
 				19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */,
+				19A171FDE4D67879B14ACBDF /* FTSIntegrationTests.swift */,
 			);
 			name = SQLiteTests;
 			path = Tests/SQLiteTests;
@@ -887,6 +892,7 @@
 				19A1769C1F3A7542BECF50FF /* DateAndTimeFunctionTests.swift in Sources */,
 				D4DB368E20C09CFD00D5A58E /* SelectTests.swift in Sources */,
 				19A17CB808ACF606726E77A8 /* QueryIntegrationTests.swift in Sources */,
+				19A17C9407AC0EE104E5CC85 /* FTSIntegrationTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -983,6 +989,7 @@
 				19A17C80076860CF7751A056 /* DateAndTimeFunctionTests.swift in Sources */,
 				D4DB368C20C09CFB00D5A58E /* SelectTests.swift in Sources */,
 				19A172A9B536D02D4A98AAAD /* QueryIntegrationTests.swift in Sources */,
+				19A17C013B00682B70D53DB8 /* FTSIntegrationTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1047,6 +1054,7 @@
 				19A172EB202970561E5C4245 /* DateAndTimeFunctionTests.swift in Sources */,
 				D4DB368D20C09CFC00D5A58E /* SelectTests.swift in Sources */,
 				19A176406BDE9D9C80CC9FA3 /* QueryIntegrationTests.swift in Sources */,
+				19A171BE056457F13BFBC4C3 /* FTSIntegrationTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/Tests/SQLiteTests/CipherTests.swift b/Tests/SQLiteTests/CipherTests.swift
index 77e8e7f0..0995fca0 100644
--- a/Tests/SQLiteTests/CipherTests.swift
+++ b/Tests/SQLiteTests/CipherTests.swift
@@ -8,22 +8,22 @@ class CipherTests: XCTestCase {
     let db1 = try! Connection()
     let db2 = try! Connection()
 
-    override func setUp() {
+    override func setUpWithError() throws {
         // db
 
-        try! db1.key("hello")
+        try db1.key("hello")
 
-        try! db1.run("CREATE TABLE foo (bar TEXT)")
-        try! db1.run("INSERT INTO foo (bar) VALUES ('world')")
+        try db1.run("CREATE TABLE foo (bar TEXT)")
+        try db1.run("INSERT INTO foo (bar) VALUES ('world')")
 
         // db2
         let key2 = keyData()
-        try! db2.key(Blob(bytes: key2.bytes, length: key2.length))
+        try db2.key(Blob(bytes: key2.bytes, length: key2.length))
 
-        try! db2.run("CREATE TABLE foo (bar TEXT)")
-        try! db2.run("INSERT INTO foo (bar) VALUES ('world')")
+        try db2.run("CREATE TABLE foo (bar TEXT)")
+        try db2.run("INSERT INTO foo (bar) VALUES ('world')")
 
-        super.setUp()
+        try super.setUpWithError()
     }
 
     func test_key() {
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index ae881289..ae9d4dfd 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -15,10 +15,9 @@ import SQLite3
 
 class ConnectionTests: SQLiteTestCase {
 
-    override func setUp() {
-        super.setUp()
-
-        createUsersTable()
+    override func setUpWithError() throws {
+        try super.setUpWithError()
+        try createUsersTable()
     }
 
     func test_init_withInMemory_returnsInMemoryConnection() {
diff --git a/Tests/SQLiteTests/CustomAggregationTests.swift b/Tests/SQLiteTests/CustomAggregationTests.swift
index d5232260..5cbfbbef 100644
--- a/Tests/SQLiteTests/CustomAggregationTests.swift
+++ b/Tests/SQLiteTests/CustomAggregationTests.swift
@@ -17,12 +17,12 @@ import SQLite3
 #if !os(Linux)
 
 class CustomAggregationTests: SQLiteTestCase {
-    override func setUp() {
-        super.setUp()
-        createUsersTable()
-        try! insertUser("Alice", age: 30, admin: true)
-        try! insertUser("Bob", age: 25, admin: true)
-        try! insertUser("Eve", age: 28, admin: false)
+    override func setUpWithError() throws {
+        try super.setUpWithError()
+        try createUsersTable()
+        try insertUser("Alice", age: 30, admin: true)
+        try insertUser("Bob", age: 25, admin: true)
+        try insertUser("Eve", age: 28, admin: false)
     }
 
     func testUnsafeCustomSum() {
diff --git a/Tests/SQLiteTests/FTSIntegrationTests.swift b/Tests/SQLiteTests/FTSIntegrationTests.swift
new file mode 100644
index 00000000..561c756f
--- /dev/null
+++ b/Tests/SQLiteTests/FTSIntegrationTests.swift
@@ -0,0 +1,64 @@
+import XCTest
+#if SQLITE_SWIFT_STANDALONE
+import sqlite3
+#elseif SQLITE_SWIFT_SQLCIPHER
+import SQLCipher
+#elseif os(Linux)
+import CSQLite
+#else
+import SQLite3
+#endif
+@testable import SQLite
+
+class FTSIntegrationTests: SQLiteTestCase {
+    let email = Expression<String>("email")
+    let index = VirtualTable("index")
+
+    private func createIndex() throws {
+        try db.run(index.create(.FTS5(FTS5Config()
+            .column(email)
+            .tokenizer(.Unicode61())
+        )))
+
+        for user in try db.prepare(users) {
+            try db.run(index.insert(email <- user[email]))
+        }
+    }
+
+    private func createTrigramIndex() throws {
+        try XCTSkipUnless(db.satisfiesMinimumVersion(minor: 34))
+        try db.run(index.create(.FTS5(FTS5Config()
+            .column(email)
+            .tokenizer(.Trigram(caseSensitive: false))
+        )))
+
+        for user in try db.prepare(users) {
+            try db.run(index.insert(email <- user[email]))
+        }
+    }
+
+    override func setUpWithError() throws {
+        try super.setUpWithError()
+        try createUsersTable()
+        try insertUsers("John", "Paul", "George", "Ringo")
+    }
+
+    func testMatch() throws {
+        try createIndex()
+        let matches = Array(try db.prepare(index.match("Paul")))
+        XCTAssertEqual(matches.map { $0[email ]}, ["Paul@example.com"])
+    }
+
+    func testMatchPartial() throws {
+        try insertUsers("Paula")
+        try createIndex()
+        let matches = Array(try db.prepare(index.match("Pa*")))
+        XCTAssertEqual(matches.map { $0[email ]}, ["Paul@example.com", "Paula@example.com"])
+    }
+
+    func testTrigramIndex() throws {
+        try createTrigramIndex()
+        let matches = Array(try db.prepare(index.match("Paul")))
+        XCTAssertEqual(1, matches.count)
+    }
+}
diff --git a/Tests/SQLiteTests/QueryIntegrationTests.swift b/Tests/SQLiteTests/QueryIntegrationTests.swift
index c98b1601..4b9c4bbf 100644
--- a/Tests/SQLiteTests/QueryIntegrationTests.swift
+++ b/Tests/SQLiteTests/QueryIntegrationTests.swift
@@ -16,10 +16,9 @@ class QueryIntegrationTests: SQLiteTestCase {
     let email = Expression<String>("email")
     let age = Expression<Int>("age")
 
-    override func setUp() {
-        super.setUp()
-
-        createUsersTable()
+    override func setUpWithError() throws {
+        try super.setUpWithError()
+        try createUsersTable()
     }
 
     // MARK: -
@@ -131,7 +130,7 @@ class QueryIntegrationTests: SQLiteTestCase {
     }
 
     func test_upsert() throws {
-        guard db.satisfiesMinimumVersion(minor: 24) else { return }
+        try XCTSkipUnless(db.satisfiesMinimumVersion(minor: 24))
         let fetchAge = { () throws -> Int? in
             try self.db.pluck(self.users.filter(self.email == "alice@example.com")).flatMap { $0[self.age] }
         }
@@ -210,7 +209,7 @@ class QueryIntegrationTests: SQLiteTestCase {
     }
 }
 
-private extension Connection {
+extension Connection {
     func satisfiesMinimumVersion(minor: Int, patch: Int = 0) -> Bool {
         guard let version = try? scalar("SELECT sqlite_version()") as? String else { return false }
         let components = version.split(separator: ".", maxSplits: 3).compactMap { Int($0) }
diff --git a/Tests/SQLiteTests/SelectTests.swift b/Tests/SQLiteTests/SelectTests.swift
index c66d401d..d1126b66 100644
--- a/Tests/SQLiteTests/SelectTests.swift
+++ b/Tests/SQLiteTests/SelectTests.swift
@@ -3,14 +3,14 @@ import XCTest
 
 class SelectTests: SQLiteTestCase {
 
-    override func setUp() {
-        super.setUp()
-        createUsersTable()
-        createUsersDataTable()
+    override func setUpWithError() throws {
+        try super.setUpWithError()
+        try createUsersTable()
+        try createUsersDataTable()
     }
 
-    func createUsersDataTable() {
-        try! db.execute("""
+    func createUsersDataTable() throws {
+        try db.execute("""
             CREATE TABLE users_name (
                 id INTEGER,
                 user_id INTEGER REFERENCES users(id),
diff --git a/Tests/SQLiteTests/StatementTests.swift b/Tests/SQLiteTests/StatementTests.swift
index 5a05675d..b4ad7c28 100644
--- a/Tests/SQLiteTests/StatementTests.swift
+++ b/Tests/SQLiteTests/StatementTests.swift
@@ -2,9 +2,9 @@ import XCTest
 import SQLite
 
 class StatementTests: SQLiteTestCase {
-    override func setUp() {
-        super.setUp()
-        createUsersTable()
+    override func setUpWithError() throws {
+        try super.setUpWithError()
+        try createUsersTable()
     }
 
     func test_cursor_to_blob() {
diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index 0aa918f0..07cc6f06 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -6,9 +6,9 @@ class SQLiteTestCase: XCTestCase {
     var db: Connection!
     let users = Table("users")
 
-    override func setUp() {
-        super.setUp()
-        db = try! Connection()
+    override func setUpWithError() throws {
+        try super.setUpWithError()
+        db = try Connection()
         trace = [String: Int]()
 
         db.trace { SQL in
@@ -17,8 +17,8 @@ class SQLiteTestCase: XCTestCase {
         }
     }
 
-    func createUsersTable() {
-        try! db.execute("""
+    func createUsersTable() throws {
+        try db.execute("""
             CREATE TABLE users (
                 id INTEGER PRIMARY KEY,
                 email TEXT NOT NULL UNIQUE,

From 7aaccafedd157148a5a69e3e4c1a767b6d704ef9 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 26 Aug 2021 00:21:03 +0200
Subject: [PATCH 440/685] Skip on Linux

---
 Package.swift | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Package.swift b/Package.swift
index 7522fa45..c1373ad8 100644
--- a/Package.swift
+++ b/Package.swift
@@ -46,6 +46,7 @@ package.dependencies = [.package(url: "https://github.com/stephencelis/CSQLite.g
 package.targets = [
     .target(name: "SQLite", exclude: ["Extensions/FTS4.swift", "Extensions/FTS5.swift"]),
     .testTarget(name: "SQLiteTests", dependencies: ["SQLite"], path: "Tests/SQLiteTests", exclude: [
+        "FTSIntegrationTests.swift",
         "FTS4Tests.swift",
         "FTS5Tests.swift"
     ])

From b1031e33bc8c08898858c3d2873e2985f8ff19cf Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 26 Aug 2021 00:49:30 +0200
Subject: [PATCH 441/685] Skip tests if not supported

---
 Tests/SQLiteTests/FTSIntegrationTests.swift | 30 ++++++++++++++-------
 1 file changed, 21 insertions(+), 9 deletions(-)

diff --git a/Tests/SQLiteTests/FTSIntegrationTests.swift b/Tests/SQLiteTests/FTSIntegrationTests.swift
index 561c756f..d629ca8b 100644
--- a/Tests/SQLiteTests/FTSIntegrationTests.swift
+++ b/Tests/SQLiteTests/FTSIntegrationTests.swift
@@ -15,10 +15,16 @@ class FTSIntegrationTests: SQLiteTestCase {
     let index = VirtualTable("index")
 
     private func createIndex() throws {
-        try db.run(index.create(.FTS5(FTS5Config()
-            .column(email)
-            .tokenizer(.Unicode61())
-        )))
+        do {
+            try db.run(index.create(.FTS5(
+                FTS5Config()
+                    .column(email)
+                    .tokenizer(.Unicode61()))
+            ))
+        } catch let error as Result {
+            try XCTSkipIf(error.description.starts(with: "no such model"))
+            throw error
+        }
 
         for user in try db.prepare(users) {
             try db.run(index.insert(email <- user[email]))
@@ -26,11 +32,17 @@ class FTSIntegrationTests: SQLiteTestCase {
     }
 
     private func createTrigramIndex() throws {
-        try XCTSkipUnless(db.satisfiesMinimumVersion(minor: 34))
-        try db.run(index.create(.FTS5(FTS5Config()
-            .column(email)
-            .tokenizer(.Trigram(caseSensitive: false))
-        )))
+        do {
+            try db.run(index.create(.FTS5(
+                FTS5Config()
+                  .column(email)
+                  .tokenizer(.Trigram(caseSensitive: false)))
+            ))
+        } catch let error as Result {
+            try XCTSkipIf(error.description.starts(with: "no such model") ||
+                          error.description.starts(with: "parse error in"))
+            throw error
+        }
 
         for user in try db.prepare(users) {
             try db.run(index.insert(email <- user[email]))

From 7f98a7b34b362a8776a429fcbc2359ae11b78aee Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 26 Aug 2021 01:12:21 +0200
Subject: [PATCH 442/685] Move into method

---
 Tests/SQLiteTests/FTSIntegrationTests.swift | 22 ++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/Tests/SQLiteTests/FTSIntegrationTests.swift b/Tests/SQLiteTests/FTSIntegrationTests.swift
index d629ca8b..da9ba8dc 100644
--- a/Tests/SQLiteTests/FTSIntegrationTests.swift
+++ b/Tests/SQLiteTests/FTSIntegrationTests.swift
@@ -15,15 +15,12 @@ class FTSIntegrationTests: SQLiteTestCase {
     let index = VirtualTable("index")
 
     private func createIndex() throws {
-        do {
+        try createOrSkip { db in
             try db.run(index.create(.FTS5(
                 FTS5Config()
                     .column(email)
                     .tokenizer(.Unicode61()))
             ))
-        } catch let error as Result {
-            try XCTSkipIf(error.description.starts(with: "no such model"))
-            throw error
         }
 
         for user in try db.prepare(users) {
@@ -32,16 +29,12 @@ class FTSIntegrationTests: SQLiteTestCase {
     }
 
     private func createTrigramIndex() throws {
-        do {
+        try createOrSkip { db in
             try db.run(index.create(.FTS5(
                 FTS5Config()
                   .column(email)
                   .tokenizer(.Trigram(caseSensitive: false)))
             ))
-        } catch let error as Result {
-            try XCTSkipIf(error.description.starts(with: "no such model") ||
-                          error.description.starts(with: "parse error in"))
-            throw error
         }
 
         for user in try db.prepare(users) {
@@ -73,4 +66,15 @@ class FTSIntegrationTests: SQLiteTestCase {
         let matches = Array(try db.prepare(index.match("Paul")))
         XCTAssertEqual(1, matches.count)
     }
+
+    private func createOrSkip(_ createIndex: (Connection) throws -> Void) throws {
+        do {
+            try createIndex(db)
+        } catch let error as Result {
+            try XCTSkipIf(error.description.starts(with: "no such module:") ||
+                          error.description.starts(with: "parse error")
+            )
+            throw error
+        }
+    }
 }

From 7e6d8b98d47c3cf7cfcb60d63fff17868eefd8c0 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Thu, 26 Aug 2021 14:24:52 +0200
Subject: [PATCH 443/685] Reverting a change in `FailableIterator`

---
 Sources/SQLite/Core/Statement.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index 48347c31..abeee24b 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -207,7 +207,7 @@ public protocol FailableIterator: IteratorProtocol {
 
 extension FailableIterator {
     public func next() -> Element? {
-        try? failableNext()
+        try! failableNext()
     }
 }
 

From 62fe865ae8b80bab15f373dfeefae04df3b555ea Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Thu, 26 Aug 2021 14:33:12 +0200
Subject: [PATCH 444/685] Fix linting

---
 Sources/SQLite/Core/Statement.swift | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index abeee24b..29d6938d 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -207,6 +207,7 @@ public protocol FailableIterator: IteratorProtocol {
 
 extension FailableIterator {
     public func next() -> Element? {
+        // swiftlint:disable:next force_cast
         try! failableNext()
     }
 }

From 870cf7b2cebe315a5e05176ca05a111cd8ab39f6 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Thu, 26 Aug 2021 15:04:55 +0200
Subject: [PATCH 445/685] Fix linting

---
 Sources/SQLite/Core/Statement.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index 29d6938d..1e2489b5 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -207,7 +207,7 @@ public protocol FailableIterator: IteratorProtocol {
 
 extension FailableIterator {
     public func next() -> Element? {
-        // swiftlint:disable:next force_cast
+        // swiftlint:disable:next force_try
         try! failableNext()
     }
 }

From 86c3f6a580fcc335694f12c90515d15671a35636 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 5 Sep 2021 17:23:39 +0200
Subject: [PATCH 446/685] Add SPM integration test

---
 .github/workflows/build.yml       |   4 ++++
 Package.swift                     |   6 +++++-
 Tests/SPM/.gitignore              |   7 +++++++
 Tests/SPM/Package.swift           |  19 +++++++++++++++++++
 Tests/SPM/Sources/test/main.swift |  11 +++++++++++
 Tests/SPM/db.sqlite               | Bin 0 -> 8192 bytes
 run-tests.sh                      |   2 ++
 7 files changed, 48 insertions(+), 1 deletion(-)
 create mode 100644 Tests/SPM/.gitignore
 create mode 100644 Tests/SPM/Package.swift
 create mode 100644 Tests/SPM/Sources/test/main.swift
 create mode 100644 Tests/SPM/db.sqlite

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 51654fba..60d487bd 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -21,6 +21,10 @@ jobs:
       env:
         PACKAGE_MANAGER_COMMAND: test -Xswiftc -warnings-as-errors
       run: ./run-tests.sh
+    - name: "Run tests (SPM integration test)"
+      env:
+        SPM: run
+      run: ./run-tests.sh
     - name: "Run tests (BUILD_SCHEME: SQLite iOS)"
       env:
         BUILD_SCHEME: SQLite iOS
diff --git a/Package.swift b/Package.swift
index c1373ad8..f4938678 100644
--- a/Package.swift
+++ b/Package.swift
@@ -44,7 +44,11 @@ let package = Package(
 #if os(Linux)
 package.dependencies = [.package(url: "https://github.com/stephencelis/CSQLite.git", from: "0.0.3")]
 package.targets = [
-    .target(name: "SQLite", exclude: ["Extensions/FTS4.swift", "Extensions/FTS5.swift"]),
+    .target(
+        name: "SQLite",
+        dependencies: [.product(name: "CSQLite", package: "CSQLite")],
+        exclude: ["Extensions/FTS4.swift", "Extensions/FTS5.swift"]
+    ),
     .testTarget(name: "SQLiteTests", dependencies: ["SQLite"], path: "Tests/SQLiteTests", exclude: [
         "FTSIntegrationTests.swift",
         "FTS4Tests.swift",
diff --git a/Tests/SPM/.gitignore b/Tests/SPM/.gitignore
new file mode 100644
index 00000000..bb460e7b
--- /dev/null
+++ b/Tests/SPM/.gitignore
@@ -0,0 +1,7 @@
+.DS_Store
+/.build
+/Packages
+/*.xcodeproj
+xcuserdata/
+DerivedData/
+.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
diff --git a/Tests/SPM/Package.swift b/Tests/SPM/Package.swift
new file mode 100644
index 00000000..810026ce
--- /dev/null
+++ b/Tests/SPM/Package.swift
@@ -0,0 +1,19 @@
+// swift-tools-version:5.3
+// The swift-tools-version declares the minimum version of Swift required to build this package.
+
+import PackageDescription
+
+let package = Package(
+    name: "test",
+    dependencies: [
+        .package(path: "../..")
+    ],
+    targets: [
+        // Targets are the basic building blocks of a package. A target can define a module or a test suite.
+        // Targets can depend on other targets in this package, and on products in packages this package depends on.
+        .target(
+            name: "test",
+            dependencies: [.product(name: "SQLite", package: "SQLite.swift")]
+	)
+    ]
+)
diff --git a/Tests/SPM/Sources/test/main.swift b/Tests/SPM/Sources/test/main.swift
new file mode 100644
index 00000000..94f12af8
--- /dev/null
+++ b/Tests/SPM/Sources/test/main.swift
@@ -0,0 +1,11 @@
+import SQLite 
+
+let table = Table("test")
+let name = Expression<String>("name")
+
+let db = try Connection("db.sqlite", readonly: true)
+
+for row in try db.prepare(table) {
+    print(row[name])
+}
+
diff --git a/Tests/SPM/db.sqlite b/Tests/SPM/db.sqlite
new file mode 100644
index 0000000000000000000000000000000000000000..f7b2e84c051df3ffdddb463bdd0dd990358789cb
GIT binary patch
diff --git a/run-tests.sh b/run-tests.sh
index 32465388..5f397553 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -14,6 +14,8 @@ elif [ -n "$VALIDATOR_SUBSPEC" ]; then
     fi
 elif [ -n "$CARTHAGE_PLATFORM" ]; then
     cd Tests/Carthage && make test CARTHAGE_PLATFORM="$CARTHAGE_PLATFORM"
+elif [ -n "$SPM" ]; then
+    cd Tests/SPM && swift run
 elif [ -n "${PACKAGE_MANAGER_COMMAND}" ]; then
     swift ${PACKAGE_MANAGER_COMMAND}
 fi

From 79eee35ca996dd0653bc06a823f4394c61b0a3d8 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 5 Sep 2021 17:31:38 +0200
Subject: [PATCH 447/685] Lint fix

---
 .github/workflows/build.yml       | 4 ++++
 Tests/SPM/Sources/test/main.swift | 3 +--
 run-tests.sh                      | 2 +-
 3 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 60d487bd..88c5803f 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -75,3 +75,7 @@ jobs:
         sudo apt-get install -y libsqlite3-dev
     - name: Test
       run: swift test
+    - name: "Run tests (SPM integration test)"
+      env:
+        SPM: run
+      run: ./run-tests.sh
diff --git a/Tests/SPM/Sources/test/main.swift b/Tests/SPM/Sources/test/main.swift
index 94f12af8..939b3391 100644
--- a/Tests/SPM/Sources/test/main.swift
+++ b/Tests/SPM/Sources/test/main.swift
@@ -1,4 +1,4 @@
-import SQLite 
+import SQLite
 
 let table = Table("test")
 let name = Expression<String>("name")
@@ -8,4 +8,3 @@ let db = try Connection("db.sqlite", readonly: true)
 for row in try db.prepare(table) {
     print(row[name])
 }
-
diff --git a/run-tests.sh b/run-tests.sh
index 5f397553..49330c12 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -15,7 +15,7 @@ elif [ -n "$VALIDATOR_SUBSPEC" ]; then
 elif [ -n "$CARTHAGE_PLATFORM" ]; then
     cd Tests/Carthage && make test CARTHAGE_PLATFORM="$CARTHAGE_PLATFORM"
 elif [ -n "$SPM" ]; then
-    cd Tests/SPM && swift run
+    cd Tests/SPM && swift ${SPM}
 elif [ -n "${PACKAGE_MANAGER_COMMAND}" ]; then
     swift ${PACKAGE_MANAGER_COMMAND}
 fi

From 09f730eaa8848ff3387bccaddbf573751694f876 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 6 Sep 2021 00:43:50 +0200
Subject: [PATCH 448/685] Update documentation

- Closes #1076
- Clarify BusyHandler usage (Closes #786)
- Integrate playground into project
---
 CHANGELOG.md                                  |  4 +
 Documentation/Index.md                        | 90 ++++++++++++++++---
 Documentation/Planning.md                     |  2 +-
 Documentation/Release.md                      |  1 +
 README.md                                     |  9 +-
 SQLite.playground/Contents.swift              | 78 +++++++++++++---
 SQLite.playground/contents.xcplayground       |  2 +-
 .../contents.xcworkspacedata                  |  7 ++
 SQLite.xcodeproj/project.pbxproj              |  2 +
 .../SQLite/Core/Connection+Aggregation.swift  |  4 +-
 Tests/SPM/Package.swift                       |  5 +-
 11 files changed, 167 insertions(+), 37 deletions(-)
 create mode 100644 SQLite.playground/playground.xcworkspace/contents.xcworkspacedata

diff --git a/CHANGELOG.md b/CHANGELOG.md
index fc09fa40..c9d09c12 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,8 @@
 
 * Support for database backup ([#919][])
 * Support for custom SQL aggregates ([#881][])
+* Restore previous iteration behavior ([#1075][])
+* Fix compilation on Linux ([#1077][])
 
 0.13.0 (22-08-2021), [diff][diff-0.13.0]
 ========================================
@@ -124,3 +126,5 @@
 [#866]: https://github.com/stephencelis/SQLite.swift/pull/866
 [#881]: https://github.com/stephencelis/SQLite.swift/pull/881
 [#919]: https://github.com/stephencelis/SQLite.swift/pull/919
+[#1075]: https://github.com/stephencelis/SQLite.swift/pull/1075
+[#1077]: https://github.com/stephencelis/SQLite.swift/issues/1077
diff --git a/Documentation/Index.md b/Documentation/Index.md
index fce068a2..1e08f6c4 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -77,9 +77,6 @@ The [Swift Package Manager][] is a tool for managing the distribution of
 Swift code. It’s integrated with the Swift build system to automate the
 process of downloading, compiling, and linking dependencies.
 
-It is the recommended approach for using SQLite.swift in OSX CLI
-applications.
-
  1. Add the following to your `Package.swift` file:
 
   ```swift
@@ -342,16 +339,15 @@ execution and can be safely accessed across threads. Threads that open
 transactions and savepoints will block other threads from executing
 statements while the transaction is open.
 
-If you maintain multiple connections for a single database, consider setting a timeout (in seconds) and/or a busy handler:
+If you maintain multiple connections for a single database, consider setting a timeout
+(in seconds) *or* a busy handler. There can only be one active at a time, so setting a busy
+handler will effectively override `busyTimeout`.
 
 ```swift
-db.busyTimeout = 5
+db.busyTimeout = 5 // error after 5 seconds (does multiple retries)
 
 db.busyHandler({ tries in
-    if tries >= 3 {
-        return false
-    }
-    return true
+    tries < 3  // error after 3 tries
 })
 ```
 
@@ -656,12 +652,13 @@ do {
 }
 ```
 
-Multiple rows can be inserted at once by similarily calling `insertMany` with an array of per-row [setters](#setters).
+Multiple rows can be inserted at once by similarily calling `insertMany` with an array of
+per-row [setters](#setters).
 
 ```swift
 do {
-    let rowid = try db.run(users.insertMany([mail <- "alice@mac.com"], [email <- "geoff@mac.com"]))
-    print("inserted id: \(rowid)")
+    let lastRowid = try db.run(users.insertMany([mail <- "alice@mac.com"], [email <- "geoff@mac.com"]))
+    print("last inserted id: \(lastRowid)")
 } catch {
     print("insertion failed: \(error)")
 }
@@ -799,6 +796,33 @@ for user in try db.prepare(users) {
 }
 ```
 
+Note that the iterator can throw *undeclared* database errors at any point during
+iteration:
+
+```swift
+let query = try db.prepare(users)
+for user in query {
+    // 💥 can throw an error here
+}
+````
+
+#### Failable iteration
+
+It is therefore recommended using the `RowIterator` API instead,
+which has explicit error handling:
+
+```swift
+let rowIterator = try db.prepareRowIterator(users)
+for user in try Array(rowIterator) {
+    print("id: \(user[id]), email: \(user[email])")
+}
+
+/// or using `map()`
+let mapRowIterator = try db.prepareRowIterator(users)
+let userIds = try mapRowIterator.map { $0[id] }
+
+```
+
 ### Plucking Rows
 
 We can pluck the first row by passing a query to the `pluck` function on a
@@ -1285,7 +1309,6 @@ try db.run(users.addColumn(suffix))
 // ALTER TABLE "users" ADD COLUMN "suffix" TEXT
 ```
 
-
 #### Added Column Constraints
 
 The `addColumn` function shares several of the same [`column` function
@@ -1337,6 +1360,13 @@ tables](#creating-a-table).
     // ALTER TABLE "posts" ADD COLUMN "user_id" INTEGER REFERENCES "users" ("id")
     ```
 
+### Renaming Columns
+
+Added in SQLite 3.25.0, not exposed yet. [#1073](https://github.com/stephencelis/SQLite.swift/issues/1073)
+
+### Dropping Columns
+
+Added in SQLite 3.35.0, not exposed yet. [#1073](https://github.com/stephencelis/SQLite.swift/issues/1073)
 
 ### Indexes
 
@@ -1762,6 +1792,19 @@ for row in stmt.bind(kUTTypeImage) { /* ... */ }
 
 [UTTypeConformsTo]: https://developer.apple.com/documentation/coreservices/1444079-uttypeconformsto
 
+## Custom Aggregations
+
+We can create custom aggregation functions by calling `createAggregation`:
+
+```swift
+let reduce: (String, [Binding?]) -> String = { (last, bindings) in
+    last + " " + (bindings.first as? String ?? "")
+}
+
+db.createAggregation("customConcat", initialValue: "", reduce: reduce, result: { $0 })
+let result = db.prepare("SELECT customConcat(email) FROM users").scalar() as! String
+```
+
 ## Custom Collations
 
 We can create custom collating sequences by calling `createCollation` on a
@@ -1944,6 +1987,19 @@ using the following functions.
     let count = try stmt.scalar() as! Int64
     ```
 
+## Online Database Backup
+
+To copy a database to another using the
+[SQLite Online Backup API](https://sqlite.org/backup.html):
+
+```swift
+// creates an in-memory copy of db.sqlite
+let db = try Connection("db.sqlite")
+let target = try Connection(.inMemory)
+
+let backup = try db.backup(usingConnection: target)
+try backup.step()
+```
 
 ## Logging
 
@@ -1955,6 +2011,14 @@ We can log SQL using the database’s `trace` function.
 #endif
 ```
 
+## Vacuum
+
+To run the [vacuum](https://www.sqlite.org/lang_vacuum.html) command:
+
+```swift
+try db.vacuum()
+```
+
 
 [ROWID]: https://sqlite.org/lang_createtable.html#rowid
 [SQLiteMigrationManager.swift]: https://github.com/garriguv/SQLiteMigrationManager.swift
diff --git a/Documentation/Planning.md b/Documentation/Planning.md
index 62df1f24..44e02c7a 100644
--- a/Documentation/Planning.md
+++ b/Documentation/Planning.md
@@ -6,7 +6,7 @@ additions and Pull Requests, as well as to keep the Issues list clear of
 enhancement requests so that bugs are more visible.
 
 > ⚠ This document is currently not actively maintained. See
-> the [0.13.0 milestone](https://github.com/stephencelis/SQLite.swift/issues?q=is%3Aopen+is%3Aissue+milestone%3A0.13.0)
+> the [0.13.1 milestone](https://github.com/stephencelis/SQLite.swift/issues?q=is%3Aopen+is%3Aissue+milestone%3A0.13.1)
 > on Github for additional information about planned features for the next release.
 
 ## Roadmap
diff --git a/Documentation/Release.md b/Documentation/Release.md
index 0177fc8f..87d715f6 100644
--- a/Documentation/Release.md
+++ b/Documentation/Release.md
@@ -1,6 +1,7 @@
 # SQLite.swift Release checklist
 
 * [ ] Make sure current master branch has a green build
+* [ ] Make sure `SQLite.playground` runs without errors
 * [ ] Make sure `CHANGELOG.md` is up-to-date
 * [ ] Update the version number in `SQLite.swift.podspec`
 * [ ] Run `pod lib lint` locally
diff --git a/README.md b/README.md
index 9242b200..ec92729f 100644
--- a/README.md
+++ b/README.md
@@ -146,6 +146,8 @@ Swift code.
   $ swift build
   ```
 
+See the [Tests/SPM](https://github.com/stephencelis/SQLite.swift/tree/master/Tests/SPM) folder for a small demo project which uses SPM.
+
 [Swift Package Manager]: https://swift.org/package-manager
 
 ### Carthage
@@ -175,8 +177,7 @@ install SQLite.swift with Carthage:
 [CocoaPods][] is a dependency manager for Cocoa projects. To install
 SQLite.swift with CocoaPods:
 
- 1. Make sure CocoaPods is [installed][CocoaPods Installation]. (SQLite.swift
-    requires version 1.6.1 or greater.)
+ 1. Make sure CocoaPods is [installed][CocoaPods Installation].
 
     ```sh
     # Using the default Ruby install will require you to use sudo when
@@ -266,7 +267,8 @@ These projects enhance or use SQLite.swift:
 
  - [SQLiteMigrationManager.swift][] (inspired by
    [FMDBMigrationManager][])
- - [Delta: Math helper](https://apps.apple.com/app/delta-math-helper/id1436506800) (see [Delta/Utils/Database.swift](https://github.com/GroupeMINASTE/Delta-iOS/blob/master/Delta/Utils/Database.swift) for production implementation example)
+ - [Delta: Math helper](https://apps.apple.com/app/delta-math-helper/id1436506800)
+   (see [Delta/Utils/Database.swift](https://github.com/GroupeMINASTE/Delta-iOS/blob/master/Delta/Utils/Database.swift) for production implementation example)
 
 
 ## Alternatives
@@ -278,7 +280,6 @@ Looking for something else? Try another Swift wrapper (or [FMDB][]):
  - [SQLiteDB](https://github.com/FahimF/SQLiteDB)
  - [Squeal](https://github.com/nerdyc/Squeal)
  - [SwiftData](https://github.com/ryanfowler/SwiftData)
- - [SwiftSQLite](https://github.com/chrismsimpson/SwiftSQLite)
 
 [Swift]: https://swift.org/
 [SQLite3]: https://www.sqlite.org
diff --git a/SQLite.playground/Contents.swift b/SQLite.playground/Contents.swift
index 11e13139..ebd5b020 100644
--- a/SQLite.playground/Contents.swift
+++ b/SQLite.playground/Contents.swift
@@ -1,43 +1,93 @@
 import SQLite
 
-let db = try! Connection()
+/// Create an in-memory database
+let db = try Connection(.inMemory)
 
+/// enable statement logging
 db.trace { print($0) }
 
+/// define a "users" table with some fields
 let users = Table("users")
 
 let id = Expression<Int64>("id")
-let email = Expression<String>("email")
-let name = Expression<String?>("name")
+let email = Expression<String>("email") // non-null
+let name = Expression<String?>("name")  // nullable
 
-try! db.run(users.create { t in
+/// prepare the query
+let statement = users.create { t in
     t.column(id, primaryKey: true)
     t.column(email, unique: true, check: email.like("%@%"))
     t.column(name)
-})
+}
+
+/// …and run it
+try db.run(statement)
+
+/// insert "alice"
+let rowid = try db.run(users.insert(email <- "alice@mac.com"))
+
+/// insert multiple rows using `insertMany`
+let lastRowid = try db.run(users.insertMany([
+  [email <- "bob@mac.com"],
+  [email <- "mallory@evil.com"]
+]))
+
+
+let query = try db.prepare(users)
+for user in query {
+    print("id: \(user[id]), email: \(user[email])")
+}
 
-let rowid = try! db.run(users.insert(email <- "alice@mac.com"))
-let alice = users.filter(id == rowid)
+// re-requery just rowid of Alice
+let alice = try db.prepare(users.filter(id == rowid))
+for user in alice {
+    print("id: \(user[id]), email: \(user[email])")
+}
 
-for user in try! db.prepare(users) {
+/// using the `RowIterator` API
+let rowIterator = try db.prepareRowIterator(users)
+for user in try Array(rowIterator) {
     print("id: \(user[id]), email: \(user[email])")
 }
 
+/// also with `map()`
+let mapRowIterator = try db.prepareRowIterator(users)
+let userIds = try mapRowIterator.map { $0[id] }
+
+/// define a virtual tabe for the FTS index
 let emails = VirtualTable("emails")
 
-let subject = Expression<String?>("subject")
+let subject = Expression<String>("subject")
 let body = Expression<String?>("body")
 
-try! db.run(emails.create(.FTS4(subject, body)))
+/// create the index
+try db.run(emails.create(.FTS5(
+    FTS5Config()
+      .column(subject)
+      .column(body)
+)))
 
-try! db.run(emails.insert(
+/// populate with data
+try db.run(emails.insert(
     subject <- "Hello, world!",
     body <- "This is a hello world message."
 ))
 
-let row = try! db.pluck(emails.match("hello"))
+/// run a query
+let ftsQuery = try db.prepare(emails.match("hello"))
 
-let query = try! db.prepare(emails.match("hello"))
-for row in query {
+for row in ftsQuery {
     print(row[subject])
 }
+
+/// custom aggregations
+let reduce: (String, [Binding?]) -> String = { (last, bindings) in
+    last + " " + (bindings.first as? String ?? "")
+}
+
+db.createAggregation("customConcat",
+                     initialValue: "users:",
+                     reduce: reduce,
+                     result: { $0 })
+let result = db.prepare("SELECT customConcat(email) FROM users").scalar() as! String
+print(result)
diff --git a/SQLite.playground/contents.xcplayground b/SQLite.playground/contents.xcplayground
index fd676d5b..441c60ef 100644
--- a/SQLite.playground/contents.xcplayground
+++ b/SQLite.playground/contents.xcplayground
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<playground version='5.0' target-platform='osx' display-mode='raw'>
+<playground version='5.0' target-platform='macos' display-mode='rendered' buildActiveScheme='true' importAppTypes='true'>
     <timeline fileName='timeline.xctimeline'/>
 </playground>
\ No newline at end of file
diff --git a/SQLite.playground/playground.xcworkspace/contents.xcworkspacedata b/SQLite.playground/playground.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 00000000..919434a6
--- /dev/null
+++ b/SQLite.playground/playground.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:">
+   </FileRef>
+</Workspace>
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 92400180..ba14e9ae 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -256,6 +256,7 @@
 		19A17E723300E5ED3771DCB5 /* Result.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Result.swift; sourceTree = "<group>"; };
 		19A17EA3A313F129011B3FA0 /* Release.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Release.md; sourceTree = "<group>"; };
 		3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomAggregationTests.swift; sourceTree = "<group>"; };
+		3D3C3CCB26E5568800759140 /* SQLite.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = SQLite.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
 		3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.0.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
 		3DDC112E26CDBA0200CE369F /* SQLiteObjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SQLiteObjc.h; path = ../SQLiteObjc/include/SQLiteObjc.h; sourceTree = "<group>"; };
 		49EB68C31F7B3CB400D89D40 /* Coding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coding.swift; sourceTree = "<group>"; };
@@ -386,6 +387,7 @@
 			children = (
 				EE247AD51C3F04ED00AE3E12 /* SQLite */,
 				EE247AE11C3F04ED00AE3E12 /* SQLiteTests */,
+				3D3C3CCB26E5568800759140 /* SQLite.playground */,
 				EE247B8A1C3F81D000AE3E12 /* Metadata */,
 				EE247AD41C3F04ED00AE3E12 /* Products */,
 				3D67B3E41DB2469200A4F4C6 /* Frameworks */,
diff --git a/Sources/SQLite/Core/Connection+Aggregation.swift b/Sources/SQLite/Core/Connection+Aggregation.swift
index 106f292c..4eea76c3 100644
--- a/Sources/SQLite/Core/Connection+Aggregation.swift
+++ b/Sources/SQLite/Core/Connection+Aggregation.swift
@@ -90,7 +90,7 @@ extension Connection {
         register(functionName, argc: argc, value: box)
     }
 
-    func createAggregation<T: AnyObject>(
+    public func createAggregation<T: AnyObject>(
             _ aggregate: String,
             argumentCount: UInt? = nil,
             deterministic: Bool = false,
@@ -122,7 +122,7 @@ extension Connection {
         createAggregation(aggregate, step: step, final: final, state: state)
     }
 
-    func createAggregation<T>(
+    public func createAggregation<T>(
             _ aggregate: String,
             argumentCount: UInt? = nil,
             deterministic: Bool = false,
diff --git a/Tests/SPM/Package.swift b/Tests/SPM/Package.swift
index 810026ce..265021e5 100644
--- a/Tests/SPM/Package.swift
+++ b/Tests/SPM/Package.swift
@@ -6,11 +6,12 @@ import PackageDescription
 let package = Package(
     name: "test",
     dependencies: [
+        // for testing from same repository
         .package(path: "../..")
+        // normally this would be:
+        // .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.13.0")
     ],
     targets: [
-        // Targets are the basic building blocks of a package. A target can define a module or a test suite.
-        // Targets can depend on other targets in this package, and on products in packages this package depends on.
         .target(
             name: "test",
             dependencies: [.product(name: "SQLite", package: "SQLite.swift")]

From ab67978f154c404e05a6a634cca30fa0206d1dd0 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 6 Sep 2021 01:00:54 +0200
Subject: [PATCH 449/685] Update screenshot

---
 Documentation/Resources/playground@2x.png | Bin 124729 -> 409028 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)

diff --git a/Documentation/Resources/playground@2x.png b/Documentation/Resources/playground@2x.png
index 32646d6aa411b7b5a7163fc692c7252fe8ee8cce..da132718cf4bc7d2cafdff82eb5020abcb46ec93 100644
GIT binary patch

From 84a878807af8e6f317a2451937567ec82a6f80d9 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 7 Sep 2021 12:57:15 +0200
Subject: [PATCH 450/685] Clarify usage

---
 Documentation/Index.md | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 1e08f6c4..1f702653 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -812,15 +812,24 @@ It is therefore recommended using the `RowIterator` API instead,
 which has explicit error handling:
 
 ```swift
+// option 1: convert results into an Array of rows
 let rowIterator = try db.prepareRowIterator(users)
 for user in try Array(rowIterator) {
     print("id: \(user[id]), email: \(user[email])")
 }
 
-/// or using `map()`
+/// option 2: transform results using `map()`
 let mapRowIterator = try db.prepareRowIterator(users)
 let userIds = try mapRowIterator.map { $0[id] }
 
+/// option 3: handle each row individually with `failableNext()`
+do {
+    while let row = try rowIterator.failableNext() {
+        // Handle row
+    }
+} catch {
+    // Handle error
+}
 ```
 
 ### Plucking Rows

From e191c7d04583a1fd4e0f95e73bec2161a30e4857 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 7 Sep 2021 13:04:24 +0200
Subject: [PATCH 451/685] Add failableNext() example to playground

---
 SQLite.playground/Contents.swift | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/SQLite.playground/Contents.swift b/SQLite.playground/Contents.swift
index ebd5b020..c089076d 100644
--- a/SQLite.playground/Contents.swift
+++ b/SQLite.playground/Contents.swift
@@ -54,6 +54,16 @@ for user in try Array(rowIterator) {
 let mapRowIterator = try db.prepareRowIterator(users)
 let userIds = try mapRowIterator.map { $0[id] }
 
+/// using `failableNext()` on `RowIterator`
+let iterator = try db.prepareRowIterator(users)
+do {
+    while let row = try rowIterator.failableNext() {
+        print(row)
+    }
+} catch {
+    // Handle error
+}
+
 /// define a virtual tabe for the FTS index
 let emails = VirtualTable("emails")
 

From 818af0882507b0e468c9ec40fa2149a52a4ad171 Mon Sep 17 00:00:00 2001
From: Calvin Cestari <calvin.cestari@gmail.com>
Date: Wed, 3 Nov 2021 12:59:38 -0700
Subject: [PATCH 452/685] Add platform versions to the SPM manifest

---
 Package.swift | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/Package.swift b/Package.swift
index f4938678..47c00b37 100644
--- a/Package.swift
+++ b/Package.swift
@@ -3,6 +3,12 @@ import PackageDescription
 
 let package = Package(
     name: "SQLite.swift",
+    platforms: [
+        .iOS(.v9),
+        .macOS(.v10_15),
+        .watchOS(.v3),
+        .tvOS(.v9)
+    ],
     products: [
         .library(
             name: "SQLite",
@@ -46,6 +52,12 @@ package.dependencies = [.package(url: "https://github.com/stephencelis/CSQLite.g
 package.targets = [
     .target(
         name: "SQLite",
+        platforms: [
+            .iOS(.v9),
+            .macOS(.v10_15),
+            .watchOS(.v3),
+            .tvOS(.v9)
+        ],
         dependencies: [.product(name: "CSQLite", package: "CSQLite")],
         exclude: ["Extensions/FTS4.swift", "Extensions/FTS5.swift"]
     ),

From 9af505317fff1d9129a4c905fa2e8757c3484fc0 Mon Sep 17 00:00:00 2001
From: Calvin Cestari <calvin.cestari@gmail.com>
Date: Wed, 3 Nov 2021 13:00:23 -0700
Subject: [PATCH 453/685] Move XCode deployment version from targets to project

---
 SQLite.xcodeproj/project.pbxproj | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index ba14e9ae..aecb424a 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1099,7 +1099,6 @@
 				SDKROOT = appletvos;
 				SKIP_INSTALL = YES;
 				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
-				TVOS_DEPLOYMENT_TARGET = 12.0;
 			};
 			name = Debug;
 		};
@@ -1121,7 +1120,6 @@
 				SDKROOT = appletvos;
 				SKIP_INSTALL = YES;
 				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
-				TVOS_DEPLOYMENT_TARGET = 12.0;
 			};
 			name = Release;
 		};
@@ -1135,7 +1133,6 @@
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = appletvos;
 				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
-				TVOS_DEPLOYMENT_TARGET = 12.0;
 			};
 			name = Debug;
 		};
@@ -1149,7 +1146,6 @@
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = appletvos;
 				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
-				TVOS_DEPLOYMENT_TARGET = 12.0;
 			};
 			name = Release;
 		};
@@ -1173,7 +1169,6 @@
 				SKIP_INSTALL = YES;
 				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
 				TARGETED_DEVICE_FAMILY = 4;
-				WATCHOS_DEPLOYMENT_TARGET = 3.0;
 			};
 			name = Debug;
 		};
@@ -1197,7 +1192,6 @@
 				SKIP_INSTALL = YES;
 				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
 				TARGETED_DEVICE_FAMILY = 4;
-				WATCHOS_DEPLOYMENT_TARGET = 3.0;
 			};
 			name = Release;
 		};
@@ -1259,8 +1253,10 @@
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
 				SWIFT_VERSION = 5.0;
 				TARGETED_DEVICE_FAMILY = "1,2,3";
+				TVOS_DEPLOYMENT_TARGET = 9.1;
 				VERSIONING_SYSTEM = "apple-generic";
 				VERSION_INFO_PREFIX = "";
+				WATCHOS_DEPLOYMENT_TARGET = 3.0;
 			};
 			name = Debug;
 		};
@@ -1315,9 +1311,11 @@
 				SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
 				SWIFT_VERSION = 5.0;
 				TARGETED_DEVICE_FAMILY = "1,2,3";
+				TVOS_DEPLOYMENT_TARGET = 9.1;
 				VALIDATE_PRODUCT = YES;
 				VERSIONING_SYSTEM = "apple-generic";
 				VERSION_INFO_PREFIX = "";
+				WATCHOS_DEPLOYMENT_TARGET = 3.0;
 			};
 			name = Release;
 		};
@@ -1334,7 +1332,6 @@
 				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
-				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				MARKETING_VERSION = 0.13.0;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
@@ -1358,7 +1355,6 @@
 				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
-				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				MARKETING_VERSION = 0.13.0;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;

From d6eb85b381da062ffe2db30739f868607dc1c4c9 Mon Sep 17 00:00:00 2001
From: Calvin Cestari <calvin.cestari@gmail.com>
Date: Fri, 5 Nov 2021 12:13:00 -0700
Subject: [PATCH 454/685] Fix test platform versions

---
 Package.swift           | 6 ------
 Tests/SPM/Package.swift | 6 ++++++
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/Package.swift b/Package.swift
index 47c00b37..abce8395 100644
--- a/Package.swift
+++ b/Package.swift
@@ -52,12 +52,6 @@ package.dependencies = [.package(url: "https://github.com/stephencelis/CSQLite.g
 package.targets = [
     .target(
         name: "SQLite",
-        platforms: [
-            .iOS(.v9),
-            .macOS(.v10_15),
-            .watchOS(.v3),
-            .tvOS(.v9)
-        ],
         dependencies: [.product(name: "CSQLite", package: "CSQLite")],
         exclude: ["Extensions/FTS4.swift", "Extensions/FTS5.swift"]
     ),
diff --git a/Tests/SPM/Package.swift b/Tests/SPM/Package.swift
index 265021e5..91c0c6d1 100644
--- a/Tests/SPM/Package.swift
+++ b/Tests/SPM/Package.swift
@@ -5,6 +5,12 @@ import PackageDescription
 
 let package = Package(
     name: "test",
+    platforms: [
+        .iOS(.v9),
+        .macOS(.v10_15),
+        .watchOS(.v3),
+        .tvOS(.v9)
+    ],
     dependencies: [
         // for testing from same repository
         .package(path: "../..")

From d02d0b4090f855acca24e105f2f684c7f71dc9a1 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 5 Nov 2021 21:20:10 +0100
Subject: [PATCH 455/685] Move OSX deployment target back to 10.10

---
 Package.swift                    | 2 +-
 SQLite.swift.podspec             | 2 +-
 SQLite.xcodeproj/project.pbxproj | 4 ++--
 Tests/SPM/Package.swift          | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/Package.swift b/Package.swift
index abce8395..24898bca 100644
--- a/Package.swift
+++ b/Package.swift
@@ -5,7 +5,7 @@ let package = Package(
     name: "SQLite.swift",
     platforms: [
         .iOS(.v9),
-        .macOS(.v10_15),
+        .macOS(.v10_10),
         .watchOS(.v3),
         .tvOS(.v9)
     ],
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index f273ffd8..80871b0b 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -20,7 +20,7 @@ Pod::Spec.new do |s|
 
   ios_deployment_target = '9.0'
   tvos_deployment_target = '9.1'
-  osx_deployment_target = '10.15'
+  osx_deployment_target = '10.10'
   watchos_deployment_target = '3.0'
 
   s.ios.deployment_target = ios_deployment_target
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index aecb424a..ecc1195c 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1245,7 +1245,7 @@
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
-				MACOSX_DEPLOYMENT_TARGET = 10.15;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
 				MTL_ENABLE_DEBUG_INFO = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				PRODUCT_NAME = "";
@@ -1304,7 +1304,7 @@
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
-				MACOSX_DEPLOYMENT_TARGET = 10.15;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				PRODUCT_NAME = "";
 				SDKROOT = iphoneos;
diff --git a/Tests/SPM/Package.swift b/Tests/SPM/Package.swift
index 91c0c6d1..dd1cd45c 100644
--- a/Tests/SPM/Package.swift
+++ b/Tests/SPM/Package.swift
@@ -7,7 +7,7 @@ let package = Package(
     name: "test",
     platforms: [
         .iOS(.v9),
-        .macOS(.v10_15),
+        .macOS(.v10_10),
         .watchOS(.v3),
         .tvOS(.v9)
     ],

From 34798be5eb2cc057040903839ba732b5cab7c02c Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 5 Nov 2021 21:32:17 +0100
Subject: [PATCH 456/685] Update changelog

---
 CHANGELOG.md | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c9d09c12..a36c6468 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,8 @@
 * Support for custom SQL aggregates ([#881][])
 * Restore previous iteration behavior ([#1075][])
 * Fix compilation on Linux ([#1077][])
+* Align platform versions in SPM manifest and Xcode ([#1094][])
+* Revert OSX deployment target back to 10.10 ([#1095][])
 
 0.13.0 (22-08-2021), [diff][diff-0.13.0]
 ========================================
@@ -128,3 +130,5 @@
 [#919]: https://github.com/stephencelis/SQLite.swift/pull/919
 [#1075]: https://github.com/stephencelis/SQLite.swift/pull/1075
 [#1077]: https://github.com/stephencelis/SQLite.swift/issues/1077
+[#1094]: https://github.com/stephencelis/SQLite.swift/pull/1094
+[#1095]: https://github.com/stephencelis/SQLite.swift/pull/1095
\ No newline at end of file

From 883117cbc847508192d2961f7833e9da5a4c5f6d Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 5 Nov 2021 21:42:45 +0100
Subject: [PATCH 457/685] "macos-latest" is not the latest :(

https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources
---
 .github/workflows/build.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 88c5803f..a633f184 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -5,7 +5,7 @@ env:
   IOS_VERSION: 14.4
 jobs:
   build:
-    runs-on: macos-latest
+    runs-on: macos-11
     steps:
     - uses: actions/checkout@v2
     - name: Install

From 13d78942f39ab4254ac6856e7f88f5032946ef3b Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 5 Nov 2021 21:49:43 +0100
Subject: [PATCH 458/685] iOS 15.0

---
 Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index 0b9a1606..c62da000 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 BUILD_TOOL = xcodebuild
 BUILD_SCHEME = SQLite Mac
 IOS_SIMULATOR = iPhone 12
-IOS_VERSION = 14.4
+IOS_VERSION = 15.0
 ifeq ($(BUILD_SCHEME),SQLite iOS)
 	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -destination "platform=iOS Simulator,name=$(IOS_SIMULATOR),OS=$(IOS_VERSION)"
 else

From 7c0106255f742218b3d99d86ed08a31b42882cf7 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 5 Nov 2021 21:58:38 +0100
Subject: [PATCH 459/685] iOS version

---
 .github/workflows/build.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index a633f184..84dc9aba 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -2,7 +2,7 @@ name: Build and test
 on: [push, pull_request]
 env:
   IOS_SIMULATOR: iPhone 12
-  IOS_VERSION: 14.4
+  IOS_VERSION: 15.0
 jobs:
   build:
     runs-on: macos-11

From 47c70041ac7237b5c1ccdcf6114e6bb78c0d9dc6 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 5 Nov 2021 22:07:30 +0100
Subject: [PATCH 460/685] YML insanity

---
 .github/workflows/build.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 84dc9aba..baa8c2d8 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -2,7 +2,7 @@ name: Build and test
 on: [push, pull_request]
 env:
   IOS_SIMULATOR: iPhone 12
-  IOS_VERSION: 15.0
+  IOS_VERSION: "15.0"
 jobs:
   build:
     runs-on: macos-11

From db48bb0bf98568c0e29976cd5b95c898c013c277 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 17 Nov 2021 00:46:07 +0100
Subject: [PATCH 461/685] Update Index.md

Clarify SQLCipher integration (#1097)
---
 Documentation/Index.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 1f702653..22c5fea5 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -170,6 +170,8 @@ If you want to use [SQLCipher][] with SQLite.swift you can require the
 
 ```ruby
 target 'YourAppTargetName' do
+  # Make sure you only require the subspec, otherwise you app might link against
+  # the system SQLite, which means the SQLCipher-specific methods won't work.
   pod 'SQLite.swift/SQLCipher', '~> 0.13.0'
 end
 ```

From 60a65015f6402b7c34b9a924f755ca0a73afeeaa Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 17 Nov 2021 00:55:18 +0100
Subject: [PATCH 462/685] Bump version

---
 CHANGELOG.md                     |  7 ++++---
 Documentation/Index.md           | 12 ++++++------
 Documentation/Planning.md        |  2 +-
 README.md                        |  6 +++---
 SQLite.swift.podspec             |  2 +-
 SQLite.xcodeproj/project.pbxproj |  4 ++--
 6 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a36c6468..d89e33f4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,9 @@
-0.13.1 (tba)
+0.13.1 (17-11-2021), [diff][diff-0.13.1]
 ========================================
 
 * Support for database backup ([#919][])
 * Support for custom SQL aggregates ([#881][])
-* Restore previous iteration behavior ([#1075][])
+* Restore previous behavior in `FailableIterator` ([#1075][])
 * Fix compilation on Linux ([#1077][])
 * Align platform versions in SPM manifest and Xcode ([#1094][])
 * Revert OSX deployment target back to 10.10 ([#1095][])
@@ -94,6 +94,7 @@
 [diff-0.12.0]: https://github.com/stephencelis/SQLite.swift/compare/0.11.6...0.12.0
 [diff-0.12.2]: https://github.com/stephencelis/SQLite.swift/compare/0.12.0...0.12.2
 [diff-0.13.0]: https://github.com/stephencelis/SQLite.swift/compare/0.12.2...0.13.0
+[diff-0.13.1]: https://github.com/stephencelis/SQLite.swift/compare/0.13.0...0.13.1
 
 [#142]: https://github.com/stephencelis/SQLite.swift/issues/142
 [#315]: https://github.com/stephencelis/SQLite.swift/issues/315
@@ -131,4 +132,4 @@
 [#1075]: https://github.com/stephencelis/SQLite.swift/pull/1075
 [#1077]: https://github.com/stephencelis/SQLite.swift/issues/1077
 [#1094]: https://github.com/stephencelis/SQLite.swift/pull/1094
-[#1095]: https://github.com/stephencelis/SQLite.swift/pull/1095
\ No newline at end of file
+[#1095]: https://github.com/stephencelis/SQLite.swift/pull/1095
diff --git a/Documentation/Index.md b/Documentation/Index.md
index 22c5fea5..96e5775c 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -81,7 +81,7 @@ process of downloading, compiling, and linking dependencies.
 
   ```swift
   dependencies: [
-    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.13.0")
+    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.13.1")
   ]
   ```
 
@@ -102,7 +102,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.13.0
+    github "stephencelis/SQLite.swift" ~> 0.13.1
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -132,7 +132,7 @@ install SQLite.swift with Carthage:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.13.0'
+        pod 'SQLite.swift', '~> 0.13.1'
     end
     ```
 
@@ -146,7 +146,7 @@ with the OS you can require the `standalone` subspec:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.13.0'
+  pod 'SQLite.swift/standalone', '~> 0.13.1'
 end
 ```
 
@@ -156,7 +156,7 @@ dependency to sqlite3 or one of its subspecs:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.13.0'
+  pod 'SQLite.swift/standalone', '~> 0.13.1'
   pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
 end
 ```
@@ -172,7 +172,7 @@ If you want to use [SQLCipher][] with SQLite.swift you can require the
 target 'YourAppTargetName' do
   # Make sure you only require the subspec, otherwise you app might link against
   # the system SQLite, which means the SQLCipher-specific methods won't work.
-  pod 'SQLite.swift/SQLCipher', '~> 0.13.0'
+  pod 'SQLite.swift/SQLCipher', '~> 0.13.1'
 end
 ```
 
diff --git a/Documentation/Planning.md b/Documentation/Planning.md
index 44e02c7a..bebfb503 100644
--- a/Documentation/Planning.md
+++ b/Documentation/Planning.md
@@ -6,7 +6,7 @@ additions and Pull Requests, as well as to keep the Issues list clear of
 enhancement requests so that bugs are more visible.
 
 > ⚠ This document is currently not actively maintained. See
-> the [0.13.1 milestone](https://github.com/stephencelis/SQLite.swift/issues?q=is%3Aopen+is%3Aissue+milestone%3A0.13.1)
+> the [0.13.2 milestone](https://github.com/stephencelis/SQLite.swift/issues?q=is%3Aopen+is%3Aissue+milestone%3A0.13.2)
 > on Github for additional information about planned features for the next release.
 
 ## Roadmap
diff --git a/README.md b/README.md
index ec92729f..bc8eac31 100644
--- a/README.md
+++ b/README.md
@@ -136,7 +136,7 @@ Swift code.
 
   ```swift
   dependencies: [
-      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.13.0")
+      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.13.1")
   ]
   ```
 
@@ -160,7 +160,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.13.0
+    github "stephencelis/SQLite.swift" ~> 0.13.1
     ```
 
  3. Run `carthage update` and
@@ -191,7 +191,7 @@ SQLite.swift with CocoaPods:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.13.0'
+        pod 'SQLite.swift', '~> 0.13.1'
     end
     ```
 
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 80871b0b..90a8a348 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.13.0"
+  s.version          = "0.13.1"
   s.summary          = "A type-safe, Swift-language layer over SQLite3."
 
   s.description      = <<-DESC
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index ecc1195c..aee41218 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1333,7 +1333,7 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
-				MARKETING_VERSION = 0.13.0;
+				MARKETING_VERSION = 0.13.1;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
@@ -1356,7 +1356,7 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
-				MARKETING_VERSION = 0.13.0;
+				MARKETING_VERSION = 0.13.1;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;

From a2bfb9eb3b0641873c886384ed96fd44f70dba0e Mon Sep 17 00:00:00 2001
From: Dylan Nunns <dylan@gnarledrootsystems.com>
Date: Thu, 2 Dec 2021 19:05:01 -0400
Subject: [PATCH 463/685] Closing bracket position

Updated position of closing bracket where `onConflictOf` parameter. In this particular area it was closing `upsert()` and making `onConflictOf` a parameter of `.run()`
---
 Documentation/Index.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 96e5775c..061b448b 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1174,7 +1174,7 @@ joined by the `<-` operator. Upserting is like inserting, except if there is a
 conflict on the specified column value, SQLite will perform an update on the row instead.
 
 ```swift
-try db.run(users.upsert(email <- "alice@mac.com", name <- "Alice"), onConflictOf: email)
+try db.run(users.upsert(email <- "alice@mac.com", name <- "Alice", onConflictOf: email))
 // INSERT INTO "users" ("email", "name") VALUES ('alice@mac.com', 'Alice') ON CONFLICT (\"email\") DO UPDATE SET \"name\" = \"excluded\".\"name\"
 ```
 

From b9489a7cc11f18a15e744193e29de1430ddd35b2 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Mon, 17 Jan 2022 17:08:36 +0100
Subject: [PATCH 464/685] Native user_version support in Connection

---
 Sources/SQLite/Core/Connection.swift | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 6b5481e3..5b1fc50a 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -151,6 +151,13 @@ public final class Connection {
     public var totalChanges: Int {
         Int(sqlite3_total_changes(handle))
     }
+    
+    /// The user version of the database.
+    /// See SQLite [PRAGMA user_version](https://sqlite.org/pragma.html#pragma_user_version)
+    public var userVersion: Int32 {
+        get { return Int32(try! scalar("PRAGMA user_version") as! Int64)}
+        set { try! run("PRAGMA user_version = \(newValue)") }
+    }
 
     // MARK: - Execute
 

From 9e162a84c964562cf6248890722c77011f81eaa4 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Mon, 17 Jan 2022 17:30:00 +0100
Subject: [PATCH 465/685] Refactoring userVersion + adding tests

---
 Sources/SQLite/Core/Connection.swift    | 20 +++++++++++++++-----
 Tests/SQLiteTests/ConnectionTests.swift |  5 +++++
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 5b1fc50a..4b1c712a 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -151,12 +151,22 @@ public final class Connection {
     public var totalChanges: Int {
         Int(sqlite3_total_changes(handle))
     }
-    
-    /// The user version of the database.
+
+    /// Gets the user version of the database.
+    /// See SQLite [PRAGMA user_version](https://sqlite.org/pragma.html#pragma_user_version)
+    /// - Returns: the user version of the database
+    public func getUserVersion() throws -> Int32? {
+        guard let userVersion = try scalar("PRAGMA user_version") as? Int64 else {
+            return nil
+        }
+        return Int32(userVersion)
+    }
+
+    /// Sets the user version of the database.
     /// See SQLite [PRAGMA user_version](https://sqlite.org/pragma.html#pragma_user_version)
-    public var userVersion: Int32 {
-        get { return Int32(try! scalar("PRAGMA user_version") as! Int64)}
-        set { try! run("PRAGMA user_version = \(newValue)") }
+    /// - Parameter userVersion: the new user version of the database
+    public func setUserVersion(to userVersion: Int32) throws {
+        try run("PRAGMA user_version = \(userVersion)")
     }
 
     // MARK: - Execute
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index ae9d4dfd..707cbc43 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -96,6 +96,11 @@ class ConnectionTests: SQLiteTestCase {
         XCTAssertEqual(2, db.totalChanges)
     }
 
+    func test_userVersion() {
+        try! db.setUserVersion(to: 2)
+        XCTAssertEqual(2, try! db.getUserVersion()!)
+    }
+
     func test_prepare_preparesAndReturnsStatements() {
         _ = try! db.prepare("SELECT * FROM users WHERE admin = 0")
         _ = try! db.prepare("SELECT * FROM users WHERE admin = ?", 0)

From d52eaaf1795e05dadb5c1c0e59cf56579c7f7112 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Tue, 18 Jan 2022 13:28:31 +0100
Subject: [PATCH 466/685] Set userVersion as a property

---
 Sources/SQLite/Core/Connection.swift    | 25 ++++++++++++-------------
 Tests/SQLiteTests/ConnectionTests.swift |  4 ++--
 2 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 4b1c712a..becc932e 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -152,21 +152,20 @@ public final class Connection {
         Int(sqlite3_total_changes(handle))
     }
 
-    /// Gets the user version of the database.
+    /// The user version of the database.
     /// See SQLite [PRAGMA user_version](https://sqlite.org/pragma.html#pragma_user_version)
-    /// - Returns: the user version of the database
-    public func getUserVersion() throws -> Int32? {
-        guard let userVersion = try scalar("PRAGMA user_version") as? Int64 else {
-            return nil
+    public var userVersion: Int32? {
+        get {
+            guard let userVersion = try? scalar("PRAGMA user_version") as? Int64 else {
+                return nil
+            }
+            return Int32(userVersion)
+        }
+        set {
+            if let userVersion = newValue {
+                _ = try? run("PRAGMA user_version = \(userVersion)")
+            }
         }
-        return Int32(userVersion)
-    }
-
-    /// Sets the user version of the database.
-    /// See SQLite [PRAGMA user_version](https://sqlite.org/pragma.html#pragma_user_version)
-    /// - Parameter userVersion: the new user version of the database
-    public func setUserVersion(to userVersion: Int32) throws {
-        try run("PRAGMA user_version = \(userVersion)")
     }
 
     // MARK: - Execute
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index 707cbc43..136271a4 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -97,8 +97,8 @@ class ConnectionTests: SQLiteTestCase {
     }
 
     func test_userVersion() {
-        try! db.setUserVersion(to: 2)
-        XCTAssertEqual(2, try! db.getUserVersion()!)
+        db.userVersion = 2
+        XCTAssertEqual(2, db.userVersion!)
     }
 
     func test_prepare_preparesAndReturnsStatements() {

From 80c8b30a4e372f92745e197047c9e8549fc4347d Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Tue, 25 Jan 2022 13:14:00 +0100
Subject: [PATCH 467/685] More compact version

---
 Sources/SQLite/Core/Connection.swift | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index becc932e..043cfafc 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -156,10 +156,7 @@ public final class Connection {
     /// See SQLite [PRAGMA user_version](https://sqlite.org/pragma.html#pragma_user_version)
     public var userVersion: Int32? {
         get {
-            guard let userVersion = try? scalar("PRAGMA user_version") as? Int64 else {
-                return nil
-            }
-            return Int32(userVersion)
+            (try? scalar("PRAGMA user_version") as? Int64).map(Int32.init)
         }
         set {
             if let userVersion = newValue {

From d00473986112b4bce7bb7f15dc68483adf29c67e Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Tue, 25 Jan 2022 14:09:11 +0100
Subject: [PATCH 468/685] Fixing tests for Linux

---
 Tests/SQLiteTests/QueryTests.swift  | 23 ++++++++++++++---------
 Tests/SQLiteTests/TestHelpers.swift | 13 ++++++++++++-
 2 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index e0749f2c..f225adb4 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -391,15 +391,20 @@ class QueryTests: XCTestCase {
         let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
                                 date: Date(timeIntervalSince1970: 0), optional: nil, sub: value1)
         let update = try emails.update(value)
-        let encodedJSON = try JSONEncoder().encode(value1)
-        let encodedJSONString = String(data: encodedJSON, encoding: .utf8)!
-        assertSQL(
-            """
-            UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0,
-             \"date\" = '1970-01-01T00:00:00.000', \"sub\" = '\(encodedJSONString)'
-            """.replacingOccurrences(of: "\n", with: ""),
-            update
-        )
+        
+        // NOTE: As Linux JSON decoding doesn't order keys the same way, we need to check prefix, suffix,
+        // and extract JSON to decode it and check the decoded object.
+        
+        let expectedPrefix = "UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0, \"date\" = '1970-01-01T00:00:00.000', \"sub\" = '"
+        let expectedSuffix = "'"
+        
+        let sql = update.asSQL()
+        XCTAssert(sql.hasPrefix(expectedPrefix))
+        XCTAssert(sql.hasSuffix(expectedSuffix))
+        
+        let extractedJSON = String(sql[sql.index(sql.startIndex, offsetBy: expectedPrefix.count) ..< sql.index(sql.endIndex, offsetBy: -expectedSuffix.count)])
+        let decodedJSON = try JSONDecoder().decode(TestCodable.self, from: extractedJSON.data(using: .utf8)!)
+        XCTAssertEqual(decodedJSON, value1)
     }
 
     func test_delete_compilesDeleteExpression() {
diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index 07cc6f06..53dabe79 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -105,7 +105,7 @@ let qualifiedTable = Table("table", database: "main")
 let virtualTable = VirtualTable("virtual_table")
 let _view = View("view") // avoid Mac XCTestCase collision
 
-class TestCodable: Codable {
+class TestCodable: Codable, Equatable {
     let int: Int
     let string: String
     let bool: Bool
@@ -125,4 +125,15 @@ class TestCodable: Codable {
         self.optional = optional
         self.sub = sub
     }
+    
+    static func == (lhs: TestCodable, rhs: TestCodable) -> Bool {
+        lhs.int == rhs.int &&
+        lhs.string == rhs.string &&
+        lhs.bool == rhs.bool &&
+        lhs.float == rhs.float &&
+        lhs.double == rhs.double &&
+        lhs.date == rhs.date &&
+        lhs.optional == rhs.optional &&
+        lhs.sub == rhs.sub
+    }
 }

From 34d3a9713e77d2a85b4140d505d3dbd3918117ff Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Tue, 25 Jan 2022 14:50:37 +0100
Subject: [PATCH 469/685] Fixing Linting

---
 Tests/SQLiteTests/QueryTests.swift  | 19 +++++++++++++------
 Tests/SQLiteTests/TestHelpers.swift |  2 +-
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index f225adb4..ad0f3b25 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -391,18 +391,25 @@ class QueryTests: XCTestCase {
         let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
                                 date: Date(timeIntervalSince1970: 0), optional: nil, sub: value1)
         let update = try emails.update(value)
-        
+
         // NOTE: As Linux JSON decoding doesn't order keys the same way, we need to check prefix, suffix,
         // and extract JSON to decode it and check the decoded object.
-        
-        let expectedPrefix = "UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0, \"date\" = '1970-01-01T00:00:00.000', \"sub\" = '"
+
+        let expectedPrefix =
+            """
+            UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0,
+            \"date\" = '1970-01-01T00:00:00.000', \"sub\" = '
+            """.replacingOccurrences(of: "\n", with: "")
         let expectedSuffix = "'"
-        
+
         let sql = update.asSQL()
         XCTAssert(sql.hasPrefix(expectedPrefix))
         XCTAssert(sql.hasSuffix(expectedSuffix))
-        
-        let extractedJSON = String(sql[sql.index(sql.startIndex, offsetBy: expectedPrefix.count) ..< sql.index(sql.endIndex, offsetBy: -expectedSuffix.count)])
+
+        let extractedJSON = String(sql[
+            sql.index(sql.startIndex, offsetBy: expectedPrefix.count) ..<
+            sql.index(sql.endIndex, offsetBy: -expectedSuffix.count)
+        ])
         let decodedJSON = try JSONDecoder().decode(TestCodable.self, from: extractedJSON.data(using: .utf8)!)
         XCTAssertEqual(decodedJSON, value1)
     }
diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index 53dabe79..4d8f78fa 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -125,7 +125,7 @@ class TestCodable: Codable, Equatable {
         self.optional = optional
         self.sub = sub
     }
-    
+
     static func == (lhs: TestCodable, rhs: TestCodable) -> Bool {
         lhs.int == rhs.int &&
         lhs.string == rhs.string &&

From 85921d83ce4921201a6d4106bc609f277253d4d8 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Tue, 25 Jan 2022 15:05:28 +0100
Subject: [PATCH 470/685] Oups

---
 Tests/SQLiteTests/QueryTests.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index ad0f3b25..f4942b88 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -398,7 +398,7 @@ class QueryTests: XCTestCase {
         let expectedPrefix =
             """
             UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0,
-            \"date\" = '1970-01-01T00:00:00.000', \"sub\" = '
+             \"date\" = '1970-01-01T00:00:00.000', \"sub\" = '
             """.replacingOccurrences(of: "\n", with: "")
         let expectedSuffix = "'"
 

From 608684aeea5b6a5c5e8b87866600447c412d3b2e Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Tue, 25 Jan 2022 15:19:40 +0100
Subject: [PATCH 471/685] Updating documentation

---
 Documentation/Index.md | 14 ++------------
 1 file changed, 2 insertions(+), 12 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 061b448b..4b4f45db 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1457,21 +1457,11 @@ try db.run(users.drop(ifExists: true))
 
 ### Migrations and Schema Versioning
 
-You can add a convenience property on `Connection` to query and set the
+You can use the convenience property on `Connection` to query and set the
 [`PRAGMA user_version`](https://sqlite.org/pragma.html#pragma_user_version).
 
 This is a great way to manage your schema’s version over migrations.
-
-```swift
-extension Connection {
-    public var userVersion: Int32 {
-        get { return Int32(try! scalar("PRAGMA user_version") as! Int64)}
-        set { try! run("PRAGMA user_version = \(newValue)") }
-    }
-}
-```
-
-Then you can conditionally run your migrations along the lines of:
+You can conditionally run your migrations along the lines of:
 
 ```swift
 if db.userVersion == 0 {

From 946f69e79c2503d2dff58813d1abf78280205fa0 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Tue, 25 Jan 2022 15:31:17 +0100
Subject: [PATCH 472/685] Bump version number

---
 CHANGELOG.md                     |  9 +++++++++
 Documentation/Index.md           | 12 ++++++------
 Documentation/Planning.md        |  2 +-
 README.md                        |  6 +++---
 SQLite.swift.podspec             |  2 +-
 SQLite.xcodeproj/project.pbxproj |  4 ++--
 6 files changed, 22 insertions(+), 13 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d89e33f4..11d0218e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+0.13.2 (25-01-2022), [diff][diff-0.13.2]
+========================================
+
+* Closing bracket position ([#1100][])
+* Native user_version support in Connection ([#1105][])
+
 0.13.1 (17-11-2021), [diff][diff-0.13.1]
 ========================================
 
@@ -95,6 +101,7 @@
 [diff-0.12.2]: https://github.com/stephencelis/SQLite.swift/compare/0.12.0...0.12.2
 [diff-0.13.0]: https://github.com/stephencelis/SQLite.swift/compare/0.12.2...0.13.0
 [diff-0.13.1]: https://github.com/stephencelis/SQLite.swift/compare/0.13.0...0.13.1
+[diff-0.13.2]: https://github.com/stephencelis/SQLite.swift/compare/0.13.1...0.13.2
 
 [#142]: https://github.com/stephencelis/SQLite.swift/issues/142
 [#315]: https://github.com/stephencelis/SQLite.swift/issues/315
@@ -133,3 +140,5 @@
 [#1077]: https://github.com/stephencelis/SQLite.swift/issues/1077
 [#1094]: https://github.com/stephencelis/SQLite.swift/pull/1094
 [#1095]: https://github.com/stephencelis/SQLite.swift/pull/1095
+[#1100]: https://github.com/stephencelis/SQLite.swift/pull/1100
+[#1105]: https://github.com/stephencelis/SQLite.swift/pull/1105
diff --git a/Documentation/Index.md b/Documentation/Index.md
index 4b4f45db..52affae4 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -81,7 +81,7 @@ process of downloading, compiling, and linking dependencies.
 
   ```swift
   dependencies: [
-    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.13.1")
+    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.13.2")
   ]
   ```
 
@@ -102,7 +102,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.13.1
+    github "stephencelis/SQLite.swift" ~> 0.13.2
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -132,7 +132,7 @@ install SQLite.swift with Carthage:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.13.1'
+        pod 'SQLite.swift', '~> 0.13.2'
     end
     ```
 
@@ -146,7 +146,7 @@ with the OS you can require the `standalone` subspec:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.13.1'
+  pod 'SQLite.swift/standalone', '~> 0.13.2'
 end
 ```
 
@@ -156,7 +156,7 @@ dependency to sqlite3 or one of its subspecs:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.13.1'
+  pod 'SQLite.swift/standalone', '~> 0.13.2'
   pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
 end
 ```
@@ -172,7 +172,7 @@ If you want to use [SQLCipher][] with SQLite.swift you can require the
 target 'YourAppTargetName' do
   # Make sure you only require the subspec, otherwise you app might link against
   # the system SQLite, which means the SQLCipher-specific methods won't work.
-  pod 'SQLite.swift/SQLCipher', '~> 0.13.1'
+  pod 'SQLite.swift/SQLCipher', '~> 0.13.2'
 end
 ```
 
diff --git a/Documentation/Planning.md b/Documentation/Planning.md
index bebfb503..5b50219a 100644
--- a/Documentation/Planning.md
+++ b/Documentation/Planning.md
@@ -6,7 +6,7 @@ additions and Pull Requests, as well as to keep the Issues list clear of
 enhancement requests so that bugs are more visible.
 
 > ⚠ This document is currently not actively maintained. See
-> the [0.13.2 milestone](https://github.com/stephencelis/SQLite.swift/issues?q=is%3Aopen+is%3Aissue+milestone%3A0.13.2)
+> the [0.13.3 milestone](https://github.com/stephencelis/SQLite.swift/issues?q=is%3Aopen+is%3Aissue+milestone%3A0.13.3)
 > on Github for additional information about planned features for the next release.
 
 ## Roadmap
diff --git a/README.md b/README.md
index bc8eac31..a2b5e537 100644
--- a/README.md
+++ b/README.md
@@ -136,7 +136,7 @@ Swift code.
 
   ```swift
   dependencies: [
-      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.13.1")
+      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.13.2")
   ]
   ```
 
@@ -160,7 +160,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.13.1
+    github "stephencelis/SQLite.swift" ~> 0.13.2
     ```
 
  3. Run `carthage update` and
@@ -191,7 +191,7 @@ SQLite.swift with CocoaPods:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.13.1'
+        pod 'SQLite.swift', '~> 0.13.2'
     end
     ```
 
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 90a8a348..23146eee 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.13.1"
+  s.version          = "0.13.2"
   s.summary          = "A type-safe, Swift-language layer over SQLite3."
 
   s.description      = <<-DESC
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index aee41218..26c5e975 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1333,7 +1333,7 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
-				MARKETING_VERSION = 0.13.1;
+				MARKETING_VERSION = 0.13.2;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
@@ -1356,7 +1356,7 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
-				MARKETING_VERSION = 0.13.1;
+				MARKETING_VERSION = 0.13.2;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;

From 5f5ad81ac0d0a0f3e56e39e646e8423c617df523 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Tue, 25 Jan 2022 16:57:56 +0100
Subject: [PATCH 473/685] Reset userVersion if set to nil

---
 Sources/SQLite/Core/Connection.swift | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 043cfafc..72e8d857 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -159,9 +159,7 @@ public final class Connection {
             (try? scalar("PRAGMA user_version") as? Int64).map(Int32.init)
         }
         set {
-            if let userVersion = newValue {
-                _ = try? run("PRAGMA user_version = \(userVersion)")
-            }
+            _ = try? run("PRAGMA user_version = \(newValue ?? 0)")
         }
     }
 

From 52e3ea84895004f81d647ab8582564d1e7ab3c73 Mon Sep 17 00:00:00 2001
From: Amy While <26681721+elihwyma@users.noreply.github.com>
Date: Sun, 6 Feb 2022 17:59:33 +0000
Subject: [PATCH 474/685] Add a Value conformance for Foundation NSURL

---
 Sources/SQLite/Foundation.swift | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/Sources/SQLite/Foundation.swift b/Sources/SQLite/Foundation.swift
index 2acbc00e..c1a4c501 100644
--- a/Sources/SQLite/Foundation.swift
+++ b/Sources/SQLite/Foundation.swift
@@ -84,3 +84,20 @@ extension UUID: Value {
     }
 
 }
+
+extension URL: Value {
+
+    public static var declaredDatatype: String {
+        String.declaredDatatype
+    }
+
+    public static func fromDatatypeValue(_ stringValue: String) -> URL {
+        URL(string: stringValue)!
+    }
+
+    public var datatypeValue: String {
+        absoluteString
+    }
+
+}
+

From 3eb1fdceda903ea3b7ba0f49a522258578a168d5 Mon Sep 17 00:00:00 2001
From: Amy While <26681721+elihwyma@users.noreply.github.com>
Date: Sat, 12 Feb 2022 13:13:42 +0000
Subject: [PATCH 475/685] Remove Extra Trailing New Line

---
 Sources/SQLite/Foundation.swift | 1 -
 1 file changed, 1 deletion(-)

diff --git a/Sources/SQLite/Foundation.swift b/Sources/SQLite/Foundation.swift
index c1a4c501..44a31736 100644
--- a/Sources/SQLite/Foundation.swift
+++ b/Sources/SQLite/Foundation.swift
@@ -100,4 +100,3 @@ extension URL: Value {
     }
 
 }
-

From da8d7b3100471349ac924e15b1351fcd17b83ade Mon Sep 17 00:00:00 2001
From: Benjamin Lewis <benrlewis@gmail.com>
Date: Fri, 18 Feb 2022 13:45:40 -0600
Subject: [PATCH 476/685] UUID Fix

---
 Sources/SQLite/Typed/Coding.swift | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index 3dc1e6cf..a8608579 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -207,6 +207,8 @@ private class SQLiteEncoder: Encoder {
                 encoder.setters.append(Expression(key.stringValue) <- data)
             } else if let date = value as? Date {
                 encoder.setters.append(Expression(key.stringValue) <- date.datatypeValue)
+            }else if let uuid = value as? UUID {
+                encoder.setters.append(Expression(key.stringValue) <- uuid.uuidString)
             } else {
                 let encoded = try JSONEncoder().encode(value)
                 let string = String(data: encoded, encoding: .utf8)

From b71549364be768397d09a91707867d2175f6261e Mon Sep 17 00:00:00 2001
From: Benjamin Lewis <benrlewis@gmail.com>
Date: Sat, 19 Feb 2022 10:52:13 -0600
Subject: [PATCH 477/685] Lint Fix and added test

---
 Sources/SQLite/Typed/Coding.swift       |  2 +-
 Tests/SQLiteTests/FoundationTests.swift | 26 +++++++++++++++++++++++++
 Tests/SQLiteTests/TestHelpers.swift     |  3 +++
 3 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index a8608579..fa9ec02d 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -207,7 +207,7 @@ private class SQLiteEncoder: Encoder {
                 encoder.setters.append(Expression(key.stringValue) <- data)
             } else if let date = value as? Date {
                 encoder.setters.append(Expression(key.stringValue) <- date.datatypeValue)
-            }else if let uuid = value as? UUID {
+            } else if let uuid = value as? UUID {
                 encoder.setters.append(Expression(key.stringValue) <- uuid.uuidString)
             } else {
                 let encoded = try JSONEncoder().encode(value)
diff --git a/Tests/SQLiteTests/FoundationTests.swift b/Tests/SQLiteTests/FoundationTests.swift
index cef485fc..23ae1fe2 100644
--- a/Tests/SQLiteTests/FoundationTests.swift
+++ b/Tests/SQLiteTests/FoundationTests.swift
@@ -25,4 +25,30 @@ class FoundationTests: XCTestCase {
         let uuid = UUID.fromDatatypeValue(string)
         XCTAssertEqual(UUID(uuidString: "4ABE10C9-FF12-4CD4-90C1-4B429001BAD3"), uuid)
     }
+    
+    func testUUIDInsert() {
+        struct Test:Codable{
+            var uuid:UUID
+            var string:String
+        }
+        let testUUID = UUID()
+        let testValue = Test(uuid: testUUID, string: "value")
+        let db = try! Connection(.temporary)
+        try! db.run(table.create { t in
+            t.column(uuid)
+            t.column(string)
+        }
+        )
+        
+        let iQuery = try! table.insert(testValue)
+        try! db.run(iQuery)
+        
+        let fQuery = table.filter(uuid == testUUID)
+        if let result = try! db.pluck(fQuery){
+            let testValueReturned = Test(uuid: result[uuid], string: result[string])
+            XCTAssertEqual(testUUID, testValueReturned.uuid)
+        }else{
+            XCTFail()
+        }
+    }
 }
diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index 4d8f78fa..a6efa2e7 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -95,6 +95,9 @@ let int64Optional = Expression<Int64?>("int64Optional")
 let string = Expression<String>("string")
 let stringOptional = Expression<String?>("stringOptional")
 
+let uuid = Expression<UUID>("uuid")
+let uuidOptional = Expression<UUID?>("uuidOptional")
+
 func assertSQL(_ expression1: @autoclosure () -> String, _ expression2: @autoclosure () -> Expressible,
                file: StaticString = #file, line: UInt = #line) {
     XCTAssertEqual(expression1(), expression2().asSQL(), file: file, line: line)

From 83f0f5de5bd978e5c41e45331154572a41204fe9 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 20 Feb 2022 23:46:24 +0100
Subject: [PATCH 478/685] Bump iOS version

---
 .github/workflows/build.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index baa8c2d8..d1659d9d 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -2,7 +2,7 @@ name: Build and test
 on: [push, pull_request]
 env:
   IOS_SIMULATOR: iPhone 12
-  IOS_VERSION: "15.0"
+  IOS_VERSION: "15.2"
 jobs:
   build:
     runs-on: macos-11

From c4483141f19a4ba796fd0475e279d4db1353000e Mon Sep 17 00:00:00 2001
From: Benjamin Lewis <benrlewis@gmail.com>
Date: Mon, 21 Feb 2022 19:33:15 -0600
Subject: [PATCH 479/685] Fixed linting issues.

---
 Tests/SQLiteTests/FoundationTests.swift | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/Tests/SQLiteTests/FoundationTests.swift b/Tests/SQLiteTests/FoundationTests.swift
index 23ae1fe2..02ab7f13 100644
--- a/Tests/SQLiteTests/FoundationTests.swift
+++ b/Tests/SQLiteTests/FoundationTests.swift
@@ -25,11 +25,11 @@ class FoundationTests: XCTestCase {
         let uuid = UUID.fromDatatypeValue(string)
         XCTAssertEqual(UUID(uuidString: "4ABE10C9-FF12-4CD4-90C1-4B429001BAD3"), uuid)
     }
-    
+
     func testUUIDInsert() {
-        struct Test:Codable{
-            var uuid:UUID
-            var string:String
+        struct Test: Codable {
+            var uuid: UUID
+            var string: String
         }
         let testUUID = UUID()
         let testValue = Test(uuid: testUUID, string: "value")
@@ -39,16 +39,16 @@ class FoundationTests: XCTestCase {
             t.column(string)
         }
         )
-        
+
         let iQuery = try! table.insert(testValue)
         try! db.run(iQuery)
-        
+
         let fQuery = table.filter(uuid == testUUID)
-        if let result = try! db.pluck(fQuery){
+        if let result = try! db.pluck(fQuery) {
             let testValueReturned = Test(uuid: result[uuid], string: result[string])
             XCTAssertEqual(testUUID, testValueReturned.uuid)
-        }else{
-            XCTFail()
+        } else {
+            XCTFail("Search for uuid failed")
         }
     }
 }

From 09e8424805b9ea02b96c6973fe2720c3caa4490f Mon Sep 17 00:00:00 2001
From: Benjamin Lewis <benrlewis@gmail.com>
Date: Tue, 22 Feb 2022 06:40:20 -0600
Subject: [PATCH 480/685] used UUID.datatypeValue and moved tests

---
 Sources/SQLite/Typed/Coding.swift       |  2 +-
 Tests/SQLiteTests/FoundationTests.swift | 25 ------------------------
 Tests/SQLiteTests/QueryTests.swift      | 26 +++++++++++++++++++++++++
 3 files changed, 27 insertions(+), 26 deletions(-)

diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index fa9ec02d..cea2565a 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -208,7 +208,7 @@ private class SQLiteEncoder: Encoder {
             } else if let date = value as? Date {
                 encoder.setters.append(Expression(key.stringValue) <- date.datatypeValue)
             } else if let uuid = value as? UUID {
-                encoder.setters.append(Expression(key.stringValue) <- uuid.uuidString)
+                encoder.setters.append(Expression(key.stringValue) <- uuid.datatypeValue)
             } else {
                 let encoded = try JSONEncoder().encode(value)
                 let string = String(data: encoded, encoding: .utf8)
diff --git a/Tests/SQLiteTests/FoundationTests.swift b/Tests/SQLiteTests/FoundationTests.swift
index 02ab7f13..075e755b 100644
--- a/Tests/SQLiteTests/FoundationTests.swift
+++ b/Tests/SQLiteTests/FoundationTests.swift
@@ -26,29 +26,4 @@ class FoundationTests: XCTestCase {
         XCTAssertEqual(UUID(uuidString: "4ABE10C9-FF12-4CD4-90C1-4B429001BAD3"), uuid)
     }
 
-    func testUUIDInsert() {
-        struct Test: Codable {
-            var uuid: UUID
-            var string: String
-        }
-        let testUUID = UUID()
-        let testValue = Test(uuid: testUUID, string: "value")
-        let db = try! Connection(.temporary)
-        try! db.run(table.create { t in
-            t.column(uuid)
-            t.column(string)
-        }
-        )
-
-        let iQuery = try! table.insert(testValue)
-        try! db.run(iQuery)
-
-        let fQuery = table.filter(uuid == testUUID)
-        if let result = try! db.pluck(fQuery) {
-            let testValueReturned = Test(uuid: result[uuid], string: result[string])
-            XCTAssertEqual(testUUID, testValueReturned.uuid)
-        } else {
-            XCTFail("Search for uuid failed")
-        }
-    }
 }
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index f4942b88..efcbab94 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -310,6 +310,32 @@ class QueryTests: XCTestCase {
     }
     #endif
 
+    func test_insert_and_search_for_UUID() {
+        struct Test: Codable {
+            var uuid: UUID
+            var string: String
+        }
+        let testUUID = UUID()
+        let testValue = Test(uuid: testUUID, string: "value")
+        let db = try! Connection(.temporary)
+        try! db.run(table.create { t in
+            t.column(uuid)
+            t.column(string)
+        }
+        )
+
+        let iQuery = try! table.insert(testValue)
+        try! db.run(iQuery)
+
+        let fQuery = table.filter(uuid == testUUID)
+        if let result = try! db.pluck(fQuery) {
+            let testValueReturned = Test(uuid: result[uuid], string: result[string])
+            XCTAssertEqual(testUUID, testValueReturned.uuid)
+        } else {
+            XCTFail("Search for uuid failed")
+        }
+    }
+
     func test_upsert_withOnConflict_compilesInsertOrOnConflictExpression() {
         assertSQL(
             """

From f1ab605ad2056944eee80cb7cf55f5b94f17e74e Mon Sep 17 00:00:00 2001
From: Justin Meiners <justinm@passivelogic.com>
Date: Thu, 24 Feb 2022 09:49:20 -0700
Subject: [PATCH 481/685] improve performance of prefixed column resolution

- Previously this allocated arrays every time it was accessed.
It will now only allocate in one of the error cases.
- It also keeps track of the columnName index for both key and
value so it doesn't need to look it up twice.
---
 Sources/SQLite/Typed/Query.swift | 25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index 2d88db63..ecb501af 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -1169,16 +1169,25 @@ public struct Row {
         }
 
         guard let idx = columnNames[column.template] else {
-            let similar = Array(columnNames.keys).filter { $0.hasSuffix(".\(column.template)") }
-
-            switch similar.count {
-            case 0:
+            func match(_ s: String) -> Bool {
+                return s.hasSuffix(".\(column.template)")
+            }
+            
+            guard let firstIndex = columnNames.firstIndex(where: { match($0.key) }) else {
                 throw QueryError.noSuchColumn(name: column.template, columns: columnNames.keys.sorted())
-            case 1:
-                return valueAtIndex(columnNames[similar[0]]!)
-            default:
-                throw QueryError.ambiguousColumn(name: column.template, similar: similar)
             }
+            
+            let secondIndex = columnNames
+                .suffix(from: columnNames.index(after: firstIndex))
+                .firstIndex(where: { match($0.key) })
+            
+            guard secondIndex == nil else {
+                throw QueryError.ambiguousColumn(
+                    name: column.template,
+                    similar: columnNames.keys.filter(match).sorted()
+                )
+            }
+            return valueAtIndex(columnNames[firstIndex].value)
         }
 
         return valueAtIndex(idx)

From 55bf2c10e10b84855ac3a26c10dc601271c6d171 Mon Sep 17 00:00:00 2001
From: Justin Meiners <justinm@passivelogic.com>
Date: Thu, 24 Feb 2022 09:52:56 -0700
Subject: [PATCH 482/685] rename match -> similar to follow convention

---
 Sources/SQLite/Typed/Query.swift | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index ecb501af..6dd07ac4 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -1169,22 +1169,22 @@ public struct Row {
         }
 
         guard let idx = columnNames[column.template] else {
-            func match(_ s: String) -> Bool {
+            func similar(_ s: String) -> Bool {
                 return s.hasSuffix(".\(column.template)")
             }
             
-            guard let firstIndex = columnNames.firstIndex(where: { match($0.key) }) else {
+            guard let firstIndex = columnNames.firstIndex(where: { similar($0.key) }) else {
                 throw QueryError.noSuchColumn(name: column.template, columns: columnNames.keys.sorted())
             }
             
             let secondIndex = columnNames
                 .suffix(from: columnNames.index(after: firstIndex))
-                .firstIndex(where: { match($0.key) })
+                .firstIndex(where: { similar($0.key) })
             
             guard secondIndex == nil else {
                 throw QueryError.ambiguousColumn(
                     name: column.template,
-                    similar: columnNames.keys.filter(match).sorted()
+                    similar: columnNames.keys.filter(similar).sorted()
                 )
             }
             return valueAtIndex(columnNames[firstIndex].value)

From eecb3cb4615534020bf96e32ad2b3a95c91504d6 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 24 Feb 2022 20:14:01 +0100
Subject: [PATCH 483/685] Adding PR template

---
 .github/PULL_REQUEST_TEMPLATE/template.md | 9 +++++++++
 1 file changed, 9 insertions(+)
 create mode 100644 .github/PULL_REQUEST_TEMPLATE/template.md

diff --git a/.github/PULL_REQUEST_TEMPLATE/template.md b/.github/PULL_REQUEST_TEMPLATE/template.md
new file mode 100644
index 00000000..b74ffd8d
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE/template.md
@@ -0,0 +1,9 @@
+Thanks for taking the time to submit a pull request.
+
+Before submitting, please do the following:
+
+- Run `make lint` to check if there are any format errors (install [swiftlint](https://github.com/realm/SwiftLint#installation) first)
+- Run `swift test` to see if the tests pass.
+- Write new tests for new functionality.
+- Update documentation comments where applicable.
+

From 3614f4e317c5969c5fe102cee1f3b3f4e1294185 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 24 Feb 2022 20:24:24 +0100
Subject: [PATCH 484/685] Rename

---
 .../template.md => pull_request_template.md}                      | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename .github/{PULL_REQUEST_TEMPLATE/template.md => pull_request_template.md} (100%)

diff --git a/.github/PULL_REQUEST_TEMPLATE/template.md b/.github/pull_request_template.md
similarity index 100%
rename from .github/PULL_REQUEST_TEMPLATE/template.md
rename to .github/pull_request_template.md

From c897ce99454216dc33caae5d57a2cd021b672e03 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 24 Feb 2022 20:26:45 +0100
Subject: [PATCH 485/685] rename

---
 .github/{ISSUE_TEMPLATE/template.md => issue_template.md} | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
 rename .github/{ISSUE_TEMPLATE/template.md => issue_template.md} (87%)

diff --git a/.github/ISSUE_TEMPLATE/template.md b/.github/issue_template.md
similarity index 87%
rename from .github/ISSUE_TEMPLATE/template.md
rename to .github/issue_template.md
index 9304a672..f9622b9b 100644
--- a/.github/ISSUE_TEMPLATE/template.md
+++ b/.github/issue_template.md
@@ -1,5 +1,5 @@
 > Issues are used to track bugs and feature requests.
-> Need  help or have a general question? Ask on Stack Overflow (tag sqlite.swift).
+> Need help or have a general question? Ask on Stack Overflow (tag sqlite.swift).
 
 ## Build Information
 

From c659dc9256f1b80505d0bd5bbca026005cd43af2 Mon Sep 17 00:00:00 2001
From: Justin Meiners <justinm@passivelogic.com>
Date: Thu, 24 Feb 2022 13:46:25 -0700
Subject: [PATCH 486/685] Fix lint issues

---
 Sources/SQLite/Typed/Query.swift | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index 6dd07ac4..93dc2a73 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -1169,18 +1169,18 @@ public struct Row {
         }
 
         guard let idx = columnNames[column.template] else {
-            func similar(_ s: String) -> Bool {
-                return s.hasSuffix(".\(column.template)")
+            func similar(_ name: String) -> Bool {
+                return name.hasSuffix(".\(column.template)")
             }
-            
+
             guard let firstIndex = columnNames.firstIndex(where: { similar($0.key) }) else {
                 throw QueryError.noSuchColumn(name: column.template, columns: columnNames.keys.sorted())
             }
-            
+
             let secondIndex = columnNames
                 .suffix(from: columnNames.index(after: firstIndex))
                 .firstIndex(where: { similar($0.key) })
-            
+
             guard secondIndex == nil else {
                 throw QueryError.ambiguousColumn(
                     name: column.template,

From ef2257a885a875868177b2a004a839eb4f21a461 Mon Sep 17 00:00:00 2001
From: JIm Boyd <jimb@cabosoft.com>
Date: Thu, 17 Mar 2022 11:09:33 -0600
Subject: [PATCH 487/685] Add prepareRowIterator method to an extension of
 Statement.

---
 Sources/SQLite/Core/Statement.swift    | 15 +++++++++++++++
 Tests/SQLiteTests/StatementTests.swift | 11 +++++++++++
 2 files changed, 26 insertions(+)

diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index 1e2489b5..8e9ed350 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -228,6 +228,21 @@ extension Statement: FailableIterator {
     }
 }
 
+extension Statement {
+    public func prepareRowIterator() -> RowIterator {
+        return RowIterator(statement: self, columnNames: self.columnNameMap)
+    }
+    
+    var columnNameMap: [String: Int] {
+        var result = [String: Int]()
+        for (index, name) in self.columnNames.enumerated() {
+            result[name.quote()] = index
+        }
+
+        return result
+    }
+}
+
 extension Statement: CustomStringConvertible {
 
     public var description: String {
diff --git a/Tests/SQLiteTests/StatementTests.swift b/Tests/SQLiteTests/StatementTests.swift
index b4ad7c28..7729a4a9 100644
--- a/Tests/SQLiteTests/StatementTests.swift
+++ b/Tests/SQLiteTests/StatementTests.swift
@@ -23,4 +23,15 @@ class StatementTests: SQLiteTestCase {
         let blobValue = try! db.scalar(blobs.select(blobColumn).limit(1, offset: 0))
         XCTAssertEqual([], blobValue.bytes)
     }
+    
+    func test_prepareRowIterator() {
+        let names = ["a", "b", "c"]
+        try! insertUsers(names)
+
+        let emailColumn = Expression<String>("email")
+        let statement = try! db.prepare("SELECT email FROM users")
+        let emails = try! statement.prepareRowIterator().map { $0[emailColumn] }
+
+        XCTAssertEqual(names.map({ "\($0)@example.com" }), emails.sorted())
+    }
 }

From 1a50a03fe0a216c75bb27cab7a4f2965669e5e30 Mon Sep 17 00:00:00 2001
From: JIm Boyd <jimb@cabosoft.com>
Date: Thu, 17 Mar 2022 11:22:55 -0600
Subject: [PATCH 488/685] Updates to documentation

---
 Documentation/Index.md | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 52affae4..b58bf995 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1963,6 +1963,14 @@ using the following functions.
         }
     }
     ```
+    Statements with results may be iterated over, using a `RowIterator` if
+    useful.
+    
+    ```swift
+    let emailColumn = Expression<String>("email")
+    let stmt = try db.prepare("SELECT id, email FROM users")
+    let emails = try! stmt.prepareRowIterator().map { $0[emailColumn] }
+    ```
 
   - `run` prepares a single `Statement` object from a SQL string, optionally
     binds values to it (using the statement’s `bind` function), executes,

From 4459338f778d49445bdfd182e40e9cd90220f8c7 Mon Sep 17 00:00:00 2001
From: JIm Boyd <jimb@cabosoft.com>
Date: Thu, 17 Mar 2022 13:43:06 -0600
Subject: [PATCH 489/685] Fix linting issues

---
 Sources/SQLite/Core/Statement.swift    | 2 +-
 Tests/SQLiteTests/StatementTests.swift | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index 8e9ed350..5ec430cf 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -232,7 +232,7 @@ extension Statement {
     public func prepareRowIterator() -> RowIterator {
         return RowIterator(statement: self, columnNames: self.columnNameMap)
     }
-    
+
     var columnNameMap: [String: Int] {
         var result = [String: Int]()
         for (index, name) in self.columnNames.enumerated() {
diff --git a/Tests/SQLiteTests/StatementTests.swift b/Tests/SQLiteTests/StatementTests.swift
index 7729a4a9..aa05de34 100644
--- a/Tests/SQLiteTests/StatementTests.swift
+++ b/Tests/SQLiteTests/StatementTests.swift
@@ -23,7 +23,7 @@ class StatementTests: SQLiteTestCase {
         let blobValue = try! db.scalar(blobs.select(blobColumn).limit(1, offset: 0))
         XCTAssertEqual([], blobValue.bytes)
     }
-    
+
     func test_prepareRowIterator() {
         let names = ["a", "b", "c"]
         try! insertUsers(names)

From 5af5c858fff85bf7a880bd01bd06b010c91c7436 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Sun, 27 Mar 2022 12:37:45 +0200
Subject: [PATCH 490/685] Adding primary key support to column with references

---
 CHANGELOG.md                        |  9 +++++++++
 Documentation/Index.md              | 12 ++++++------
 Documentation/Planning.md           |  2 +-
 README.md                           |  6 +++---
 SQLite.swift.podspec                |  2 +-
 SQLite.xcodeproj/project.pbxproj    |  4 ++--
 Sources/SQLite/Typed/Schema.swift   | 20 ++++++++++++++++++++
 Tests/SQLiteTests/SchemaTests.swift | 27 +++++++++++++++++++++++++++
 8 files changed, 69 insertions(+), 13 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 11d0218e..9bf5682b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+0.13.3 (25-01-2022), [diff][diff-0.13.3]
+========================================
+
+* UUID Fix ([#1112][])
+* Adding primary key support to column with references ([#1121][])
+
 0.13.2 (25-01-2022), [diff][diff-0.13.2]
 ========================================
 
@@ -102,6 +108,7 @@
 [diff-0.13.0]: https://github.com/stephencelis/SQLite.swift/compare/0.12.2...0.13.0
 [diff-0.13.1]: https://github.com/stephencelis/SQLite.swift/compare/0.13.0...0.13.1
 [diff-0.13.2]: https://github.com/stephencelis/SQLite.swift/compare/0.13.1...0.13.2
+[diff-0.13.3]: https://github.com/stephencelis/SQLite.swift/compare/0.13.2...0.13.3
 
 [#142]: https://github.com/stephencelis/SQLite.swift/issues/142
 [#315]: https://github.com/stephencelis/SQLite.swift/issues/315
@@ -142,3 +149,5 @@
 [#1095]: https://github.com/stephencelis/SQLite.swift/pull/1095
 [#1100]: https://github.com/stephencelis/SQLite.swift/pull/1100
 [#1105]: https://github.com/stephencelis/SQLite.swift/pull/1105
+[#1112]: https://github.com/stephencelis/SQLite.swift/pull/1112
+[#1121]: https://github.com/stephencelis/SQLite.swift/pull/1121
diff --git a/Documentation/Index.md b/Documentation/Index.md
index 52affae4..987b0814 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -81,7 +81,7 @@ process of downloading, compiling, and linking dependencies.
 
   ```swift
   dependencies: [
-    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.13.2")
+    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.13.3")
   ]
   ```
 
@@ -102,7 +102,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.13.2
+    github "stephencelis/SQLite.swift" ~> 0.13.3
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -132,7 +132,7 @@ install SQLite.swift with Carthage:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.13.2'
+        pod 'SQLite.swift', '~> 0.13.3'
     end
     ```
 
@@ -146,7 +146,7 @@ with the OS you can require the `standalone` subspec:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.13.2'
+  pod 'SQLite.swift/standalone', '~> 0.13.3'
 end
 ```
 
@@ -156,7 +156,7 @@ dependency to sqlite3 or one of its subspecs:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.13.2'
+  pod 'SQLite.swift/standalone', '~> 0.13.3'
   pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
 end
 ```
@@ -172,7 +172,7 @@ If you want to use [SQLCipher][] with SQLite.swift you can require the
 target 'YourAppTargetName' do
   # Make sure you only require the subspec, otherwise you app might link against
   # the system SQLite, which means the SQLCipher-specific methods won't work.
-  pod 'SQLite.swift/SQLCipher', '~> 0.13.2'
+  pod 'SQLite.swift/SQLCipher', '~> 0.13.3'
 end
 ```
 
diff --git a/Documentation/Planning.md b/Documentation/Planning.md
index 5b50219a..0dea6d71 100644
--- a/Documentation/Planning.md
+++ b/Documentation/Planning.md
@@ -6,7 +6,7 @@ additions and Pull Requests, as well as to keep the Issues list clear of
 enhancement requests so that bugs are more visible.
 
 > ⚠ This document is currently not actively maintained. See
-> the [0.13.3 milestone](https://github.com/stephencelis/SQLite.swift/issues?q=is%3Aopen+is%3Aissue+milestone%3A0.13.3)
+> the [0.13.4 milestone](https://github.com/stephencelis/SQLite.swift/issues?q=is%3Aopen+is%3Aissue+milestone%3A0.13.4)
 > on Github for additional information about planned features for the next release.
 
 ## Roadmap
diff --git a/README.md b/README.md
index a2b5e537..1b04c7c8 100644
--- a/README.md
+++ b/README.md
@@ -136,7 +136,7 @@ Swift code.
 
   ```swift
   dependencies: [
-      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.13.2")
+      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.13.3")
   ]
   ```
 
@@ -160,7 +160,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.13.2
+    github "stephencelis/SQLite.swift" ~> 0.13.3
     ```
 
  3. Run `carthage update` and
@@ -191,7 +191,7 @@ SQLite.swift with CocoaPods:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.13.2'
+        pod 'SQLite.swift', '~> 0.13.3'
     end
     ```
 
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 23146eee..4a1787bb 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.13.2"
+  s.version          = "0.13.3"
   s.summary          = "A type-safe, Swift-language layer over SQLite3."
 
   s.description      = <<-DESC
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 26c5e975..7387d0e9 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1333,7 +1333,7 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
-				MARKETING_VERSION = 0.13.2;
+				MARKETING_VERSION = 0.13.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
@@ -1356,7 +1356,7 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
-				MARKETING_VERSION = 0.13.2;
+				MARKETING_VERSION = 0.13.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
diff --git a/Sources/SQLite/Typed/Schema.swift b/Sources/SQLite/Typed/Schema.swift
index 726f3e27..55e525bc 100644
--- a/Sources/SQLite/Typed/Schema.swift
+++ b/Sources/SQLite/Typed/Schema.swift
@@ -308,6 +308,26 @@ public final class TableBuilder {
                                  references table: QueryType, _ other: Expression<V>) where V.Datatype == Int64 {
         column(name, V.declaredDatatype, nil, true, unique, check, nil, (table, other), nil)
     }
+    
+    public func column<V: Value>(_ name: Expression<V>, primaryKey: Bool, check: Expression<Bool>? = nil,
+                                 references table: QueryType, _ other: Expression<V>) where V.Datatype == Int64 {
+        column(name, V.declaredDatatype, primaryKey ? .default : nil, false, false, check, nil, (table, other), nil)
+    }
+
+    public func column<V: Value>(_ name: Expression<V>, primaryKey: Bool, check: Expression<Bool?>,
+                                 references table: QueryType, _ other: Expression<V>) where V.Datatype == Int64 {
+        column(name, V.declaredDatatype, primaryKey ? .default : nil, false, false, check, nil, (table, other), nil)
+    }
+
+    public func column<V: Value>(_ name: Expression<V?>, primaryKey: Bool, check: Expression<Bool>? = nil,
+                                 references table: QueryType, _ other: Expression<V>) where V.Datatype == Int64 {
+        column(name, V.declaredDatatype, primaryKey ? .default : nil, true, false, check, nil, (table, other), nil)
+    }
+
+    public func column<V: Value>(_ name: Expression<V?>, primaryKey: Bool, check: Expression<Bool?>,
+                                 references table: QueryType, _ other: Expression<V>) where V.Datatype == Int64 {
+        column(name, V.declaredDatatype, primaryKey ? .default : nil, true, false, check, nil, (table, other), nil)
+    }
 
     public func column<V: Value>(_ name: Expression<V>, unique: Bool = false, check: Expression<Bool>? = nil,
                                  defaultValue: Expression<V>? = nil, collate: Collation) where V.Datatype == String {
diff --git a/Tests/SQLiteTests/SchemaTests.swift b/Tests/SQLiteTests/SchemaTests.swift
index 495a5e51..a7de8bcf 100644
--- a/Tests/SQLiteTests/SchemaTests.swift
+++ b/Tests/SQLiteTests/SchemaTests.swift
@@ -317,6 +317,10 @@ class SchemaTests: XCTestCase {
             "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL UNIQUE REFERENCES \"table\" (\"int64\"))",
             table.create { t in t.column(int64, unique: true, references: table, int64) }
         )
+        XCTAssertEqual(
+            "CREATE TABLE \"table\" (\"int64\" INTEGER PRIMARY KEY NOT NULL REFERENCES \"table\" (\"int64\"))",
+            table.create { t in t.column(int64, primaryKey: true, references: table, int64) }
+        )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL CHECK (\"int64\" > 0) REFERENCES \"table\" (\"int64\"))",
             table.create { t in t.column(int64, check: int64 > 0, references: table, int64) }
@@ -329,6 +333,10 @@ class SchemaTests: XCTestCase {
             "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL UNIQUE CHECK (\"int64\" > 0) REFERENCES \"table\" (\"int64\"))",
             table.create { t in t.column(int64, unique: true, check: int64 > 0, references: table, int64) }
         )
+        XCTAssertEqual(
+            "CREATE TABLE \"table\" (\"int64\" INTEGER PRIMARY KEY NOT NULL CHECK (\"int64\" > 0) REFERENCES \"table\" (\"int64\"))",
+            table.create { t in t.column(int64, primaryKey: true, check: int64 > 0, references: table, int64) }
+        )
         XCTAssertEqual(
             """
             CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL UNIQUE CHECK (\"int64Optional\" > 0) REFERENCES
@@ -336,6 +344,13 @@ class SchemaTests: XCTestCase {
             """.replacingOccurrences(of: "\n", with: ""),
             table.create { t in t.column(int64, unique: true, check: int64Optional > 0, references: table, int64) }
         )
+        XCTAssertEqual(
+            """
+            CREATE TABLE \"table\" (\"int64\" INTEGER PRIMARY KEY NOT NULL CHECK (\"int64Optional\" > 0) REFERENCES
+             \"table\" (\"int64\"))
+            """.replacingOccurrences(of: "\n", with: ""),
+            table.create { t in t.column(int64, primaryKey: true, check: int64Optional > 0, references: table, int64) }
+        )
 
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"int64Optional\" INTEGER REFERENCES \"table\" (\"int64\"))",
@@ -345,6 +360,10 @@ class SchemaTests: XCTestCase {
             "CREATE TABLE \"table\" (\"int64Optional\" INTEGER UNIQUE REFERENCES \"table\" (\"int64\"))",
             table.create { t in t.column(int64Optional, unique: true, references: table, int64) }
         )
+        XCTAssertEqual(
+            "CREATE TABLE \"table\" (\"int64Optional\" INTEGER PRIMARY KEY REFERENCES \"table\" (\"int64\"))",
+            table.create { t in t.column(int64Optional, primaryKey: true, references: table, int64) }
+        )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"int64Optional\" INTEGER CHECK (\"int64\" > 0) REFERENCES \"table\" (\"int64\"))",
             table.create { t in t.column(int64Optional, check: int64 > 0, references: table, int64) }
@@ -357,10 +376,18 @@ class SchemaTests: XCTestCase {
             "CREATE TABLE \"table\" (\"int64Optional\" INTEGER UNIQUE CHECK (\"int64\" > 0) REFERENCES \"table\" (\"int64\"))",
             table.create { t in t.column(int64Optional, unique: true, check: int64 > 0, references: table, int64) }
         )
+        XCTAssertEqual(
+            "CREATE TABLE \"table\" (\"int64Optional\" INTEGER PRIMARY KEY CHECK (\"int64\" > 0) REFERENCES \"table\" (\"int64\"))",
+            table.create { t in t.column(int64Optional, primaryKey: true, check: int64 > 0, references: table, int64) }
+        )
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"int64Optional\" INTEGER UNIQUE CHECK (\"int64Optional\" > 0) REFERENCES \"table\" (\"int64\"))",
             table.create { t in t.column(int64Optional, unique: true, check: int64Optional > 0, references: table, int64) }
         )
+        XCTAssertEqual(
+            "CREATE TABLE \"table\" (\"int64Optional\" INTEGER PRIMARY KEY CHECK (\"int64Optional\" > 0) REFERENCES \"table\" (\"int64\"))",
+            table.create { t in t.column(int64Optional, primaryKey: true, check: int64Optional > 0, references: table, int64) }
+        )
     }
 
     func test_column_withStringExpression_compilesCollatedColumnDefinitionExpression() {

From 05fce4eeeb7b77aeaf75792276e502d9b88ecff1 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Sun, 27 Mar 2022 12:42:30 +0200
Subject: [PATCH 491/685] Fixing Trailing Whitespace Violation

---
 Sources/SQLite/Typed/Schema.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Sources/SQLite/Typed/Schema.swift b/Sources/SQLite/Typed/Schema.swift
index 55e525bc..e162cf34 100644
--- a/Sources/SQLite/Typed/Schema.swift
+++ b/Sources/SQLite/Typed/Schema.swift
@@ -308,7 +308,7 @@ public final class TableBuilder {
                                  references table: QueryType, _ other: Expression<V>) where V.Datatype == Int64 {
         column(name, V.declaredDatatype, nil, true, unique, check, nil, (table, other), nil)
     }
-    
+
     public func column<V: Value>(_ name: Expression<V>, primaryKey: Bool, check: Expression<Bool>? = nil,
                                  references table: QueryType, _ other: Expression<V>) where V.Datatype == Int64 {
         column(name, V.declaredDatatype, primaryKey ? .default : nil, false, false, check, nil, (table, other), nil)

From b53434e2d2bf6c4457b25c212104fca94dcbba2d Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Sun, 27 Mar 2022 12:47:24 +0200
Subject: [PATCH 492/685] Updated Changelog

---
 CHANGELOG.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9bf5682b..786084f8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
 ========================================
 
 * UUID Fix ([#1112][])
+* Add prepareRowIterator method to an extension of Statement. ([#1119][])
 * Adding primary key support to column with references ([#1121][])
 
 0.13.2 (25-01-2022), [diff][diff-0.13.2]
@@ -150,4 +151,5 @@
 [#1100]: https://github.com/stephencelis/SQLite.swift/pull/1100
 [#1105]: https://github.com/stephencelis/SQLite.swift/pull/1105
 [#1112]: https://github.com/stephencelis/SQLite.swift/pull/1112
+[#1119]: https://github.com/stephencelis/SQLite.swift/pull/1119
 [#1121]: https://github.com/stephencelis/SQLite.swift/pull/1121

From c42167feb9e33dc97e9da05232fa96cf354efbbb Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 27 Apr 2022 09:37:46 +0200
Subject: [PATCH 493/685] removeDiacritics => remove_diacritics

https://www.sqlite.org/fts3.html#tokenizer

Closes #1128
---
 Sources/SQLite/Extensions/FTS4.swift | 2 +-
 Tests/SQLiteTests/FTS4Tests.swift    | 6 +++---
 Tests/SQLiteTests/FTS5Tests.swift    | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/Sources/SQLite/Extensions/FTS4.swift b/Sources/SQLite/Extensions/FTS4.swift
index 0e48943a..52fec955 100644
--- a/Sources/SQLite/Extensions/FTS4.swift
+++ b/Sources/SQLite/Extensions/FTS4.swift
@@ -103,7 +103,7 @@ public struct Tokenizer {
         var arguments = [String]()
 
         if let removeDiacritics = removeDiacritics {
-            arguments.append("removeDiacritics=\(removeDiacritics ? 1 : 0)".quote())
+            arguments.append("remove_diacritics=\(removeDiacritics ? 1 : 0)".quote())
         }
 
         if !tokenchars.isEmpty {
diff --git a/Tests/SQLiteTests/FTS4Tests.swift b/Tests/SQLiteTests/FTS4Tests.swift
index 33be422c..d6385b0c 100644
--- a/Tests/SQLiteTests/FTS4Tests.swift
+++ b/Tests/SQLiteTests/FTS4Tests.swift
@@ -21,12 +21,12 @@ class FTS4Tests: XCTestCase {
             virtualTable.create(.FTS4([string], tokenize: .Porter))
         )
         XCTAssertEqual(
-            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(tokenize=unicode61 \"removeDiacritics=0\")",
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(tokenize=unicode61 \"remove_diacritics=0\")",
             virtualTable.create(.FTS4(tokenize: .Unicode61(removeDiacritics: false)))
         )
         XCTAssertEqual(
             """
-            CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(tokenize=unicode61 \"removeDiacritics=1\"
+            CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(tokenize=unicode61 \"remove_diacritics=1\"
              \"tokenchars=.\" \"separators=X\")
             """.replacingOccurrences(of: "\n", with: ""),
             virtualTable.create(.FTS4(tokenize: .Unicode61(removeDiacritics: true,
@@ -116,7 +116,7 @@ class FTS4ConfigTests: XCTestCase {
     func test_tokenizer_unicode61_with_options() {
         XCTAssertEqual(
             """
-            CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(tokenize=unicode61 \"removeDiacritics=1\"
+            CREATE VIRTUAL TABLE \"virtual_table\" USING fts4(tokenize=unicode61 \"remove_diacritics=1\"
              \"tokenchars=.\" \"separators=X\")
             """.replacingOccurrences(of: "\n", with: ""),
             sql(config.tokenizer(.Unicode61(removeDiacritics: true, tokenchars: ["."], separators: ["X"]))))
diff --git a/Tests/SQLiteTests/FTS5Tests.swift b/Tests/SQLiteTests/FTS5Tests.swift
index c271be9d..199ec415 100644
--- a/Tests/SQLiteTests/FTS5Tests.swift
+++ b/Tests/SQLiteTests/FTS5Tests.swift
@@ -77,7 +77,7 @@ class FTS5Tests: XCTestCase {
 
     func test_tokenizer_unicode61_with_options() {
         XCTAssertEqual(
-            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(tokenize=unicode61 \"removeDiacritics=1\" \"tokenchars=.\" \"separators=X\")",
+            "CREATE VIRTUAL TABLE \"virtual_table\" USING fts5(tokenize=unicode61 \"remove_diacritics=1\" \"tokenchars=.\" \"separators=X\")",
             sql(config.tokenizer(.Unicode61(removeDiacritics: true, tokenchars: ["."], separators: ["X"]))))
     }
 

From 626cc79344db350887b28016673b71645de5668b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Maciej=20=C5=9Awi=C4=87?= <maciej@swic.name>
Date: Fri, 29 Apr 2022 17:17:44 +0300
Subject: [PATCH 494/685] Fixed build order

---
 SQLite.xcodeproj/project.pbxproj | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 7387d0e9..61c2773a 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -592,9 +592,9 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 03A65E6F1C6BB0F60062603F /* Build configuration list for PBXNativeTarget "SQLite tvOS" */;
 			buildPhases = (
+				03A65E571C6BB0F50062603F /* Headers */,
 				03A65E551C6BB0F50062603F /* Sources */,
 				03A65E561C6BB0F50062603F /* Frameworks */,
-				03A65E571C6BB0F50062603F /* Headers */,
 				03A65E581C6BB0F50062603F /* Resources */,
 			);
 			buildRules = (
@@ -628,9 +628,9 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = A121AC4C1CA35C79005A31D1 /* Build configuration list for PBXNativeTarget "SQLite watchOS" */;
 			buildPhases = (
+				A121AC421CA35C79005A31D1 /* Headers */,
 				A121AC401CA35C79005A31D1 /* Sources */,
 				A121AC411CA35C79005A31D1 /* Frameworks */,
-				A121AC421CA35C79005A31D1 /* Headers */,
 				A121AC431CA35C79005A31D1 /* Resources */,
 			);
 			buildRules = (
@@ -646,9 +646,9 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = EE247AE71C3F04ED00AE3E12 /* Build configuration list for PBXNativeTarget "SQLite iOS" */;
 			buildPhases = (
+				EE247AD01C3F04ED00AE3E12 /* Headers */,
 				EE247ACE1C3F04ED00AE3E12 /* Sources */,
 				EE247ACF1C3F04ED00AE3E12 /* Frameworks */,
-				EE247AD01C3F04ED00AE3E12 /* Headers */,
 				EE247AD11C3F04ED00AE3E12 /* Resources */,
 			);
 			buildRules = (
@@ -682,9 +682,9 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = EE247B511C3F3ED000AE3E12 /* Build configuration list for PBXNativeTarget "SQLite Mac" */;
 			buildPhases = (
+				EE247B391C3F3ED000AE3E12 /* Headers */,
 				EE247B371C3F3ED000AE3E12 /* Sources */,
 				EE247B381C3F3ED000AE3E12 /* Frameworks */,
-				EE247B391C3F3ED000AE3E12 /* Headers */,
 				EE247B3A1C3F3ED000AE3E12 /* Resources */,
 			);
 			buildRules = (

From b45781a6659e186f85509a83b3678d4701221cc6 Mon Sep 17 00:00:00 2001
From: Justin Meiners <justinm@passivelogic.com>
Date: Mon, 9 May 2022 15:06:50 -0600
Subject: [PATCH 495/685] Improve string quote performance

---
 Sources/SQLite/Helpers.swift | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/Sources/SQLite/Helpers.swift b/Sources/SQLite/Helpers.swift
index d4c6828e..e3d37e11 100644
--- a/Sources/SQLite/Helpers.swift
+++ b/Sources/SQLite/Helpers.swift
@@ -54,12 +54,17 @@ extension Optional: _OptionalType {
 let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self)
 
 extension String {
-
     func quote(_ mark: Character = "\"") -> String {
-        let escaped = reduce("") { string, character in
-            string + (character == mark ? "\(mark)\(mark)" : "\(character)")
+        var quoted = ""
+        quoted.append(mark)
+        for character in self {
+            quoted.append(character)
+            if character == mark {
+                quoted.append(character)
+            }
         }
-        return "\(mark)\(escaped)\(mark)"
+        quoted.append(mark)
+        return quoted
     }
 
     func join(_ expressions: [Expressible]) -> Expressible {

From 75dfb4e4af53b572ed433588fece3950d2c52c35 Mon Sep 17 00:00:00 2001
From: Atulya <atultw@outlook.com>
Date: Thu, 9 Jun 2022 17:20:20 -0700
Subject: [PATCH 496/685] add decoding for UUID

---
 Sources/SQLite/Typed/Coding.swift | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index cea2565a..ca9ca055 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -387,7 +387,11 @@ private class SQLiteDecoder: Decoder {
             } else if type == Date.self {
                 let date = try row.get(Expression<Date>(key.stringValue))
                 return date as! T
+            } else if type == UUID.self {
+                let uuid = try row.get(Expression<UUID>(key.stringValue))
+                return uuid as! T
             }
+            
             // swiftlint:enable force_cast
             guard let JSONString = try row.get(Expression<String?>(key.stringValue)) else {
                 throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,

From 84783d370c94b15ac23e4624027d56f0735d7b5b Mon Sep 17 00:00:00 2001
From: Atulya <atultw@outlook.com>
Date: Mon, 13 Jun 2022 18:20:22 -0700
Subject: [PATCH 497/685] remove trailing whitespace for swiftlint

---
 Sources/SQLite/Typed/Coding.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index ca9ca055..4033365f 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -391,7 +391,7 @@ private class SQLiteDecoder: Decoder {
                 let uuid = try row.get(Expression<UUID>(key.stringValue))
                 return uuid as! T
             }
-            
+
             // swiftlint:enable force_cast
             guard let JSONString = try row.get(Expression<String?>(key.stringValue)) else {
                 throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,

From 7715f7d626261e152c5f718e0770a28d728ba632 Mon Sep 17 00:00:00 2001
From: Atulya <atultw@outlook.com>
Date: Tue, 14 Jun 2022 18:22:44 -0700
Subject: [PATCH 498/685] add tests for codable UUID

---
 Tests/SQLiteTests/QueryIntegrationTests.swift |  7 +--
 Tests/SQLiteTests/QueryTests.swift            | 44 +++++++++----------
 Tests/SQLiteTests/TestHelpers.swift           |  5 ++-
 3 files changed, 30 insertions(+), 26 deletions(-)

diff --git a/Tests/SQLiteTests/QueryIntegrationTests.swift b/Tests/SQLiteTests/QueryIntegrationTests.swift
index 4b9c4bbf..82ee50a3 100644
--- a/Tests/SQLiteTests/QueryIntegrationTests.swift
+++ b/Tests/SQLiteTests/QueryIntegrationTests.swift
@@ -75,15 +75,15 @@ class QueryIntegrationTests: SQLiteTestCase {
             builder.column(Expression<Double>("float"))
             builder.column(Expression<Double>("double"))
             builder.column(Expression<Date>("date"))
+            builder.column(Expression<UUID>("uuid"))
             builder.column(Expression<String?>("optional"))
             builder.column(Expression<Data>("sub"))
         })
 
         let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
-                                 date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+                                 date: Date(timeIntervalSince1970: 0), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: nil, sub: nil)
         let value = TestCodable(int: 5, string: "6", bool: true, float: 7, double: 8,
-                                date: Date(timeIntervalSince1970: 5000), optional: "optional", sub: value1)
-
+                                date: Date(timeIntervalSince1970: 5000), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: "optional", sub: value1)
         try db.run(table.insert(value))
 
         let rows = try db.prepare(table)
@@ -95,6 +95,7 @@ class QueryIntegrationTests: SQLiteTestCase {
         XCTAssertEqual(values[0].float, 7)
         XCTAssertEqual(values[0].double, 8)
         XCTAssertEqual(values[0].date, Date(timeIntervalSince1970: 5000))
+        XCTAssertEqual(values[0].uuid, UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!)
         XCTAssertEqual(values[0].optional, "optional")
         XCTAssertEqual(values[0].sub?.int, 1)
         XCTAssertEqual(values[0].sub?.string, "2")
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index efcbab94..efaf7d15 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -279,12 +279,12 @@ class QueryTests: XCTestCase {
     func test_insert_encodable() throws {
         let emails = Table("emails")
         let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
-                                date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+                                date: Date(timeIntervalSince1970: 0), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: nil, sub: nil)
         let insert = try emails.insert(value)
         assertSQL(
             """
-            INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\")
-             VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000')
+            INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\", \"uuid\")
+             VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000', 'E621E1F8-C36C-495A-93FC-0C247A3E6E5F')
             """.replacingOccurrences(of: "\n", with: ""),
             insert
         )
@@ -294,16 +294,16 @@ class QueryTests: XCTestCase {
     func test_insert_encodable_with_nested_encodable() throws {
         let emails = Table("emails")
         let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
-                                 date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+                                 date: Date(timeIntervalSince1970: 0), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: nil, sub: nil)
         let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
-                                date: Date(timeIntervalSince1970: 0), optional: "optional", sub: value1)
+                                date: Date(timeIntervalSince1970: 0), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: "optional", sub: value1)
         let insert = try emails.insert(value)
         let encodedJSON = try JSONEncoder().encode(value1)
         let encodedJSONString = String(data: encodedJSON, encoding: .utf8)!
         assertSQL(
             """
-            INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\", \"optional\",
-             \"sub\") VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000', 'optional', '\(encodedJSONString)')
+            INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\", \"uuid\", \"optional\",
+             \"sub\") VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000', 'E621E1F8-C36C-495A-93FC-0C247A3E6E5F', 'optional', '\(encodedJSONString)')
             """.replacingOccurrences(of: "\n", with: ""),
             insert
         )
@@ -350,14 +350,14 @@ class QueryTests: XCTestCase {
         let emails = Table("emails")
         let string = Expression<String>("string")
         let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
-                                date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+                                date: Date(timeIntervalSince1970: 0), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: nil, sub: nil)
         let insert = try emails.upsert(value, onConflictOf: string)
         assertSQL(
             """
-            INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\")
-             VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000') ON CONFLICT (\"string\")
+            INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\", \"uuid\")
+             VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000', 'E621E1F8-C36C-495A-93FC-0C247A3E6E5F') ON CONFLICT (\"string\")
              DO UPDATE SET \"int\" = \"excluded\".\"int\", \"bool\" = \"excluded\".\"bool\",
-             \"float\" = \"excluded\".\"float\", \"double\" = \"excluded\".\"double\", \"date\" = \"excluded\".\"date\"
+             \"float\" = \"excluded\".\"float\", \"double\" = \"excluded\".\"double\", \"date\" = \"excluded\".\"date\", \"uuid\" = \"excluded\".\"uuid\"
             """.replacingOccurrences(of: "\n", with: ""),
             insert
         )
@@ -366,17 +366,17 @@ class QueryTests: XCTestCase {
     func test_insert_many_encodable() throws {
         let emails = Table("emails")
         let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
-                                 date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+                                 date: Date(timeIntervalSince1970: 0), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: nil, sub: nil)
         let value2 = TestCodable(int: 2, string: "3", bool: true, float: 3, double: 5,
-                                 date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+                                 date: Date(timeIntervalSince1970: 0), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: nil, sub: nil)
         let value3 = TestCodable(int: 3, string: "4", bool: true, float: 3, double: 6,
-                                 date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+                                 date: Date(timeIntervalSince1970: 0), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: nil, sub: nil)
         let insert = try emails.insertMany([value1, value2, value3])
         assertSQL(
             """
-            INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\")
-             VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000'), (2, '3', 1, 3.0, 5.0, '1970-01-01T00:00:00.000'),
-             (3, '4', 1, 3.0, 6.0, '1970-01-01T00:00:00.000')
+            INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\", \"uuid\")
+             VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000', 'E621E1F8-C36C-495A-93FC-0C247A3E6E5F'), (2, '3', 1, 3.0, 5.0, '1970-01-01T00:00:00.000', 'E621E1F8-C36C-495A-93FC-0C247A3E6E5F'),
+             (3, '4', 1, 3.0, 6.0, '1970-01-01T00:00:00.000', 'E621E1F8-C36C-495A-93FC-0C247A3E6E5F')
             """.replacingOccurrences(of: "\n", with: ""),
             insert
         )
@@ -399,12 +399,12 @@ class QueryTests: XCTestCase {
     func test_update_encodable() throws {
         let emails = Table("emails")
         let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
-                                date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+                                date: Date(timeIntervalSince1970: 0), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: nil, sub: nil)
         let update = try emails.update(value)
         assertSQL(
             """
             UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0,
-             \"date\" = '1970-01-01T00:00:00.000'
+             \"date\" = '1970-01-01T00:00:00.000', \"uuid\" = 'E621E1F8-C36C-495A-93FC-0C247A3E6E5F'
             """.replacingOccurrences(of: "\n", with: ""),
             update
         )
@@ -413,9 +413,9 @@ class QueryTests: XCTestCase {
     func test_update_encodable_with_nested_encodable() throws {
         let emails = Table("emails")
         let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
-                                 date: Date(timeIntervalSince1970: 0), optional: nil, sub: nil)
+                                 date: Date(timeIntervalSince1970: 0), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: nil, sub: nil)
         let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
-                                date: Date(timeIntervalSince1970: 0), optional: nil, sub: value1)
+                                date: Date(timeIntervalSince1970: 0), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: nil, sub: value1)
         let update = try emails.update(value)
 
         // NOTE: As Linux JSON decoding doesn't order keys the same way, we need to check prefix, suffix,
@@ -424,7 +424,7 @@ class QueryTests: XCTestCase {
         let expectedPrefix =
             """
             UPDATE \"emails\" SET \"int\" = 1, \"string\" = '2', \"bool\" = 1, \"float\" = 3.0, \"double\" = 4.0,
-             \"date\" = '1970-01-01T00:00:00.000', \"sub\" = '
+             \"date\" = '1970-01-01T00:00:00.000', \"uuid\" = 'E621E1F8-C36C-495A-93FC-0C247A3E6E5F', \"sub\" = '
             """.replacingOccurrences(of: "\n", with: "")
         let expectedSuffix = "'"
 
diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index a6efa2e7..bc538c5b 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -115,16 +115,18 @@ class TestCodable: Codable, Equatable {
     let float: Float
     let double: Double
     let date: Date
+    let uuid: UUID
     let optional: String?
     let sub: TestCodable?
 
-    init(int: Int, string: String, bool: Bool, float: Float, double: Double, date: Date, optional: String?, sub: TestCodable?) {
+    init(int: Int, string: String, bool: Bool, float: Float, double: Double, date: Date, uuid: UUID, optional: String?, sub: TestCodable?) {
         self.int = int
         self.string = string
         self.bool = bool
         self.float = float
         self.double = double
         self.date = date
+        self.uuid = uuid
         self.optional = optional
         self.sub = sub
     }
@@ -136,6 +138,7 @@ class TestCodable: Codable, Equatable {
         lhs.float == rhs.float &&
         lhs.double == rhs.double &&
         lhs.date == rhs.date &&
+        lhs.uuid == lhs.uuid &&
         lhs.optional == rhs.optional &&
         lhs.sub == rhs.sub
     }

From 8fece72b9be693a41d15ff20d7432bd30964610e Mon Sep 17 00:00:00 2001
From: Atulya <atultw@outlook.com>
Date: Mon, 27 Jun 2022 12:38:57 -0700
Subject: [PATCH 499/685] create a constant for the UUID used in tests

---
 Tests/SQLiteTests/QueryIntegrationTests.swift |  6 +++---
 Tests/SQLiteTests/QueryTests.swift            | 20 +++++++++----------
 Tests/SQLiteTests/TestHelpers.swift           |  2 ++
 3 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/Tests/SQLiteTests/QueryIntegrationTests.swift b/Tests/SQLiteTests/QueryIntegrationTests.swift
index 82ee50a3..b3d9cf96 100644
--- a/Tests/SQLiteTests/QueryIntegrationTests.swift
+++ b/Tests/SQLiteTests/QueryIntegrationTests.swift
@@ -81,9 +81,9 @@ class QueryIntegrationTests: SQLiteTestCase {
         })
 
         let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
-                                 date: Date(timeIntervalSince1970: 0), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: nil, sub: nil)
+                                 date: Date(timeIntervalSince1970: 0), uuid: testUUIDValue, optional: nil, sub: nil)
         let value = TestCodable(int: 5, string: "6", bool: true, float: 7, double: 8,
-                                date: Date(timeIntervalSince1970: 5000), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: "optional", sub: value1)
+                                date: Date(timeIntervalSince1970: 5000), uuid: testUUIDValue, optional: "optional", sub: value1)
         try db.run(table.insert(value))
 
         let rows = try db.prepare(table)
@@ -95,7 +95,7 @@ class QueryIntegrationTests: SQLiteTestCase {
         XCTAssertEqual(values[0].float, 7)
         XCTAssertEqual(values[0].double, 8)
         XCTAssertEqual(values[0].date, Date(timeIntervalSince1970: 5000))
-        XCTAssertEqual(values[0].uuid, UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!)
+        XCTAssertEqual(values[0].uuid, testUUIDValue)
         XCTAssertEqual(values[0].optional, "optional")
         XCTAssertEqual(values[0].sub?.int, 1)
         XCTAssertEqual(values[0].sub?.string, "2")
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index efaf7d15..e4353e52 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -279,7 +279,7 @@ class QueryTests: XCTestCase {
     func test_insert_encodable() throws {
         let emails = Table("emails")
         let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
-                                date: Date(timeIntervalSince1970: 0), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: nil, sub: nil)
+                                date: Date(timeIntervalSince1970: 0), uuid: testUUIDValue, optional: nil, sub: nil)
         let insert = try emails.insert(value)
         assertSQL(
             """
@@ -294,9 +294,9 @@ class QueryTests: XCTestCase {
     func test_insert_encodable_with_nested_encodable() throws {
         let emails = Table("emails")
         let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
-                                 date: Date(timeIntervalSince1970: 0), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: nil, sub: nil)
+                                 date: Date(timeIntervalSince1970: 0), uuid: testUUIDValue, optional: nil, sub: nil)
         let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
-                                date: Date(timeIntervalSince1970: 0), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: "optional", sub: value1)
+                                date: Date(timeIntervalSince1970: 0), uuid: testUUIDValue, optional: "optional", sub: value1)
         let insert = try emails.insert(value)
         let encodedJSON = try JSONEncoder().encode(value1)
         let encodedJSONString = String(data: encodedJSON, encoding: .utf8)!
@@ -350,7 +350,7 @@ class QueryTests: XCTestCase {
         let emails = Table("emails")
         let string = Expression<String>("string")
         let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
-                                date: Date(timeIntervalSince1970: 0), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: nil, sub: nil)
+                                date: Date(timeIntervalSince1970: 0), uuid: testUUIDValue, optional: nil, sub: nil)
         let insert = try emails.upsert(value, onConflictOf: string)
         assertSQL(
             """
@@ -366,11 +366,11 @@ class QueryTests: XCTestCase {
     func test_insert_many_encodable() throws {
         let emails = Table("emails")
         let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
-                                 date: Date(timeIntervalSince1970: 0), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: nil, sub: nil)
+                                 date: Date(timeIntervalSince1970: 0), uuid: testUUIDValue, optional: nil, sub: nil)
         let value2 = TestCodable(int: 2, string: "3", bool: true, float: 3, double: 5,
-                                 date: Date(timeIntervalSince1970: 0), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: nil, sub: nil)
+                                 date: Date(timeIntervalSince1970: 0), uuid: testUUIDValue, optional: nil, sub: nil)
         let value3 = TestCodable(int: 3, string: "4", bool: true, float: 3, double: 6,
-                                 date: Date(timeIntervalSince1970: 0), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: nil, sub: nil)
+                                 date: Date(timeIntervalSince1970: 0), uuid: testUUIDValue, optional: nil, sub: nil)
         let insert = try emails.insertMany([value1, value2, value3])
         assertSQL(
             """
@@ -399,7 +399,7 @@ class QueryTests: XCTestCase {
     func test_update_encodable() throws {
         let emails = Table("emails")
         let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
-                                date: Date(timeIntervalSince1970: 0), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: nil, sub: nil)
+                                date: Date(timeIntervalSince1970: 0), uuid: testUUIDValue, optional: nil, sub: nil)
         let update = try emails.update(value)
         assertSQL(
             """
@@ -413,9 +413,9 @@ class QueryTests: XCTestCase {
     func test_update_encodable_with_nested_encodable() throws {
         let emails = Table("emails")
         let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
-                                 date: Date(timeIntervalSince1970: 0), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: nil, sub: nil)
+                                 date: Date(timeIntervalSince1970: 0), uuid: testUUIDValue, optional: nil, sub: nil)
         let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
-                                date: Date(timeIntervalSince1970: 0), uuid: UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!, optional: nil, sub: value1)
+                                date: Date(timeIntervalSince1970: 0), uuid: testUUIDValue, optional: nil, sub: value1)
         let update = try emails.update(value)
 
         // NOTE: As Linux JSON decoding doesn't order keys the same way, we need to check prefix, suffix,
diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index bc538c5b..4a71fd40 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -98,6 +98,8 @@ let stringOptional = Expression<String?>("stringOptional")
 let uuid = Expression<UUID>("uuid")
 let uuidOptional = Expression<UUID?>("uuidOptional")
 
+let testUUIDValue = UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!
+
 func assertSQL(_ expression1: @autoclosure () -> String, _ expression2: @autoclosure () -> Expressible,
                file: StaticString = #file, line: UInt = #line) {
     XCTAssertEqual(expression1(), expression2().asSQL(), file: file, line: line)

From 92760e03cc71643dbb51402eb21c2dbbb59405b3 Mon Sep 17 00:00:00 2001
From: Atulya <atultw@outlook.com>
Date: Mon, 27 Jun 2022 12:51:15 -0700
Subject: [PATCH 500/685] use a switch to accommodate more types

---
 Sources/SQLite/Typed/Coding.swift | 166 +++++++++++++++---------------
 1 file changed, 84 insertions(+), 82 deletions(-)

diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index 4033365f..e7f5b7bb 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -44,7 +44,7 @@ extension QueryType {
         try encodable.encode(to: encoder)
         return self.insert(encoder.setters + otherSetters)
     }
-
+    
     /// Creates an `INSERT` statement by encoding the given object
     /// This method converts any custom nested types to JSON data and does not handle any sort
     /// of object relationships. If you want to support relationships between objects you will
@@ -69,7 +69,7 @@ extension QueryType {
         try encodable.encode(to: encoder)
         return self.insert(or: onConflict, encoder.setters + otherSetters)
     }
-
+    
     /// Creates a batch `INSERT` statement by encoding the array of given objects
     /// This method converts any custom nested types to JSON data and does not handle any sort
     /// of object relationships. If you want to support relationships between objects you will
@@ -93,7 +93,7 @@ extension QueryType {
         }
         return self.insertMany(combinedSetters)
     }
-
+    
     /// Creates an `INSERT ON CONFLICT DO UPDATE` statement, aka upsert, by encoding the given object
     /// This method converts any custom nested types to JSON data and does not handle any sort
     /// of object relationships. If you want to support relationships between objects you will
@@ -116,7 +116,7 @@ extension QueryType {
         try encodable.encode(to: encoder)
         return self.upsert(encoder.setters + otherSetters, onConflictOf: conflicting)
     }
-
+    
     /// Creates an `UPDATE` statement by encoding the given object
     /// This method converts any custom nested types to JSON data and does not handle any sort
     /// of object relationships. If you want to support relationships between objects you will
@@ -151,7 +151,7 @@ extension Row {
     public func decode<V: Decodable>(userInfo: [CodingUserInfoKey: Any] = [:]) throws -> V {
         try V(from: decoder(userInfo: userInfo))
     }
-
+    
     public func decoder(userInfo: [CodingUserInfoKey: Any] = [:]) -> Decoder {
         SQLiteDecoder(row: self, userInfo: userInfo)
     }
@@ -162,130 +162,131 @@ private class SQLiteEncoder: Encoder {
     class SQLiteKeyedEncodingContainer<MyKey: CodingKey>: KeyedEncodingContainerProtocol {
         // swiftlint:disable nesting
         typealias Key = MyKey
-
+        
         let encoder: SQLiteEncoder
         let codingPath: [CodingKey] = []
-
+        
         init(encoder: SQLiteEncoder) {
             self.encoder = encoder
         }
-
+        
         func superEncoder() -> Swift.Encoder {
             fatalError("SQLiteEncoding does not support super encoders")
         }
-
+        
         func superEncoder(forKey key: Key) -> Swift.Encoder {
             fatalError("SQLiteEncoding does not support super encoders")
         }
-
+        
         func encodeNil(forKey key: SQLiteEncoder.SQLiteKeyedEncodingContainer<Key>.Key) throws {
             encoder.setters.append(Expression<String?>(key.stringValue) <- nil)
         }
-
+        
         func encode(_ value: Int, forKey key: SQLiteEncoder.SQLiteKeyedEncodingContainer<Key>.Key) throws {
             encoder.setters.append(Expression(key.stringValue) <- value)
         }
-
+        
         func encode(_ value: Bool, forKey key: Key) throws {
             encoder.setters.append(Expression(key.stringValue) <- value)
         }
-
+        
         func encode(_ value: Float, forKey key: Key) throws {
             encoder.setters.append(Expression(key.stringValue) <- Double(value))
         }
-
+        
         func encode(_ value: Double, forKey key: Key) throws {
             encoder.setters.append(Expression(key.stringValue) <- value)
         }
-
+        
         func encode(_ value: String, forKey key: Key) throws {
             encoder.setters.append(Expression(key.stringValue) <- value)
         }
-
+        
         func encode<T>(_ value: T, forKey key: Key) throws where T: Swift.Encodable {
-            if let data = value as? Data {
+            switch value {
+            case let data as Data:
                 encoder.setters.append(Expression(key.stringValue) <- data)
-            } else if let date = value as? Date {
+            case let date as Date:
                 encoder.setters.append(Expression(key.stringValue) <- date.datatypeValue)
-            } else if let uuid = value as? UUID {
+            case let uuid as UUID:
                 encoder.setters.append(Expression(key.stringValue) <- uuid.datatypeValue)
-            } else {
+            default:
                 let encoded = try JSONEncoder().encode(value)
                 let string = String(data: encoded, encoding: .utf8)
                 encoder.setters.append(Expression(key.stringValue) <- string)
             }
         }
-
+        
         func encode(_ value: Int8, forKey key: Key) throws {
             throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an Int8 is not supported"))
         }
-
+        
         func encode(_ value: Int16, forKey key: Key) throws {
             throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an Int16 is not supported"))
         }
-
+        
         func encode(_ value: Int32, forKey key: Key) throws {
             throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an Int32 is not supported"))
         }
-
+        
         func encode(_ value: Int64, forKey key: Key) throws {
             encoder.setters.append(Expression(key.stringValue) <- value)
         }
-
+        
         func encode(_ value: UInt, forKey key: Key) throws {
             throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an UInt is not supported"))
         }
-
+        
         func encode(_ value: UInt8, forKey key: Key) throws {
             throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an UInt8 is not supported"))
         }
-
+        
         func encode(_ value: UInt16, forKey key: Key) throws {
             throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an UInt16 is not supported"))
         }
-
+        
         func encode(_ value: UInt32, forKey key: Key) throws {
             throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an UInt32 is not supported"))
         }
-
+        
         func encode(_ value: UInt64, forKey key: Key) throws {
             throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an UInt64 is not supported"))
         }
-
+        
         func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key)
-                        -> KeyedEncodingContainer<NestedKey> where NestedKey: CodingKey {
+        -> KeyedEncodingContainer<NestedKey> where NestedKey: CodingKey {
             fatalError("encoding a nested container is not supported")
         }
-
+        
         func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
             fatalError("encoding nested values is not supported")
         }
     }
-
+    
     fileprivate var setters: [Setter] = []
     let codingPath: [CodingKey] = []
     let userInfo: [CodingUserInfoKey: Any]
-
+    
     init(userInfo: [CodingUserInfoKey: Any]) {
         self.userInfo = userInfo
     }
-
+    
     func singleValueContainer() -> SingleValueEncodingContainer {
         fatalError("not supported")
     }
-
+    
     func unkeyedContainer() -> UnkeyedEncodingContainer {
         fatalError("not supported")
     }
-
+    
     func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key: CodingKey {
         KeyedEncodingContainer(SQLiteKeyedEncodingContainer(encoder: self))
     }
@@ -294,156 +295,157 @@ private class SQLiteEncoder: Encoder {
 private class SQLiteDecoder: Decoder {
     class SQLiteKeyedDecodingContainer<MyKey: CodingKey>: KeyedDecodingContainerProtocol {
         typealias Key = MyKey
-
+        
         let codingPath: [CodingKey] = []
         let row: Row
-
+        
         init(row: Row) {
             self.row = row
         }
-
+        
         var allKeys: [Key] {
             row.columnNames.keys.compactMap({ Key(stringValue: $0) })
         }
-
+        
         func contains(_ key: Key) -> Bool {
             row.hasValue(for: key.stringValue)
         }
-
+        
         func decodeNil(forKey key: Key) throws -> Bool {
             !contains(key)
         }
-
+        
         func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool {
             try row.get(Expression(key.stringValue))
         }
-
+        
         func decode(_ type: Int.Type, forKey key: Key) throws -> Int {
             try row.get(Expression(key.stringValue))
         }
-
+        
         func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 {
             throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an Int8 is not supported"))
         }
-
+        
         func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 {
             throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an Int16 is not supported"))
         }
-
+        
         func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 {
             throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an Int32 is not supported"))
         }
-
+        
         func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
             try row.get(Expression(key.stringValue))
         }
-
+        
         func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {
             throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an UInt is not supported"))
-
+            
         }
-
+        
         func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 {
             throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an UInt8 is not supported"))
         }
-
+        
         func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 {
             throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an UInt16 is not supported"))
         }
-
+        
         func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 {
             throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an UInt32 is not supported"))
         }
-
+        
         func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 {
             throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an UInt64 is not supported"))
         }
-
+        
         func decode(_ type: Float.Type, forKey key: Key) throws -> Float {
             Float(try row.get(Expression<Double>(key.stringValue)))
         }
-
+        
         func decode(_ type: Double.Type, forKey key: Key) throws -> Double {
             try row.get(Expression(key.stringValue))
         }
-
+        
         func decode(_ type: String.Type, forKey key: Key) throws -> String {
             try row.get(Expression(key.stringValue))
         }
-
+        
         func decode<T>(_ type: T.Type, forKey key: Key) throws -> T where T: Swift.Decodable {
             // swiftlint:disable force_cast
-            if type == Data.self {
+            switch type {
+            case is Data.Type:
                 let data = try row.get(Expression<Data>(key.stringValue))
                 return data as! T
-            } else if type == Date.self {
+            case is Date.Type:
                 let date = try row.get(Expression<Date>(key.stringValue))
                 return date as! T
-            } else if type == UUID.self {
+            case is UUID.Type:
                 let uuid = try row.get(Expression<UUID>(key.stringValue))
                 return uuid as! T
+            default:
+                // swiftlint:enable force_cast
+                guard let JSONString = try row.get(Expression<String?>(key.stringValue)) else {
+                    throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
+                                                                                 debugDescription: "an unsupported type was found"))
+                }
+                guard let data = JSONString.data(using: .utf8) else {
+                    throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,
+                                                                            debugDescription: "invalid utf8 data found"))
+                }
+                return try JSONDecoder().decode(type, from: data)
             }
-
-            // swiftlint:enable force_cast
-            guard let JSONString = try row.get(Expression<String?>(key.stringValue)) else {
-                throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
-                                                                             debugDescription: "an unsupported type was found"))
-            }
-            guard let data = JSONString.data(using: .utf8) else {
-                throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,
-                                                                        debugDescription: "invalid utf8 data found"))
-            }
-            return try JSONDecoder().decode(type, from: data)
         }
-
+        
         func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws
-                        -> KeyedDecodingContainer<NestedKey> where NestedKey: CodingKey {
+        -> KeyedDecodingContainer<NestedKey> where NestedKey: CodingKey {
             throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,
                                                                     debugDescription: "decoding nested containers is not supported"))
         }
-
+        
         func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
             throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,
                                                                     debugDescription: "decoding unkeyed containers is not supported"))
         }
-
+        
         func superDecoder() throws -> Swift.Decoder {
             throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,
                                                                     debugDescription: "decoding super encoders containers is not supported"))
         }
-
+        
         func superDecoder(forKey key: Key) throws -> Swift.Decoder {
             throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,
                                                                     debugDescription: "decoding super decoders is not supported"))
         }
     }
-
+    
     let row: Row
     let codingPath: [CodingKey] = []
     let userInfo: [CodingUserInfoKey: Any]
-
+    
     init(row: Row, userInfo: [CodingUserInfoKey: Any]) {
         self.row = row
         self.userInfo = userInfo
     }
-
+    
     func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> where Key: CodingKey {
         KeyedDecodingContainer(SQLiteKeyedDecodingContainer(row: row))
     }
-
+    
     func unkeyedContainer() throws -> UnkeyedDecodingContainer {
         throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,
                                                                 debugDescription: "decoding an unkeyed container is not supported"))
     }
-
+    
     func singleValueContainer() throws -> SingleValueDecodingContainer {
         throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,
                                                                 debugDescription: "decoding a single value container is not supported"))

From bc63d3ab1a154d941ac67b8c75216b625cd0efdf Mon Sep 17 00:00:00 2001
From: Atulya <atultw@outlook.com>
Date: Mon, 27 Jun 2022 12:52:36 -0700
Subject: [PATCH 501/685] swiftlint fix

---
 Sources/SQLite/Typed/Coding.swift | 124 +++++++++++++++---------------
 1 file changed, 62 insertions(+), 62 deletions(-)

diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index e7f5b7bb..ec2e0d6c 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -44,7 +44,7 @@ extension QueryType {
         try encodable.encode(to: encoder)
         return self.insert(encoder.setters + otherSetters)
     }
-    
+
     /// Creates an `INSERT` statement by encoding the given object
     /// This method converts any custom nested types to JSON data and does not handle any sort
     /// of object relationships. If you want to support relationships between objects you will
@@ -69,7 +69,7 @@ extension QueryType {
         try encodable.encode(to: encoder)
         return self.insert(or: onConflict, encoder.setters + otherSetters)
     }
-    
+
     /// Creates a batch `INSERT` statement by encoding the array of given objects
     /// This method converts any custom nested types to JSON data and does not handle any sort
     /// of object relationships. If you want to support relationships between objects you will
@@ -93,7 +93,7 @@ extension QueryType {
         }
         return self.insertMany(combinedSetters)
     }
-    
+
     /// Creates an `INSERT ON CONFLICT DO UPDATE` statement, aka upsert, by encoding the given object
     /// This method converts any custom nested types to JSON data and does not handle any sort
     /// of object relationships. If you want to support relationships between objects you will
@@ -116,7 +116,7 @@ extension QueryType {
         try encodable.encode(to: encoder)
         return self.upsert(encoder.setters + otherSetters, onConflictOf: conflicting)
     }
-    
+
     /// Creates an `UPDATE` statement by encoding the given object
     /// This method converts any custom nested types to JSON data and does not handle any sort
     /// of object relationships. If you want to support relationships between objects you will
@@ -151,7 +151,7 @@ extension Row {
     public func decode<V: Decodable>(userInfo: [CodingUserInfoKey: Any] = [:]) throws -> V {
         try V(from: decoder(userInfo: userInfo))
     }
-    
+
     public func decoder(userInfo: [CodingUserInfoKey: Any] = [:]) -> Decoder {
         SQLiteDecoder(row: self, userInfo: userInfo)
     }
@@ -162,46 +162,46 @@ private class SQLiteEncoder: Encoder {
     class SQLiteKeyedEncodingContainer<MyKey: CodingKey>: KeyedEncodingContainerProtocol {
         // swiftlint:disable nesting
         typealias Key = MyKey
-        
+
         let encoder: SQLiteEncoder
         let codingPath: [CodingKey] = []
-        
+
         init(encoder: SQLiteEncoder) {
             self.encoder = encoder
         }
-        
+
         func superEncoder() -> Swift.Encoder {
             fatalError("SQLiteEncoding does not support super encoders")
         }
-        
+
         func superEncoder(forKey key: Key) -> Swift.Encoder {
             fatalError("SQLiteEncoding does not support super encoders")
         }
-        
+
         func encodeNil(forKey key: SQLiteEncoder.SQLiteKeyedEncodingContainer<Key>.Key) throws {
             encoder.setters.append(Expression<String?>(key.stringValue) <- nil)
         }
-        
+
         func encode(_ value: Int, forKey key: SQLiteEncoder.SQLiteKeyedEncodingContainer<Key>.Key) throws {
             encoder.setters.append(Expression(key.stringValue) <- value)
         }
-        
+
         func encode(_ value: Bool, forKey key: Key) throws {
             encoder.setters.append(Expression(key.stringValue) <- value)
         }
-        
+
         func encode(_ value: Float, forKey key: Key) throws {
             encoder.setters.append(Expression(key.stringValue) <- Double(value))
         }
-        
+
         func encode(_ value: Double, forKey key: Key) throws {
             encoder.setters.append(Expression(key.stringValue) <- value)
         }
-        
+
         func encode(_ value: String, forKey key: Key) throws {
             encoder.setters.append(Expression(key.stringValue) <- value)
         }
-        
+
         func encode<T>(_ value: T, forKey key: Key) throws where T: Swift.Encodable {
             switch value {
             case let data as Data:
@@ -216,77 +216,77 @@ private class SQLiteEncoder: Encoder {
                 encoder.setters.append(Expression(key.stringValue) <- string)
             }
         }
-        
+
         func encode(_ value: Int8, forKey key: Key) throws {
             throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an Int8 is not supported"))
         }
-        
+
         func encode(_ value: Int16, forKey key: Key) throws {
             throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an Int16 is not supported"))
         }
-        
+
         func encode(_ value: Int32, forKey key: Key) throws {
             throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an Int32 is not supported"))
         }
-        
+
         func encode(_ value: Int64, forKey key: Key) throws {
             encoder.setters.append(Expression(key.stringValue) <- value)
         }
-        
+
         func encode(_ value: UInt, forKey key: Key) throws {
             throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an UInt is not supported"))
         }
-        
+
         func encode(_ value: UInt8, forKey key: Key) throws {
             throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an UInt8 is not supported"))
         }
-        
+
         func encode(_ value: UInt16, forKey key: Key) throws {
             throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an UInt16 is not supported"))
         }
-        
+
         func encode(_ value: UInt32, forKey key: Key) throws {
             throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an UInt32 is not supported"))
         }
-        
+
         func encode(_ value: UInt64, forKey key: Key) throws {
             throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an UInt64 is not supported"))
         }
-        
+
         func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key)
         -> KeyedEncodingContainer<NestedKey> where NestedKey: CodingKey {
             fatalError("encoding a nested container is not supported")
         }
-        
+
         func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
             fatalError("encoding nested values is not supported")
         }
     }
-    
+
     fileprivate var setters: [Setter] = []
     let codingPath: [CodingKey] = []
     let userInfo: [CodingUserInfoKey: Any]
-    
+
     init(userInfo: [CodingUserInfoKey: Any]) {
         self.userInfo = userInfo
     }
-    
+
     func singleValueContainer() -> SingleValueEncodingContainer {
         fatalError("not supported")
     }
-    
+
     func unkeyedContainer() -> UnkeyedEncodingContainer {
         fatalError("not supported")
     }
-    
+
     func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key: CodingKey {
         KeyedEncodingContainer(SQLiteKeyedEncodingContainer(encoder: self))
     }
@@ -295,91 +295,91 @@ private class SQLiteEncoder: Encoder {
 private class SQLiteDecoder: Decoder {
     class SQLiteKeyedDecodingContainer<MyKey: CodingKey>: KeyedDecodingContainerProtocol {
         typealias Key = MyKey
-        
+
         let codingPath: [CodingKey] = []
         let row: Row
-        
+
         init(row: Row) {
             self.row = row
         }
-        
+
         var allKeys: [Key] {
             row.columnNames.keys.compactMap({ Key(stringValue: $0) })
         }
-        
+
         func contains(_ key: Key) -> Bool {
             row.hasValue(for: key.stringValue)
         }
-        
+
         func decodeNil(forKey key: Key) throws -> Bool {
             !contains(key)
         }
-        
+
         func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool {
             try row.get(Expression(key.stringValue))
         }
-        
+
         func decode(_ type: Int.Type, forKey key: Key) throws -> Int {
             try row.get(Expression(key.stringValue))
         }
-        
+
         func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 {
             throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an Int8 is not supported"))
         }
-        
+
         func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 {
             throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an Int16 is not supported"))
         }
-        
+
         func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 {
             throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an Int32 is not supported"))
         }
-        
+
         func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
             try row.get(Expression(key.stringValue))
         }
-        
+
         func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {
             throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an UInt is not supported"))
-            
+
         }
-        
+
         func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 {
             throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an UInt8 is not supported"))
         }
-        
+
         func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 {
             throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an UInt16 is not supported"))
         }
-        
+
         func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 {
             throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an UInt32 is not supported"))
         }
-        
+
         func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 {
             throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                          debugDescription: "decoding an UInt64 is not supported"))
         }
-        
+
         func decode(_ type: Float.Type, forKey key: Key) throws -> Float {
             Float(try row.get(Expression<Double>(key.stringValue)))
         }
-        
+
         func decode(_ type: Double.Type, forKey key: Key) throws -> Double {
             try row.get(Expression(key.stringValue))
         }
-        
+
         func decode(_ type: String.Type, forKey key: Key) throws -> String {
             try row.get(Expression(key.stringValue))
         }
-        
+
         func decode<T>(_ type: T.Type, forKey key: Key) throws -> T where T: Swift.Decodable {
             // swiftlint:disable force_cast
             switch type {
@@ -405,47 +405,47 @@ private class SQLiteDecoder: Decoder {
                 return try JSONDecoder().decode(type, from: data)
             }
         }
-        
+
         func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws
         -> KeyedDecodingContainer<NestedKey> where NestedKey: CodingKey {
             throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,
                                                                     debugDescription: "decoding nested containers is not supported"))
         }
-        
+
         func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
             throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,
                                                                     debugDescription: "decoding unkeyed containers is not supported"))
         }
-        
+
         func superDecoder() throws -> Swift.Decoder {
             throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,
                                                                     debugDescription: "decoding super encoders containers is not supported"))
         }
-        
+
         func superDecoder(forKey key: Key) throws -> Swift.Decoder {
             throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,
                                                                     debugDescription: "decoding super decoders is not supported"))
         }
     }
-    
+
     let row: Row
     let codingPath: [CodingKey] = []
     let userInfo: [CodingUserInfoKey: Any]
-    
+
     init(row: Row, userInfo: [CodingUserInfoKey: Any]) {
         self.row = row
         self.userInfo = userInfo
     }
-    
+
     func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> where Key: CodingKey {
         KeyedDecodingContainer(SQLiteKeyedDecodingContainer(row: row))
     }
-    
+
     func unkeyedContainer() throws -> UnkeyedDecodingContainer {
         throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,
                                                                 debugDescription: "decoding an unkeyed container is not supported"))
     }
-    
+
     func singleValueContainer() throws -> SingleValueDecodingContainer {
         throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,
                                                                 debugDescription: "decoding a single value container is not supported"))

From 3fac726365dc5813625aed56069c3b9feb446762 Mon Sep 17 00:00:00 2001
From: Atulya <atultw@outlook.com>
Date: Tue, 28 Jun 2022 12:27:52 -0700
Subject: [PATCH 502/685] silence swiftlint line_length for some sql strings

---
 Tests/SQLiteTests/QueryTests.swift | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index e4353e52..d9cce086 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -300,6 +300,7 @@ class QueryTests: XCTestCase {
         let insert = try emails.insert(value)
         let encodedJSON = try JSONEncoder().encode(value1)
         let encodedJSONString = String(data: encodedJSON, encoding: .utf8)!
+        // swiftlint:disable line_length
         assertSQL(
             """
             INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\", \"uuid\", \"optional\",
@@ -307,6 +308,7 @@ class QueryTests: XCTestCase {
             """.replacingOccurrences(of: "\n", with: ""),
             insert
         )
+        // swiftlint:enable line_length
     }
     #endif
 
@@ -352,6 +354,7 @@ class QueryTests: XCTestCase {
         let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
                                 date: Date(timeIntervalSince1970: 0), uuid: testUUIDValue, optional: nil, sub: nil)
         let insert = try emails.upsert(value, onConflictOf: string)
+        // swiftlint:disable line_length
         assertSQL(
             """
             INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\", \"uuid\")
@@ -361,6 +364,7 @@ class QueryTests: XCTestCase {
             """.replacingOccurrences(of: "\n", with: ""),
             insert
         )
+        // swiftlint:enable line_length
     }
 
     func test_insert_many_encodable() throws {
@@ -372,6 +376,7 @@ class QueryTests: XCTestCase {
         let value3 = TestCodable(int: 3, string: "4", bool: true, float: 3, double: 6,
                                  date: Date(timeIntervalSince1970: 0), uuid: testUUIDValue, optional: nil, sub: nil)
         let insert = try emails.insertMany([value1, value2, value3])
+        // swiftlint:disable line_length
         assertSQL(
             """
             INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\", \"uuid\")
@@ -380,6 +385,7 @@ class QueryTests: XCTestCase {
             """.replacingOccurrences(of: "\n", with: ""),
             insert
         )
+        // swiftlint:enable line_length
     }
 
     func test_update_compilesUpdateExpression() {

From be3a5ced7e790619f225024db1ac93795b01cf81 Mon Sep 17 00:00:00 2001
From: Atulya <atultw@outlook.com>
Date: Wed, 29 Jun 2022 09:34:32 -0700
Subject: [PATCH 503/685] remove swiftlint line_length disables

---
 Tests/SQLiteTests/QueryTests.swift | 15 ++++++---------
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index d9cce086..2201caef 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -300,15 +300,14 @@ class QueryTests: XCTestCase {
         let insert = try emails.insert(value)
         let encodedJSON = try JSONEncoder().encode(value1)
         let encodedJSONString = String(data: encodedJSON, encoding: .utf8)!
-        // swiftlint:disable line_length
         assertSQL(
             """
             INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\", \"uuid\", \"optional\",
-             \"sub\") VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000', 'E621E1F8-C36C-495A-93FC-0C247A3E6E5F', 'optional', '\(encodedJSONString)')
+             \"sub\") VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000', 'E621E1F8-C36C-495A-93FC-0C247A3E6E5F',
+             'optional', '\(encodedJSONString)')
             """.replacingOccurrences(of: "\n", with: ""),
             insert
         )
-        // swiftlint:enable line_length
     }
     #endif
 
@@ -354,17 +353,16 @@ class QueryTests: XCTestCase {
         let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
                                 date: Date(timeIntervalSince1970: 0), uuid: testUUIDValue, optional: nil, sub: nil)
         let insert = try emails.upsert(value, onConflictOf: string)
-        // swiftlint:disable line_length
         assertSQL(
             """
             INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\", \"uuid\")
              VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000', 'E621E1F8-C36C-495A-93FC-0C247A3E6E5F') ON CONFLICT (\"string\")
              DO UPDATE SET \"int\" = \"excluded\".\"int\", \"bool\" = \"excluded\".\"bool\",
-             \"float\" = \"excluded\".\"float\", \"double\" = \"excluded\".\"double\", \"date\" = \"excluded\".\"date\", \"uuid\" = \"excluded\".\"uuid\"
+             \"float\" = \"excluded\".\"float\", \"double\" = \"excluded\".\"double\", \"date\" = \"excluded\".\"date\",
+             \"uuid\" = \"excluded\".\"uuid\"
             """.replacingOccurrences(of: "\n", with: ""),
             insert
         )
-        // swiftlint:enable line_length
     }
 
     func test_insert_many_encodable() throws {
@@ -376,16 +374,15 @@ class QueryTests: XCTestCase {
         let value3 = TestCodable(int: 3, string: "4", bool: true, float: 3, double: 6,
                                  date: Date(timeIntervalSince1970: 0), uuid: testUUIDValue, optional: nil, sub: nil)
         let insert = try emails.insertMany([value1, value2, value3])
-        // swiftlint:disable line_length
         assertSQL(
             """
             INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\", \"uuid\")
-             VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000', 'E621E1F8-C36C-495A-93FC-0C247A3E6E5F'), (2, '3', 1, 3.0, 5.0, '1970-01-01T00:00:00.000', 'E621E1F8-C36C-495A-93FC-0C247A3E6E5F'),
+             VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000', 'E621E1F8-C36C-495A-93FC-0C247A3E6E5F'),
+             (2, '3', 1, 3.0, 5.0, '1970-01-01T00:00:00.000', 'E621E1F8-C36C-495A-93FC-0C247A3E6E5F'),
              (3, '4', 1, 3.0, 6.0, '1970-01-01T00:00:00.000', 'E621E1F8-C36C-495A-93FC-0C247A3E6E5F')
             """.replacingOccurrences(of: "\n", with: ""),
             insert
         )
-        // swiftlint:enable line_length
     }
 
     func test_update_compilesUpdateExpression() {

From ba5165ac7aaddc3f240f04e54d3f978ae2208a5d Mon Sep 17 00:00:00 2001
From: Geoff MacDonald <geoffmacd@gmail.com>
Date: Fri, 1 Jul 2022 12:36:17 -0700
Subject: [PATCH 504/685] fix insertMany() failing with encodables which have
 assymmetric optional values

---
 Sources/SQLite/Typed/Coding.swift             | 88 +++++++++++++++++--
 Tests/SQLiteTests/QueryIntegrationTests.swift | 21 +++++
 Tests/SQLiteTests/QueryTests.swift            | 12 +--
 Tests/SQLiteTests/TestHelpers.swift           | 20 +++++
 4 files changed, 129 insertions(+), 12 deletions(-)

diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index ec2e0d6c..14a469ab 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -86,12 +86,22 @@ extension QueryType {
     /// - Returns: An `INSERT` statement for the encodable objects
     public func insertMany(_ encodables: [Encodable], userInfo: [CodingUserInfoKey: Any] = [:],
                            otherSetters: [Setter] = []) throws -> Insert {
-        let combinedSetters = try encodables.map { encodable -> [Setter] in
-            let encoder = SQLiteEncoder(userInfo: userInfo)
+        let combinedSettersWithoutNils = try encodables.map { encodable -> [Setter] in
+            let encoder = SQLiteEncoder(userInfo: userInfo, forcingNilValueSetters: false)
             try encodable.encode(to: encoder)
             return encoder.setters + otherSetters
         }
-        return self.insertMany(combinedSetters)
+        // requires the same number of setters per encodable
+        guard Set(combinedSettersWithoutNils.map(\.count)).count == 1 else {
+            // asymmetric sets of value insertions (some nil, some not), requires NULL value to satisfy INSERT query
+            let combinedSymmetricSetters = try encodables.map { encodable -> [Setter] in
+                let encoder = SQLiteEncoder(userInfo: userInfo, forcingNilValueSetters: true)
+                try encodable.encode(to: encoder)
+                return encoder.setters + otherSetters
+            }
+            return self.insertMany(combinedSymmetricSetters)
+        }
+        return self.insertMany(combinedSettersWithoutNils)
     }
 
     /// Creates an `INSERT ON CONFLICT DO UPDATE` statement, aka upsert, by encoding the given object
@@ -165,9 +175,11 @@ private class SQLiteEncoder: Encoder {
 
         let encoder: SQLiteEncoder
         let codingPath: [CodingKey] = []
+        let forcingNilValueSetters: Bool
 
-        init(encoder: SQLiteEncoder) {
+        init(encoder: SQLiteEncoder, forcingNilValueSetters: Bool = false) {
             self.encoder = encoder
+            self.forcingNilValueSetters = forcingNilValueSetters
         }
 
         func superEncoder() -> Swift.Encoder {
@@ -202,6 +214,46 @@ private class SQLiteEncoder: Encoder {
             encoder.setters.append(Expression(key.stringValue) <- value)
         }
 
+        func encodeIfPresent(_ value: Int?, forKey key: SQLiteEncoder.SQLiteKeyedEncodingContainer<Key>.Key) throws {
+            if let value = value {
+                encoder.setters.append(Expression(key.stringValue) <- value)
+            } else if forcingNilValueSetters {
+                encoder.setters.append(Expression<Int?>(key.stringValue) <- nil)
+            }
+        }
+
+        func encodeIfPresent(_ value: Bool?, forKey key: Key) throws {
+            if let value = value {
+                encoder.setters.append(Expression(key.stringValue) <- value)
+            } else if forcingNilValueSetters {
+                encoder.setters.append(Expression<Bool?>(key.stringValue) <- nil)
+            }
+        }
+
+        func encodeIfPresent(_ value: Float?, forKey key: Key) throws {
+            if let value = value {
+                encoder.setters.append(Expression(key.stringValue) <- Double(value))
+            } else if forcingNilValueSetters{
+                encoder.setters.append(Expression<Double?>(key.stringValue) <- nil)
+            }
+        }
+
+        func encodeIfPresent(_ value: Double?, forKey key: Key) throws {
+            if let value = value {
+                encoder.setters.append(Expression(key.stringValue) <- value)
+            } else if forcingNilValueSetters {
+                encoder.setters.append(Expression<Double?>(key.stringValue) <- nil)
+            }
+        }
+
+        func encodeIfPresent(_ value: String?, forKey key: MyKey) throws {
+            if let value = value {
+                encoder.setters.append(Expression(key.stringValue) <- value)
+            } else if forcingNilValueSetters {
+                encoder.setters.append(Expression<String?>(key.stringValue) <- nil)
+            }
+        }
+
         func encode<T>(_ value: T, forKey key: Key) throws where T: Swift.Encodable {
             switch value {
             case let data as Data:
@@ -217,6 +269,28 @@ private class SQLiteEncoder: Encoder {
             }
         }
 
+        func encodeIfPresent<T>(_ value: T?, forKey key: Key) throws where T: Swift.Encodable {
+            guard let value = value else {
+                guard forcingNilValueSetters else {
+                    return
+                }
+                encoder.setters.append(Expression<String?>(key.stringValue) <- nil)
+                return
+            }
+            switch value {
+            case let data as Data:
+                encoder.setters.append(Expression(key.stringValue) <- data)
+            case let date as Date:
+                encoder.setters.append(Expression(key.stringValue) <- date.datatypeValue)
+            case let uuid as UUID:
+                encoder.setters.append(Expression(key.stringValue) <- uuid.datatypeValue)
+            default:
+                let encoded = try JSONEncoder().encode(value)
+                let string = String(data: encoded, encoding: .utf8)
+                encoder.setters.append(Expression(key.stringValue) <- string)
+            }
+        }
+
         func encode(_ value: Int8, forKey key: Key) throws {
             throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
                                                                           debugDescription: "encoding an Int8 is not supported"))
@@ -274,9 +348,11 @@ private class SQLiteEncoder: Encoder {
     fileprivate var setters: [Setter] = []
     let codingPath: [CodingKey] = []
     let userInfo: [CodingUserInfoKey: Any]
+    let forcingNilValueSetters: Bool
 
-    init(userInfo: [CodingUserInfoKey: Any]) {
+    init(userInfo: [CodingUserInfoKey: Any], forcingNilValueSetters: Bool = false) {
         self.userInfo = userInfo
+        self.forcingNilValueSetters = forcingNilValueSetters
     }
 
     func singleValueContainer() -> SingleValueEncodingContainer {
@@ -288,7 +364,7 @@ private class SQLiteEncoder: Encoder {
     }
 
     func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key: CodingKey {
-        KeyedEncodingContainer(SQLiteKeyedEncodingContainer(encoder: self))
+        KeyedEncodingContainer(SQLiteKeyedEncodingContainer(encoder: self, forcingNilValueSetters: forcingNilValueSetters))
     }
 }
 
diff --git a/Tests/SQLiteTests/QueryIntegrationTests.swift b/Tests/SQLiteTests/QueryIntegrationTests.swift
index b3d9cf96..3ea06745 100644
--- a/Tests/SQLiteTests/QueryIntegrationTests.swift
+++ b/Tests/SQLiteTests/QueryIntegrationTests.swift
@@ -130,6 +130,27 @@ class QueryIntegrationTests: SQLiteTestCase {
         XCTAssertEqual(2, id)
     }
 
+    func test_insert_many_encodables() throws {
+        let table = Table("codable")
+        try db.run(table.create { builder in
+            builder.column(Expression<Int?>("int"))
+            builder.column(Expression<String?>("string"))
+            builder.column(Expression<Bool?>("bool"))
+            builder.column(Expression<Double?>("float"))
+            builder.column(Expression<Double?>("double"))
+            builder.column(Expression<Date?>("date"))
+            builder.column(Expression<UUID?>("uuid"))
+        })
+
+        let value1 = TestOptionalCodable(int: 5, string: "6", bool: true, float: 7, double: 8, date: Date(timeIntervalSince1970: 5000), uuid: testUUIDValue)
+        let valueWithNils = TestOptionalCodable(int: nil, string: nil, bool: nil, float: nil, double: nil, date: nil, uuid: nil)
+        try db.run(table.insertMany([value1, valueWithNils]))
+
+         let rows = try db.prepare(table)
+         let values: [TestOptionalCodable] = try rows.map({ try $0.decode() })
+         XCTAssertEqual(values.count, 2)
+    }
+
     func test_upsert() throws {
         try XCTSkipUnless(db.satisfiesMinimumVersion(minor: 24))
         let fetchAge = { () throws -> Int? in
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index 2201caef..b2f679e0 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -365,21 +365,21 @@ class QueryTests: XCTestCase {
         )
     }
 
-    func test_insert_many_encodable() throws {
+    func test_insert_many_encodables() throws {
         let emails = Table("emails")
         let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
                                  date: Date(timeIntervalSince1970: 0), uuid: testUUIDValue, optional: nil, sub: nil)
         let value2 = TestCodable(int: 2, string: "3", bool: true, float: 3, double: 5,
-                                 date: Date(timeIntervalSince1970: 0), uuid: testUUIDValue, optional: nil, sub: nil)
+                                 date: Date(timeIntervalSince1970: 0), uuid: testUUIDValue, optional: "optional", sub: nil)
         let value3 = TestCodable(int: 3, string: "4", bool: true, float: 3, double: 6,
                                  date: Date(timeIntervalSince1970: 0), uuid: testUUIDValue, optional: nil, sub: nil)
         let insert = try emails.insertMany([value1, value2, value3])
         assertSQL(
             """
-            INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\", \"uuid\")
-             VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000', 'E621E1F8-C36C-495A-93FC-0C247A3E6E5F'),
-             (2, '3', 1, 3.0, 5.0, '1970-01-01T00:00:00.000', 'E621E1F8-C36C-495A-93FC-0C247A3E6E5F'),
-             (3, '4', 1, 3.0, 6.0, '1970-01-01T00:00:00.000', 'E621E1F8-C36C-495A-93FC-0C247A3E6E5F')
+            INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\", \"uuid\", \"optional\", \"sub\")
+             VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000', 'E621E1F8-C36C-495A-93FC-0C247A3E6E5F', NULL, NULL),
+             (2, '3', 1, 3.0, 5.0, '1970-01-01T00:00:00.000', 'E621E1F8-C36C-495A-93FC-0C247A3E6E5F', 'optional', NULL),
+             (3, '4', 1, 3.0, 6.0, '1970-01-01T00:00:00.000', 'E621E1F8-C36C-495A-93FC-0C247A3E6E5F', NULL, NULL)
             """.replacingOccurrences(of: "\n", with: ""),
             insert
         )
diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index 4a71fd40..f43310c9 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -145,3 +145,23 @@ class TestCodable: Codable, Equatable {
         lhs.sub == rhs.sub
     }
 }
+
+struct TestOptionalCodable: Codable, Equatable {
+    let int: Int?
+    let string: String?
+    let bool: Bool?
+    let float: Float?
+    let double: Double?
+    let date: Date?
+    let uuid: UUID?
+
+    init(int: Int?, string: String?, bool: Bool?, float: Float?, double: Double?, date: Date?, uuid: UUID?) {
+        self.int = int
+        self.string = string
+        self.bool = bool
+        self.float = float
+        self.double = double
+        self.date = date
+        self.uuid = uuid
+    }
+}

From c4bdad8f3c47a41d1902d32e988f148e4734075e Mon Sep 17 00:00:00 2001
From: Geoff MacDonald <geoffmacd@gmail.com>
Date: Fri, 1 Jul 2022 12:39:10 -0700
Subject: [PATCH 505/685] lint

---
 Sources/SQLite/Typed/Coding.swift             | 2 +-
 Tests/SQLiteTests/QueryIntegrationTests.swift | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index 14a469ab..08b7131a 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -233,7 +233,7 @@ private class SQLiteEncoder: Encoder {
         func encodeIfPresent(_ value: Float?, forKey key: Key) throws {
             if let value = value {
                 encoder.setters.append(Expression(key.stringValue) <- Double(value))
-            } else if forcingNilValueSetters{
+            } else if forcingNilValueSetters {
                 encoder.setters.append(Expression<Double?>(key.stringValue) <- nil)
             }
         }
diff --git a/Tests/SQLiteTests/QueryIntegrationTests.swift b/Tests/SQLiteTests/QueryIntegrationTests.swift
index 3ea06745..f3b4bcd3 100644
--- a/Tests/SQLiteTests/QueryIntegrationTests.swift
+++ b/Tests/SQLiteTests/QueryIntegrationTests.swift
@@ -142,7 +142,8 @@ class QueryIntegrationTests: SQLiteTestCase {
             builder.column(Expression<UUID?>("uuid"))
         })
 
-        let value1 = TestOptionalCodable(int: 5, string: "6", bool: true, float: 7, double: 8, date: Date(timeIntervalSince1970: 5000), uuid: testUUIDValue)
+        let value1 = TestOptionalCodable(int: 5, string: "6", bool: true, float: 7, double: 8,
+                                         date: Date(timeIntervalSince1970: 5000), uuid: testUUIDValue)
         let valueWithNils = TestOptionalCodable(int: nil, string: nil, bool: nil, float: nil, double: nil, date: nil, uuid: nil)
         try db.run(table.insertMany([value1, valueWithNils]))
 

From abff512bb57f46cb155a8b9ccf744c72f72a886f Mon Sep 17 00:00:00 2001
From: Geoff MacDonald <geoffmacd@gmail.com>
Date: Sat, 2 Jul 2022 11:04:17 -0700
Subject: [PATCH 506/685] feedback

---
 Sources/SQLite/Typed/Coding.swift | 23 ++++++-----------------
 1 file changed, 6 insertions(+), 17 deletions(-)

diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index 08b7131a..b96bc64e 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -216,7 +216,7 @@ private class SQLiteEncoder: Encoder {
 
         func encodeIfPresent(_ value: Int?, forKey key: SQLiteEncoder.SQLiteKeyedEncodingContainer<Key>.Key) throws {
             if let value = value {
-                encoder.setters.append(Expression(key.stringValue) <- value)
+                try encode(value, forKey: key)
             } else if forcingNilValueSetters {
                 encoder.setters.append(Expression<Int?>(key.stringValue) <- nil)
             }
@@ -224,7 +224,7 @@ private class SQLiteEncoder: Encoder {
 
         func encodeIfPresent(_ value: Bool?, forKey key: Key) throws {
             if let value = value {
-                encoder.setters.append(Expression(key.stringValue) <- value)
+                try encode(value, forKey: key)
             } else if forcingNilValueSetters {
                 encoder.setters.append(Expression<Bool?>(key.stringValue) <- nil)
             }
@@ -232,7 +232,7 @@ private class SQLiteEncoder: Encoder {
 
         func encodeIfPresent(_ value: Float?, forKey key: Key) throws {
             if let value = value {
-                encoder.setters.append(Expression(key.stringValue) <- Double(value))
+                try encode(value, forKey: key)
             } else if forcingNilValueSetters {
                 encoder.setters.append(Expression<Double?>(key.stringValue) <- nil)
             }
@@ -240,7 +240,7 @@ private class SQLiteEncoder: Encoder {
 
         func encodeIfPresent(_ value: Double?, forKey key: Key) throws {
             if let value = value {
-                encoder.setters.append(Expression(key.stringValue) <- value)
+                try encode(value, forKey: key)
             } else if forcingNilValueSetters {
                 encoder.setters.append(Expression<Double?>(key.stringValue) <- nil)
             }
@@ -248,7 +248,7 @@ private class SQLiteEncoder: Encoder {
 
         func encodeIfPresent(_ value: String?, forKey key: MyKey) throws {
             if let value = value {
-                encoder.setters.append(Expression(key.stringValue) <- value)
+                try encode(value, forKey: key)
             } else if forcingNilValueSetters {
                 encoder.setters.append(Expression<String?>(key.stringValue) <- nil)
             }
@@ -277,18 +277,7 @@ private class SQLiteEncoder: Encoder {
                 encoder.setters.append(Expression<String?>(key.stringValue) <- nil)
                 return
             }
-            switch value {
-            case let data as Data:
-                encoder.setters.append(Expression(key.stringValue) <- data)
-            case let date as Date:
-                encoder.setters.append(Expression(key.stringValue) <- date.datatypeValue)
-            case let uuid as UUID:
-                encoder.setters.append(Expression(key.stringValue) <- uuid.datatypeValue)
-            default:
-                let encoded = try JSONEncoder().encode(value)
-                let string = String(data: encoded, encoding: .utf8)
-                encoder.setters.append(Expression(key.stringValue) <- string)
-            }
+            try encode(value, forKey: key)
         }
 
         func encode(_ value: Int8, forKey key: Key) throws {

From 12e2166c90b24f900869b916d9d8b8a6ac24e839 Mon Sep 17 00:00:00 2001
From: Matthew Jee <matthew@marmphco.com>
Date: Thu, 7 Jul 2022 15:38:55 -0700
Subject: [PATCH 507/685] Add support for the WITH clause

The `WITH` clause provides the ability to do hierarchical or recursive queries of tree and graph-like data. See https://www.sqlite.org/lang_with.html.

**Details**

- Add `all` parameter to `QueryType.union` to allow `UNION ALL` to be used in a query. I opted to add the parameter to the start of the list so that it does not dangle at the end when the union's query is long:

```swift
users.union(all: true, posts.join(users, on: users[id] == posts[userId]))
// It's a little easier to read than:
users.union(posts.join(users, on: users[id] == posts[userId]), all: true)
```

- Add `with` function to `QueryType`. This function adds a `WITH` clause to a query. The function may be called multiple times to add multiple clauses to a query. If multiple clauses are added to the query with conflicting `recursive` parameters, the whole `WITH` clause will be considered recursive.

  Like the `union` function, I put the `subquery` parameter at the end so that the `recursive` and `materializationHint` options don't dangle at the end of a long query.

```swift
let users = Table("users")
let users = Table("posts")
let first = Table("first")
let second = Table("second")
first.with(first, recursive: true as: users).with(second, recursive: false, as: posts)
// WITH RECURSIVE "first" AS (SELECT * from users), "second" AS (SELECT * from posts) SELECT * from "first"
```
---
 Sources/SQLite/Typed/Query.swift              | 105 +++++++++++++++++-
 Tests/SQLiteTests/QueryIntegrationTests.swift |  41 +++++++
 Tests/SQLiteTests/QueryTests.swift            |  60 ++++++++++
 3 files changed, 201 insertions(+), 5 deletions(-)

diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index 93dc2a73..c328aef6 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -193,12 +193,14 @@ extension QueryType {
     ///
     /// - Parameters:
     ///
+    ///   - all: If false, duplicate rows are removed from the result.
+    ///
     ///   - table: A query representing the other table.
     ///
     /// - Returns: A query with the given `UNION` clause applied.
-    public func union(_ table: QueryType) -> Self {
+    public func union(all: Bool = false, _ table: QueryType) -> Self {
         var query = self
-        query.clauses.union.append(table)
+        query.clauses.union.append((all, table))
         return query
     }
 
@@ -496,6 +498,37 @@ extension QueryType {
         query.clauses.limit = length.map { ($0, offset) }
         return query
     }
+    
+    // MARK: WITH
+    
+    /// Sets a `WITH` clause on the query.
+    ///
+    ///     let users = Table("users")
+    ///     let id = Expression<String>("email")
+    ///     let name = Expression<String?>("name")
+    ///
+    ///     let userNames = Table("user_names")
+    ///     userCategories.with(userNames, as: users.select(name))
+    ///     // WITH "user_names" as (SELECT "name" FROM "users") SELECT * FROM "user_names"
+    ///
+    /// - Parameters:
+    ///
+    ///   -  alias: A name to assign to the table expression.
+    ///
+    ///   -  recursive: Whether to evaluate the expression recursively.
+    ///
+    ///   -  materializationHint: Provides a hint to the query planner for how the expression should be implemented.
+    ///
+    ///   -  subquery: A query that generates the rows for the table expression.
+    ///
+    /// - Returns: A query with the given `ORDER BY` clause applied.
+    public func with(_ alias: Table, columns: [Expressible]? = nil, recursive: Bool = false, materializationHint: MaterializationHint? = nil, as subquery: QueryType) -> Self {
+        var query = self
+        let clause = WithClauses.Clause(alias: alias, columns: columns, materializationHint: materializationHint, query: subquery)
+        query.clauses.with.recursive = query.clauses.with.recursive || recursive
+        query.clauses.with.clauses.append(clause)
+        return query
+    }
 
     // MARK: - Clauses
     //
@@ -596,13 +629,50 @@ extension QueryType {
             return nil
         }
 
-        return " ".join(clauses.union.map { query in
+        return " ".join(clauses.union.map { (all, query) in
             " ".join([
-                Expression<Void>(literal: "UNION"),
+                Expression<Void>(literal: all ? "UNION ALL" : "UNION"),
                 query
             ])
         })
     }
+    
+    fileprivate var withClause: Expressible? {
+        guard !clauses.with.clauses.isEmpty else {
+            return nil
+        }
+
+        let innerClauses = ", ".join(clauses.with.clauses.map { (clause) in
+            let hintExpr: Expression<Void>?
+            if let hint = clause.materializationHint {
+                hintExpr = Expression<Void>(literal: hint.rawValue)
+            } else {
+                hintExpr = nil
+            }
+            
+            let columnExpr: Expression<Void>?
+            if let columns = clause.columns {
+                columnExpr = "".wrap(", ".join(columns))
+            } else {
+                columnExpr = nil
+            }
+            
+            let expressions: [Expressible?] = [
+                clause.alias.tableName(),
+                columnExpr,
+                Expression<Void>(literal: "AS"),
+                hintExpr,
+                "".wrap(clause.query) as Expression<Void>
+            ]
+            
+            return " ".join(expressions.compactMap { $0 })
+        })
+        
+        return " ".join([
+            Expression<Void>(literal: clauses.with.recursive ? "WITH RECURSIVE" : "WITH"),
+            innerClauses
+        ])
+    }
 
     // MARK: -
 
@@ -856,6 +926,7 @@ extension QueryType {
 
     public var expression: Expression<Void> {
         let clauses: [Expressible?] = [
+            withClause,
             selectClause,
             joinClause,
             whereClause,
@@ -1233,8 +1304,30 @@ public enum OnConflict: String {
 
 }
 
+/// Materialization hints for `WITH` clause
+public enum MaterializationHint: String {
+
+    case materialized = "MATERIALIZED"
+
+    case notMaterialized = "NOT MATERIALIZED"
+}
+
 // MARK: - Private
 
+struct WithClauses {
+    struct Clause {
+        var alias: Table
+        var columns: [Expressible]?
+        var materializationHint: MaterializationHint?
+        var query: QueryType
+    }
+    /// The `RECURSIVE` flag is applied to the entire `WITH` clause
+    var recursive: Bool = false
+    
+    /// Each `WITH` clause may have multiple subclauses
+    var clauses: [Clause] = []
+}
+
 public struct QueryClauses {
 
     var select = (distinct: false, columns: [Expression<Void>(literal: "*") as Expressible])
@@ -1251,7 +1344,9 @@ public struct QueryClauses {
 
     var limit: (length: Int, offset: Int?)?
 
-    var union = [QueryType]()
+    var union = [(all: Bool, table: QueryType)]()
+    
+    var with = WithClauses()
 
     fileprivate init(_ name: String, alias: String?, database: String?) {
         from = (name, alias, database)
diff --git a/Tests/SQLiteTests/QueryIntegrationTests.swift b/Tests/SQLiteTests/QueryIntegrationTests.swift
index f3b4bcd3..c1cd97a5 100644
--- a/Tests/SQLiteTests/QueryIntegrationTests.swift
+++ b/Tests/SQLiteTests/QueryIntegrationTests.swift
@@ -230,6 +230,47 @@ class QueryIntegrationTests: SQLiteTestCase {
         let result = Array(try db.prepare(users.select(email).order(Expression<Int>.random()).limit(1)))
         XCTAssertEqual(1, result.count)
     }
+    
+    func test_with_recursive() {
+        let nodes = Table("nodes")
+        let id = Expression<Int64>("id")
+        let parent = Expression<Int64?>("parent")
+        let value = Expression<Int64>("value")
+                
+        try! db.run(nodes.create { builder in
+            builder.column(id)
+            builder.column(parent)
+            builder.column(value)
+        })
+        
+        try! db.run(nodes.insertMany([
+            [id <- 0, parent <- nil, value <- 2],
+            [id <- 1, parent <- 0, value <- 4],
+            [id <- 2, parent <- 0, value <- 9],
+            [id <- 3, parent <- 2, value <- 8],
+            [id <- 4, parent <- 2, value <- 7],
+            [id <- 5, parent <- 4, value <- 3],
+        ]))
+        
+        // Compute the sum of the values of node 5 and its ancestors
+        let ancestors = Table("ancestors")
+        let sum = try! db.scalar(
+            ancestors
+                .select(value.sum)
+                .with(ancestors,
+                      columns: [id, parent, value],
+                      recursive: true,
+                      as: nodes
+                        .where(id == 5)
+                        .union(all: true,
+                               nodes.join(ancestors, on: nodes[id] == ancestors[parent])
+                                    .select(nodes[id], nodes[parent], nodes[value])
+                              )
+                     )
+        )
+        
+        XCTAssertEqual(21, sum)
+    }
 }
 
 extension Connection {
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index b2f679e0..6baf59b3 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -58,6 +58,11 @@ class QueryTests: XCTestCase {
     func test_selectDistinct_withStar_compilesSelectClause() {
         assertSQL("SELECT DISTINCT * FROM \"users\"", users.select(distinct: *))
     }
+    
+    func test_union_compilesUnionClause() {
+        assertSQL("SELECT * FROM \"users\" UNION SELECT * FROM \"posts\"", users.union(posts))
+        assertSQL("SELECT * FROM \"users\" UNION ALL SELECT * FROM \"posts\"", users.union(all: true, posts))
+    }
 
     func test_join_compilesJoinClause() {
         assertSQL(
@@ -219,6 +224,61 @@ class QueryTests: XCTestCase {
             users.join(managers, on: managers[id] == users[managerId])
         )
     }
+    
+    func test_with_compilesWithClause() {
+        let temp = Table("temp")
+        
+        assertSQL("WITH \"temp\" AS (SELECT * FROM \"users\") SELECT * FROM \"temp\"",
+                  temp.with(temp, as: users))
+    }
+    
+    func test_with_recursive_compilesWithClause() {
+        let temp = Table("temp")
+        
+        assertSQL("WITH RECURSIVE \"temp\" AS (SELECT * FROM \"users\") SELECT * FROM \"temp\"",
+                  temp.with(temp, recursive: true, as: users))
+        
+        assertSQL("WITH \"temp\" AS (SELECT * FROM \"users\") SELECT * FROM \"temp\"",
+                  temp.with(temp, recursive: false, as: users))
+    }
+    
+    func test_with_materialization_compilesWithClause() {
+        let temp = Table("temp")
+        
+        assertSQL("WITH \"temp\" AS MATERIALIZED (SELECT * FROM \"users\") SELECT * FROM \"temp\"",
+                  temp.with(temp, materializationHint: .materialized, as: users))
+        
+        assertSQL("WITH \"temp\" AS NOT MATERIALIZED (SELECT * FROM \"users\") SELECT * FROM \"temp\"",
+                  temp.with(temp, materializationHint: .notMaterialized, as: users))
+    }
+    
+    func test_with_columns_compilesWithClause() {
+        let temp = Table("temp")
+
+        assertSQL("WITH \"temp\" (\"id\", \"email\") AS (SELECT * FROM \"users\") SELECT * FROM \"temp\"",
+                  temp.with(temp, columns: [id, email], recursive: false, materializationHint: nil, as: users))
+    }
+    
+    func test_with_multiple_compilesWithClause() {
+        let temp = Table("temp")
+        let second = Table("second")
+        let third = Table("third")
+
+        let query = temp
+            .with(temp, recursive: true, as: users)
+            .with(second, recursive: true, as: posts)
+            .with(third, materializationHint: .materialized, as:categories)
+        
+        assertSQL(
+            """
+            WITH RECURSIVE \"temp\" AS (SELECT * FROM \"users\"),
+             \"second\" AS (SELECT * FROM \"posts\"),
+             \"third\" AS MATERIALIZED (SELECT * FROM \"categories\")
+             SELECT * FROM \"temp\"
+            """.replacingOccurrences(of: "\n", with: ""),
+            query
+        )
+    }
 
     func test_insert_compilesInsertExpression() {
         assertSQL(

From 03b56886891d1816bb03567584f7c6b00ae96e75 Mon Sep 17 00:00:00 2001
From: Matthew Jee <matthew@marmphco.com>
Date: Thu, 7 Jul 2022 17:03:31 -0700
Subject: [PATCH 508/685] documentation

---
 Documentation/Index.md | 57 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index e28b24bb..7b5af41f 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -34,6 +34,7 @@
         - [Filter Operators and Functions](#filter-operators-and-functions)
       - [Sorting Rows](#sorting-rows)
       - [Limiting and Paging Results](#limiting-and-paging-results)
+      - [Recursive and Hierarchical Queries](#recursive-and-hierarchical-queries)
       - [Aggregation](#aggregation)
   - [Upserting Rows](#upserting-rows)
   - [Updating Rows](#updating-rows)
@@ -1086,6 +1087,62 @@ users.limit(5, offset: 5)
 ```
 
 
+#### Recursive and Hierarchical Queries
+
+We can perform a recursive or hierarchical query using a [query's](#queries) `with`
+function. Column names and a materialization hint can optionally be provided.
+
+```swift
+// Get the management chain for the manager with id == 8
+
+let chain = Table("chain")
+let id = Expression<Int64>("id")
+let managerId = Expression<Int64>("manager_id")
+
+let query = managers
+    .where(id == 8)
+    .union(chain.join(managers, on: chain[managerId] == managers[id])
+
+chain.with(chain, recursive: true, as: query)
+// WITH RECURSIVE
+//   "chain" AS (
+//     SELECT * FROM "managers" WHERE "id" = 8 
+//     UNION 
+//     SELECT * from "chain" 
+//     JOIN "managers" ON "chain"."manager_id" = "managers"."id"
+//   ) 
+// SELECT * FROM "chain"
+
+// Add a "level" column to the query representing manager's position in the chain
+
+let level = Expression<Int64>("level")
+
+let queryWithLevel = 
+    managers
+        .select(id, managerId, 0)
+        .where(id == 8)
+        .union(
+            chain
+                .select(managers[id], managers[manager_id], level + 1)
+                .join(managers, on: chain[managerId] == managers[id])
+        )
+
+chain.with(chain, 
+           columns: [id, managerId, level], 
+           recursive: true,
+           materializationHint: .materialize,
+           as: queryWithLevel)
+// WITH RECURSIVE
+//   "chain" ("id", "manager_id", "level") AS MATERIALIZED (
+//     SELECT ("id", "manager_id", 0) FROM "managers" WHERE "id" = 8 
+//     UNION 
+//     SELECT ("manager"."id", "manager"."manager_id", "level" + 1) FROM "chain" 
+//     JOIN "managers" ON "chain"."manager_id" = "managers"."id"
+//   ) 
+// SELECT * FROM "chain"
+```
+
+
 #### Aggregation
 
 [Queries](#queries) come with a number of functions that quickly return

From 76d34dd8ff668b58d6b5530528460dd6d2786c0e Mon Sep 17 00:00:00 2001
From: Matthew Jee <matthew@marmphco.com>
Date: Thu, 7 Jul 2022 17:36:18 -0700
Subject: [PATCH 509/685] Heed linter warnings

Note sure how to get the line length of Query back down below 500 without harming readability though.
---
 Documentation/Index.md                        |  2 +-
 Sources/SQLite/Typed/Query.swift              | 29 +++++++++--------
 Tests/SQLiteTests/QueryIntegrationTests.swift | 12 +++----
 Tests/SQLiteTests/QueryTests.swift            | 32 +++++++++----------
 4 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 7b5af41f..44304c1c 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1130,7 +1130,7 @@ let queryWithLevel =
 chain.with(chain, 
            columns: [id, managerId, level], 
            recursive: true,
-           materializationHint: .materialize,
+           hint: .materialize,
            as: queryWithLevel)
 // WITH RECURSIVE
 //   "chain" ("id", "manager_id", "level") AS MATERIALIZED (
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index c328aef6..b34570a7 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -498,9 +498,9 @@ extension QueryType {
         query.clauses.limit = length.map { ($0, offset) }
         return query
     }
-    
+
     // MARK: WITH
-    
+
     /// Sets a `WITH` clause on the query.
     ///
     ///     let users = Table("users")
@@ -517,14 +517,15 @@ extension QueryType {
     ///
     ///   -  recursive: Whether to evaluate the expression recursively.
     ///
-    ///   -  materializationHint: Provides a hint to the query planner for how the expression should be implemented.
+    ///   -  hint: Provides a hint to the query planner for how the expression should be implemented.
     ///
     ///   -  subquery: A query that generates the rows for the table expression.
     ///
     /// - Returns: A query with the given `ORDER BY` clause applied.
-    public func with(_ alias: Table, columns: [Expressible]? = nil, recursive: Bool = false, materializationHint: MaterializationHint? = nil, as subquery: QueryType) -> Self {
+    public func with(_ alias: Table, columns: [Expressible]? = nil, recursive: Bool = false,
+                     hint: MaterializationHint? = nil, as subquery: QueryType) -> Self {
         var query = self
-        let clause = WithClauses.Clause(alias: alias, columns: columns, materializationHint: materializationHint, query: subquery)
+        let clause = WithClauses.Clause(alias: alias, columns: columns, hint: hint, query: subquery)
         query.clauses.with.recursive = query.clauses.with.recursive || recursive
         query.clauses.with.clauses.append(clause)
         return query
@@ -636,7 +637,7 @@ extension QueryType {
             ])
         })
     }
-    
+
     fileprivate var withClause: Expressible? {
         guard !clauses.with.clauses.isEmpty else {
             return nil
@@ -644,19 +645,19 @@ extension QueryType {
 
         let innerClauses = ", ".join(clauses.with.clauses.map { (clause) in
             let hintExpr: Expression<Void>?
-            if let hint = clause.materializationHint {
+            if let hint = clause.hint {
                 hintExpr = Expression<Void>(literal: hint.rawValue)
             } else {
                 hintExpr = nil
             }
-            
+
             let columnExpr: Expression<Void>?
             if let columns = clause.columns {
                 columnExpr = "".wrap(", ".join(columns))
             } else {
                 columnExpr = nil
             }
-            
+
             let expressions: [Expressible?] = [
                 clause.alias.tableName(),
                 columnExpr,
@@ -664,10 +665,10 @@ extension QueryType {
                 hintExpr,
                 "".wrap(clause.query) as Expression<Void>
             ]
-            
+
             return " ".join(expressions.compactMap { $0 })
         })
-        
+
         return " ".join([
             Expression<Void>(literal: clauses.with.recursive ? "WITH RECURSIVE" : "WITH"),
             innerClauses
@@ -1318,12 +1319,12 @@ struct WithClauses {
     struct Clause {
         var alias: Table
         var columns: [Expressible]?
-        var materializationHint: MaterializationHint?
+        var hint: MaterializationHint?
         var query: QueryType
     }
     /// The `RECURSIVE` flag is applied to the entire `WITH` clause
     var recursive: Bool = false
-    
+
     /// Each `WITH` clause may have multiple subclauses
     var clauses: [Clause] = []
 }
@@ -1345,7 +1346,7 @@ public struct QueryClauses {
     var limit: (length: Int, offset: Int?)?
 
     var union = [(all: Bool, table: QueryType)]()
-    
+
     var with = WithClauses()
 
     fileprivate init(_ name: String, alias: String?, database: String?) {
diff --git a/Tests/SQLiteTests/QueryIntegrationTests.swift b/Tests/SQLiteTests/QueryIntegrationTests.swift
index c1cd97a5..db4e2e4e 100644
--- a/Tests/SQLiteTests/QueryIntegrationTests.swift
+++ b/Tests/SQLiteTests/QueryIntegrationTests.swift
@@ -230,28 +230,28 @@ class QueryIntegrationTests: SQLiteTestCase {
         let result = Array(try db.prepare(users.select(email).order(Expression<Int>.random()).limit(1)))
         XCTAssertEqual(1, result.count)
     }
-    
+
     func test_with_recursive() {
         let nodes = Table("nodes")
         let id = Expression<Int64>("id")
         let parent = Expression<Int64?>("parent")
         let value = Expression<Int64>("value")
-                
+
         try! db.run(nodes.create { builder in
             builder.column(id)
             builder.column(parent)
             builder.column(value)
         })
-        
+
         try! db.run(nodes.insertMany([
             [id <- 0, parent <- nil, value <- 2],
             [id <- 1, parent <- 0, value <- 4],
             [id <- 2, parent <- 0, value <- 9],
             [id <- 3, parent <- 2, value <- 8],
             [id <- 4, parent <- 2, value <- 7],
-            [id <- 5, parent <- 4, value <- 3],
+            [id <- 5, parent <- 4, value <- 3]
         ]))
-        
+
         // Compute the sum of the values of node 5 and its ancestors
         let ancestors = Table("ancestors")
         let sum = try! db.scalar(
@@ -268,7 +268,7 @@ class QueryIntegrationTests: SQLiteTestCase {
                               )
                      )
         )
-        
+
         XCTAssertEqual(21, sum)
     }
 }
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index 6baf59b3..a96ff38c 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -58,7 +58,7 @@ class QueryTests: XCTestCase {
     func test_selectDistinct_withStar_compilesSelectClause() {
         assertSQL("SELECT DISTINCT * FROM \"users\"", users.select(distinct: *))
     }
-    
+
     func test_union_compilesUnionClause() {
         assertSQL("SELECT * FROM \"users\" UNION SELECT * FROM \"posts\"", users.union(posts))
         assertSQL("SELECT * FROM \"users\" UNION ALL SELECT * FROM \"posts\"", users.union(all: true, posts))
@@ -224,41 +224,41 @@ class QueryTests: XCTestCase {
             users.join(managers, on: managers[id] == users[managerId])
         )
     }
-    
+
     func test_with_compilesWithClause() {
         let temp = Table("temp")
-        
+
         assertSQL("WITH \"temp\" AS (SELECT * FROM \"users\") SELECT * FROM \"temp\"",
                   temp.with(temp, as: users))
     }
-    
+
     func test_with_recursive_compilesWithClause() {
         let temp = Table("temp")
-        
+
         assertSQL("WITH RECURSIVE \"temp\" AS (SELECT * FROM \"users\") SELECT * FROM \"temp\"",
                   temp.with(temp, recursive: true, as: users))
-        
+
         assertSQL("WITH \"temp\" AS (SELECT * FROM \"users\") SELECT * FROM \"temp\"",
                   temp.with(temp, recursive: false, as: users))
     }
-    
+
     func test_with_materialization_compilesWithClause() {
         let temp = Table("temp")
-        
+
         assertSQL("WITH \"temp\" AS MATERIALIZED (SELECT * FROM \"users\") SELECT * FROM \"temp\"",
-                  temp.with(temp, materializationHint: .materialized, as: users))
-        
+                  temp.with(temp, hint: .materialized, as: users))
+
         assertSQL("WITH \"temp\" AS NOT MATERIALIZED (SELECT * FROM \"users\") SELECT * FROM \"temp\"",
-                  temp.with(temp, materializationHint: .notMaterialized, as: users))
+                  temp.with(temp, hint: .notMaterialized, as: users))
     }
-    
+
     func test_with_columns_compilesWithClause() {
         let temp = Table("temp")
 
         assertSQL("WITH \"temp\" (\"id\", \"email\") AS (SELECT * FROM \"users\") SELECT * FROM \"temp\"",
-                  temp.with(temp, columns: [id, email], recursive: false, materializationHint: nil, as: users))
+                  temp.with(temp, columns: [id, email], recursive: false, hint: nil, as: users))
     }
-    
+
     func test_with_multiple_compilesWithClause() {
         let temp = Table("temp")
         let second = Table("second")
@@ -267,8 +267,8 @@ class QueryTests: XCTestCase {
         let query = temp
             .with(temp, recursive: true, as: users)
             .with(second, recursive: true, as: posts)
-            .with(third, materializationHint: .materialized, as:categories)
-        
+            .with(third, hint: .materialized, as: categories)
+
         assertSQL(
             """
             WITH RECURSIVE \"temp\" AS (SELECT * FROM \"users\"),

From bdacf4df697eb73cb1a0887a6b3db776b55b3b0d Mon Sep 17 00:00:00 2001
From: Matthew Jee <matthew@marmphco.com>
Date: Thu, 7 Jul 2022 17:39:50 -0700
Subject: [PATCH 510/685] Slight documentation tweak

---
 Documentation/Index.md | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 44304c1c..7a9a390f 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1090,7 +1090,7 @@ users.limit(5, offset: 5)
 #### Recursive and Hierarchical Queries
 
 We can perform a recursive or hierarchical query using a [query's](#queries) `with`
-function. Column names and a materialization hint can optionally be provided.
+function.
 
 ```swift
 // Get the management chain for the manager with id == 8
@@ -1112,9 +1112,12 @@ chain.with(chain, recursive: true, as: query)
 //     JOIN "managers" ON "chain"."manager_id" = "managers"."id"
 //   ) 
 // SELECT * FROM "chain"
+```
 
-// Add a "level" column to the query representing manager's position in the chain
+Column names and a materialization hint can optionally be provided.
 
+```swift
+// Add a "level" column to the query representing manager's position in the chain
 let level = Expression<Int64>("level")
 
 let queryWithLevel = 

From ced185132ea17b9ba7391322bc52982f930538bd Mon Sep 17 00:00:00 2001
From: Matthew Jee <matthew@marmphco.com>
Date: Wed, 13 Jul 2022 20:22:25 -0700
Subject: [PATCH 511/685] Move WITH support members to extension in
 Query+with.swift

---
 SQLite.xcodeproj/project.pbxproj      | 10 +++
 Sources/SQLite/Typed/Query+with.swift | 95 +++++++++++++++++++++++++++
 Sources/SQLite/Typed/Query.swift      | 69 -------------------
 3 files changed, 105 insertions(+), 69 deletions(-)
 create mode 100644 Sources/SQLite/Typed/Query+with.swift

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 61c2773a..fc38e5e9 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -130,6 +130,10 @@
 		49EB68C51F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
 		49EB68C61F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
 		49EB68C71F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
+		997DF2AE287FC06D00F8DF95 /* Query+with.swift in Sources */ = {isa = PBXBuildFile; fileRef = 997DF2AD287FC06D00F8DF95 /* Query+with.swift */; };
+		997DF2AF287FC06D00F8DF95 /* Query+with.swift in Sources */ = {isa = PBXBuildFile; fileRef = 997DF2AD287FC06D00F8DF95 /* Query+with.swift */; };
+		997DF2B0287FC06D00F8DF95 /* Query+with.swift in Sources */ = {isa = PBXBuildFile; fileRef = 997DF2AD287FC06D00F8DF95 /* Query+with.swift */; };
+		997DF2B1287FC06D00F8DF95 /* Query+with.swift in Sources */ = {isa = PBXBuildFile; fileRef = 997DF2AD287FC06D00F8DF95 /* Query+with.swift */; };
 		D4DB368C20C09CFB00D5A58E /* SelectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4DB368A20C09C9B00D5A58E /* SelectTests.swift */; };
 		D4DB368D20C09CFC00D5A58E /* SelectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4DB368A20C09C9B00D5A58E /* SelectTests.swift */; };
 		D4DB368E20C09CFD00D5A58E /* SelectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4DB368A20C09C9B00D5A58E /* SelectTests.swift */; };
@@ -260,6 +264,7 @@
 		3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.0.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
 		3DDC112E26CDBA0200CE369F /* SQLiteObjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SQLiteObjc.h; path = ../SQLiteObjc/include/SQLiteObjc.h; sourceTree = "<group>"; };
 		49EB68C31F7B3CB400D89D40 /* Coding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coding.swift; sourceTree = "<group>"; };
+		997DF2AD287FC06D00F8DF95 /* Query+with.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Query+with.swift"; sourceTree = "<group>"; };
 		A121AC451CA35C79005A31D1 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		D4DB368A20C09C9B00D5A58E /* SelectTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectTests.swift; sourceTree = "<group>"; };
 		EE247AD31C3F04ED00AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -499,6 +504,7 @@
 				EE247AFE1C3F06E900AE3E12 /* Expression.swift */,
 				EE247AFF1C3F06E900AE3E12 /* Operators.swift */,
 				EE247B001C3F06E900AE3E12 /* Query.swift */,
+				997DF2AD287FC06D00F8DF95 /* Query+with.swift */,
 				EE247B011C3F06E900AE3E12 /* Schema.swift */,
 				EE247B021C3F06E900AE3E12 /* Setter.swift */,
 				49EB68C31F7B3CB400D89D40 /* Coding.swift */,
@@ -862,6 +868,7 @@
 				19A17FF4A10B44D3937C8CAC /* Errors.swift in Sources */,
 				19A1737286A74F3CF7412906 /* DateAndTimeFunctions.swift in Sources */,
 				19A17073552293CA063BEA66 /* Result.swift in Sources */,
+				997DF2B0287FC06D00F8DF95 /* Query+with.swift in Sources */,
 				19A179B59450FE7C4811AB8A /* Connection+Aggregation.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -904,6 +911,7 @@
 			files = (
 				3D67B3F91DB246E700A4F4C6 /* SQLiteObjc.m in Sources */,
 				49EB68C71F7B3CB400D89D40 /* Coding.swift in Sources */,
+				997DF2B1287FC06D00F8DF95 /* Query+with.swift in Sources */,
 				3D67B3F71DB246D700A4F4C6 /* Foundation.swift in Sources */,
 				3D67B3F81DB246D700A4F4C6 /* Helpers.swift in Sources */,
 				3D67B3E91DB246D100A4F4C6 /* Statement.swift in Sources */,
@@ -959,6 +967,7 @@
 				19A1792C0520D4E83C2EB075 /* Errors.swift in Sources */,
 				19A17E29278A12BC4F542506 /* DateAndTimeFunctions.swift in Sources */,
 				19A173EFEF0B3BD0B3ED406C /* Result.swift in Sources */,
+				997DF2AE287FC06D00F8DF95 /* Query+with.swift in Sources */,
 				19A176376CB6A94759F7980A /* Connection+Aggregation.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -1024,6 +1033,7 @@
 				19A17490543609FCED53CACC /* Errors.swift in Sources */,
 				19A17152E32A9585831E3FE0 /* DateAndTimeFunctions.swift in Sources */,
 				19A17F1B3F0A3C96B5ED6D64 /* Result.swift in Sources */,
+				997DF2AF287FC06D00F8DF95 /* Query+with.swift in Sources */,
 				19A170ACC97B19730FB7BA4D /* Connection+Aggregation.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
diff --git a/Sources/SQLite/Typed/Query+with.swift b/Sources/SQLite/Typed/Query+with.swift
new file mode 100644
index 00000000..005f490c
--- /dev/null
+++ b/Sources/SQLite/Typed/Query+with.swift
@@ -0,0 +1,95 @@
+//
+// SQLite.swift
+// https://github.com/stephencelis/SQLite.swift
+// Copyright © 2014-2015 Stephen Celis.
+//
+// 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.
+//
+import Foundation
+
+extension QueryType {
+
+    /// Sets a `WITH` clause on the query.
+    ///
+    ///     let users = Table("users")
+    ///     let id = Expression<String>("email")
+    ///     let name = Expression<String?>("name")
+    ///
+    ///     let userNames = Table("user_names")
+    ///     userCategories.with(userNames, as: users.select(name))
+    ///     // WITH "user_names" as (SELECT "name" FROM "users") SELECT * FROM "user_names"
+    ///
+    /// - Parameters:
+    ///
+    ///   -  alias: A name to assign to the table expression.
+    ///
+    ///   -  recursive: Whether to evaluate the expression recursively.
+    ///
+    ///   -  hint: Provides a hint to the query planner for how the expression should be implemented.
+    ///
+    ///   -  subquery: A query that generates the rows for the table expression.
+    ///
+    /// - Returns: A query with the given `ORDER BY` clause applied.
+    public func with(_ alias: Table, columns: [Expressible]? = nil, recursive: Bool = false,
+                     hint: MaterializationHint? = nil, as subquery: QueryType) -> Self {
+        var query = self
+        let clause = WithClauses.Clause(alias: alias, columns: columns, hint: hint, query: subquery)
+        query.clauses.with.recursive = query.clauses.with.recursive || recursive
+        query.clauses.with.clauses.append(clause)
+        return query
+    }
+
+    /// self.clauses.with transformed to an Expressible
+    var withClause: Expressible? {
+        guard !clauses.with.clauses.isEmpty else {
+            return nil
+        }
+
+        let innerClauses = ", ".join(clauses.with.clauses.map { (clause) in
+            let hintExpr: Expression<Void>?
+            if let hint = clause.hint {
+                hintExpr = Expression<Void>(literal: hint.rawValue)
+            } else {
+                hintExpr = nil
+            }
+
+            let columnExpr: Expression<Void>?
+            if let columns = clause.columns {
+                columnExpr = "".wrap(", ".join(columns))
+            } else {
+                columnExpr = nil
+            }
+
+            let expressions: [Expressible?] = [
+                clause.alias.tableName(),
+                columnExpr,
+                Expression<Void>(literal: "AS"),
+                hintExpr,
+                "".wrap(clause.query) as Expression<Void>
+            ]
+
+            return " ".join(expressions.compactMap { $0 })
+        })
+
+        return " ".join([
+            Expression<Void>(literal: clauses.with.recursive ? "WITH RECURSIVE" : "WITH"),
+            innerClauses
+        ])
+    }
+}
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index b34570a7..f688cfe6 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -499,38 +499,6 @@ extension QueryType {
         return query
     }
 
-    // MARK: WITH
-
-    /// Sets a `WITH` clause on the query.
-    ///
-    ///     let users = Table("users")
-    ///     let id = Expression<String>("email")
-    ///     let name = Expression<String?>("name")
-    ///
-    ///     let userNames = Table("user_names")
-    ///     userCategories.with(userNames, as: users.select(name))
-    ///     // WITH "user_names" as (SELECT "name" FROM "users") SELECT * FROM "user_names"
-    ///
-    /// - Parameters:
-    ///
-    ///   -  alias: A name to assign to the table expression.
-    ///
-    ///   -  recursive: Whether to evaluate the expression recursively.
-    ///
-    ///   -  hint: Provides a hint to the query planner for how the expression should be implemented.
-    ///
-    ///   -  subquery: A query that generates the rows for the table expression.
-    ///
-    /// - Returns: A query with the given `ORDER BY` clause applied.
-    public func with(_ alias: Table, columns: [Expressible]? = nil, recursive: Bool = false,
-                     hint: MaterializationHint? = nil, as subquery: QueryType) -> Self {
-        var query = self
-        let clause = WithClauses.Clause(alias: alias, columns: columns, hint: hint, query: subquery)
-        query.clauses.with.recursive = query.clauses.with.recursive || recursive
-        query.clauses.with.clauses.append(clause)
-        return query
-    }
-
     // MARK: - Clauses
     //
     // MARK: SELECT
@@ -638,43 +606,6 @@ extension QueryType {
         })
     }
 
-    fileprivate var withClause: Expressible? {
-        guard !clauses.with.clauses.isEmpty else {
-            return nil
-        }
-
-        let innerClauses = ", ".join(clauses.with.clauses.map { (clause) in
-            let hintExpr: Expression<Void>?
-            if let hint = clause.hint {
-                hintExpr = Expression<Void>(literal: hint.rawValue)
-            } else {
-                hintExpr = nil
-            }
-
-            let columnExpr: Expression<Void>?
-            if let columns = clause.columns {
-                columnExpr = "".wrap(", ".join(columns))
-            } else {
-                columnExpr = nil
-            }
-
-            let expressions: [Expressible?] = [
-                clause.alias.tableName(),
-                columnExpr,
-                Expression<Void>(literal: "AS"),
-                hintExpr,
-                "".wrap(clause.query) as Expression<Void>
-            ]
-
-            return " ".join(expressions.compactMap { $0 })
-        })
-
-        return " ".join([
-            Expression<Void>(literal: clauses.with.recursive ? "WITH RECURSIVE" : "WITH"),
-            innerClauses
-        ])
-    }
-
     // MARK: -
 
     public func alias(_ aliasName: String) -> Self {

From ed43285b6e02a7244c86c8aa58d6069cf6ed803d Mon Sep 17 00:00:00 2001
From: Matthew Jee <matthew@marmphco.com>
Date: Thu, 14 Jul 2022 20:55:31 -0700
Subject: [PATCH 512/685] Move WithClauses to Query+with.swift

---
 Sources/SQLite/Typed/Query+with.swift | 14 ++++++++++++++
 Sources/SQLite/Typed/Query.swift      | 14 --------------
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/Sources/SQLite/Typed/Query+with.swift b/Sources/SQLite/Typed/Query+with.swift
index 005f490c..697e77fd 100644
--- a/Sources/SQLite/Typed/Query+with.swift
+++ b/Sources/SQLite/Typed/Query+with.swift
@@ -93,3 +93,17 @@ extension QueryType {
         ])
     }
 }
+
+struct WithClauses {
+    struct Clause {
+        var alias: Table
+        var columns: [Expressible]?
+        var hint: MaterializationHint?
+        var query: QueryType
+    }
+    /// The `RECURSIVE` flag is applied to the entire `WITH` clause
+    var recursive: Bool = false
+
+    /// Each `WITH` clause may have multiple subclauses
+    var clauses: [Clause] = []
+}
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index f688cfe6..b4f9f46f 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -1246,20 +1246,6 @@ public enum MaterializationHint: String {
 
 // MARK: - Private
 
-struct WithClauses {
-    struct Clause {
-        var alias: Table
-        var columns: [Expressible]?
-        var hint: MaterializationHint?
-        var query: QueryType
-    }
-    /// The `RECURSIVE` flag is applied to the entire `WITH` clause
-    var recursive: Bool = false
-
-    /// Each `WITH` clause may have multiple subclauses
-    var clauses: [Clause] = []
-}
-
 public struct QueryClauses {
 
     var select = (distinct: false, columns: [Expression<Void>(literal: "*") as Expressible])

From 0dfc7b0452455b5ef0805939ed35cccd66f46429 Mon Sep 17 00:00:00 2001
From: Matthew Jee <matthew@marmphco.com>
Date: Fri, 15 Jul 2022 08:01:00 -0700
Subject: [PATCH 513/685] MaterializationHint > Query+with

---
 Sources/SQLite/Typed/Query+with.swift | 8 ++++++++
 Sources/SQLite/Typed/Query.swift      | 8 --------
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/Sources/SQLite/Typed/Query+with.swift b/Sources/SQLite/Typed/Query+with.swift
index 697e77fd..d06c8896 100644
--- a/Sources/SQLite/Typed/Query+with.swift
+++ b/Sources/SQLite/Typed/Query+with.swift
@@ -94,6 +94,14 @@ extension QueryType {
     }
 }
 
+/// Materialization hints for `WITH` clause
+public enum MaterializationHint: String {
+
+    case materialized = "MATERIALIZED"
+
+    case notMaterialized = "NOT MATERIALIZED"
+}
+
 struct WithClauses {
     struct Clause {
         var alias: Table
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index b4f9f46f..cfa7544e 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -1236,14 +1236,6 @@ public enum OnConflict: String {
 
 }
 
-/// Materialization hints for `WITH` clause
-public enum MaterializationHint: String {
-
-    case materialized = "MATERIALIZED"
-
-    case notMaterialized = "NOT MATERIALIZED"
-}
-
 // MARK: - Private
 
 public struct QueryClauses {

From cfa6010717800bd3ed4bc28bb019223871188853 Mon Sep 17 00:00:00 2001
From: Matthew Jee <matthew@marmphco.com>
Date: Fri, 15 Jul 2022 19:28:56 -0700
Subject: [PATCH 514/685] Split test cases

---
 Tests/SQLiteTests/QueryTests.swift | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index a96ff38c..eae1d923 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -61,6 +61,9 @@ class QueryTests: XCTestCase {
 
     func test_union_compilesUnionClause() {
         assertSQL("SELECT * FROM \"users\" UNION SELECT * FROM \"posts\"", users.union(posts))
+    }
+
+    func test_union_compilesUnionAllClause() {
         assertSQL("SELECT * FROM \"users\" UNION ALL SELECT * FROM \"posts\"", users.union(all: true, posts))
     }
 
@@ -232,21 +235,22 @@ class QueryTests: XCTestCase {
                   temp.with(temp, as: users))
     }
 
-    func test_with_recursive_compilesWithClause() {
+    func test_with_compilesWithRecursiveClause() {
         let temp = Table("temp")
 
         assertSQL("WITH RECURSIVE \"temp\" AS (SELECT * FROM \"users\") SELECT * FROM \"temp\"",
                   temp.with(temp, recursive: true, as: users))
-
-        assertSQL("WITH \"temp\" AS (SELECT * FROM \"users\") SELECT * FROM \"temp\"",
-                  temp.with(temp, recursive: false, as: users))
     }
 
-    func test_with_materialization_compilesWithClause() {
+    func test_with_compilesWithMaterializedClause() {
         let temp = Table("temp")
 
         assertSQL("WITH \"temp\" AS MATERIALIZED (SELECT * FROM \"users\") SELECT * FROM \"temp\"",
                   temp.with(temp, hint: .materialized, as: users))
+    }
+
+    func test_with_compilesWithNotMaterializedClause() {
+        let temp = Table("temp")
 
         assertSQL("WITH \"temp\" AS NOT MATERIALIZED (SELECT * FROM \"users\") SELECT * FROM \"temp\"",
                   temp.with(temp, hint: .notMaterialized, as: users))

From ee905fe357157b6b48ed6641aa5abcf16a6ac354 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 16 Jul 2022 23:27:17 +0200
Subject: [PATCH 515/685] Add tests for NSURL conformance

---
 Tests/SQLiteTests/FoundationTests.swift | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/Tests/SQLiteTests/FoundationTests.swift b/Tests/SQLiteTests/FoundationTests.swift
index 075e755b..453febcd 100644
--- a/Tests/SQLiteTests/FoundationTests.swift
+++ b/Tests/SQLiteTests/FoundationTests.swift
@@ -26,4 +26,15 @@ class FoundationTests: XCTestCase {
         XCTAssertEqual(UUID(uuidString: "4ABE10C9-FF12-4CD4-90C1-4B429001BAD3"), uuid)
     }
 
+    func testURLFromString() {
+        let string = "http://foo.com"
+        let url = URL.fromDatatypeValue(string)
+        XCTAssertEqual(URL(string: string), url)
+    }
+
+    func testStringFromURL() {
+        let url = URL(string: "http://foo.com")!
+        let string = url.datatypeValue
+        XCTAssertEqual("http://foo.com", string)
+    }
 }

From 9d0c0b9f58c62099e767bf29a901879c3b8be668 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 17 Jul 2022 15:49:56 +0200
Subject: [PATCH 516/685] Add support for ATTACH/DETACH (#30)

---
 Package.swift                               |   3 +-
 SQLite.xcodeproj/project.pbxproj            |  28 ++
 Sources/SQLite/Core/Connection+Attach.swift |  23 ++
 Sources/SQLite/Core/Connection.swift        |  16 +-
 Sources/SQLite/Core/URIQueryParameter.swift |  52 ++++
 Tests/SQLiteTests/ConnectionTests.swift     | 280 +++++++++++---------
 Tests/SQLiteTests/Fixtures.swift            |  12 +-
 Tests/SQLiteTests/ResultTests.swift         |  52 ++++
 Tests/SQLiteTests/TestHelpers.swift         |   4 +-
 Tests/SQLiteTests/fixtures/test.sqlite      | Bin 0 -> 12288 bytes
 10 files changed, 330 insertions(+), 140 deletions(-)
 create mode 100644 Sources/SQLite/Core/Connection+Attach.swift
 create mode 100644 Sources/SQLite/Core/URIQueryParameter.swift
 create mode 100644 Tests/SQLiteTests/ResultTests.swift
 create mode 100644 Tests/SQLiteTests/fixtures/test.sqlite

diff --git a/Package.swift b/Package.swift
index 24898bca..1130d571 100644
--- a/Package.swift
+++ b/Package.swift
@@ -41,7 +41,8 @@ let package = Package(
             ],
             resources: [
                 .copy("fixtures/encrypted-3.x.sqlite"),
-                .copy("fixtures/encrypted-4.x.sqlite")
+                .copy("fixtures/encrypted-4.x.sqlite"),
+                .copy("fixtures/test.sqlite")
             ]
         )
     ]
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index fc38e5e9..4e01067f 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -126,6 +126,17 @@
 		3DDC113626CDBE1900CE369F /* SQLiteObjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 3DDC112E26CDBA0200CE369F /* SQLiteObjc.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		3DDC113726CDBE1900CE369F /* SQLiteObjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 3DDC112E26CDBA0200CE369F /* SQLiteObjc.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		3DDC113826CDBE1C00CE369F /* SQLiteObjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 3DDC112E26CDBA0200CE369F /* SQLiteObjc.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3DF7B78828842972005DD8CA /* Connection+Attach.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B78728842972005DD8CA /* Connection+Attach.swift */; };
+		3DF7B78928842972005DD8CA /* Connection+Attach.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B78728842972005DD8CA /* Connection+Attach.swift */; };
+		3DF7B78A28842972005DD8CA /* Connection+Attach.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B78728842972005DD8CA /* Connection+Attach.swift */; };
+		3DF7B78B28842972005DD8CA /* Connection+Attach.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B78728842972005DD8CA /* Connection+Attach.swift */; };
+		3DF7B78D28842C23005DD8CA /* ResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B78C28842C23005DD8CA /* ResultTests.swift */; };
+		3DF7B78E28842C23005DD8CA /* ResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B78C28842C23005DD8CA /* ResultTests.swift */; };
+		3DF7B78F28842C23005DD8CA /* ResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B78C28842C23005DD8CA /* ResultTests.swift */; };
+		3DF7B791288449BA005DD8CA /* URIQueryParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B790288449BA005DD8CA /* URIQueryParameter.swift */; };
+		3DF7B792288449BA005DD8CA /* URIQueryParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B790288449BA005DD8CA /* URIQueryParameter.swift */; };
+		3DF7B793288449BA005DD8CA /* URIQueryParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B790288449BA005DD8CA /* URIQueryParameter.swift */; };
+		3DF7B794288449BA005DD8CA /* URIQueryParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B790288449BA005DD8CA /* URIQueryParameter.swift */; };
 		49EB68C41F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
 		49EB68C51F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
 		49EB68C61F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
@@ -263,6 +274,9 @@
 		3D3C3CCB26E5568800759140 /* SQLite.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = SQLite.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
 		3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.0.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
 		3DDC112E26CDBA0200CE369F /* SQLiteObjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SQLiteObjc.h; path = ../SQLiteObjc/include/SQLiteObjc.h; sourceTree = "<group>"; };
+		3DF7B78728842972005DD8CA /* Connection+Attach.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Connection+Attach.swift"; sourceTree = "<group>"; };
+		3DF7B78C28842C23005DD8CA /* ResultTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultTests.swift; sourceTree = "<group>"; };
+		3DF7B790288449BA005DD8CA /* URIQueryParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URIQueryParameter.swift; sourceTree = "<group>"; };
 		49EB68C31F7B3CB400D89D40 /* Coding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coding.swift; sourceTree = "<group>"; };
 		997DF2AD287FC06D00F8DF95 /* Query+with.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Query+with.swift"; sourceTree = "<group>"; };
 		A121AC451CA35C79005A31D1 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -461,6 +475,7 @@
 				D4DB368A20C09C9B00D5A58E /* SelectTests.swift */,
 				19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */,
 				19A171FDE4D67879B14ACBDF /* FTSIntegrationTests.swift */,
+				3DF7B78C28842C23005DD8CA /* ResultTests.swift */,
 			);
 			name = SQLiteTests;
 			path = Tests/SQLiteTests;
@@ -479,6 +494,8 @@
 				02A43A9722738CF100FEC494 /* Backup.swift */,
 				19A17E723300E5ED3771DCB5 /* Result.swift */,
 				19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */,
+				3DF7B78728842972005DD8CA /* Connection+Attach.swift */,
+				3DF7B790288449BA005DD8CA /* URIQueryParameter.swift */,
 			);
 			path = Core;
 			sourceTree = "<group>";
@@ -847,12 +864,14 @@
 				49EB68C61F7B3CB400D89D40 /* Coding.swift in Sources */,
 				03A65E761C6BB2E60062603F /* Blob.swift in Sources */,
 				03A65E7D1C6BB2F70062603F /* RTree.swift in Sources */,
+				3DF7B793288449BA005DD8CA /* URIQueryParameter.swift in Sources */,
 				03A65E791C6BB2EF0062603F /* SQLiteObjc.m in Sources */,
 				03A65E7B1C6BB2F70062603F /* Value.swift in Sources */,
 				03A65E821C6BB2FB0062603F /* Expression.swift in Sources */,
 				03A65E731C6BB2D80062603F /* Foundation.swift in Sources */,
 				03A65E7F1C6BB2FB0062603F /* Collation.swift in Sources */,
 				03A65E861C6BB2FB0062603F /* Setter.swift in Sources */,
+				3DF7B78A28842972005DD8CA /* Connection+Attach.swift in Sources */,
 				03A65E811C6BB2FB0062603F /* CustomFunctions.swift in Sources */,
 				03A65E7A1C6BB2F70062603F /* Statement.swift in Sources */,
 				03A65E741C6BB2DA0062603F /* Helpers.swift in Sources */,
@@ -877,6 +896,7 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				3DF7B78F28842C23005DD8CA /* ResultTests.swift in Sources */,
 				03A65E881C6BB3030062603F /* BlobTests.swift in Sources */,
 				03A65E901C6BB3030062603F /* RTreeTests.swift in Sources */,
 				03A65E941C6BB3030062603F /* ValueTests.swift in Sources */,
@@ -910,6 +930,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				3D67B3F91DB246E700A4F4C6 /* SQLiteObjc.m in Sources */,
+				3DF7B78B28842972005DD8CA /* Connection+Attach.swift in Sources */,
 				49EB68C71F7B3CB400D89D40 /* Coding.swift in Sources */,
 				997DF2B1287FC06D00F8DF95 /* Query+with.swift in Sources */,
 				3D67B3F71DB246D700A4F4C6 /* Foundation.swift in Sources */,
@@ -925,6 +946,7 @@
 				3D67B3F11DB246D100A4F4C6 /* CustomFunctions.swift in Sources */,
 				3D67B3F21DB246D100A4F4C6 /* Expression.swift in Sources */,
 				3D67B3F31DB246D100A4F4C6 /* Operators.swift in Sources */,
+				3DF7B794288449BA005DD8CA /* URIQueryParameter.swift in Sources */,
 				3D67B3F41DB246D100A4F4C6 /* Query.swift in Sources */,
 				3D67B3F51DB246D100A4F4C6 /* Schema.swift in Sources */,
 				3D67B3F61DB246D100A4F4C6 /* Setter.swift in Sources */,
@@ -946,12 +968,14 @@
 				49EB68C41F7B3CB400D89D40 /* Coding.swift in Sources */,
 				EE247B0A1C3F06E900AE3E12 /* RTree.swift in Sources */,
 				EE247B031C3F06E900AE3E12 /* Blob.swift in Sources */,
+				3DF7B791288449BA005DD8CA /* URIQueryParameter.swift in Sources */,
 				EE247B0B1C3F06E900AE3E12 /* Foundation.swift in Sources */,
 				EE247B041C3F06E900AE3E12 /* Connection.swift in Sources */,
 				EE247B111C3F06E900AE3E12 /* Expression.swift in Sources */,
 				EE247B0C1C3F06E900AE3E12 /* Helpers.swift in Sources */,
 				EE247B0E1C3F06E900AE3E12 /* Collation.swift in Sources */,
 				EE247B151C3F06E900AE3E12 /* Setter.swift in Sources */,
+				3DF7B78828842972005DD8CA /* Connection+Attach.swift in Sources */,
 				EE247B101C3F06E900AE3E12 /* CustomFunctions.swift in Sources */,
 				EE247B091C3F06E900AE3E12 /* FTS4.swift in Sources */,
 				EE247B081C3F06E900AE3E12 /* Value.swift in Sources */,
@@ -976,6 +1000,7 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				3DF7B78D28842C23005DD8CA /* ResultTests.swift in Sources */,
 				EE247B261C3F137700AE3E12 /* CoreFunctionsTests.swift in Sources */,
 				EE247B291C3F137700AE3E12 /* FTS4Tests.swift in Sources */,
 				EE247B191C3F134A00AE3E12 /* SetterTests.swift in Sources */,
@@ -1012,12 +1037,14 @@
 				49EB68C51F7B3CB400D89D40 /* Coding.swift in Sources */,
 				EE247B651C3F3FEC00AE3E12 /* Blob.swift in Sources */,
 				EE247B6C1C3F3FEC00AE3E12 /* RTree.swift in Sources */,
+				3DF7B792288449BA005DD8CA /* URIQueryParameter.swift in Sources */,
 				EE247B681C3F3FEC00AE3E12 /* SQLiteObjc.m in Sources */,
 				EE247B6A1C3F3FEC00AE3E12 /* Value.swift in Sources */,
 				EE247B711C3F3FEC00AE3E12 /* Expression.swift in Sources */,
 				EE247B631C3F3FDB00AE3E12 /* Foundation.swift in Sources */,
 				EE247B6E1C3F3FEC00AE3E12 /* Collation.swift in Sources */,
 				EE247B751C3F3FEC00AE3E12 /* Setter.swift in Sources */,
+				3DF7B78928842972005DD8CA /* Connection+Attach.swift in Sources */,
 				EE247B701C3F3FEC00AE3E12 /* CustomFunctions.swift in Sources */,
 				EE247B691C3F3FEC00AE3E12 /* Statement.swift in Sources */,
 				EE247B641C3F3FDB00AE3E12 /* Helpers.swift in Sources */,
@@ -1042,6 +1069,7 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				3DF7B78E28842C23005DD8CA /* ResultTests.swift in Sources */,
 				EE247B561C3F3FC700AE3E12 /* CoreFunctionsTests.swift in Sources */,
 				EE247B5A1C3F3FC700AE3E12 /* OperatorsTests.swift in Sources */,
 				EE247B541C3F3FC700AE3E12 /* BlobTests.swift in Sources */,
diff --git a/Sources/SQLite/Core/Connection+Attach.swift b/Sources/SQLite/Core/Connection+Attach.swift
new file mode 100644
index 00000000..b9c08117
--- /dev/null
+++ b/Sources/SQLite/Core/Connection+Attach.swift
@@ -0,0 +1,23 @@
+import Foundation
+#if SQLITE_SWIFT_STANDALONE
+import sqlite3
+#elseif SQLITE_SWIFT_SQLCIPHER
+import SQLCipher
+#elseif os(Linux)
+import CSQLite
+#else
+import SQLite3
+#endif
+
+extension Connection {
+
+    /// See  https://www3.sqlite.org/lang_attach.html
+    public func attach(_ location: Location, as schemaName: String) throws {
+        try run("ATTACH DATABASE ? AS ?", location.description, schemaName)
+    }
+
+    /// See https://www3.sqlite.org/lang_detach.html
+    public func detach(_ schemaName: String) throws {
+        try run("DETACH DATABASE ?", schemaName)
+    }
+}
diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 72e8d857..60b9f1bd 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -55,7 +55,8 @@ public final class Connection {
         /// See: <https://www.sqlite.org/uri.html>
         ///
         /// - Parameter filename: A URI filename
-        case uri(String)
+        /// - Parameter parameters: optional query parameters
+        case uri(String, parameters: [URIQueryParameter] = [])
     }
 
     /// An SQL operation passed to update callbacks.
@@ -727,8 +728,17 @@ extension Connection.Location: CustomStringConvertible {
             return ":memory:"
         case .temporary:
             return ""
-        case .uri(let URI):
-            return URI
+        case let .uri(URI, parameters):
+            guard parameters.count > 0,
+                  var components = URLComponents(string: URI) else {
+                return URI
+            }
+            components.queryItems =
+                (components.queryItems ?? []) + parameters.map(\.queryItem)
+            if components.scheme == nil {
+                components.scheme = "file"
+            }
+            return components.description
         }
     }
 
diff --git a/Sources/SQLite/Core/URIQueryParameter.swift b/Sources/SQLite/Core/URIQueryParameter.swift
new file mode 100644
index 00000000..c82a7cf7
--- /dev/null
+++ b/Sources/SQLite/Core/URIQueryParameter.swift
@@ -0,0 +1,52 @@
+import Foundation
+
+public enum URIQueryParameter: CustomStringConvertible {
+    public enum FileMode: String {
+        case readOnly = "ro", readWrite = "rw", readWriteCreate = "rwc", memory
+    }
+
+    public enum CacheMode: String {
+        case shared, `private`
+    }
+
+    /// The cache query parameter determines if the new database is opened using shared cache mode or with a private cache.
+    case cache(CacheMode)
+
+    /// The immutable query parameter is a boolean that signals to SQLite that the underlying database file is held on read-only media
+    /// and cannot be modified, even by another process with elevated privileges.
+    case immutable(Bool)
+
+    /// When creating a new database file during `sqlite3_open_v2()` on unix systems, SQLite will try to set the permissions of the new database
+    /// file to match the existing file "filename".
+    case modeOf(String)
+
+    /// The mode query parameter determines if the new database is opened read-only, read-write, read-write and created if it does not exist,
+    /// or that the database is a pure in-memory database that never interacts with disk, respectively.
+    case mode(FileMode)
+
+    /// The nolock query parameter is a boolean that disables all calls to the `xLock`, ` xUnlock`, and `xCheckReservedLock` methods
+    /// of the VFS when true.
+    case nolock(Bool)
+
+    /// The psow query parameter overrides the `powersafe_overwrite` property of the database file being opened.
+    case psow(Bool)
+
+    /// The vfs query parameter causes the database connection to be opened using the VFS called NAME.
+    case vfs(String)
+
+    public var description: String {
+        queryItem.description
+    }
+
+    var queryItem: URLQueryItem {
+        switch self {
+        case .cache(let mode): return .init(name: "cache", value: mode.rawValue)
+        case .immutable(let bool): return .init(name: "immutable", value: NSNumber(value: bool).description)
+        case .modeOf(let filename): return .init(name: "modeOf", value: filename)
+        case .mode(let fileMode): return .init(name: "mode", value: fileMode.rawValue)
+        case .nolock(let bool): return .init(name: "nolock", value: NSNumber(value: bool).description)
+        case .psow(let bool): return .init(name: "psow", value: NSNumber(value: bool).description)
+        case .vfs(let name): return .init(name: "vfs", value: name)
+        }
+    }
+}
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index 136271a4..cf51c104 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -20,39 +20,49 @@ class ConnectionTests: SQLiteTestCase {
         try createUsersTable()
     }
 
-    func test_init_withInMemory_returnsInMemoryConnection() {
-        let db = try! Connection(.inMemory)
+    func test_init_withInMemory_returnsInMemoryConnection() throws {
+        let db = try Connection(.inMemory)
         XCTAssertEqual("", db.description)
     }
 
-    func test_init_returnsInMemoryByDefault() {
-        let db = try! Connection()
+    func test_init_returnsInMemoryByDefault() throws {
+        let db = try Connection()
         XCTAssertEqual("", db.description)
     }
 
-    func test_init_withTemporary_returnsTemporaryConnection() {
-        let db = try! Connection(.temporary)
+    func test_init_withTemporary_returnsTemporaryConnection() throws {
+        let db = try Connection(.temporary)
         XCTAssertEqual("", db.description)
     }
 
-    func test_init_withURI_returnsURIConnection() {
-        let db = try! Connection(.uri("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3"))
+    func test_init_withURI_returnsURIConnection() throws {
+        let db = try Connection(.uri("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3"))
         let url = URL(fileURLWithPath: db.description)
         XCTAssertEqual(url.lastPathComponent, "SQLite.swift Tests.sqlite3")
     }
 
-    func test_init_withString_returnsURIConnection() {
-        let db = try! Connection("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3")
+    func test_init_withString_returnsURIConnection() throws {
+        let db = try Connection("\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3")
         let url = URL(fileURLWithPath: db.description)
         XCTAssertEqual(url.lastPathComponent, "SQLite.swift Tests.sqlite3")
     }
 
+    func testLocationWithoutUriParameters() {
+        let location: Connection.Location = .uri("foo")
+        XCTAssertEqual(location.description, "foo")
+    }
+
+    func testLocationWithUriParameters() {
+        let location: Connection.Location = .uri("foo", parameters: [.mode(.readOnly), .cache(.private)])
+        XCTAssertEqual(location.description, "file:foo?mode=ro&cache=private")
+    }
+
     func test_readonly_returnsFalseOnReadWriteConnections() {
         XCTAssertFalse(db.readonly)
     }
 
-    func test_readonly_returnsTrueOnReadOnlyConnections() {
-        let db = try! Connection(readonly: true)
+    func test_readonly_returnsTrueOnReadOnlyConnections() throws {
+        let db = try Connection(readonly: true)
         XCTAssertTrue(db.readonly)
     }
 
@@ -60,14 +70,14 @@ class ConnectionTests: SQLiteTestCase {
         XCTAssertEqual(0, db.changes)
     }
 
-    func test_lastInsertRowid_returnsLastIdAfterInserts() {
-        try! insertUser("alice")
+    func test_lastInsertRowid_returnsLastIdAfterInserts() throws {
+        try insertUser("alice")
         XCTAssertEqual(1, db.lastInsertRowid)
     }
 
-    func test_lastInsertRowid_doesNotResetAfterError() {
+    func test_lastInsertRowid_doesNotResetAfterError() throws {
         XCTAssert(db.lastInsertRowid == 0)
-        try! insertUser("alice")
+        try insertUser("alice")
         XCTAssertEqual(1, db.lastInsertRowid)
         XCTAssertThrowsError(
             try db.run("INSERT INTO \"users\" (email, age, admin) values ('invalid@example.com', 12, 'invalid')")
@@ -81,18 +91,18 @@ class ConnectionTests: SQLiteTestCase {
         XCTAssertEqual(1, db.lastInsertRowid)
     }
 
-    func test_changes_returnsNumberOfChanges() {
-        try! insertUser("alice")
+    func test_changes_returnsNumberOfChanges() throws {
+        try insertUser("alice")
         XCTAssertEqual(1, db.changes)
-        try! insertUser("betsy")
+        try insertUser("betsy")
         XCTAssertEqual(1, db.changes)
     }
 
-    func test_totalChanges_returnsTotalNumberOfChanges() {
+    func test_totalChanges_returnsTotalNumberOfChanges() throws {
         XCTAssertEqual(0, db.totalChanges)
-        try! insertUser("alice")
+        try insertUser("alice")
         XCTAssertEqual(1, db.totalChanges)
-        try! insertUser("betsy")
+        try insertUser("betsy")
         XCTAssertEqual(2, db.totalChanges)
     }
 
@@ -101,53 +111,53 @@ class ConnectionTests: SQLiteTestCase {
         XCTAssertEqual(2, db.userVersion!)
     }
 
-    func test_prepare_preparesAndReturnsStatements() {
-        _ = try! db.prepare("SELECT * FROM users WHERE admin = 0")
-        _ = try! db.prepare("SELECT * FROM users WHERE admin = ?", 0)
-        _ = try! db.prepare("SELECT * FROM users WHERE admin = ?", [0])
-        _ = try! db.prepare("SELECT * FROM users WHERE admin = $admin", ["$admin": 0])
+    func test_prepare_preparesAndReturnsStatements() throws {
+        _ = try db.prepare("SELECT * FROM users WHERE admin = 0")
+        _ = try db.prepare("SELECT * FROM users WHERE admin = ?", 0)
+        _ = try db.prepare("SELECT * FROM users WHERE admin = ?", [0])
+        _ = try db.prepare("SELECT * FROM users WHERE admin = $admin", ["$admin": 0])
     }
 
-    func test_run_preparesRunsAndReturnsStatements() {
-        try! db.run("SELECT * FROM users WHERE admin = 0")
-        try! db.run("SELECT * FROM users WHERE admin = ?", 0)
-        try! db.run("SELECT * FROM users WHERE admin = ?", [0])
-        try! db.run("SELECT * FROM users WHERE admin = $admin", ["$admin": 0])
+    func test_run_preparesRunsAndReturnsStatements() throws {
+        try db.run("SELECT * FROM users WHERE admin = 0")
+        try db.run("SELECT * FROM users WHERE admin = ?", 0)
+        try db.run("SELECT * FROM users WHERE admin = ?", [0])
+        try db.run("SELECT * FROM users WHERE admin = $admin", ["$admin": 0])
         assertSQL("SELECT * FROM users WHERE admin = 0", 4)
     }
 
-    func test_vacuum() {
-        try! db.vacuum()
+    func test_vacuum() throws {
+        try db.vacuum()
     }
 
-    func test_scalar_preparesRunsAndReturnsScalarValues() {
-        XCTAssertEqual(0, try! db.scalar("SELECT count(*) FROM users WHERE admin = 0") as? Int64)
-        XCTAssertEqual(0, try! db.scalar("SELECT count(*) FROM users WHERE admin = ?", 0) as? Int64)
-        XCTAssertEqual(0, try! db.scalar("SELECT count(*) FROM users WHERE admin = ?", [0]) as? Int64)
-        XCTAssertEqual(0, try! db.scalar("SELECT count(*) FROM users WHERE admin = $admin", ["$admin": 0]) as? Int64)
+    func test_scalar_preparesRunsAndReturnsScalarValues() throws {
+        XCTAssertEqual(0, try db.scalar("SELECT count(*) FROM users WHERE admin = 0") as? Int64)
+        XCTAssertEqual(0, try db.scalar("SELECT count(*) FROM users WHERE admin = ?", 0) as? Int64)
+        XCTAssertEqual(0, try db.scalar("SELECT count(*) FROM users WHERE admin = ?", [0]) as? Int64)
+        XCTAssertEqual(0, try db.scalar("SELECT count(*) FROM users WHERE admin = $admin", ["$admin": 0]) as? Int64)
         assertSQL("SELECT count(*) FROM users WHERE admin = 0", 4)
     }
 
-    func test_execute_comment() {
-        try! db.run("-- this is a comment\nSELECT 1")
+    func test_execute_comment() throws {
+        try db.run("-- this is a comment\nSELECT 1")
         assertSQL("-- this is a comment", 0)
         assertSQL("SELECT 1", 0)
     }
 
-    func test_transaction_executesBeginDeferred() {
-        try! db.transaction(.deferred) {}
+    func test_transaction_executesBeginDeferred() throws {
+        try db.transaction(.deferred) {}
 
         assertSQL("BEGIN DEFERRED TRANSACTION")
     }
 
-    func test_transaction_executesBeginImmediate() {
-        try! db.transaction(.immediate) {}
+    func test_transaction_executesBeginImmediate() throws {
+        try db.transaction(.immediate) {}
 
         assertSQL("BEGIN IMMEDIATE TRANSACTION")
     }
 
-    func test_transaction_executesBeginExclusive() {
-        try! db.transaction(.exclusive) {}
+    func test_transaction_executesBeginExclusive() throws {
+        try db.transaction(.exclusive) {}
 
         assertSQL("BEGIN EXCLUSIVE TRANSACTION")
     }
@@ -164,10 +174,10 @@ class ConnectionTests: SQLiteTestCase {
         XCTAssertEqual(users.map { $0[0] as? String }, ["alice@example.com", "betsy@example.com"])
     }
 
-    func test_transaction_beginsAndCommitsTransactions() {
-        let stmt = try! db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com")
+    func test_transaction_beginsAndCommitsTransactions() throws {
+        let stmt = try db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com")
 
-        try! db.transaction {
+        try db.transaction {
             try stmt.run()
         }
 
@@ -177,8 +187,8 @@ class ConnectionTests: SQLiteTestCase {
         assertSQL("ROLLBACK TRANSACTION", 0)
     }
 
-    func test_transaction_rollsBackTransactionsIfCommitsFail() {
-        let sqliteVersion = String(describing: try! db.scalar("SELECT sqlite_version()")!)
+    func test_transaction_rollsBackTransactionsIfCommitsFail() throws {
+        let sqliteVersion = String(describing: try db.scalar("SELECT sqlite_version()")!)
             .split(separator: ".").compactMap { Int($0) }
         // PRAGMA defer_foreign_keys only supported in SQLite >= 3.8.0
         guard sqliteVersion[0] == 3 && sqliteVersion[1] >= 8 else {
@@ -187,9 +197,9 @@ class ConnectionTests: SQLiteTestCase {
         }
         // This test case needs to emulate an environment where the individual statements succeed, but committing the
         // transaction fails. Using deferred foreign keys is one option to achieve this.
-        try! db.execute("PRAGMA foreign_keys = ON;")
-        try! db.execute("PRAGMA defer_foreign_keys = ON;")
-        let stmt = try! db.prepare("INSERT INTO users (email, manager_id) VALUES (?, ?)", "alice@example.com", 100)
+        try db.execute("PRAGMA foreign_keys = ON;")
+        try db.execute("PRAGMA defer_foreign_keys = ON;")
+        let stmt = try db.prepare("INSERT INTO users (email, manager_id) VALUES (?, ?)", "alice@example.com", 100)
 
         do {
             try db.transaction {
@@ -209,14 +219,14 @@ class ConnectionTests: SQLiteTestCase {
 
         // Run another transaction to ensure that a subsequent transaction does not fail with an "cannot start a
         // transaction within a transaction" error.
-        let stmt2 = try! db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com")
-        try! db.transaction {
+        let stmt2 = try db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com")
+        try db.transaction {
             try stmt2.run()
         }
     }
 
-    func test_transaction_beginsAndRollsTransactionsBack() {
-        let stmt = try! db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com")
+    func test_transaction_beginsAndRollsTransactionsBack() throws {
+        let stmt = try db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com")
 
         do {
             try db.transaction {
@@ -232,8 +242,8 @@ class ConnectionTests: SQLiteTestCase {
         assertSQL("COMMIT TRANSACTION", 0)
     }
 
-    func test_savepoint_beginsAndCommitsSavepoints() {
-        try! db.savepoint("1") {
+    func test_savepoint_beginsAndCommitsSavepoints() throws {
+        try db.savepoint("1") {
             try db.savepoint("2") {
                 try db.run("INSERT INTO users (email) VALUES (?)", "alice@example.com")
             }
@@ -248,8 +258,8 @@ class ConnectionTests: SQLiteTestCase {
         assertSQL("ROLLBACK TO SAVEPOINT '1'", 0)
     }
 
-    func test_savepoint_beginsAndRollsSavepointsBack() {
-        let stmt = try! db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com")
+    func test_savepoint_beginsAndRollsSavepointsBack() throws {
+        let stmt = try db.prepare("INSERT INTO users (email) VALUES (?)", "alice@example.com")
 
         do {
             try db.savepoint("1") {
@@ -276,8 +286,8 @@ class ConnectionTests: SQLiteTestCase {
         assertSQL("RELEASE SAVEPOINT '1'", 0)
     }
 
-    func test_updateHook_setsUpdateHook_withInsert() {
-        async { done in
+    func test_updateHook_setsUpdateHook_withInsert() throws {
+        try async { done in
             db.updateHook { operation, db, table, rowid in
                 XCTAssertEqual(Connection.Operation.insert, operation)
                 XCTAssertEqual("main", db)
@@ -285,13 +295,13 @@ class ConnectionTests: SQLiteTestCase {
                 XCTAssertEqual(1, rowid)
                 done()
             }
-            try! insertUser("alice")
+            try insertUser("alice")
         }
     }
 
-    func test_updateHook_setsUpdateHook_withUpdate() {
-        try! insertUser("alice")
-        async { done in
+    func test_updateHook_setsUpdateHook_withUpdate() throws {
+        try insertUser("alice")
+        try async { done in
             db.updateHook { operation, db, table, rowid in
                 XCTAssertEqual(Connection.Operation.update, operation)
                 XCTAssertEqual("main", db)
@@ -299,13 +309,13 @@ class ConnectionTests: SQLiteTestCase {
                 XCTAssertEqual(1, rowid)
                 done()
             }
-            try! db.run("UPDATE users SET email = 'alice@example.com'")
+            try db.run("UPDATE users SET email = 'alice@example.com'")
         }
     }
 
-    func test_updateHook_setsUpdateHook_withDelete() {
-        try! insertUser("alice")
-        async { done in
+    func test_updateHook_setsUpdateHook_withDelete() throws {
+        try insertUser("alice")
+        try async { done in
             db.updateHook { operation, db, table, rowid in
                 XCTAssertEqual(Connection.Operation.delete, operation)
                 XCTAssertEqual("main", db)
@@ -313,24 +323,24 @@ class ConnectionTests: SQLiteTestCase {
                 XCTAssertEqual(1, rowid)
                 done()
             }
-            try! db.run("DELETE FROM users WHERE id = 1")
+            try db.run("DELETE FROM users WHERE id = 1")
         }
     }
 
-    func test_commitHook_setsCommitHook() {
-        async { done in
+    func test_commitHook_setsCommitHook() throws {
+        try async { done in
             db.commitHook {
                 done()
             }
-            try! db.transaction {
+            try db.transaction {
                 try insertUser("alice")
             }
-            XCTAssertEqual(1, try! db.scalar("SELECT count(*) FROM users") as? Int64)
+            XCTAssertEqual(1, try db.scalar("SELECT count(*) FROM users") as? Int64)
         }
     }
 
-    func test_rollbackHook_setsRollbackHook() {
-        async { done in
+    func test_rollbackHook_setsRollbackHook() throws {
+        try async { done in
             db.rollbackHook(done)
             do {
                 try db.transaction {
@@ -339,12 +349,12 @@ class ConnectionTests: SQLiteTestCase {
                 }
             } catch {
             }
-            XCTAssertEqual(0, try! db.scalar("SELECT count(*) FROM users") as? Int64)
+            XCTAssertEqual(0, try db.scalar("SELECT count(*) FROM users") as? Int64)
         }
     }
 
-    func test_commitHook_withRollback_rollsBack() {
-        async { done in
+    func test_commitHook_withRollback_rollsBack() throws {
+        try async { done in
             db.commitHook {
                 throw NSError(domain: "com.stephencelis.SQLiteTests", code: 1, userInfo: nil)
             }
@@ -355,41 +365,41 @@ class ConnectionTests: SQLiteTestCase {
                 }
             } catch {
             }
-            XCTAssertEqual(0, try! db.scalar("SELECT count(*) FROM users") as? Int64)
+            XCTAssertEqual(0, try db.scalar("SELECT count(*) FROM users") as? Int64)
         }
     }
 
     // https://github.com/stephencelis/SQLite.swift/issues/1071
     #if !os(Linux)
-    func test_createFunction_withArrayArguments() {
+    func test_createFunction_withArrayArguments() throws {
         db.createFunction("hello") { $0[0].map { "Hello, \($0)!" } }
 
-        XCTAssertEqual("Hello, world!", try! db.scalar("SELECT hello('world')") as? String)
-        XCTAssert(try! db.scalar("SELECT hello(NULL)") == nil)
+        XCTAssertEqual("Hello, world!", try db.scalar("SELECT hello('world')") as? String)
+        XCTAssert(try db.scalar("SELECT hello(NULL)") == nil)
     }
 
-    func test_createFunction_createsQuotableFunction() {
+    func test_createFunction_createsQuotableFunction() throws {
         db.createFunction("hello world") { $0[0].map { "Hello, \($0)!" } }
 
-        XCTAssertEqual("Hello, world!", try! db.scalar("SELECT \"hello world\"('world')") as? String)
-        XCTAssert(try! db.scalar("SELECT \"hello world\"(NULL)") == nil)
+        XCTAssertEqual("Hello, world!", try db.scalar("SELECT \"hello world\"('world')") as? String)
+        XCTAssert(try db.scalar("SELECT \"hello world\"(NULL)") == nil)
     }
 
-    func test_createCollation_createsCollation() {
-        try! db.createCollation("NODIACRITIC") { lhs, rhs in
+    func test_createCollation_createsCollation() throws {
+        try db.createCollation("NODIACRITIC") { lhs, rhs in
             lhs.compare(rhs, options: .diacriticInsensitive)
         }
-        XCTAssertEqual(1, try! db.scalar("SELECT ? = ? COLLATE NODIACRITIC", "cafe", "café") as? Int64)
+        XCTAssertEqual(1, try db.scalar("SELECT ? = ? COLLATE NODIACRITIC", "cafe", "café") as? Int64)
     }
 
-    func test_createCollation_createsQuotableCollation() {
-        try! db.createCollation("NO DIACRITIC") { lhs, rhs in
+    func test_createCollation_createsQuotableCollation() throws {
+        try db.createCollation("NO DIACRITIC") { lhs, rhs in
             lhs.compare(rhs, options: .diacriticInsensitive)
         }
-        XCTAssertEqual(1, try! db.scalar("SELECT ? = ? COLLATE \"NO DIACRITIC\"", "cafe", "café") as? Int64)
+        XCTAssertEqual(1, try db.scalar("SELECT ? = ? COLLATE \"NO DIACRITIC\"", "cafe", "café") as? Int64)
     }
 
-    func test_interrupt_interruptsLongRunningQuery() {
+    func test_interrupt_interruptsLongRunningQuery() throws {
         let semaphore = DispatchSemaphore(value: 0)
         db.createFunction("sleep") { _ in
             DispatchQueue.global(qos: .background).async {
@@ -399,7 +409,7 @@ class ConnectionTests: SQLiteTestCase {
             semaphore.wait()
             return nil
         }
-        let stmt = try! db.prepare("SELECT sleep()")
+        let stmt = try db.prepare("SELECT sleep()")
         XCTAssertThrowsError(try stmt.run()) { error in
             if case Result.error(_, let code, _) = error {
                 XCTAssertEqual(code, SQLITE_INTERRUPT)
@@ -410,13 +420,13 @@ class ConnectionTests: SQLiteTestCase {
     }
     #endif
 
-    func test_concurrent_access_single_connection() {
+    func test_concurrent_access_single_connection() throws {
         // test can fail on iOS/tvOS 9.x: SQLite compile-time differences?
         guard #available(iOS 10.0, OSX 10.10, tvOS 10.0, watchOS 2.2, *) else { return }
 
-        let conn = try! Connection("\(NSTemporaryDirectory())/\(UUID().uuidString)")
-        try! conn.execute("DROP TABLE IF EXISTS test; CREATE TABLE test(value);")
-        try! conn.run("INSERT INTO test(value) VALUES(?)", 0)
+        let conn = try Connection("\(NSTemporaryDirectory())/\(UUID().uuidString)")
+        try conn.execute("DROP TABLE IF EXISTS test; CREATE TABLE test(value);")
+        try conn.run("INSERT INTO test(value) VALUES(?)", 0)
         let queue = DispatchQueue(label: "Readers", attributes: [.concurrent])
 
         let nReaders = 5
@@ -430,43 +440,51 @@ class ConnectionTests: SQLiteTestCase {
         }
         semaphores.forEach { $0.wait() }
     }
-}
 
-class ResultTests: XCTestCase {
-    let connection = try! Connection(.inMemory)
+    func test_attach_detach_memory_database() throws {
+        let schemaName = "test"
 
-    func test_init_with_ok_code_returns_nil() {
-        XCTAssertNil(Result(errorCode: SQLITE_OK, connection: connection, statement: nil) as Result?)
-    }
+        try db.attach(.inMemory, as: schemaName)
 
-    func test_init_with_row_code_returns_nil() {
-        XCTAssertNil(Result(errorCode: SQLITE_ROW, connection: connection, statement: nil) as Result?)
-    }
+        let table = Table("attached_users", database: schemaName)
+        let name = Expression<String>("string")
 
-    func test_init_with_done_code_returns_nil() {
-        XCTAssertNil(Result(errorCode: SQLITE_DONE, connection: connection, statement: nil) as Result?)
-    }
+        // create a table, insert some data
+        try db.run(table.create { builder in
+            builder.column(name)
+        })
+        _ = try db.run(table.insert(name <- "test"))
 
-    func test_init_with_other_code_returns_error() {
-        if case .some(.error(let message, let code, let statement)) =
-            Result(errorCode: SQLITE_MISUSE, connection: connection, statement: nil) {
-            XCTAssertEqual("not an error", message)
-            XCTAssertEqual(SQLITE_MISUSE, code)
-            XCTAssertNil(statement)
-            XCTAssert(connection === connection)
-        } else {
-            XCTFail("no error")
-        }
+        // query data
+        let rows = try db.prepare(table.select(name)).map { $0[name] }
+        XCTAssertEqual(["test"], rows)
+
+        try db.detach(schemaName)
     }
 
-    func test_description_contains_error_code() {
-        XCTAssertEqual("not an error (code: 21)",
-            Result(errorCode: SQLITE_MISUSE, connection: connection, statement: nil)?.description)
+    func test_attach_detach_file_database() throws {
+        let schemaName = "test"
+        let testDb = fixture("test", withExtension: "sqlite")
+
+        try db.attach(.uri(testDb, parameters: [.mode(.readOnly)]), as: schemaName)
+
+        let table = Table("tests", database: schemaName)
+        let email = Expression<String>("email")
+
+        let rows = try db.prepare(table.select(email)).map { $0[email] }
+        XCTAssertEqual(["foo@bar.com"], rows)
+
+        try db.detach(schemaName)
     }
 
-    func test_description_contains_statement_and_error_code() {
-        let statement = try! Statement(connection, "SELECT 1")
-        XCTAssertEqual("not an error (SELECT 1) (code: 21)",
-            Result(errorCode: SQLITE_MISUSE, connection: connection, statement: statement)?.description)
+    func test_detach_invalid_schema_name_errors_with_no_such_database() throws {
+        XCTAssertThrowsError(try db.detach("no-exist")) { error in
+            if case let Result.error(message, code, _) = error {
+                XCTAssertEqual(code, SQLITE_ERROR)
+                XCTAssertEqual("no such database: no-exist", message)
+            } else {
+                XCTFail("unexpected error: \(error)")
+            }
+        }
     }
 }
diff --git a/Tests/SQLiteTests/Fixtures.swift b/Tests/SQLiteTests/Fixtures.swift
index d0683130..f3851cba 100644
--- a/Tests/SQLiteTests/Fixtures.swift
+++ b/Tests/SQLiteTests/Fixtures.swift
@@ -2,7 +2,13 @@ import Foundation
 
 func fixture(_ name: String, withExtension: String?) -> String {
     let testBundle = Bundle(for: SQLiteTestCase.self)
-    return testBundle.url(
-        forResource: name,
-        withExtension: withExtension)!.path
+
+    for resource in [name, "fixtures/\(name)"] {
+        if let url = testBundle.url(
+            forResource: resource,
+            withExtension: withExtension) {
+            return url.path
+        }
+    }
+    fatalError("Cannot find \(name).\(withExtension ?? "")")
 }
diff --git a/Tests/SQLiteTests/ResultTests.swift b/Tests/SQLiteTests/ResultTests.swift
new file mode 100644
index 00000000..ccedcfe2
--- /dev/null
+++ b/Tests/SQLiteTests/ResultTests.swift
@@ -0,0 +1,52 @@
+import XCTest
+import Foundation
+@testable import SQLite
+
+#if SQLITE_SWIFT_STANDALONE
+import sqlite3
+#elseif SQLITE_SWIFT_SQLCIPHER
+import SQLCipher
+#elseif os(Linux)
+import CSQLite
+#else
+import SQLite3
+#endif
+
+class ResultTests: XCTestCase {
+    let connection = try! Connection(.inMemory)
+
+    func test_init_with_ok_code_returns_nil() {
+        XCTAssertNil(Result(errorCode: SQLITE_OK, connection: connection, statement: nil) as Result?)
+    }
+
+    func test_init_with_row_code_returns_nil() {
+        XCTAssertNil(Result(errorCode: SQLITE_ROW, connection: connection, statement: nil) as Result?)
+    }
+
+    func test_init_with_done_code_returns_nil() {
+        XCTAssertNil(Result(errorCode: SQLITE_DONE, connection: connection, statement: nil) as Result?)
+    }
+
+    func test_init_with_other_code_returns_error() {
+        if case .some(.error(let message, let code, let statement)) =
+            Result(errorCode: SQLITE_MISUSE, connection: connection, statement: nil) {
+            XCTAssertEqual("not an error", message)
+            XCTAssertEqual(SQLITE_MISUSE, code)
+            XCTAssertNil(statement)
+            XCTAssert(connection === connection)
+        } else {
+            XCTFail("no error")
+        }
+    }
+
+    func test_description_contains_error_code() {
+        XCTAssertEqual("not an error (code: 21)",
+            Result(errorCode: SQLITE_MISUSE, connection: connection, statement: nil)?.description)
+    }
+
+    func test_description_contains_statement_and_error_code() {
+        let statement = try! Statement(connection, "SELECT 1")
+        XCTAssertEqual("not an error (SELECT 1) (code: 21)",
+            Result(errorCode: SQLITE_MISUSE, connection: connection, statement: statement)?.description)
+    }
+}
diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index f43310c9..6e8e9ebb 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -66,9 +66,9 @@ class SQLiteTestCase: XCTestCase {
 //        if let count = trace[SQL] { trace[SQL] = count - 1 }
 //    }
 
-    func async(expect description: String = "async", timeout: Double = 5, block: (@escaping () -> Void) -> Void) {
+    func async(expect description: String = "async", timeout: Double = 5, block: (@escaping () -> Void) throws -> Void) throws {
         let expectation = self.expectation(description: description)
-        block({ expectation.fulfill() })
+        try block({ expectation.fulfill() })
         waitForExpectations(timeout: timeout, handler: nil)
     }
 
diff --git a/Tests/SQLiteTests/fixtures/test.sqlite b/Tests/SQLiteTests/fixtures/test.sqlite
new file mode 100644
index 0000000000000000000000000000000000000000..7b39b423d7afdd43d0d793bb0c87de0248b8910d
GIT binary patch

From 544e7b9c5c291bbe1973abd06eb88afa22f6f296 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 17 Jul 2022 16:07:32 +0200
Subject: [PATCH 517/685] Remove force tries in tests

---
 Tests/SQLiteTests/CipherTests.swift           | 52 +++++------
 .../SQLiteTests/CustomAggregationTests.swift  | 22 ++---
 Tests/SQLiteTests/CustomFunctionsTests.swift  | 90 +++++++++----------
 Tests/SQLiteTests/FTS4Tests.swift             | 10 +--
 Tests/SQLiteTests/QueryIntegrationTests.swift | 76 ++++++++--------
 Tests/SQLiteTests/QueryTests.swift            | 12 +--
 Tests/SQLiteTests/ResultTests.swift           | 10 ++-
 Tests/SQLiteTests/RowTests.swift              | 16 ++--
 Tests/SQLiteTests/SelectTests.swift           |  8 +-
 Tests/SQLiteTests/StatementTests.swift        | 24 ++---
 Tests/SQLiteTests/TestHelpers.swift           |  4 +-
 11 files changed, 164 insertions(+), 160 deletions(-)

diff --git a/Tests/SQLiteTests/CipherTests.swift b/Tests/SQLiteTests/CipherTests.swift
index 0995fca0..f25dbe5b 100644
--- a/Tests/SQLiteTests/CipherTests.swift
+++ b/Tests/SQLiteTests/CipherTests.swift
@@ -5,8 +5,8 @@ import SQLCipher
 
 class CipherTests: XCTestCase {
 
-    let db1 = try! Connection()
-    let db2 = try! Connection()
+    let db1 = try Connection()
+    let db2 = try Connection()
 
     override func setUpWithError() throws {
         // db
@@ -26,41 +26,41 @@ class CipherTests: XCTestCase {
         try super.setUpWithError()
     }
 
-    func test_key() {
-        XCTAssertEqual(1, try! db1.scalar("SELECT count(*) FROM foo") as? Int64)
+    func test_key() throws {
+        XCTAssertEqual(1, try db1.scalar("SELECT count(*) FROM foo") as? Int64)
     }
 
     func test_key_blob_literal() {
-        let db = try! Connection()
-        try! db.key("x'2DD29CA851E7B56E4697B0E1F08507293D761A05CE4D1B628663F411A8086D99'")
+        let db = try Connection()
+        try db.key("x'2DD29CA851E7B56E4697B0E1F08507293D761A05CE4D1B628663F411A8086D99'")
     }
 
-    func test_rekey() {
-        try! db1.rekey("goodbye")
-        XCTAssertEqual(1, try! db1.scalar("SELECT count(*) FROM foo") as? Int64)
+    func test_rekey() throws {
+        try db1.rekey("goodbye")
+        XCTAssertEqual(1, try db1.scalar("SELECT count(*) FROM foo") as? Int64)
     }
 
-    func test_data_key() {
-        XCTAssertEqual(1, try! db2.scalar("SELECT count(*) FROM foo") as? Int64)
+    func test_data_key() throws {
+        XCTAssertEqual(1, try db2.scalar("SELECT count(*) FROM foo") as? Int64)
     }
 
-    func test_data_rekey() {
+    func test_data_rekey() throws {
         let newKey = keyData()
-        try! db2.rekey(Blob(bytes: newKey.bytes, length: newKey.length))
-        XCTAssertEqual(1, try! db2.scalar("SELECT count(*) FROM foo") as? Int64)
+        try db2.rekey(Blob(bytes: newKey.bytes, length: newKey.length))
+        XCTAssertEqual(1, try db2.scalar("SELECT count(*) FROM foo") as? Int64)
     }
 
-    func test_keyFailure() {
+    func test_keyFailure() throws {
         let path = "\(NSTemporaryDirectory())/db.sqlite3"
         _ = try? FileManager.default.removeItem(atPath: path)
 
-        let connA = try! Connection(path)
-        defer { try! FileManager.default.removeItem(atPath: path) }
+        let connA = try Connection(path)
+        defer { try FileManager.default.removeItem(atPath: path) }
 
-        try! connA.key("hello")
-        try! connA.run("CREATE TABLE foo (bar TEXT)")
+        try connA.key("hello")
+        try connA.run("CREATE TABLE foo (bar TEXT)")
 
-        let connB = try! Connection(path, readonly: true)
+        let connB = try Connection(path, readonly: true)
 
         do {
             try connB.key("world")
@@ -72,7 +72,7 @@ class CipherTests: XCTestCase {
         }
     }
 
-    func test_open_db_encrypted_with_sqlcipher() {
+    func test_open_db_encrypted_with_sqlcipher() throws {
         // $ sqlcipher Tests/SQLiteTests/fixtures/encrypted-[version].x.sqlite
         // sqlite> pragma key = 'sqlcipher-test';
         // sqlite> CREATE TABLE foo (bar TEXT);
@@ -85,17 +85,17 @@ class CipherTests: XCTestCase {
             fixture("encrypted-3.x", withExtension: "sqlite") :
             fixture("encrypted-4.x", withExtension: "sqlite")
 
-        try! FileManager.default.setAttributes([FileAttributeKey.immutable: 1], ofItemAtPath: encryptedFile)
+        try FileManager.default.setAttributes([FileAttributeKey.immutable: 1], ofItemAtPath: encryptedFile)
         XCTAssertFalse(FileManager.default.isWritableFile(atPath: encryptedFile))
 
         defer {
             // ensure file can be cleaned up afterwards
-            try! FileManager.default.setAttributes([FileAttributeKey.immutable: 0], ofItemAtPath: encryptedFile)
+            try FileManager.default.setAttributes([FileAttributeKey.immutable: 0], ofItemAtPath: encryptedFile)
         }
 
-        let conn = try! Connection(encryptedFile)
-        try! conn.key("sqlcipher-test")
-        XCTAssertEqual(1, try! conn.scalar("SELECT count(*) FROM foo") as? Int64)
+        let conn = try Connection(encryptedFile)
+        try conn.key("sqlcipher-test")
+        XCTAssertEqual(1, try conn.scalar("SELECT count(*) FROM foo") as? Int64)
     }
 
     private func keyData(length: Int = 64) -> NSMutableData {
diff --git a/Tests/SQLiteTests/CustomAggregationTests.swift b/Tests/SQLiteTests/CustomAggregationTests.swift
index 5cbfbbef..71cbba9c 100644
--- a/Tests/SQLiteTests/CustomAggregationTests.swift
+++ b/Tests/SQLiteTests/CustomAggregationTests.swift
@@ -25,7 +25,7 @@ class CustomAggregationTests: SQLiteTestCase {
         try insertUser("Eve", age: 28, admin: false)
     }
 
-    func testUnsafeCustomSum() {
+    func testUnsafeCustomSum() throws {
         let step = { (bindings: [Binding?], state: UnsafeMutablePointer<Int64>) in
             if let v = bindings[0] as? Int64 {
                 state.pointee += v
@@ -43,7 +43,7 @@ class CustomAggregationTests: SQLiteTestCase {
             v[0] = 0
             return v.baseAddress!
         }
-        let result = try! db.prepare("SELECT mySUM1(age) AS s FROM users")
+        let result = try db.prepare("SELECT mySUM1(age) AS s FROM users")
         let i = result.columnNames.firstIndex(of: "s")!
         for row in result {
             let value = row[i] as? Int64
@@ -51,7 +51,7 @@ class CustomAggregationTests: SQLiteTestCase {
         }
     }
 
-    func testUnsafeCustomSumGrouping() {
+    func testUnsafeCustomSumGrouping() throws {
         let step = { (bindings: [Binding?], state: UnsafeMutablePointer<Int64>) in
             if let v = bindings[0] as? Int64 {
                 state.pointee += v
@@ -68,19 +68,19 @@ class CustomAggregationTests: SQLiteTestCase {
             v[0] = 0
             return v.baseAddress!
         }
-        let result = try! db.prepare("SELECT mySUM2(age) AS s FROM users GROUP BY admin ORDER BY s")
+        let result = try db.prepare("SELECT mySUM2(age) AS s FROM users GROUP BY admin ORDER BY s")
         let i = result.columnNames.firstIndex(of: "s")!
         let values = result.compactMap { $0[i] as? Int64 }
         XCTAssertTrue(values.elementsEqual([28, 55]))
     }
 
-    func testCustomSum() {
+    func testCustomSum() throws {
         let reduce: (Int64, [Binding?]) -> Int64 = { (last, bindings) in
             let v = (bindings[0] as? Int64) ?? 0
             return last + v
         }
         db.createAggregation("myReduceSUM1", initialValue: Int64(2000), reduce: reduce, result: { $0 })
-        let result = try! db.prepare("SELECT myReduceSUM1(age) AS s FROM users")
+        let result = try db.prepare("SELECT myReduceSUM1(age) AS s FROM users")
         let i = result.columnNames.firstIndex(of: "s")!
         for row in result {
             let value = row[i] as? Int64
@@ -88,26 +88,26 @@ class CustomAggregationTests: SQLiteTestCase {
         }
     }
 
-    func testCustomSumGrouping() {
+    func testCustomSumGrouping() throws {
         let reduce: (Int64, [Binding?]) -> Int64 = { (last, bindings) in
             let v = (bindings[0] as? Int64) ?? 0
             return last + v
         }
         db.createAggregation("myReduceSUM2", initialValue: Int64(3000), reduce: reduce, result: { $0 })
-        let result = try! db.prepare("SELECT myReduceSUM2(age) AS s FROM users GROUP BY admin ORDER BY s")
+        let result = try db.prepare("SELECT myReduceSUM2(age) AS s FROM users GROUP BY admin ORDER BY s")
         let i = result.columnNames.firstIndex(of: "s")!
         let values = result.compactMap { $0[i] as? Int64 }
         XCTAssertTrue(values.elementsEqual([3028, 3055]))
     }
 
-    func testCustomStringAgg() {
+    func testCustomStringAgg() throws {
         let initial = String(repeating: " ", count: 64)
         let reduce: (String, [Binding?]) -> String = { (last, bindings) in
             let v = (bindings[0] as? String) ?? ""
             return last + v
         }
         db.createAggregation("myReduceSUM3", initialValue: initial, reduce: reduce, result: { $0 })
-        let result = try! db.prepare("SELECT myReduceSUM3(email) AS s FROM users")
+        let result = try db.prepare("SELECT myReduceSUM3(email) AS s FROM users")
 
         let i = result.columnNames.firstIndex(of: "s")!
         for row in result {
@@ -116,7 +116,7 @@ class CustomAggregationTests: SQLiteTestCase {
         }
     }
 
-    func testCustomObjectSum() {
+    func testCustomObjectSum() throws {
         {
             let initial = TestObject(value: 1000)
             let reduce: (TestObject, [Binding?]) -> TestObject = { (last, bindings) in
diff --git a/Tests/SQLiteTests/CustomFunctionsTests.swift b/Tests/SQLiteTests/CustomFunctionsTests.swift
index 3d897f8e..c4eb51e6 100644
--- a/Tests/SQLiteTests/CustomFunctionsTests.swift
+++ b/Tests/SQLiteTests/CustomFunctionsTests.swift
@@ -8,19 +8,19 @@ class CustomFunctionNoArgsTests: SQLiteTestCase {
     typealias FunctionNoOptional              = ()  -> Expression<String>
     typealias FunctionResultOptional          = ()  -> Expression<String?>
 
-    func testFunctionNoOptional() {
-        let _: FunctionNoOptional = try! db.createFunction("test", deterministic: true) {
+    func testFunctionNoOptional() throws {
+        let _: FunctionNoOptional = try db.createFunction("test", deterministic: true) {
             "a"
         }
-        let result = try! db.prepare("SELECT test()").scalar() as! String
+        let result = try db.prepare("SELECT test()").scalar() as! String
         XCTAssertEqual("a", result)
     }
 
-    func testFunctionResultOptional() {
-        let _: FunctionResultOptional = try! db.createFunction("test", deterministic: true) {
+    func testFunctionResultOptional() throws {
+        let _: FunctionResultOptional = try db.createFunction("test", deterministic: true) {
             "a"
         }
-        let result = try! db.prepare("SELECT test()").scalar() as! String?
+        let result = try db.prepare("SELECT test()").scalar() as! String?
         XCTAssertEqual("a", result)
     }
 }
@@ -31,35 +31,35 @@ class CustomFunctionWithOneArgTests: SQLiteTestCase {
     typealias FunctionResultOptional          = (Expression<String>)  -> Expression<String?>
     typealias FunctionLeftResultOptional      = (Expression<String?>) -> Expression<String?>
 
-    func testFunctionNoOptional() {
-        let _: FunctionNoOptional = try! db.createFunction("test", deterministic: true) { a in
+    func testFunctionNoOptional() throws {
+        let _: FunctionNoOptional = try db.createFunction("test", deterministic: true) { a in
             "b" + a
         }
-        let result = try! db.prepare("SELECT test(?)").scalar("a") as! String
+        let result = try db.prepare("SELECT test(?)").scalar("a") as! String
         XCTAssertEqual("ba", result)
     }
 
-    func testFunctionLeftOptional() {
-        let _: FunctionLeftOptional = try! db.createFunction("test", deterministic: true) { a in
+    func testFunctionLeftOptional() throws {
+        let _: FunctionLeftOptional = try db.createFunction("test", deterministic: true) { a in
             "b" + a!
         }
-        let result = try! db.prepare("SELECT test(?)").scalar("a") as! String
+        let result = try db.prepare("SELECT test(?)").scalar("a") as! String
         XCTAssertEqual("ba", result)
     }
 
-    func testFunctionResultOptional() {
-        let _: FunctionResultOptional = try! db.createFunction("test", deterministic: true) { a in
+    func testFunctionResultOptional() throws {
+        let _: FunctionResultOptional = try db.createFunction("test", deterministic: true) { a in
             "b" + a
         }
-        let result = try! db.prepare("SELECT test(?)").scalar("a") as! String
+        let result = try db.prepare("SELECT test(?)").scalar("a") as! String
         XCTAssertEqual("ba", result)
     }
 
-    func testFunctionLeftResultOptional() {
-        let _: FunctionLeftResultOptional = try! db.createFunction("test", deterministic: true) { (a: String?) -> String? in
+    func testFunctionLeftResultOptional() throws {
+        let _: FunctionLeftResultOptional = try db.createFunction("test", deterministic: true) { (a: String?) -> String? in
             "b" + a!
         }
-        let result = try! db.prepare("SELECT test(?)").scalar("a") as! String
+        let result = try db.prepare("SELECT test(?)").scalar("a") as! String
         XCTAssertEqual("ba", result)
     }
 }
@@ -74,76 +74,76 @@ class CustomFunctionWithTwoArgsTests: SQLiteTestCase {
     typealias FunctionRightResultOptional     = (Expression<String>, Expression<String?>) -> Expression<String?>
     typealias FunctionLeftRightResultOptional = (Expression<String?>, Expression<String?>) -> Expression<String?>
 
-    func testNoOptional() {
-        let _: FunctionNoOptional = try! db.createFunction("test", deterministic: true) { a, b in
+    func testNoOptional() throws {
+        let _: FunctionNoOptional = try db.createFunction("test", deterministic: true) { a, b in
             a + b
         }
-        let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String
+        let result = try db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String
         XCTAssertEqual("ab", result)
     }
 
-    func testLeftOptional() {
-        let _: FunctionLeftOptional = try! db.createFunction("test", deterministic: true) { a, b in
+    func testLeftOptional() throws {
+        let _: FunctionLeftOptional = try db.createFunction("test", deterministic: true) { a, b in
             a! + b
         }
-        let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String
+        let result = try db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String
         XCTAssertEqual("ab", result)
     }
 
-    func testRightOptional() {
-        let _: FunctionRightOptional = try! db.createFunction("test", deterministic: true) { a, b in
+    func testRightOptional() throws {
+        let _: FunctionRightOptional = try db.createFunction("test", deterministic: true) { a, b in
             a + b!
         }
-        let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String
+        let result = try db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String
         XCTAssertEqual("ab", result)
     }
 
-    func testResultOptional() {
-        let _: FunctionResultOptional = try! db.createFunction("test", deterministic: true) { a, b in
+    func testResultOptional() throws {
+        let _: FunctionResultOptional = try db.createFunction("test", deterministic: true) { a, b in
             a + b
         }
-        let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String?
+        let result = try db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String?
         XCTAssertEqual("ab", result)
     }
 
-    func testFunctionLeftRightOptional() {
-        let _: FunctionLeftRightOptional = try! db.createFunction("test", deterministic: true) { a, b in
+    func testFunctionLeftRightOptional() throws {
+        let _: FunctionLeftRightOptional = try db.createFunction("test", deterministic: true) { a, b in
             a! + b!
         }
-        let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String
+        let result = try db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String
         XCTAssertEqual("ab", result)
     }
 
-    func testFunctionLeftResultOptional() {
-        let _: FunctionLeftResultOptional = try! db.createFunction("test", deterministic: true) { a, b in
+    func testFunctionLeftResultOptional() throws {
+        let _: FunctionLeftResultOptional = try db.createFunction("test", deterministic: true) { a, b in
             a! + b
         }
-        let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String?
+        let result = try db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String?
         XCTAssertEqual("ab", result)
     }
 
-    func testFunctionRightResultOptional() {
-        let _: FunctionRightResultOptional = try! db.createFunction("test", deterministic: true) { a, b in
+    func testFunctionRightResultOptional() throws {
+        let _: FunctionRightResultOptional = try db.createFunction("test", deterministic: true) { a, b in
             a + b!
         }
-        let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String?
+        let result = try db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String?
         XCTAssertEqual("ab", result)
     }
 
-    func testFunctionLeftRightResultOptional() {
-        let _: FunctionLeftRightResultOptional = try! db.createFunction("test", deterministic: true) { a, b in
+    func testFunctionLeftRightResultOptional() throws {
+        let _: FunctionLeftRightResultOptional = try db.createFunction("test", deterministic: true) { a, b in
             a! + b!
         }
-        let result = try! db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String?
+        let result = try db.prepare("SELECT test(?, ?)").scalar("a", "b") as! String?
         XCTAssertEqual("ab", result)
     }
 }
 
 class CustomFunctionTruncation: SQLiteTestCase {
     // https://github.com/stephencelis/SQLite.swift/issues/468
-    func testStringTruncation() {
-        _ = try! db.createFunction("customLower") { (value: String) in value.lowercased() }
-        let result = try! db.prepare("SELECT customLower(?)").scalar("TÖL-AA 12") as? String
+    func testStringTruncation() throws {
+        _ = try db.createFunction("customLower") { (value: String) in value.lowercased() }
+        let result = try db.prepare("SELECT customLower(?)").scalar("TÖL-AA 12") as? String
         XCTAssertEqual("töl-aa 12", result)
     }
 }
diff --git a/Tests/SQLiteTests/FTS4Tests.swift b/Tests/SQLiteTests/FTS4Tests.swift
index d6385b0c..aa6ac41f 100644
--- a/Tests/SQLiteTests/FTS4Tests.swift
+++ b/Tests/SQLiteTests/FTS4Tests.swift
@@ -191,7 +191,7 @@ class FTS4ConfigTests: XCTestCase {
 
 class FTS4IntegrationTests: SQLiteTestCase {
 #if !SQLITE_SWIFT_STANDALONE && !SQLITE_SWIFT_SQLCIPHER
-    func test_registerTokenizer_registersTokenizer() {
+    func test_registerTokenizer_registersTokenizer() throws {
         let emails = VirtualTable("emails")
         let subject = Expression<String?>("subject")
         let body = Expression<String?>("body")
@@ -200,7 +200,7 @@ class FTS4IntegrationTests: SQLiteTestCase {
         let tokenizerName = "tokenizer"
         let tokenizer = CFStringTokenizerCreate(nil, "" as CFString, CFRangeMake(0, 0),
                                                 UInt(kCFStringTokenizerUnitWord), locale)
-        try! db.registerTokenizer(tokenizerName) { string in
+        try db.registerTokenizer(tokenizerName) { string in
             CFStringTokenizerSetString(tokenizer, string as CFString,
                                        CFRangeMake(0, CFStringGetLength(string as CFString)))
             if CFStringTokenizerAdvanceToNextToken(tokenizer).isEmpty {
@@ -214,14 +214,14 @@ class FTS4IntegrationTests: SQLiteTestCase {
             return (token as String, string.range(of: input as String)!)
         }
 
-        try! db.run(emails.create(.FTS4([subject, body], tokenize: .Custom(tokenizerName))))
+        try db.run(emails.create(.FTS4([subject, body], tokenize: .Custom(tokenizerName))))
         assertSQL("""
                   CREATE VIRTUAL TABLE \"emails\" USING fts4(\"subject\", \"body\",
                    tokenize=\"SQLite.swift\" \"tokenizer\")
                   """.replacingOccurrences(of: "\n", with: ""))
 
-        try! _ = db.run(emails.insert(subject <- "Aún más cáfe!"))
-        XCTAssertEqual(1, try! db.scalar(emails.filter(emails.match("aun")).count))
+        try _ = db.run(emails.insert(subject <- "Aún más cáfe!"))
+        XCTAssertEqual(1, try db.scalar(emails.filter(emails.match("aun")).count))
     }
 #endif
 }
diff --git a/Tests/SQLiteTests/QueryIntegrationTests.swift b/Tests/SQLiteTests/QueryIntegrationTests.swift
index db4e2e4e..27b78c0a 100644
--- a/Tests/SQLiteTests/QueryIntegrationTests.swift
+++ b/Tests/SQLiteTests/QueryIntegrationTests.swift
@@ -23,45 +23,45 @@ class QueryIntegrationTests: SQLiteTestCase {
 
     // MARK: -
 
-    func test_select() {
+    func test_select() throws {
         let managerId = Expression<Int64>("manager_id")
         let managers = users.alias("managers")
 
-        let alice = try! db.run(users.insert(email <- "alice@example.com"))
-        _ = try! db.run(users.insert(email <- "betsy@example.com", managerId <- alice))
+        let alice = try db.run(users.insert(email <- "alice@example.com"))
+        _ = try db.run(users.insert(email <- "betsy@example.com", managerId <- alice))
 
-        for user in try! db.prepare(users.join(managers, on: managers[id] == users[managerId])) {
+        for user in try db.prepare(users.join(managers, on: managers[id] == users[managerId])) {
             _ = user[users[managerId]]
         }
     }
 
-    func test_prepareRowIterator() {
+    func test_prepareRowIterator() throws {
         let names = ["a", "b", "c"]
-        try! insertUsers(names)
+        try insertUsers(names)
 
         let emailColumn = Expression<String>("email")
-        let emails = try! db.prepareRowIterator(users).map { $0[emailColumn] }
+        let emails = try db.prepareRowIterator(users).map { $0[emailColumn] }
 
         XCTAssertEqual(names.map({ "\($0)@example.com" }), emails.sorted())
     }
 
-    func test_ambiguousMap() {
+    func test_ambiguousMap() throws {
         let names = ["a", "b", "c"]
-        try! insertUsers(names)
+        try insertUsers(names)
 
-        let emails = try! db.prepare("select email from users", []).map { $0[0] as! String  }
+        let emails = try db.prepare("select email from users", []).map { $0[0] as! String  }
 
         XCTAssertEqual(names.map({ "\($0)@example.com" }), emails.sorted())
     }
 
-    func test_select_optional() {
+    func test_select_optional() throws {
         let managerId = Expression<Int64?>("manager_id")
         let managers = users.alias("managers")
 
-        let alice = try! db.run(users.insert(email <- "alice@example.com"))
-        _ = try! db.run(users.insert(email <- "betsy@example.com", managerId <- alice))
+        let alice = try db.run(users.insert(email <- "alice@example.com"))
+        _ = try db.run(users.insert(email <- "betsy@example.com", managerId <- alice))
 
-        for user in try! db.prepare(users.join(managers, on: managers[id] == users[managerId])) {
+        for user in try db.prepare(users.join(managers, on: managers[id] == users[managerId])) {
             _ = user[users[managerId]]
         }
     }
@@ -107,26 +107,26 @@ class QueryIntegrationTests: SQLiteTestCase {
         XCTAssertNil(values[0].sub?.sub)
     }
 
-    func test_scalar() {
-        XCTAssertEqual(0, try! db.scalar(users.count))
-        XCTAssertEqual(false, try! db.scalar(users.exists))
+    func test_scalar() throws {
+        XCTAssertEqual(0, try db.scalar(users.count))
+        XCTAssertEqual(false, try db.scalar(users.exists))
 
-        try! insertUsers("alice")
-        XCTAssertEqual(1, try! db.scalar(users.select(id.average)))
+        try insertUsers("alice")
+        XCTAssertEqual(1, try db.scalar(users.select(id.average)))
     }
 
-    func test_pluck() {
-        let rowid = try! db.run(users.insert(email <- "alice@example.com"))
-        XCTAssertEqual(rowid, try! db.pluck(users)![id])
+    func test_pluck() throws {
+        let rowid = try db.run(users.insert(email <- "alice@example.com"))
+        XCTAssertEqual(rowid, try db.pluck(users)![id])
     }
 
-    func test_insert() {
-        let id = try! db.run(users.insert(email <- "alice@example.com"))
+    func test_insert() throws {
+        let id = try db.run(users.insert(email <- "alice@example.com"))
         XCTAssertEqual(1, id)
     }
 
-    func test_insert_many() {
-        let id = try! db.run(users.insertMany([[email <- "alice@example.com"], [email <- "geoff@example.com"]]))
+    func test_insert_many() throws {
+        let id = try db.run(users.insertMany([[email <- "alice@example.com"], [email <- "geoff@example.com"]]))
         XCTAssertEqual(2, id)
     }
 
@@ -167,13 +167,13 @@ class QueryIntegrationTests: SQLiteTestCase {
         XCTAssertEqual(42, try fetchAge())
     }
 
-    func test_update() {
-        let changes = try! db.run(users.update(email <- "alice@example.com"))
+    func test_update() throws {
+        let changes = try db.run(users.update(email <- "alice@example.com"))
         XCTAssertEqual(0, changes)
     }
 
-    func test_delete() {
-        let changes = try! db.run(users.delete())
+    func test_delete() throws {
+        let changes = try db.run(users.delete())
         XCTAssertEqual(0, changes)
     }
 
@@ -200,8 +200,8 @@ class QueryIntegrationTests: SQLiteTestCase {
 
     func test_no_such_column() throws {
         let doesNotExist = Expression<String>("doesNotExist")
-        try! insertUser("alice")
-        let row = try! db.pluck(users.filter(email == "alice@example.com"))!
+        try insertUser("alice")
+        let row = try db.pluck(users.filter(email == "alice@example.com"))!
 
         XCTAssertThrowsError(try row.get(doesNotExist)) { error in
             if case QueryError.noSuchColumn(let name, _) = error {
@@ -212,8 +212,8 @@ class QueryIntegrationTests: SQLiteTestCase {
         }
     }
 
-    func test_catchConstraintError() {
-        try! db.run(users.insert(email <- "alice@example.com"))
+    func test_catchConstraintError() throws {
+        try db.run(users.insert(email <- "alice@example.com"))
         do {
             try db.run(users.insert(email <- "alice@example.com"))
             XCTFail("expected error")
@@ -231,19 +231,19 @@ class QueryIntegrationTests: SQLiteTestCase {
         XCTAssertEqual(1, result.count)
     }
 
-    func test_with_recursive() {
+    func test_with_recursive() throws {
         let nodes = Table("nodes")
         let id = Expression<Int64>("id")
         let parent = Expression<Int64?>("parent")
         let value = Expression<Int64>("value")
 
-        try! db.run(nodes.create { builder in
+        try db.run(nodes.create { builder in
             builder.column(id)
             builder.column(parent)
             builder.column(value)
         })
 
-        try! db.run(nodes.insertMany([
+        try db.run(nodes.insertMany([
             [id <- 0, parent <- nil, value <- 2],
             [id <- 1, parent <- 0, value <- 4],
             [id <- 2, parent <- 0, value <- 9],
@@ -254,7 +254,7 @@ class QueryIntegrationTests: SQLiteTestCase {
 
         // Compute the sum of the values of node 5 and its ancestors
         let ancestors = Table("ancestors")
-        let sum = try! db.scalar(
+        let sum = try db.scalar(
             ancestors
                 .select(value.sum)
                 .with(ancestors,
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/QueryTests.swift
index eae1d923..82a33808 100644
--- a/Tests/SQLiteTests/QueryTests.swift
+++ b/Tests/SQLiteTests/QueryTests.swift
@@ -375,25 +375,25 @@ class QueryTests: XCTestCase {
     }
     #endif
 
-    func test_insert_and_search_for_UUID() {
+    func test_insert_and_search_for_UUID() throws {
         struct Test: Codable {
             var uuid: UUID
             var string: String
         }
         let testUUID = UUID()
         let testValue = Test(uuid: testUUID, string: "value")
-        let db = try! Connection(.temporary)
-        try! db.run(table.create { t in
+        let db = try Connection(.temporary)
+        try db.run(table.create { t in
             t.column(uuid)
             t.column(string)
         }
         )
 
-        let iQuery = try! table.insert(testValue)
-        try! db.run(iQuery)
+        let iQuery = try table.insert(testValue)
+        try db.run(iQuery)
 
         let fQuery = table.filter(uuid == testUUID)
-        if let result = try! db.pluck(fQuery) {
+        if let result = try db.pluck(fQuery) {
             let testValueReturned = Test(uuid: result[uuid], string: result[string])
             XCTAssertEqual(testUUID, testValueReturned.uuid)
         } else {
diff --git a/Tests/SQLiteTests/ResultTests.swift b/Tests/SQLiteTests/ResultTests.swift
index ccedcfe2..fab4a0bb 100644
--- a/Tests/SQLiteTests/ResultTests.swift
+++ b/Tests/SQLiteTests/ResultTests.swift
@@ -13,7 +13,11 @@ import SQLite3
 #endif
 
 class ResultTests: XCTestCase {
-    let connection = try! Connection(.inMemory)
+    var connection: Connection!
+
+    override func setUpWithError() throws {
+        connection = try Connection(.inMemory)
+    }
 
     func test_init_with_ok_code_returns_nil() {
         XCTAssertNil(Result(errorCode: SQLITE_OK, connection: connection, statement: nil) as Result?)
@@ -44,8 +48,8 @@ class ResultTests: XCTestCase {
             Result(errorCode: SQLITE_MISUSE, connection: connection, statement: nil)?.description)
     }
 
-    func test_description_contains_statement_and_error_code() {
-        let statement = try! Statement(connection, "SELECT 1")
+    func test_description_contains_statement_and_error_code() throws {
+        let statement = try Statement(connection, "SELECT 1")
         XCTAssertEqual("not an error (SELECT 1) (code: 21)",
             Result(errorCode: SQLITE_MISUSE, connection: connection, statement: statement)?.description)
     }
diff --git a/Tests/SQLiteTests/RowTests.swift b/Tests/SQLiteTests/RowTests.swift
index 36721f80..506f6b10 100644
--- a/Tests/SQLiteTests/RowTests.swift
+++ b/Tests/SQLiteTests/RowTests.swift
@@ -3,9 +3,9 @@ import XCTest
 
 class RowTests: XCTestCase {
 
-    public func test_get_value() {
+    public func test_get_value() throws {
         let row = Row(["\"foo\"": 0], ["value"])
-        let result = try! row.get(Expression<String>("foo"))
+        let result = try row.get(Expression<String>("foo"))
 
         XCTAssertEqual("value", result)
     }
@@ -17,9 +17,9 @@ class RowTests: XCTestCase {
         XCTAssertEqual("value", result)
     }
 
-    public func test_get_value_optional() {
+    public func test_get_value_optional() throws {
         let row = Row(["\"foo\"": 0], ["value"])
-        let result = try! row.get(Expression<String?>("foo"))
+        let result = try row.get(Expression<String?>("foo"))
 
         XCTAssertEqual("value", result)
     }
@@ -31,9 +31,9 @@ class RowTests: XCTestCase {
         XCTAssertEqual("value", result)
     }
 
-    public func test_get_value_optional_nil() {
+    public func test_get_value_optional_nil() throws {
         let row = Row(["\"foo\"": 0], [nil])
-        let result = try! row.get(Expression<String?>("foo"))
+        let result = try row.get(Expression<String?>("foo"))
 
         XCTAssertNil(result)
     }
@@ -56,9 +56,9 @@ class RowTests: XCTestCase {
         }
     }
 
-    public func test_get_type_mismatch_optional_returns_nil() {
+    public func test_get_type_mismatch_optional_returns_nil() throws {
         let row = Row(["\"foo\"": 0], ["value"])
-        let result = try! row.get(Expression<Int?>("foo"))
+        let result = try row.get(Expression<Int?>("foo"))
         XCTAssertNil(result)
     }
 
diff --git a/Tests/SQLiteTests/SelectTests.swift b/Tests/SQLiteTests/SelectTests.swift
index d1126b66..52d5bb6b 100644
--- a/Tests/SQLiteTests/SelectTests.swift
+++ b/Tests/SQLiteTests/SelectTests.swift
@@ -20,7 +20,7 @@ class SelectTests: SQLiteTestCase {
         )
     }
 
-    func test_select_columns_from_multiple_tables() {
+    func test_select_columns_from_multiple_tables() throws {
         let usersData = Table("users_name")
         let users = Table("users")
 
@@ -29,14 +29,14 @@ class SelectTests: SQLiteTestCase {
         let userID = Expression<Int64>("user_id")
         let email = Expression<String>("email")
 
-        try! insertUser("Joey")
-        try! db.run(usersData.insert(
+        try insertUser("Joey")
+        try db.run(usersData.insert(
             id <- 1,
             userID <- 1,
             name <- "Joey"
         ))
 
-        try! db.prepare(users.select(name, email).join(usersData, on: userID == users[id])).forEach {
+        try db.prepare(users.select(name, email).join(usersData, on: userID == users[id])).forEach {
             XCTAssertEqual($0[name], "Joey")
             XCTAssertEqual($0[email], "Joey@example.com")
         }
diff --git a/Tests/SQLiteTests/StatementTests.swift b/Tests/SQLiteTests/StatementTests.swift
index aa05de34..3286b792 100644
--- a/Tests/SQLiteTests/StatementTests.swift
+++ b/Tests/SQLiteTests/StatementTests.swift
@@ -7,30 +7,30 @@ class StatementTests: SQLiteTestCase {
         try createUsersTable()
     }
 
-    func test_cursor_to_blob() {
-        try! insertUsers("alice")
-        let statement = try! db.prepare("SELECT email FROM users")
-        XCTAssert(try! statement.step())
+    func test_cursor_to_blob() throws {
+        try insertUsers("alice")
+        let statement = try db.prepare("SELECT email FROM users")
+        XCTAssert(try statement.step())
         let blob = statement.row[0] as Blob
         XCTAssertEqual("alice@example.com", String(bytes: blob.bytes, encoding: .utf8)!)
     }
 
-    func test_zero_sized_blob_returns_null() {
+    func test_zero_sized_blob_returns_null() throws {
         let blobs = Table("blobs")
         let blobColumn = Expression<Blob>("blob_column")
-        try! db.run(blobs.create { $0.column(blobColumn) })
-        try! db.run(blobs.insert(blobColumn <- Blob(bytes: [])))
-        let blobValue = try! db.scalar(blobs.select(blobColumn).limit(1, offset: 0))
+        try db.run(blobs.create { $0.column(blobColumn) })
+        try db.run(blobs.insert(blobColumn <- Blob(bytes: [])))
+        let blobValue = try db.scalar(blobs.select(blobColumn).limit(1, offset: 0))
         XCTAssertEqual([], blobValue.bytes)
     }
 
-    func test_prepareRowIterator() {
+    func test_prepareRowIterator() throws {
         let names = ["a", "b", "c"]
-        try! insertUsers(names)
+        try insertUsers(names)
 
         let emailColumn = Expression<String>("email")
-        let statement = try! db.prepare("SELECT email FROM users")
-        let emails = try! statement.prepareRowIterator().map { $0[emailColumn] }
+        let statement = try db.prepare("SELECT email FROM users")
+        let emails = try statement.prepareRowIterator().map { $0[emailColumn] }
 
         XCTAssertEqual(names.map({ "\($0)@example.com" }), emails.sorted())
     }
diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index 6e8e9ebb..2a8c7e39 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -54,8 +54,8 @@ class SQLiteTestCase: XCTestCase {
         )
     }
 
-    func assertSQL(_ SQL: String, _ statement: Statement, _ message: String? = nil, file: StaticString = #file, line: UInt = #line) {
-        try! statement.run()
+    func assertSQL(_ SQL: String, _ statement: Statement, _ message: String? = nil, file: StaticString = #file, line: UInt = #line) throws {
+        try statement.run()
         assertSQL(SQL, 1, message, file: file, line: line)
         if let count = trace[SQL] { trace[SQL] = count - 1 }
     }

From 44383dfe5f4d9c4b07a5f921f153e051e82d32a4 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 17 Jul 2022 16:21:17 +0200
Subject: [PATCH 518/685] Fix bundle lookup

---
 Tests/SQLiteTests/Fixtures.swift | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Tests/SQLiteTests/Fixtures.swift b/Tests/SQLiteTests/Fixtures.swift
index f3851cba..1306aa5a 100644
--- a/Tests/SQLiteTests/Fixtures.swift
+++ b/Tests/SQLiteTests/Fixtures.swift
@@ -1,7 +1,11 @@
 import Foundation
 
 func fixture(_ name: String, withExtension: String?) -> String {
+    #if SWIFT_PACKAGE
+    let testBundle = Bundle.module
+    #else
     let testBundle = Bundle(for: SQLiteTestCase.self)
+    #endif
 
     for resource in [name, "fixtures/\(name)"] {
         if let url = testBundle.url(

From 96b014df6095a7434d38950fb819f945d1222191 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 17 Jul 2022 18:14:08 +0200
Subject: [PATCH 519/685] Always enable URI filenames

https://sqlite.org/uri.html
---
 Sources/SQLite/Core/Connection.swift | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 60b9f1bd..35edfce9 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -105,7 +105,10 @@ public final class Connection {
     /// - Returns: A new database connection.
     public init(_ location: Location = .inMemory, readonly: Bool = false) throws {
         let flags = readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE
-        try check(sqlite3_open_v2(location.description, &_handle, flags | SQLITE_OPEN_FULLMUTEX, nil))
+        try check(sqlite3_open_v2(location.description,
+                                  &_handle,
+                                  flags | SQLITE_OPEN_FULLMUTEX | SQLITE_OPEN_URI,
+                                  nil))
         queue.setSpecific(key: Connection.queueKey, value: queueContext)
     }
 

From 41ce3784a0a521aecb309bc7fbc24fa5017a3daf Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 17 Jul 2022 19:06:11 +0200
Subject: [PATCH 520/685] Move fixtures to more default `Resources`

---
 Package.swift                                 |  19 ++++++++++--------
 SQLite.swift.podspec                          |   6 +++---
 SQLite.xcodeproj/project.pbxproj              |  16 +++++++--------
 Sources/SQLite/Core/Connection.swift          |   2 +-
 Tests/SQLiteTests/CipherTests.swift           |  15 +++++++-------
 Tests/SQLiteTests/ConnectionTests.swift       |   9 +++++++--
 Tests/SQLiteTests/Fixtures.swift              |   2 +-
 .../encrypted-3.x.sqlite                      | Bin
 .../encrypted-4.x.sqlite                      | Bin
 .../{fixtures => Resources}/test.sqlite       | Bin
 10 files changed, 39 insertions(+), 30 deletions(-)
 rename Tests/SQLiteTests/{fixtures => Resources}/encrypted-3.x.sqlite (100%)
 rename Tests/SQLiteTests/{fixtures => Resources}/encrypted-4.x.sqlite (100%)
 rename Tests/SQLiteTests/{fixtures => Resources}/test.sqlite (100%)

diff --git a/Package.swift b/Package.swift
index 1130d571..b32fd881 100644
--- a/Package.swift
+++ b/Package.swift
@@ -40,9 +40,7 @@ let package = Package(
                 "Info.plist"
             ],
             resources: [
-                .copy("fixtures/encrypted-3.x.sqlite"),
-                .copy("fixtures/encrypted-4.x.sqlite"),
-                .copy("fixtures/test.sqlite")
+                .copy("Resources")
             ]
         )
     ]
@@ -56,10 +54,15 @@ package.targets = [
         dependencies: [.product(name: "CSQLite", package: "CSQLite")],
         exclude: ["Extensions/FTS4.swift", "Extensions/FTS5.swift"]
     ),
-    .testTarget(name: "SQLiteTests", dependencies: ["SQLite"], path: "Tests/SQLiteTests", exclude: [
-        "FTSIntegrationTests.swift",
-        "FTS4Tests.swift",
-        "FTS5Tests.swift"
-    ])
+    .testTarget(
+        name: "SQLiteTests",
+        dependencies: ["SQLite"],
+        path: "Tests/SQLiteTests", exclude: [
+            "FTSIntegrationTests.swift",
+            "FTS4Tests.swift",
+            "FTS5Tests.swift"
+        ],
+        resources: [ .copy("Resources") ]
+    )
 ]
 #endif
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 4a1787bb..451b4886 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -35,7 +35,7 @@ Pod::Spec.new do |s|
     ss.library = 'sqlite3'
 
     ss.test_spec 'tests' do |test_spec|
-      test_spec.resources = 'Tests/SQLiteTests/fixtures/*'
+      test_spec.resources = 'Tests/SQLiteTests/Resources/*'
       test_spec.source_files = 'Tests/SQLiteTests/*.swift'
       test_spec.ios.deployment_target = ios_deployment_target
       test_spec.tvos.deployment_target = tvos_deployment_target
@@ -55,7 +55,7 @@ Pod::Spec.new do |s|
     ss.dependency 'sqlite3'
 
     ss.test_spec 'tests' do |test_spec|
-      test_spec.resources = 'Tests/SQLiteTests/fixtures/*'
+      test_spec.resources = 'Tests/SQLiteTests/Resources/*'
       test_spec.source_files = 'Tests/SQLiteTests/*.swift'
       test_spec.ios.deployment_target = ios_deployment_target
       test_spec.tvos.deployment_target = tvos_deployment_target
@@ -73,7 +73,7 @@ Pod::Spec.new do |s|
     ss.dependency 'SQLCipher', '>= 4.0.0'
 
     ss.test_spec 'tests' do |test_spec|
-      test_spec.resources = 'Tests/SQLiteTests/fixtures/*'
+      test_spec.resources = 'Tests/SQLiteTests/Resources/*'
       test_spec.source_files = 'Tests/SQLiteTests/*.swift'
       test_spec.ios.deployment_target = ios_deployment_target
       test_spec.tvos.deployment_target = tvos_deployment_target
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 4e01067f..45e6ea63 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -68,7 +68,6 @@
 		19A17490543609FCED53CACC /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
 		19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
 		19A1750CEE9B05267995CF3D /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
-		19A175DFF47B84757E547C62 /* fixtures in Resources */ = {isa = PBXBuildFile; fileRef = 19A17E2695737FAB5D6086E3 /* fixtures */; };
 		19A176376CB6A94759F7980A /* Connection+Aggregation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */; };
 		19A176406BDE9D9C80CC9FA3 /* QueryIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */; };
 		19A1769C1F3A7542BECF50FF /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */; };
@@ -92,10 +91,8 @@
 		19A17E29278A12BC4F542506 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
 		19A17EC0D68BA8C03288ADF7 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
 		19A17F1B3F0A3C96B5ED6D64 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17E723300E5ED3771DCB5 /* Result.swift */; };
-		19A17F3E1F7ACA33BD43E138 /* fixtures in Resources */ = {isa = PBXBuildFile; fileRef = 19A17E2695737FAB5D6086E3 /* fixtures */; };
 		19A17F60B685636D1F83C2DD /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; };
 		19A17FB80B94E882050AA908 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
-		19A17FDA323BAFDEC627E76F /* fixtures in Resources */ = {isa = PBXBuildFile; fileRef = 19A17E2695737FAB5D6086E3 /* fixtures */; };
 		19A17FF4A10B44D3937C8CAC /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
 		3717F908221F5D8800B9BD3D /* CustomAggregationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */; };
 		3717F909221F5D8900B9BD3D /* CustomAggregationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */; };
@@ -137,6 +134,9 @@
 		3DF7B792288449BA005DD8CA /* URIQueryParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B790288449BA005DD8CA /* URIQueryParameter.swift */; };
 		3DF7B793288449BA005DD8CA /* URIQueryParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B790288449BA005DD8CA /* URIQueryParameter.swift */; };
 		3DF7B794288449BA005DD8CA /* URIQueryParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B790288449BA005DD8CA /* URIQueryParameter.swift */; };
+		3DF7B79628846FCC005DD8CA /* Resources in Resources */ = {isa = PBXBuildFile; fileRef = 3DF7B79528846FCC005DD8CA /* Resources */; };
+		3DF7B79828846FED005DD8CA /* Resources in Resources */ = {isa = PBXBuildFile; fileRef = 3DF7B79528846FCC005DD8CA /* Resources */; };
+		3DF7B79928847055005DD8CA /* Resources in Resources */ = {isa = PBXBuildFile; fileRef = 3DF7B79528846FCC005DD8CA /* Resources */; };
 		49EB68C41F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
 		49EB68C51F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
 		49EB68C61F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
@@ -267,7 +267,6 @@
 		19A17B93B48B5560E6E51791 /* Fixtures.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Fixtures.swift; sourceTree = "<group>"; };
 		19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAndTimeFunctions.swift; sourceTree = "<group>"; };
 		19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryIntegrationTests.swift; sourceTree = "<group>"; };
-		19A17E2695737FAB5D6086E3 /* fixtures */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = folder; path = fixtures; sourceTree = "<group>"; };
 		19A17E723300E5ED3771DCB5 /* Result.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Result.swift; sourceTree = "<group>"; };
 		19A17EA3A313F129011B3FA0 /* Release.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Release.md; sourceTree = "<group>"; };
 		3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomAggregationTests.swift; sourceTree = "<group>"; };
@@ -277,6 +276,7 @@
 		3DF7B78728842972005DD8CA /* Connection+Attach.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Connection+Attach.swift"; sourceTree = "<group>"; };
 		3DF7B78C28842C23005DD8CA /* ResultTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultTests.swift; sourceTree = "<group>"; };
 		3DF7B790288449BA005DD8CA /* URIQueryParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URIQueryParameter.swift; sourceTree = "<group>"; };
+		3DF7B79528846FCC005DD8CA /* Resources */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Resources; sourceTree = "<group>"; };
 		49EB68C31F7B3CB400D89D40 /* Coding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coding.swift; sourceTree = "<group>"; };
 		997DF2AD287FC06D00F8DF95 /* Query+with.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Query+with.swift"; sourceTree = "<group>"; };
 		A121AC451CA35C79005A31D1 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -448,7 +448,7 @@
 		EE247AE11C3F04ED00AE3E12 /* SQLiteTests */ = {
 			isa = PBXGroup;
 			children = (
-				19A17E2695737FAB5D6086E3 /* fixtures */,
+				3DF7B79528846FCC005DD8CA /* Resources */,
 				EE247B1A1C3F137700AE3E12 /* AggregateFunctionsTests.swift */,
 				EE247B1B1C3F137700AE3E12 /* BlobTests.swift */,
 				EE247B1D1C3F137700AE3E12 /* ConnectionTests.swift */,
@@ -812,7 +812,7 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				19A17F3E1F7ACA33BD43E138 /* fixtures in Resources */,
+				3DF7B79828846FED005DD8CA /* Resources in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -834,7 +834,7 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				19A17FDA323BAFDEC627E76F /* fixtures in Resources */,
+				3DF7B79628846FCC005DD8CA /* Resources in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -849,7 +849,7 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				19A175DFF47B84757E547C62 /* fixtures in Resources */,
+				3DF7B79928847055005DD8CA /* Resources in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 35edfce9..68b83821 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -104,7 +104,7 @@ public final class Connection {
     ///
     /// - Returns: A new database connection.
     public init(_ location: Location = .inMemory, readonly: Bool = false) throws {
-        let flags = readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE
+        let flags = readonly ? SQLITE_OPEN_READONLY : (SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE)
         try check(sqlite3_open_v2(location.description,
                                   &_handle,
                                   flags | SQLITE_OPEN_FULLMUTEX | SQLITE_OPEN_URI,
diff --git a/Tests/SQLiteTests/CipherTests.swift b/Tests/SQLiteTests/CipherTests.swift
index f25dbe5b..e2d09901 100644
--- a/Tests/SQLiteTests/CipherTests.swift
+++ b/Tests/SQLiteTests/CipherTests.swift
@@ -4,12 +4,13 @@ import SQLite
 import SQLCipher
 
 class CipherTests: XCTestCase {
-
-    let db1 = try Connection()
-    let db2 = try Connection()
+    var db1: Connection!
+    var db2: Connection!
 
     override func setUpWithError() throws {
-        // db
+        db1 = try Connection()
+        db2 = try Connection()
+        // db1
 
         try db1.key("hello")
 
@@ -30,7 +31,7 @@ class CipherTests: XCTestCase {
         XCTAssertEqual(1, try db1.scalar("SELECT count(*) FROM foo") as? Int64)
     }
 
-    func test_key_blob_literal() {
+    func test_key_blob_literal() throws {
         let db = try Connection()
         try db.key("x'2DD29CA851E7B56E4697B0E1F08507293D761A05CE4D1B628663F411A8086D99'")
     }
@@ -55,7 +56,7 @@ class CipherTests: XCTestCase {
         _ = try? FileManager.default.removeItem(atPath: path)
 
         let connA = try Connection(path)
-        defer { try FileManager.default.removeItem(atPath: path) }
+        defer { try? FileManager.default.removeItem(atPath: path) }
 
         try connA.key("hello")
         try connA.run("CREATE TABLE foo (bar TEXT)")
@@ -90,7 +91,7 @@ class CipherTests: XCTestCase {
 
         defer {
             // ensure file can be cleaned up afterwards
-            try FileManager.default.setAttributes([FileAttributeKey.immutable: 0], ofItemAtPath: encryptedFile)
+            try? FileManager.default.setAttributes([FileAttributeKey.immutable: 0], ofItemAtPath: encryptedFile)
         }
 
         let conn = try Connection(encryptedFile)
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/ConnectionTests.swift
index cf51c104..347516f5 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/ConnectionTests.swift
@@ -47,12 +47,17 @@ class ConnectionTests: SQLiteTestCase {
         XCTAssertEqual(url.lastPathComponent, "SQLite.swift Tests.sqlite3")
     }
 
-    func testLocationWithoutUriParameters() {
+    func test_init_with_Uri_and_Parameters() throws {
+        let testDb = fixture("test", withExtension: "sqlite")
+        _ = try Connection(.uri(testDb, parameters: [.cache(.shared)]))
+    }
+
+    func test_location_without_Uri_parameters() {
         let location: Connection.Location = .uri("foo")
         XCTAssertEqual(location.description, "foo")
     }
 
-    func testLocationWithUriParameters() {
+    func test_location_with_Uri_parameters() {
         let location: Connection.Location = .uri("foo", parameters: [.mode(.readOnly), .cache(.private)])
         XCTAssertEqual(location.description, "file:foo?mode=ro&cache=private")
     }
diff --git a/Tests/SQLiteTests/Fixtures.swift b/Tests/SQLiteTests/Fixtures.swift
index 1306aa5a..95b2b6dc 100644
--- a/Tests/SQLiteTests/Fixtures.swift
+++ b/Tests/SQLiteTests/Fixtures.swift
@@ -7,7 +7,7 @@ func fixture(_ name: String, withExtension: String?) -> String {
     let testBundle = Bundle(for: SQLiteTestCase.self)
     #endif
 
-    for resource in [name, "fixtures/\(name)"] {
+    for resource in [name, "Resources/\(name)"] {
         if let url = testBundle.url(
             forResource: resource,
             withExtension: withExtension) {
diff --git a/Tests/SQLiteTests/fixtures/encrypted-3.x.sqlite b/Tests/SQLiteTests/Resources/encrypted-3.x.sqlite
similarity index 100%
rename from Tests/SQLiteTests/fixtures/encrypted-3.x.sqlite
rename to Tests/SQLiteTests/Resources/encrypted-3.x.sqlite
diff --git a/Tests/SQLiteTests/fixtures/encrypted-4.x.sqlite b/Tests/SQLiteTests/Resources/encrypted-4.x.sqlite
similarity index 100%
rename from Tests/SQLiteTests/fixtures/encrypted-4.x.sqlite
rename to Tests/SQLiteTests/Resources/encrypted-4.x.sqlite
diff --git a/Tests/SQLiteTests/fixtures/test.sqlite b/Tests/SQLiteTests/Resources/test.sqlite
similarity index 100%
rename from Tests/SQLiteTests/fixtures/test.sqlite
rename to Tests/SQLiteTests/Resources/test.sqlite

From 9023fbc52ba86e0b002275698f071efa6eaeb899 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 18 Jul 2022 00:44:53 +0200
Subject: [PATCH 521/685] Add documenation, update changelog

---
 CHANGELOG.md                                | 24 ++++++++++++++++
 Documentation/Index.md                      | 32 ++++++++++++++++++++-
 SQLite.xcodeproj/project.pbxproj            |  2 ++
 Sources/SQLite/Core/URIQueryParameter.swift |  5 ++--
 4 files changed, 60 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 786084f8..210e324d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,15 @@
+0.14.0 (tbd), [diff][diff-0.14.0]
+========================================
+
+* Support ATTACH/DETACH ([#30][], [##1142][])
+* Support WITH clause ([#1139][])
+* Add value conformance for NSURL ([#1141][])
+* Add decoding for UUID ([#1137][])
+* Fix insertMany([Encodable]) ([#1130][], [#1138]][])
+* Fix incorrect spelling of 'remove_diacritics' ([#1128][])
+* Fix project build order ([#1131][])
+* Performance improvements ([#1109][], [#1115][], [#1132][])
+
 0.13.3 (25-01-2022), [diff][diff-0.13.3]
 ========================================
 
@@ -110,7 +122,9 @@
 [diff-0.13.1]: https://github.com/stephencelis/SQLite.swift/compare/0.13.0...0.13.1
 [diff-0.13.2]: https://github.com/stephencelis/SQLite.swift/compare/0.13.1...0.13.2
 [diff-0.13.3]: https://github.com/stephencelis/SQLite.swift/compare/0.13.2...0.13.3
+[diff-0.14.0]: https://github.com/stephencelis/SQLite.swift/compare/0.13.3...0.14.0
 
+[#30]: https://github.com/stephencelis/SQLite.swift/issues/30
 [#142]: https://github.com/stephencelis/SQLite.swift/issues/142
 [#315]: https://github.com/stephencelis/SQLite.swift/issues/315
 [#426]: https://github.com/stephencelis/SQLite.swift/pull/426
@@ -150,6 +164,16 @@
 [#1095]: https://github.com/stephencelis/SQLite.swift/pull/1095
 [#1100]: https://github.com/stephencelis/SQLite.swift/pull/1100
 [#1105]: https://github.com/stephencelis/SQLite.swift/pull/1105
+[#1109]: https://github.com/stephencelis/SQLite.swift/issues/1109
 [#1112]: https://github.com/stephencelis/SQLite.swift/pull/1112
+[#1115]: https://github.com/stephencelis/SQLite.swift/pull/1115
 [#1119]: https://github.com/stephencelis/SQLite.swift/pull/1119
 [#1121]: https://github.com/stephencelis/SQLite.swift/pull/1121
+[#1128]: https://github.com/stephencelis/SQLite.swift/issues/1128
+[#1130]: https://github.com/stephencelis/SQLite.swift/issues/1130
+[#1131]: https://github.com/stephencelis/SQLite.swift/pull/1131
+[#1132]: https://github.com/stephencelis/SQLite.swift/pull/1132
+[#1137]: https://github.com/stephencelis/SQLite.swift/pull/1137
+[#1138]: https://github.com/stephencelis/SQLite.swift/pull/1138
+[#1139]: https://github.com/stephencelis/SQLite.swift/pull/1139
+[#1142]: https://github.com/stephencelis/SQLite.swift/pull/1142
diff --git a/Documentation/Index.md b/Documentation/Index.md
index 7a9a390f..aded5739 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -10,6 +10,7 @@
       - [Read-Write Databases](#read-write-databases)
       - [Read-Only Databases](#read-only-databases)
       - [In-Memory Databases](#in-memory-databases)
+      - [URI parameters](#uri-parameters)
       - [Thread-Safety](#thread-safety)
   - [Building Type-Safe SQL](#building-type-safe-sql)
     - [Expressions](#expressions)
@@ -61,9 +62,9 @@
   - [Custom Collations](#custom-collations)
   - [Full-text Search](#full-text-search)
   - [Executing Arbitrary SQL](#executing-arbitrary-sql)
+  - [Attaching and detaching databases](#attaching-and-detaching-databases)
   - [Logging](#logging)
 
-
 [↩]: #sqliteswift-documentation
 
 
@@ -334,6 +335,16 @@ let db = try Connection(.temporary)
 In-memory databases are automatically deleted when the database connection is
 closed.
 
+#### URI parameters
+
+We can pass `.uri` to the `Connection` initializer to control more aspects of
+the database connection with the help of `URIQueryParameter`s:
+
+```swift
+let db = try Connection(.uri("file.sqlite", parameters: [.cache(.private)], .noLock(true)]))
+```
+
+See [Uniform Resource Identifiers](https://www.sqlite.org/uri.html) for more details.
 
 #### Thread-Safety
 
@@ -2070,6 +2081,25 @@ let backup = try db.backup(usingConnection: target)
 try backup.step()
 ```
 
+## Attaching and detaching databases
+
+We can [ATTACH](https://www3.sqlite.org/lang_attach.html) and [DETACH](https://www3.sqlite.org/lang_detach.html)
+databases to an existing connection:
+
+```swift
+let db = try Connection("db.sqlite")
+
+try db.attach(.uri("external.sqlite", parameters: [.mode(.readOnly)), as: "external")
+// ATTACH DATABASE 'file:external.sqlite?mode=ro' AS 'external'
+
+let table = Table("table", database: "external")
+let count = try db.scalar(table.count)
+// SELECT count(*) FROM 'external.table'
+
+try db.detach("external")
+// DETACH DATABASE 'external'
+```
+
 ## Logging
 
 We can log SQL using the database’s `trace` function.
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 45e6ea63..064357a2 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -277,6 +277,7 @@
 		3DF7B78C28842C23005DD8CA /* ResultTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultTests.swift; sourceTree = "<group>"; };
 		3DF7B790288449BA005DD8CA /* URIQueryParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URIQueryParameter.swift; sourceTree = "<group>"; };
 		3DF7B79528846FCC005DD8CA /* Resources */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Resources; sourceTree = "<group>"; };
+		3DF7B79A2884C353005DD8CA /* CHANGELOG.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = "<group>"; };
 		49EB68C31F7B3CB400D89D40 /* Coding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coding.swift; sourceTree = "<group>"; };
 		997DF2AD287FC06D00F8DF95 /* Query+with.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Query+with.swift"; sourceTree = "<group>"; };
 		A121AC451CA35C79005A31D1 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -534,6 +535,7 @@
 			isa = PBXGroup;
 			children = (
 				EE247B771C3F40D700AE3E12 /* README.md */,
+				3DF7B79A2884C353005DD8CA /* CHANGELOG.md */,
 				EE247B8B1C3F820300AE3E12 /* CONTRIBUTING.md */,
 				EE247B931C3F826100AE3E12 /* SQLite.swift.podspec */,
 				EE247B8D1C3F821200AE3E12 /* Makefile */,
diff --git a/Sources/SQLite/Core/URIQueryParameter.swift b/Sources/SQLite/Core/URIQueryParameter.swift
index c82a7cf7..abbab2e7 100644
--- a/Sources/SQLite/Core/URIQueryParameter.swift
+++ b/Sources/SQLite/Core/URIQueryParameter.swift
@@ -1,5 +1,6 @@
 import Foundation
 
+/// See https://www.sqlite.org/uri.html
 public enum URIQueryParameter: CustomStringConvertible {
     public enum FileMode: String {
         case readOnly = "ro", readWrite = "rw", readWriteCreate = "rwc", memory
@@ -29,7 +30,7 @@ public enum URIQueryParameter: CustomStringConvertible {
     case nolock(Bool)
 
     /// The psow query parameter overrides the `powersafe_overwrite` property of the database file being opened.
-    case psow(Bool)
+    case powersafeOverwrite(Bool)
 
     /// The vfs query parameter causes the database connection to be opened using the VFS called NAME.
     case vfs(String)
@@ -45,7 +46,7 @@ public enum URIQueryParameter: CustomStringConvertible {
         case .modeOf(let filename): return .init(name: "modeOf", value: filename)
         case .mode(let fileMode): return .init(name: "mode", value: fileMode.rawValue)
         case .nolock(let bool): return .init(name: "nolock", value: NSNumber(value: bool).description)
-        case .psow(let bool): return .init(name: "psow", value: NSNumber(value: bool).description)
+        case .powersafeOverwrite(let bool): return .init(name: "psow", value: NSNumber(value: bool).description)
         case .vfs(let name): return .init(name: "vfs", value: name)
         }
     }

From 2eed2003e548630a3116a6d0fb850a341e3405a9 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 18 Jul 2022 00:55:40 +0200
Subject: [PATCH 522/685] Fix doc errors

---
 CHANGELOG.md                     | 16 +++++++++-------
 Documentation/Index.md           |  6 +++---
 Documentation/Planning.md        |  2 --
 SQLite.xcodeproj/project.pbxproj |  2 ++
 4 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 210e324d..37e96955 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,16 +1,16 @@
 0.14.0 (tbd), [diff][diff-0.14.0]
 ========================================
 
-* Support ATTACH/DETACH ([#30][], [##1142][])
-* Support WITH clause ([#1139][])
-* Add value conformance for NSURL ([#1141][])
-* Add decoding for UUID ([#1137][])
-* Fix insertMany([Encodable]) ([#1130][], [#1138]][])
-* Fix incorrect spelling of 'remove_diacritics' ([#1128][])
+* Support `ATTACH`/`DETACH` ([#30][], [#1142][])
+* Support `WITH` clause ([#1139][])
+* Add `Value` conformance for `NSURL` ([#1110][], [#1141][])
+* Add decoding for `UUID` ([#1137][])
+* Fix `insertMany([Encodable])` ([#1130][], [#1138][])
+* Fix incorrect spelling of `remove_diacritics` ([#1128][])
 * Fix project build order ([#1131][])
 * Performance improvements ([#1109][], [#1115][], [#1132][])
 
-0.13.3 (25-01-2022), [diff][diff-0.13.3]
+0.13.3 (27-03-2022), [diff][diff-0.13.3]
 ========================================
 
 * UUID Fix ([#1112][])
@@ -165,6 +165,7 @@
 [#1100]: https://github.com/stephencelis/SQLite.swift/pull/1100
 [#1105]: https://github.com/stephencelis/SQLite.swift/pull/1105
 [#1109]: https://github.com/stephencelis/SQLite.swift/issues/1109
+[#1110]: https://github.com/stephencelis/SQLite.swift/pull/1110
 [#1112]: https://github.com/stephencelis/SQLite.swift/pull/1112
 [#1115]: https://github.com/stephencelis/SQLite.swift/pull/1115
 [#1119]: https://github.com/stephencelis/SQLite.swift/pull/1119
@@ -176,4 +177,5 @@
 [#1137]: https://github.com/stephencelis/SQLite.swift/pull/1137
 [#1138]: https://github.com/stephencelis/SQLite.swift/pull/1138
 [#1139]: https://github.com/stephencelis/SQLite.swift/pull/1139
+[#1141]: https://github.com/stephencelis/SQLite.swift/pull/1141
 [#1142]: https://github.com/stephencelis/SQLite.swift/pull/1142
diff --git a/Documentation/Index.md b/Documentation/Index.md
index aded5739..f036520f 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -341,10 +341,10 @@ We can pass `.uri` to the `Connection` initializer to control more aspects of
 the database connection with the help of `URIQueryParameter`s:
 
 ```swift
-let db = try Connection(.uri("file.sqlite", parameters: [.cache(.private)], .noLock(true)]))
+let db = try Connection(.uri("file.sqlite", parameters: [.cache(.private), .noLock(true)]))
 ```
 
-See [Uniform Resource Identifiers](https://www.sqlite.org/uri.html) for more details.
+See [Uniform Resource Identifiers](https://www.sqlite.org/uri.html#recognized_query_parameters) for more details.
 
 #### Thread-Safety
 
@@ -2089,7 +2089,7 @@ databases to an existing connection:
 ```swift
 let db = try Connection("db.sqlite")
 
-try db.attach(.uri("external.sqlite", parameters: [.mode(.readOnly)), as: "external")
+try db.attach(.uri("external.sqlite", parameters: [.mode(.readOnly)], as: "external")
 // ATTACH DATABASE 'file:external.sqlite?mode=ro' AS 'external'
 
 let table = Table("table", database: "external")
diff --git a/Documentation/Planning.md b/Documentation/Planning.md
index 0dea6d71..6067b81e 100644
--- a/Documentation/Planning.md
+++ b/Documentation/Planning.md
@@ -21,8 +21,6 @@ be referred to when it comes time to add the corresponding feature._
 
 ### Features
 
- * encapsulate ATTACH DATABASE / DETACH DATABASE as methods, per
-   [#30](https://github.com/stephencelis/SQLite.swift/issues/30)
  * provide separate threads for update vs read, so updates don't block reads,
    per [#236](https://github.com/stephencelis/SQLite.swift/issues/236)
  * expose triggers, per
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 064357a2..45ff075f 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -278,6 +278,7 @@
 		3DF7B790288449BA005DD8CA /* URIQueryParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URIQueryParameter.swift; sourceTree = "<group>"; };
 		3DF7B79528846FCC005DD8CA /* Resources */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Resources; sourceTree = "<group>"; };
 		3DF7B79A2884C353005DD8CA /* CHANGELOG.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = "<group>"; };
+		3DF7B79B2884C901005DD8CA /* Planning.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Planning.md; sourceTree = "<group>"; };
 		49EB68C31F7B3CB400D89D40 /* Coding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coding.swift; sourceTree = "<group>"; };
 		997DF2AD287FC06D00F8DF95 /* Query+with.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Query+with.swift"; sourceTree = "<group>"; };
 		A121AC451CA35C79005A31D1 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -551,6 +552,7 @@
 			isa = PBXGroup;
 			children = (
 				EE247B8F1C3F822500AE3E12 /* Index.md */,
+				3DF7B79B2884C901005DD8CA /* Planning.md */,
 				EE247B901C3F822500AE3E12 /* Resources */,
 				19A17EA3A313F129011B3FA0 /* Release.md */,
 				19A1794B7972D14330A65BBD /* Linux.md */,

From 0af0e4d55e7571bc5a53bb10f12e0669fdf0470e Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 18 Jul 2022 01:03:57 +0200
Subject: [PATCH 523/685] More supported types

---
 Documentation/Index.md | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index f036520f..0930aab0 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -383,6 +383,9 @@ to their [SQLite counterparts](https://www.sqlite.org/datatype3.html).
 | `String`        | `TEXT`      |
 | `nil`           | `NULL`      |
 | `SQLite.Blob`†  | `BLOB`      |
+| `URL`           | `TEXT`      |
+| `UUID`          | `TEXT`      |
+| `Date`          | `TEXT`      |
 
 > *While `Int64` is the basic, raw type (to preserve 64-bit integers on
 > 32-bit platforms), `Int` and `Bool` work transparently.

From 7868fdfcf606c2aaf18fb0471393234113b537a5 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 18 Jul 2022 01:22:27 +0200
Subject: [PATCH 524/685] Fix doc

---
 Documentation/Index.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 0930aab0..75c1d2cc 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1103,8 +1103,8 @@ users.limit(5, offset: 5)
 
 #### Recursive and Hierarchical Queries
 
-We can perform a recursive or hierarchical query using a [query's](#queries) `with`
-function.
+We can perform a recursive or hierarchical query using a [query's](#queries)
+[`WITH`](https://sqlite.org/lang_with.html) function.
 
 ```swift
 // Get the management chain for the manager with id == 8
@@ -2092,7 +2092,7 @@ databases to an existing connection:
 ```swift
 let db = try Connection("db.sqlite")
 
-try db.attach(.uri("external.sqlite", parameters: [.mode(.readOnly)], as: "external")
+try db.attach(.uri("external.sqlite", parameters: [.mode(.readOnly)]), as: "external")
 // ATTACH DATABASE 'file:external.sqlite?mode=ro' AS 'external'
 
 let table = Table("table", database: "external")

From be14b42fc71f3c3e8cd977d858ecfe593a168434 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 17 Jul 2022 12:45:04 +0200
Subject: [PATCH 525/685] Add sqlcipher_export

---
 CHANGELOG.md                                |  2 ++
 Documentation/Index.md                      | 11 +++++++++--
 Sources/SQLite/Core/Connection+Attach.swift | 12 ++++++++++-
 Sources/SQLite/Extensions/Cipher.swift      | 22 +++++++++++++++++++--
 Tests/SQLiteTests/CipherTests.swift         |  9 +++++++++
 Tests/SQLiteTests/Fixtures.swift            |  4 ++++
 6 files changed, 55 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 37e96955..eb7213c1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,7 @@
 * Support `WITH` clause ([#1139][])
 * Add `Value` conformance for `NSURL` ([#1110][], [#1141][])
 * Add decoding for `UUID` ([#1137][])
+* SQLCipher: improve documentation ([#1098][]), add `sqlcipher_export`
 * Fix `insertMany([Encodable])` ([#1130][], [#1138][])
 * Fix incorrect spelling of `remove_diacritics` ([#1128][])
 * Fix project build order ([#1131][])
@@ -162,6 +163,7 @@
 [#1077]: https://github.com/stephencelis/SQLite.swift/issues/1077
 [#1094]: https://github.com/stephencelis/SQLite.swift/pull/1094
 [#1095]: https://github.com/stephencelis/SQLite.swift/pull/1095
+[#1098]: https://github.com/stephencelis/SQLite.swift/issues/1098
 [#1100]: https://github.com/stephencelis/SQLite.swift/pull/1100
 [#1105]: https://github.com/stephencelis/SQLite.swift/pull/1105
 [#1109]: https://github.com/stephencelis/SQLite.swift/issues/1109
diff --git a/Documentation/Index.md b/Documentation/Index.md
index 75c1d2cc..dd832ee2 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -184,9 +184,16 @@ extend `Connection` with methods to change the database key:
 ```swift
 import SQLite
 
-let db = try Connection("path/to/db.sqlite3")
+let db = try Connection("path/to/encrypted.sqlite3")
 try db.key("secret")
-try db.rekey("another secret")
+try db.rekey("new secret") // changes encryption key on already encrypted db
+```
+
+To encrypt an existing database:
+
+```swift
+let db = try Connection("path/to/unencrypted.sqlite3")
+try db.sqlcipher_export(.uri("encrypted.sqlite3"), key: "secret")
 ```
 
 [CocoaPods]: https://cocoapods.org
diff --git a/Sources/SQLite/Core/Connection+Attach.swift b/Sources/SQLite/Core/Connection+Attach.swift
index b9c08117..47e6af5e 100644
--- a/Sources/SQLite/Core/Connection+Attach.swift
+++ b/Sources/SQLite/Core/Connection+Attach.swift
@@ -10,11 +10,21 @@ import SQLite3
 #endif
 
 extension Connection {
-
+    #if SQLITE_SWIFT_SQLCIPHER
+    /// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#attach
+    public func attach(_ location: Location, as schemaName: String, key: String? = nil) throws {
+        if let key = key {
+            try run("ATTACH DATABASE ? AS ? KEY ?", location.description, schemaName, key)
+        } else {
+            try run("ATTACH DATABASE ? AS ?", location.description, schemaName)
+        }
+    }
+    #else
     /// See  https://www3.sqlite.org/lang_attach.html
     public func attach(_ location: Location, as schemaName: String) throws {
         try run("ATTACH DATABASE ? AS ?", location.description, schemaName)
     }
+    #endif
 
     /// See https://www3.sqlite.org/lang_detach.html
     public func detach(_ schemaName: String) throws {
diff --git a/Sources/SQLite/Extensions/Cipher.swift b/Sources/SQLite/Extensions/Cipher.swift
index b96c2761..8af04df9 100644
--- a/Sources/SQLite/Extensions/Cipher.swift
+++ b/Sources/SQLite/Extensions/Cipher.swift
@@ -6,6 +6,8 @@ import SQLCipher
 extension Connection {
 
     /// - Returns: the SQLCipher version
+    ///
+    /// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_version
     public var cipherVersion: String? {
         (try? scalar("PRAGMA cipher_version")) as? String
     }
@@ -23,6 +25,8 @@ extension Connection {
     ///            of key data.
     ///            e.g. x'2DD29CA851E7B56E4697B0E1F08507293D761A05CE4D1B628663F411A8086D99'
     /// @param db name of the database, defaults to 'main'
+    ///
+    /// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#sqlite3_key
     public func key(_ key: String, db: String = "main") throws {
         try _key_v2(db: db, keyPointer: key, keySize: key.utf8.count)
     }
@@ -39,6 +43,7 @@ extension Connection {
     /// As "PRAGMA cipher_migrate;" is time-consuming, it is recommended to use this function
     /// only after failure of `key(_ key: String, db: String = "main")`, if older versions of
     /// your app may ise older version of SQLCipher
+    ///
     /// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_migrate
     /// and https://discuss.zetetic.net/t/upgrading-to-sqlcipher-4/3283
     /// for more details regarding SQLCipher upgrade
@@ -51,11 +56,13 @@ extension Connection {
         try _key_v2(db: db, keyPointer: key.bytes, keySize: key.bytes.count, migrate: true)
     }
 
-    /// Change the key on an open database.  If the current database is not encrypted, this routine
-    /// will encrypt it.
+    /// Change the key on an open database. NB: only works if the database is already encrypted.
+    ///
     /// To change the key on an existing encrypted database, it must first be unlocked with the
     /// current encryption key. Once the database is readable and writeable, rekey can be used
     /// to re-encrypt every page in the database with a new key.
+    ///
+    /// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#sqlite3_rekey
     public func rekey(_ key: String, db: String = "main") throws {
         try _rekey_v2(db: db, keyPointer: key, keySize: key.utf8.count)
     }
@@ -64,6 +71,17 @@ extension Connection {
         try _rekey_v2(db: db, keyPointer: key.bytes, keySize: key.bytes.count)
     }
 
+    /// Converts a non-encrypted database to an encrypted one.
+    ///
+    /// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#sqlcipher_export
+    public func sqlcipher_export(_ location: Location, key: String) throws {
+        let schemaName = "cipher_export"
+
+        try attach(location, as: schemaName, key: key)
+        try run("SELECT sqlcipher_export(?)", schemaName)
+        try detach(schemaName)
+    }
+
     // MARK: - private
     private func _key_v2(db: String,
                          keyPointer: UnsafePointer<UInt8>,
diff --git a/Tests/SQLiteTests/CipherTests.swift b/Tests/SQLiteTests/CipherTests.swift
index e2d09901..cc43272e 100644
--- a/Tests/SQLiteTests/CipherTests.swift
+++ b/Tests/SQLiteTests/CipherTests.swift
@@ -99,6 +99,15 @@ class CipherTests: XCTestCase {
         XCTAssertEqual(1, try conn.scalar("SELECT count(*) FROM foo") as? Int64)
     }
 
+    func test_export() throws {
+        let tmp = temporaryFile()
+        try db1.sqlcipher_export(.uri(tmp), key: "mykey")
+
+        let conn = try Connection(tmp)
+        try conn.key("mykey")
+        XCTAssertEqual(1, try conn.scalar("SELECT count(*) FROM foo") as? Int64)
+    }
+
     private func keyData(length: Int = 64) -> NSMutableData {
         let keyData = NSMutableData(length: length)!
         let result  = SecRandomCopyBytes(kSecRandomDefault, length,
diff --git a/Tests/SQLiteTests/Fixtures.swift b/Tests/SQLiteTests/Fixtures.swift
index 95b2b6dc..bd261d2c 100644
--- a/Tests/SQLiteTests/Fixtures.swift
+++ b/Tests/SQLiteTests/Fixtures.swift
@@ -16,3 +16,7 @@ func fixture(_ name: String, withExtension: String?) -> String {
     }
     fatalError("Cannot find \(name).\(withExtension ?? "")")
 }
+
+func temporaryFile() -> String {
+    URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString).path
+}

From ceb13aa1adc8b05fd5d8ccb29cf1af97c79ebd1d Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 19 Jul 2022 01:13:28 +0200
Subject: [PATCH 526/685] Document changes

---
 CHANGELOG.md           | 3 ++-
 Documentation/Index.md | 7 +++++++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index eb7213c1..68a5133f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,7 +5,7 @@
 * Support `WITH` clause ([#1139][])
 * Add `Value` conformance for `NSURL` ([#1110][], [#1141][])
 * Add decoding for `UUID` ([#1137][])
-* SQLCipher: improve documentation ([#1098][]), add `sqlcipher_export`
+* SQLCipher: improve documentation ([#1098][]), add `sqlcipher_export` ([#1101][])
 * Fix `insertMany([Encodable])` ([#1130][], [#1138][])
 * Fix incorrect spelling of `remove_diacritics` ([#1128][])
 * Fix project build order ([#1131][])
@@ -165,6 +165,7 @@
 [#1095]: https://github.com/stephencelis/SQLite.swift/pull/1095
 [#1098]: https://github.com/stephencelis/SQLite.swift/issues/1098
 [#1100]: https://github.com/stephencelis/SQLite.swift/pull/1100
+[#1101]: https://github.com/stephencelis/SQLite.swift/issues/1101
 [#1105]: https://github.com/stephencelis/SQLite.swift/pull/1105
 [#1109]: https://github.com/stephencelis/SQLite.swift/issues/1109
 [#1110]: https://github.com/stephencelis/SQLite.swift/pull/1110
diff --git a/Documentation/Index.md b/Documentation/Index.md
index dd832ee2..96fc1ee1 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -2110,6 +2110,13 @@ try db.detach("external")
 // DETACH DATABASE 'external'
 ```
 
+When compiled for SQLCipher, you can additionally pass a `key` parameter to `attach`:
+
+```swift
+try db.attach(.uri("encrypted.sqlite"), as: "encrypted", key: "secret")
+// ATTACH DATABASE 'encrypted.sqlite' AS 'encrypted' KEY 'secret'
+```
+
 ## Logging
 
 We can log SQL using the database’s `trace` function.

From 136c8a8c4358255fc921be5b1f3148acc514ee36 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 19 Jul 2022 13:01:26 +0200
Subject: [PATCH 527/685] Remove FTS4 Tokenizer / SQLiteObjc

 Closes #1104
---
 Package.swift                           |  11 +-
 SQLite.xcodeproj/project.pbxproj        |  38 +-----
 Sources/SQLite/Extensions/FTS4.swift    |  27 ----
 Sources/SQLite/SQLite.h                 |   2 -
 Sources/SQLiteObjc/SQLiteObjc.m         | 138 --------------------
 Sources/SQLiteObjc/fts3_tokenizer.h     | 161 ------------------------
 Sources/SQLiteObjc/include/SQLiteObjc.h |  38 ------
 Tests/SQLiteTests/FTS4Tests.swift       |  37 ------
 8 files changed, 7 insertions(+), 445 deletions(-)
 delete mode 100644 Sources/SQLiteObjc/SQLiteObjc.m
 delete mode 100644 Sources/SQLiteObjc/fts3_tokenizer.h
 delete mode 100644 Sources/SQLiteObjc/include/SQLiteObjc.h

diff --git a/Package.swift b/Package.swift
index b32fd881..ab9cbd43 100644
--- a/Package.swift
+++ b/Package.swift
@@ -18,18 +18,10 @@ let package = Package(
     targets: [
         .target(
             name: "SQLite",
-            dependencies: ["SQLiteObjc"],
             exclude: [
                 "Info.plist"
             ]
         ),
-        .target(
-            name: "SQLiteObjc",
-            dependencies: [],
-            exclude: [
-                "fts3_tokenizer.h"
-            ]
-        ),
         .testTarget(
             name: "SQLiteTests",
             dependencies: [
@@ -57,7 +49,8 @@ package.targets = [
     .testTarget(
         name: "SQLiteTests",
         dependencies: ["SQLite"],
-        path: "Tests/SQLiteTests", exclude: [
+        path: "Tests/SQLiteTests",
+        exclude: [
             "FTSIntegrationTests.swift",
             "FTS4Tests.swift",
             "FTS5Tests.swift"
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 45ff075f..3e67c03e 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -17,8 +17,6 @@
 		03A65E741C6BB2DA0062603F /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF81C3F06E900AE3E12 /* Helpers.swift */; };
 		03A65E761C6BB2E60062603F /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
 		03A65E771C6BB2E60062603F /* Connection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEF1C3F06E900AE3E12 /* Connection.swift */; };
-		03A65E781C6BB2EA0062603F /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */; };
-		03A65E791C6BB2EF0062603F /* SQLiteObjc.m in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF11C3F06E900AE3E12 /* SQLiteObjc.m */; };
 		03A65E7A1C6BB2F70062603F /* Statement.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF21C3F06E900AE3E12 /* Statement.swift */; };
 		03A65E7B1C6BB2F70062603F /* Value.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF31C3F06E900AE3E12 /* Value.swift */; };
 		03A65E7C1C6BB2F70062603F /* FTS4.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF51C3F06E900AE3E12 /* FTS4.swift */; };
@@ -116,13 +114,7 @@
 		3D67B3F61DB246D100A4F4C6 /* Setter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B021C3F06E900AE3E12 /* Setter.swift */; };
 		3D67B3F71DB246D700A4F4C6 /* Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF71C3F06E900AE3E12 /* Foundation.swift */; };
 		3D67B3F81DB246D700A4F4C6 /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF81C3F06E900AE3E12 /* Helpers.swift */; };
-		3D67B3F91DB246E700A4F4C6 /* SQLiteObjc.m in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF11C3F06E900AE3E12 /* SQLiteObjc.m */; };
 		3D67B3FC1DB2471B00A4F4C6 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		3D67B3FD1DB2472D00A4F4C6 /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */; };
-		3DDC112F26CDBA0200CE369F /* SQLiteObjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 3DDC112E26CDBA0200CE369F /* SQLiteObjc.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		3DDC113626CDBE1900CE369F /* SQLiteObjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 3DDC112E26CDBA0200CE369F /* SQLiteObjc.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		3DDC113726CDBE1900CE369F /* SQLiteObjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 3DDC112E26CDBA0200CE369F /* SQLiteObjc.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		3DDC113826CDBE1C00CE369F /* SQLiteObjc.h in Headers */ = {isa = PBXBuildFile; fileRef = 3DDC112E26CDBA0200CE369F /* SQLiteObjc.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		3DF7B78828842972005DD8CA /* Connection+Attach.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B78728842972005DD8CA /* Connection+Attach.swift */; };
 		3DF7B78928842972005DD8CA /* Connection+Attach.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B78728842972005DD8CA /* Connection+Attach.swift */; };
 		3DF7B78A28842972005DD8CA /* Connection+Attach.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B78728842972005DD8CA /* Connection+Attach.swift */; };
@@ -152,8 +144,6 @@
 		EE247ADE1C3F04ED00AE3E12 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE247AD31C3F04ED00AE3E12 /* SQLite.framework */; };
 		EE247B031C3F06E900AE3E12 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
 		EE247B041C3F06E900AE3E12 /* Connection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEF1C3F06E900AE3E12 /* Connection.swift */; };
-		EE247B051C3F06E900AE3E12 /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */; };
-		EE247B061C3F06E900AE3E12 /* SQLiteObjc.m in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF11C3F06E900AE3E12 /* SQLiteObjc.m */; };
 		EE247B071C3F06E900AE3E12 /* Statement.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF21C3F06E900AE3E12 /* Statement.swift */; };
 		EE247B081C3F06E900AE3E12 /* Value.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF31C3F06E900AE3E12 /* Value.swift */; };
 		EE247B091C3F06E900AE3E12 /* FTS4.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF51C3F06E900AE3E12 /* FTS4.swift */; };
@@ -205,8 +195,6 @@
 		EE247B641C3F3FDB00AE3E12 /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF81C3F06E900AE3E12 /* Helpers.swift */; };
 		EE247B651C3F3FEC00AE3E12 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
 		EE247B661C3F3FEC00AE3E12 /* Connection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEF1C3F06E900AE3E12 /* Connection.swift */; };
-		EE247B671C3F3FEC00AE3E12 /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */; };
-		EE247B681C3F3FEC00AE3E12 /* SQLiteObjc.m in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF11C3F06E900AE3E12 /* SQLiteObjc.m */; };
 		EE247B691C3F3FEC00AE3E12 /* Statement.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF21C3F06E900AE3E12 /* Statement.swift */; };
 		EE247B6A1C3F3FEC00AE3E12 /* Value.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF31C3F06E900AE3E12 /* Value.swift */; };
 		EE247B6B1C3F3FEC00AE3E12 /* FTS4.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF51C3F06E900AE3E12 /* FTS4.swift */; };
@@ -272,13 +260,13 @@
 		3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomAggregationTests.swift; sourceTree = "<group>"; };
 		3D3C3CCB26E5568800759140 /* SQLite.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = SQLite.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
 		3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.0.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
-		3DDC112E26CDBA0200CE369F /* SQLiteObjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SQLiteObjc.h; path = ../SQLiteObjc/include/SQLiteObjc.h; sourceTree = "<group>"; };
 		3DF7B78728842972005DD8CA /* Connection+Attach.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Connection+Attach.swift"; sourceTree = "<group>"; };
 		3DF7B78C28842C23005DD8CA /* ResultTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultTests.swift; sourceTree = "<group>"; };
 		3DF7B790288449BA005DD8CA /* URIQueryParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URIQueryParameter.swift; sourceTree = "<group>"; };
 		3DF7B79528846FCC005DD8CA /* Resources */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Resources; sourceTree = "<group>"; };
 		3DF7B79A2884C353005DD8CA /* CHANGELOG.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = "<group>"; };
 		3DF7B79B2884C901005DD8CA /* Planning.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Planning.md; sourceTree = "<group>"; };
+		3DFC0B862886C239001C8FC9 /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = "<group>"; };
 		49EB68C31F7B3CB400D89D40 /* Coding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coding.swift; sourceTree = "<group>"; };
 		997DF2AD287FC06D00F8DF95 /* Query+with.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Query+with.swift"; sourceTree = "<group>"; };
 		A121AC451CA35C79005A31D1 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -290,8 +278,6 @@
 		EE247AE41C3F04ED00AE3E12 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		EE247AEE1C3F06E900AE3E12 /* Blob.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Blob.swift; sourceTree = "<group>"; };
 		EE247AEF1C3F06E900AE3E12 /* Connection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Connection.swift; sourceTree = "<group>"; };
-		EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = fts3_tokenizer.h; path = ../../SQLiteObjc/fts3_tokenizer.h; sourceTree = "<group>"; };
-		EE247AF11C3F06E900AE3E12 /* SQLiteObjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SQLiteObjc.m; path = ../../SQLiteObjc/SQLiteObjc.m; sourceTree = "<group>"; };
 		EE247AF21C3F06E900AE3E12 /* Statement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Statement.swift; sourceTree = "<group>"; };
 		EE247AF31C3F06E900AE3E12 /* Value.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Value.swift; sourceTree = "<group>"; };
 		EE247AF51C3F06E900AE3E12 /* FTS4.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS4.swift; sourceTree = "<group>"; };
@@ -406,9 +392,10 @@
 		EE247AC91C3F04ED00AE3E12 = {
 			isa = PBXGroup;
 			children = (
+				3DFC0B862886C239001C8FC9 /* Package.swift */,
+				3D3C3CCB26E5568800759140 /* SQLite.playground */,
 				EE247AD51C3F04ED00AE3E12 /* SQLite */,
 				EE247AE11C3F04ED00AE3E12 /* SQLiteTests */,
-				3D3C3CCB26E5568800759140 /* SQLite.playground */,
 				EE247B8A1C3F81D000AE3E12 /* Metadata */,
 				EE247AD41C3F04ED00AE3E12 /* Products */,
 				3D67B3E41DB2469200A4F4C6 /* Frameworks */,
@@ -435,7 +422,6 @@
 			isa = PBXGroup;
 			children = (
 				EE247AD61C3F04ED00AE3E12 /* SQLite.h */,
-				3DDC112E26CDBA0200CE369F /* SQLiteObjc.h */,
 				EE247AF71C3F06E900AE3E12 /* Foundation.swift */,
 				EE247AF81C3F06E900AE3E12 /* Helpers.swift */,
 				EE247AD81C3F04ED00AE3E12 /* Info.plist */,
@@ -488,8 +474,6 @@
 			children = (
 				EE247AEE1C3F06E900AE3E12 /* Blob.swift */,
 				EE247AEF1C3F06E900AE3E12 /* Connection.swift */,
-				EE247AF01C3F06E900AE3E12 /* fts3_tokenizer.h */,
-				EE247AF11C3F06E900AE3E12 /* SQLiteObjc.m */,
 				EE247AF21C3F06E900AE3E12 /* Statement.swift */,
 				EE247AF31C3F06E900AE3E12 /* Value.swift */,
 				19A1710E73A46D5AC721CDA9 /* Errors.swift */,
@@ -505,10 +489,10 @@
 		EE247AF41C3F06E900AE3E12 /* Extensions */ = {
 			isa = PBXGroup;
 			children = (
+				19A178A39ACA9667A62663CC /* Cipher.swift */,
 				EE247AF51C3F06E900AE3E12 /* FTS4.swift */,
-				EE247AF61C3F06E900AE3E12 /* RTree.swift */,
 				19A1730E4390C775C25677D1 /* FTS5.swift */,
-				19A178A39ACA9667A62663CC /* Cipher.swift */,
+				EE247AF61C3F06E900AE3E12 /* RTree.swift */,
 			);
 			path = Extensions;
 			sourceTree = "<group>";
@@ -576,8 +560,6 @@
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				03A65E781C6BB2EA0062603F /* fts3_tokenizer.h in Headers */,
-				3DDC113626CDBE1900CE369F /* SQLiteObjc.h in Headers */,
 				03A65E721C6BB2D30062603F /* SQLite.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -587,8 +569,6 @@
 			buildActionMask = 2147483647;
 			files = (
 				3D67B3FC1DB2471B00A4F4C6 /* SQLite.h in Headers */,
-				3DDC113726CDBE1900CE369F /* SQLiteObjc.h in Headers */,
-				3D67B3FD1DB2472D00A4F4C6 /* fts3_tokenizer.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -596,8 +576,6 @@
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				EE247B051C3F06E900AE3E12 /* fts3_tokenizer.h in Headers */,
-				3DDC113826CDBE1C00CE369F /* SQLiteObjc.h in Headers */,
 				EE247AD71C3F04ED00AE3E12 /* SQLite.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -606,8 +584,6 @@
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				EE247B671C3F3FEC00AE3E12 /* fts3_tokenizer.h in Headers */,
-				3DDC112F26CDBA0200CE369F /* SQLiteObjc.h in Headers */,
 				EE247B621C3F3FDB00AE3E12 /* SQLite.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -869,7 +845,6 @@
 				03A65E761C6BB2E60062603F /* Blob.swift in Sources */,
 				03A65E7D1C6BB2F70062603F /* RTree.swift in Sources */,
 				3DF7B793288449BA005DD8CA /* URIQueryParameter.swift in Sources */,
-				03A65E791C6BB2EF0062603F /* SQLiteObjc.m in Sources */,
 				03A65E7B1C6BB2F70062603F /* Value.swift in Sources */,
 				03A65E821C6BB2FB0062603F /* Expression.swift in Sources */,
 				03A65E731C6BB2D80062603F /* Foundation.swift in Sources */,
@@ -933,7 +908,6 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				3D67B3F91DB246E700A4F4C6 /* SQLiteObjc.m in Sources */,
 				3DF7B78B28842972005DD8CA /* Connection+Attach.swift in Sources */,
 				49EB68C71F7B3CB400D89D40 /* Coding.swift in Sources */,
 				997DF2B1287FC06D00F8DF95 /* Query+with.swift in Sources */,
@@ -986,7 +960,6 @@
 				EE247B121C3F06E900AE3E12 /* Operators.swift in Sources */,
 				EE247B141C3F06E900AE3E12 /* Schema.swift in Sources */,
 				EE247B131C3F06E900AE3E12 /* Query.swift in Sources */,
-				EE247B061C3F06E900AE3E12 /* SQLiteObjc.m in Sources */,
 				EE247B071C3F06E900AE3E12 /* Statement.swift in Sources */,
 				EE247B0D1C3F06E900AE3E12 /* AggregateFunctions.swift in Sources */,
 				19A1717B10CC941ACB5533D6 /* FTS5.swift in Sources */,
@@ -1042,7 +1015,6 @@
 				EE247B651C3F3FEC00AE3E12 /* Blob.swift in Sources */,
 				EE247B6C1C3F3FEC00AE3E12 /* RTree.swift in Sources */,
 				3DF7B792288449BA005DD8CA /* URIQueryParameter.swift in Sources */,
-				EE247B681C3F3FEC00AE3E12 /* SQLiteObjc.m in Sources */,
 				EE247B6A1C3F3FEC00AE3E12 /* Value.swift in Sources */,
 				EE247B711C3F3FEC00AE3E12 /* Expression.swift in Sources */,
 				EE247B631C3F3FDB00AE3E12 /* Foundation.swift in Sources */,
diff --git a/Sources/SQLite/Extensions/FTS4.swift b/Sources/SQLite/Extensions/FTS4.swift
index 52fec955..e9e65746 100644
--- a/Sources/SQLite/Extensions/FTS4.swift
+++ b/Sources/SQLite/Extensions/FTS4.swift
@@ -22,10 +22,6 @@
 // THE SOFTWARE.
 //
 
-#if SWIFT_PACKAGE
-import SQLiteObjc
-#endif
-
 extension Module {
 
     public static func FTS4(_ column: Expressible, _ more: Expressible...) -> Module {
@@ -149,29 +145,6 @@ extension Tokenizer: CustomStringConvertible {
 
 }
 
-extension Connection {
-
-    public func registerTokenizer(_ submoduleName: String, next: @escaping (String) -> (String, Range<String.Index>)?) throws {
-        try check(_SQLiteRegisterTokenizer(handle, Tokenizer.moduleName, submoduleName) {
-            (input: UnsafePointer<Int8>, offset: UnsafeMutablePointer<Int32>, length: UnsafeMutablePointer<Int32>) in
-            let string = String(cString: input)
-
-            guard let (token, range) = next(string) else { return nil }
-
-            let view: String.UTF8View = string.utf8
-
-            if let from = range.lowerBound.samePosition(in: view),
-               let to = range.upperBound.samePosition(in: view) {
-                offset.pointee += Int32(string[string.startIndex..<range.lowerBound].utf8.count)
-                length.pointee = Int32(view.distance(from: from, to: to))
-                return token
-            } else {
-                return nil
-            }
-        })
-    }
-}
-
 /// Configuration options shared between the [FTS4](https://www.sqlite.org/fts3.html) and
 /// [FTS5](https://www.sqlite.org/fts5.html) extensions.
 open class FTSConfig {
diff --git a/Sources/SQLite/SQLite.h b/Sources/SQLite/SQLite.h
index fe1e3dfe..21ed899f 100644
--- a/Sources/SQLite/SQLite.h
+++ b/Sources/SQLite/SQLite.h
@@ -2,5 +2,3 @@
 
 FOUNDATION_EXPORT double SQLiteVersionNumber;
 FOUNDATION_EXPORT const unsigned char SQLiteVersionString[];
-
-#import "SQLiteObjc.h"
diff --git a/Sources/SQLiteObjc/SQLiteObjc.m b/Sources/SQLiteObjc/SQLiteObjc.m
deleted file mode 100644
index 9f2be0bd..00000000
--- a/Sources/SQLiteObjc/SQLiteObjc.m
+++ /dev/null
@@ -1,138 +0,0 @@
-//
-// SQLite.swift
-// https://github.com/stephencelis/SQLite.swift
-// Copyright © 2014-2015 Stephen Celis.
-//
-// 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.
-//
-
-#import "SQLiteObjc.h"
-#import "fts3_tokenizer.h"
-
-#pragma mark - FTS
-
-typedef struct __SQLiteTokenizer {
-    sqlite3_tokenizer base;
-    __unsafe_unretained _SQLiteTokenizerNextCallback callback;
-} __SQLiteTokenizer;
-
-typedef struct __SQLiteTokenizerCursor {
-    void * base;
-    const char * input;
-    int inputOffset;
-    int inputLength;
-    int idx;
-} __SQLiteTokenizerCursor;
-
-static NSMutableDictionary * __SQLiteTokenizerMap;
-
-static int __SQLiteTokenizerCreate(int argc, const char * const * argv, sqlite3_tokenizer ** ppTokenizer) {
-    __SQLiteTokenizer * tokenizer = (__SQLiteTokenizer *)sqlite3_malloc(sizeof(__SQLiteTokenizer));
-    if (!tokenizer) {
-        return SQLITE_NOMEM;
-    }
-    memset(tokenizer, 0, sizeof(* tokenizer));
-
-    NSString * key = [NSString stringWithUTF8String:argv[0]];
-    tokenizer->callback = [__SQLiteTokenizerMap objectForKey:key];
-    if (!tokenizer->callback) {
-        return SQLITE_ERROR;
-    }
-
-    *ppTokenizer = &tokenizer->base;
-    return SQLITE_OK;
-}
-
-static int __SQLiteTokenizerDestroy(sqlite3_tokenizer * pTokenizer) {
-    sqlite3_free(pTokenizer);
-    return SQLITE_OK;
-}
-
-static int __SQLiteTokenizerOpen(sqlite3_tokenizer * pTokenizer, const char * pInput, int nBytes, sqlite3_tokenizer_cursor ** ppCursor) {
-    __SQLiteTokenizerCursor * cursor = (__SQLiteTokenizerCursor *)sqlite3_malloc(sizeof(__SQLiteTokenizerCursor));
-    if (!cursor) {
-        return SQLITE_NOMEM;
-    }
-
-    cursor->input = pInput;
-    cursor->inputOffset = 0;
-    cursor->inputLength = 0;
-    cursor->idx = 0;
-
-    *ppCursor = (sqlite3_tokenizer_cursor *)cursor;
-    return SQLITE_OK;
-}
-
-static int __SQLiteTokenizerClose(sqlite3_tokenizer_cursor * pCursor) {
-    sqlite3_free(pCursor);
-    return SQLITE_OK;
-}
-
-static int __SQLiteTokenizerNext(sqlite3_tokenizer_cursor * pCursor, const char ** ppToken, int * pnBytes, int * piStartOffset, int * piEndOffset, int * piPosition) {
-    __SQLiteTokenizerCursor * cursor = (__SQLiteTokenizerCursor *)pCursor;
-    __SQLiteTokenizer * tokenizer = (__SQLiteTokenizer *)cursor->base;
-
-    cursor->inputOffset += cursor->inputLength;
-    const char * input = cursor->input + cursor->inputOffset;
-    const char * token = [tokenizer->callback(input, &cursor->inputOffset, &cursor->inputLength) cStringUsingEncoding:NSUTF8StringEncoding];
-    if (!token) {
-        return SQLITE_DONE;
-    }
-
-    *ppToken = token;
-    *pnBytes = (int)strlen(token);
-    *piStartOffset = cursor->inputOffset;
-    *piEndOffset = cursor->inputOffset + cursor->inputLength;
-    *piPosition = cursor->idx++;
-    return SQLITE_OK;
-}
-
-static const sqlite3_tokenizer_module __SQLiteTokenizerModule = {
-    0,
-    __SQLiteTokenizerCreate,
-    __SQLiteTokenizerDestroy,
-    __SQLiteTokenizerOpen,
-    __SQLiteTokenizerClose,
-    __SQLiteTokenizerNext
-};
-
-int _SQLiteRegisterTokenizer(sqlite3 *db, const char * moduleName, const char * submoduleName, _SQLiteTokenizerNextCallback callback) {
-    static dispatch_once_t onceToken;
-    dispatch_once(&onceToken, ^{
-        __SQLiteTokenizerMap = [NSMutableDictionary new];
-    });
-
-    sqlite3_stmt * stmt;
-    int status = sqlite3_prepare_v2(db, "SELECT fts3_tokenizer(?, ?)", -1, &stmt, 0);
-    if (status != SQLITE_OK ){
-        return status;
-    }
-    const sqlite3_tokenizer_module * pModule = &__SQLiteTokenizerModule;
-    sqlite3_bind_text(stmt, 1, moduleName, -1, SQLITE_STATIC);
-    sqlite3_bind_blob(stmt, 2, &pModule, sizeof(pModule), SQLITE_STATIC);
-    sqlite3_step(stmt);
-    status = sqlite3_finalize(stmt);
-    if (status != SQLITE_OK ){
-        return status;
-    }
-
-    [__SQLiteTokenizerMap setObject:[callback copy] forKey:[NSString stringWithUTF8String:submoduleName]];
-
-    return SQLITE_OK;
-}
diff --git a/Sources/SQLiteObjc/fts3_tokenizer.h b/Sources/SQLiteObjc/fts3_tokenizer.h
deleted file mode 100644
index d8a1e44b..00000000
--- a/Sources/SQLiteObjc/fts3_tokenizer.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
-** 2006 July 10
-**
-** The author disclaims copyright to this source code.
-**
-*************************************************************************
-** Defines the interface to tokenizers used by fulltext-search.  There
-** are three basic components:
-**
-** sqlite3_tokenizer_module is a singleton defining the tokenizer
-** interface functions.  This is essentially the class structure for
-** tokenizers.
-**
-** sqlite3_tokenizer is used to define a particular tokenizer, perhaps
-** including customization information defined at creation time.
-**
-** sqlite3_tokenizer_cursor is generated by a tokenizer to generate
-** tokens from a particular input.
-*/
-#ifndef _FTS3_TOKENIZER_H_
-#define _FTS3_TOKENIZER_H_
-
-/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time.
-** If tokenizers are to be allowed to call sqlite3_*() functions, then
-** we will need a way to register the API consistently.
-*/
-#import "sqlite3.h"
-
-/*
-** Structures used by the tokenizer interface. When a new tokenizer
-** implementation is registered, the caller provides a pointer to
-** an sqlite3_tokenizer_module containing pointers to the callback
-** functions that make up an implementation.
-**
-** When an fts3 table is created, it passes any arguments passed to
-** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the
-** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer
-** implementation. The xCreate() function in turn returns an 
-** sqlite3_tokenizer structure representing the specific tokenizer to
-** be used for the fts3 table (customized by the tokenizer clause arguments).
-**
-** To tokenize an input buffer, the sqlite3_tokenizer_module.xOpen()
-** method is called. It returns an sqlite3_tokenizer_cursor object
-** that may be used to tokenize a specific input buffer based on
-** the tokenization rules supplied by a specific sqlite3_tokenizer
-** object.
-*/
-typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module;
-typedef struct sqlite3_tokenizer sqlite3_tokenizer;
-typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor;
-
-struct sqlite3_tokenizer_module {
-
-  /*
-  ** Structure version. Should always be set to 0 or 1.
-  */
-  int iVersion;
-
-  /*
-  ** Create a new tokenizer. The values in the argv[] array are the
-  ** arguments passed to the "tokenizer" clause of the CREATE VIRTUAL
-  ** TABLE statement that created the fts3 table. For example, if
-  ** the following SQL is executed:
-  **
-  **   CREATE .. USING fts3( ... , tokenizer <tokenizer-name> arg1 arg2)
-  **
-  ** then argc is set to 2, and the argv[] array contains pointers
-  ** to the strings "arg1" and "arg2".
-  **
-  ** This method should return either SQLITE_OK (0), or an SQLite error 
-  ** code. If SQLITE_OK is returned, then *ppTokenizer should be set
-  ** to point at the newly created tokenizer structure. The generic
-  ** sqlite3_tokenizer.pModule variable should not be initialized by
-  ** this callback. The caller will do so.
-  */
-  int (*xCreate)(
-    int argc,                           /* Size of argv array */
-    const char *const*argv,             /* Tokenizer argument strings */
-    sqlite3_tokenizer **ppTokenizer     /* OUT: Created tokenizer */
-  );
-
-  /*
-  ** Destroy an existing tokenizer. The fts3 module calls this method
-  ** exactly once for each successful call to xCreate().
-  */
-  int (*xDestroy)(sqlite3_tokenizer *pTokenizer);
-
-  /*
-  ** Create a tokenizer cursor to tokenize an input buffer. The caller
-  ** is responsible for ensuring that the input buffer remains valid
-  ** until the cursor is closed (using the xClose() method). 
-  */
-  int (*xOpen)(
-    sqlite3_tokenizer *pTokenizer,       /* Tokenizer object */
-    const char *pInput, int nBytes,      /* Input buffer */
-    sqlite3_tokenizer_cursor **ppCursor  /* OUT: Created tokenizer cursor */
-  );
-
-  /*
-  ** Destroy an existing tokenizer cursor. The fts3 module calls this 
-  ** method exactly once for each successful call to xOpen().
-  */
-  int (*xClose)(sqlite3_tokenizer_cursor *pCursor);
-
-  /*
-  ** Retrieve the next token from the tokenizer cursor pCursor. This
-  ** method should either return SQLITE_OK and set the values of the
-  ** "OUT" variables identified below, or SQLITE_DONE to indicate that
-  ** the end of the buffer has been reached, or an SQLite error code.
-  **
-  ** *ppToken should be set to point at a buffer containing the 
-  ** normalized version of the token (i.e. after any case-folding and/or
-  ** stemming has been performed). *pnBytes should be set to the length
-  ** of this buffer in bytes. The input text that generated the token is
-  ** identified by the byte offsets returned in *piStartOffset and
-  ** *piEndOffset. *piStartOffset should be set to the index of the first
-  ** byte of the token in the input buffer. *piEndOffset should be set
-  ** to the index of the first byte just past the end of the token in
-  ** the input buffer.
-  **
-  ** The buffer *ppToken is set to point at is managed by the tokenizer
-  ** implementation. It is only required to be valid until the next call
-  ** to xNext() or xClose(). 
-  */
-  /* TODO(shess) current implementation requires pInput to be
-  ** nul-terminated.  This should either be fixed, or pInput/nBytes
-  ** should be converted to zInput.
-  */
-  int (*xNext)(
-    sqlite3_tokenizer_cursor *pCursor,   /* Tokenizer cursor */
-    const char **ppToken, int *pnBytes,  /* OUT: Normalized text for token */
-    int *piStartOffset,  /* OUT: Byte offset of token in input buffer */
-    int *piEndOffset,    /* OUT: Byte offset of end of token in input buffer */
-    int *piPosition      /* OUT: Number of tokens returned before this one */
-  );
-
-  /***********************************************************************
-  ** Methods below this point are only available if iVersion>=1.
-  */
-
-  /* 
-  ** Configure the language id of a tokenizer cursor.
-  */
-  int (*xLanguageid)(sqlite3_tokenizer_cursor *pCsr, int iLangid);
-};
-
-struct sqlite3_tokenizer {
-  const sqlite3_tokenizer_module *pModule;  /* The module for this tokenizer */
-  /* Tokenizer implementations will typically add additional fields */
-};
-
-struct sqlite3_tokenizer_cursor {
-  sqlite3_tokenizer *pTokenizer;       /* Tokenizer for this cursor. */
-  /* Tokenizer implementations will typically add additional fields */
-};
-
-int fts3_global_term_cnt(int iTerm, int iCol);
-int fts3_term_cnt(int iTerm, int iCol);
-
-
-#endif /* _FTS3_TOKENIZER_H_ */
diff --git a/Sources/SQLiteObjc/include/SQLiteObjc.h b/Sources/SQLiteObjc/include/SQLiteObjc.h
deleted file mode 100644
index 610cdf10..00000000
--- a/Sources/SQLiteObjc/include/SQLiteObjc.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-// SQLite.swift
-// https://github.com/stephencelis/SQLite.swift
-// Copyright © 2014-2015 Stephen Celis.
-//
-// 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.
-//
-
-@import Foundation;
-#if defined(SQLITE_SWIFT_STANDALONE)
-@import sqlite3;
-#elif defined(SQLITE_SWIFT_SQLCIPHER)
-@import SQLCipher;
-#else
-@import SQLite3;
-#endif
-
-NS_ASSUME_NONNULL_BEGIN
-typedef NSString * _Nullable (^_SQLiteTokenizerNextCallback)(const char *input, int *inputOffset, int *inputLength);
-int _SQLiteRegisterTokenizer(sqlite3 *db, const char *module, const char *tokenizer, _Nullable _SQLiteTokenizerNextCallback callback);
-NS_ASSUME_NONNULL_END
-
diff --git a/Tests/SQLiteTests/FTS4Tests.swift b/Tests/SQLiteTests/FTS4Tests.swift
index aa6ac41f..5e595007 100644
--- a/Tests/SQLiteTests/FTS4Tests.swift
+++ b/Tests/SQLiteTests/FTS4Tests.swift
@@ -188,40 +188,3 @@ class FTS4ConfigTests: XCTestCase {
         virtualTable.create(.FTS4(config))
     }
 }
-
-class FTS4IntegrationTests: SQLiteTestCase {
-#if !SQLITE_SWIFT_STANDALONE && !SQLITE_SWIFT_SQLCIPHER
-    func test_registerTokenizer_registersTokenizer() throws {
-        let emails = VirtualTable("emails")
-        let subject = Expression<String?>("subject")
-        let body = Expression<String?>("body")
-
-        let locale = CFLocaleCopyCurrent()
-        let tokenizerName = "tokenizer"
-        let tokenizer = CFStringTokenizerCreate(nil, "" as CFString, CFRangeMake(0, 0),
-                                                UInt(kCFStringTokenizerUnitWord), locale)
-        try db.registerTokenizer(tokenizerName) { string in
-            CFStringTokenizerSetString(tokenizer, string as CFString,
-                                       CFRangeMake(0, CFStringGetLength(string as CFString)))
-            if CFStringTokenizerAdvanceToNextToken(tokenizer).isEmpty {
-                return nil
-            }
-            let range = CFStringTokenizerGetCurrentTokenRange(tokenizer)
-            let input = CFStringCreateWithSubstring(kCFAllocatorDefault, string as CFString, range)!
-            let token = CFStringCreateMutableCopy(nil, range.length, input)!
-            CFStringLowercase(token, locale)
-            CFStringTransform(token, nil, kCFStringTransformStripDiacritics, false)
-            return (token as String, string.range(of: input as String)!)
-        }
-
-        try db.run(emails.create(.FTS4([subject, body], tokenize: .Custom(tokenizerName))))
-        assertSQL("""
-                  CREATE VIRTUAL TABLE \"emails\" USING fts4(\"subject\", \"body\",
-                   tokenize=\"SQLite.swift\" \"tokenizer\")
-                  """.replacingOccurrences(of: "\n", with: ""))
-
-        try _ = db.run(emails.insert(subject <- "Aún más cáfe!"))
-        XCTAssertEqual(1, try db.scalar(emails.filter(emails.match("aun")).count))
-    }
-#endif
-}

From f63aca44e06e511dd0bdeeeb4b335b2aafbf36b1 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 19 Jul 2022 13:40:38 +0200
Subject: [PATCH 528/685] Fix podspec, update docs

---
 CHANGELOG.md           |  3 +++
 Documentation/Index.md |  2 --
 Package.swift          | 23 +++++------------------
 SQLite.swift.podspec   |  9 +++------
 4 files changed, 11 insertions(+), 26 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 68a5133f..71ce9858 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@
 * Fix incorrect spelling of `remove_diacritics` ([#1128][])
 * Fix project build order ([#1131][])
 * Performance improvements ([#1109][], [#1115][], [#1132][])
+* Removed FTS3/4 tokenizer integration (`registerTokenizer`, [#1104][], [#1144[]])
 
 0.13.3 (27-03-2022), [diff][diff-0.13.3]
 ========================================
@@ -166,6 +167,7 @@
 [#1098]: https://github.com/stephencelis/SQLite.swift/issues/1098
 [#1100]: https://github.com/stephencelis/SQLite.swift/pull/1100
 [#1101]: https://github.com/stephencelis/SQLite.swift/issues/1101
+[#1104]: https://github.com/stephencelis/SQLite.swift/issues/1104
 [#1105]: https://github.com/stephencelis/SQLite.swift/pull/1105
 [#1109]: https://github.com/stephencelis/SQLite.swift/issues/1109
 [#1110]: https://github.com/stephencelis/SQLite.swift/pull/1110
@@ -182,3 +184,4 @@
 [#1139]: https://github.com/stephencelis/SQLite.swift/pull/1139
 [#1141]: https://github.com/stephencelis/SQLite.swift/pull/1141
 [#1142]: https://github.com/stephencelis/SQLite.swift/pull/1142
+[#1144]: https://github.com/stephencelis/SQLite.swift/pull/1144
diff --git a/Documentation/Index.md b/Documentation/Index.md
index 96fc1ee1..b71cdc4f 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1983,8 +1983,6 @@ try db.run(emails.create(.FTS5(config)))
 // the last FTS4 query above as:
 let replies = emails.filter(emails.match("subject:\"Re:\"*"))
 // SELECT * FROM "emails" WHERE "emails" MATCH 'subject:"Re:"*'
-
-// https://www.sqlite.org/fts5.html#_changes_to_select_statements_
 ```
 
 ## Executing Arbitrary SQL
diff --git a/Package.swift b/Package.swift
index ab9cbd43..9664e99a 100644
--- a/Package.swift
+++ b/Package.swift
@@ -39,23 +39,10 @@ let package = Package(
 )
 
 #if os(Linux)
-package.dependencies = [.package(url: "https://github.com/stephencelis/CSQLite.git", from: "0.0.3")]
-package.targets = [
-    .target(
-        name: "SQLite",
-        dependencies: [.product(name: "CSQLite", package: "CSQLite")],
-        exclude: ["Extensions/FTS4.swift", "Extensions/FTS5.swift"]
-    ),
-    .testTarget(
-        name: "SQLiteTests",
-        dependencies: ["SQLite"],
-        path: "Tests/SQLiteTests",
-        exclude: [
-            "FTSIntegrationTests.swift",
-            "FTS4Tests.swift",
-            "FTS5Tests.swift"
-        ],
-        resources: [ .copy("Resources") ]
-    )
+package.dependencies = [
+    .package(url: "https://github.com/stephencelis/CSQLite.git", from: "0.0.3")
+]
+package.targets.first?.dependencies += [
+    .product(name: "CSQLite", package: "CSQLite")
 ]
 #endif
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 451b4886..d36d0330 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -29,9 +29,8 @@ Pod::Spec.new do |s|
   s.watchos.deployment_target = watchos_deployment_target
 
   s.subspec 'standard' do |ss|
-    ss.source_files = 'Sources/{SQLite,SQLiteObjc}/**/*.{c,h,m,swift}'
+    ss.source_files = 'Sources/SQLite/**/*.{c,h,m,swift}'
     ss.exclude_files = 'Sources/**/Cipher.swift'
-    ss.private_header_files = 'Sources/SQLiteObjc/fts3_tokenizer.h'
     ss.library = 'sqlite3'
 
     ss.test_spec 'tests' do |test_spec|
@@ -44,9 +43,8 @@ Pod::Spec.new do |s|
   end
 
   s.subspec 'standalone' do |ss|
-    ss.source_files = 'Sources/{SQLite,SQLiteObjc}/**/*.{c,h,m,swift}'
+    ss.source_files = 'Sources/SQLite/**/*.{c,h,m,swift}'
     ss.exclude_files = 'Sources/**/Cipher.swift'
-    ss.private_header_files = 'Sources/SQLiteObjc/fts3_tokenizer.h'
 
     ss.xcconfig = {
       'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_SWIFT_STANDALONE',
@@ -64,8 +62,7 @@ Pod::Spec.new do |s|
   end
 
   s.subspec 'SQLCipher' do |ss|
-    ss.source_files = 'Sources/{SQLite,SQLiteObjc}/**/*.{c,h,m,swift}'
-    ss.private_header_files = 'Sources/SQLiteObjc/fts3_tokenizer.h'
+    ss.source_files = 'Sources/SQLite/**/*.{c,h,m,swift}'
     ss.xcconfig = {
       'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_SWIFT_SQLCIPHER',
       'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SQLITE_HAS_CODEC=1 SQLITE_SWIFT_SQLCIPHER=1'

From 8d9f74e919a75da41f19c47869a4577c10638a0c Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 19 Jul 2022 13:59:27 +0200
Subject: [PATCH 529/685] Works now

---
 CHANGELOG.md           | 2 +-
 Documentation/Linux.md | 3 +--
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 71ce9858..7b3f78b4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,7 +10,7 @@
 * Fix incorrect spelling of `remove_diacritics` ([#1128][])
 * Fix project build order ([#1131][])
 * Performance improvements ([#1109][], [#1115][], [#1132][])
-* Removed FTS3/4 tokenizer integration (`registerTokenizer`, [#1104][], [#1144[]])
+* Removed FTS3/4 tokenizer integration (`registerTokenizer`, [#1104][], [#1144][])
 
 0.13.3 (27-03-2022), [diff][diff-0.13.3]
 ========================================
diff --git a/Documentation/Linux.md b/Documentation/Linux.md
index 640ced6f..0c88ff5c 100644
--- a/Documentation/Linux.md
+++ b/Documentation/Linux.md
@@ -2,9 +2,8 @@
 
 ## Limitations
 
-* Custom functions are currently not supported and crash, caused by a bug in Swift.
+* Custom functions/aggregations are currently not supported and crash, caused by a bug in Swift.
 See [#1071](https://github.com/stephencelis/SQLite.swift/issues/1071).
-* FTS5 might not work, see [#1007](https://github.com/stephencelis/SQLite.swift/issues/1007)
 
 ## Debugging
 

From ef4854f0f742f1f52416aab88db75c6b686385ec Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 19 Jul 2022 14:29:59 +0200
Subject: [PATCH 530/685] Update mileston

---
 Documentation/Planning.md        | 2 +-
 SQLite.xcodeproj/project.pbxproj | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/Planning.md b/Documentation/Planning.md
index 6067b81e..cdfca9c4 100644
--- a/Documentation/Planning.md
+++ b/Documentation/Planning.md
@@ -6,7 +6,7 @@ additions and Pull Requests, as well as to keep the Issues list clear of
 enhancement requests so that bugs are more visible.
 
 > ⚠ This document is currently not actively maintained. See
-> the [0.13.4 milestone](https://github.com/stephencelis/SQLite.swift/issues?q=is%3Aopen+is%3Aissue+milestone%3A0.13.4)
+> the [0.14.1 milestone](https://github.com/stephencelis/SQLite.swift/issues?q=is%3Aopen+is%3Aissue+milestone%3A0.14.1)
 > on Github for additional information about planned features for the next release.
 
 ## Roadmap
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 3e67c03e..2656ed6a 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -392,7 +392,6 @@
 		EE247AC91C3F04ED00AE3E12 = {
 			isa = PBXGroup;
 			children = (
-				3DFC0B862886C239001C8FC9 /* Package.swift */,
 				3D3C3CCB26E5568800759140 /* SQLite.playground */,
 				EE247AD51C3F04ED00AE3E12 /* SQLite */,
 				EE247AE11C3F04ED00AE3E12 /* SQLiteTests */,
@@ -523,6 +522,7 @@
 				3DF7B79A2884C353005DD8CA /* CHANGELOG.md */,
 				EE247B8B1C3F820300AE3E12 /* CONTRIBUTING.md */,
 				EE247B931C3F826100AE3E12 /* SQLite.swift.podspec */,
+				3DFC0B862886C239001C8FC9 /* Package.swift */,
 				EE247B8D1C3F821200AE3E12 /* Makefile */,
 				EE9180931C46EA210038162A /* libsqlite3.tbd */,
 				EE9180911C46E9D30038162A /* libsqlite3.tbd */,

From 4442ad0bbd06d2e843a5bb280cc96070aafec2c8 Mon Sep 17 00:00:00 2001
From: Adam Wulf <adam.wulf@gmail.com>
Date: Thu, 21 Jul 2022 15:01:04 -0500
Subject: [PATCH 531/685] Adding public method to reset a prepared statement.
 This is needed so that clients can reset any prepared statements they keep in
 memory, which allows for transactions to completely finish. without closing
 transactions (regardless of commit), the wal file cannot be checkpointed and
 will grow unbounded.

---
 Sources/SQLite/Core/Statement.swift    |  6 ++-
 Tests/SQLiteTests/StatementTests.swift | 57 ++++++++++++++++++++++++++
 2 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index 5ec430cf..7ba4026c 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -185,7 +185,11 @@ public final class Statement {
         try connection.sync { try connection.check(sqlite3_step(handle)) == SQLITE_ROW }
     }
 
-    fileprivate func reset(clearBindings shouldClear: Bool = true) {
+    public func reset() {
+        reset(clearBindings: true)
+    }
+
+    fileprivate func reset(clearBindings shouldClear: Bool) {
         sqlite3_reset(handle)
         if shouldClear { sqlite3_clear_bindings(handle) }
     }
diff --git a/Tests/SQLiteTests/StatementTests.swift b/Tests/SQLiteTests/StatementTests.swift
index 3286b792..77bc09c1 100644
--- a/Tests/SQLiteTests/StatementTests.swift
+++ b/Tests/SQLiteTests/StatementTests.swift
@@ -34,4 +34,61 @@ class StatementTests: SQLiteTestCase {
 
         XCTAssertEqual(names.map({ "\($0)@example.com" }), emails.sorted())
     }
+
+    /// Check that a statement reset will close the implicit transaction, allowing wal file to checkpoint
+    func test_reset_statement() throws {
+        // Remove old test db if any
+        let path = "\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3"
+        try? FileManager.default.removeItem(atPath: path)
+        try? FileManager.default.removeItem(atPath: path + "-shm")
+        try? FileManager.default.removeItem(atPath: path + "-wal")
+
+        // create new db on disk in wal mode
+        let db = try Connection(.uri(path))
+        let url = URL(fileURLWithPath: db.description)
+        XCTAssertEqual(url.lastPathComponent, "SQLite.swift Tests.sqlite3")
+        try db.run("PRAGMA journal_mode=WAL;")
+
+        // create users table
+        try db.execute("""
+            CREATE TABLE users (
+                id INTEGER PRIMARY KEY,
+                email TEXT NOT NULL UNIQUE,
+                age INTEGER,
+                salary REAL,
+                admin BOOLEAN NOT NULL DEFAULT 0 CHECK (admin IN (0, 1)),
+                manager_id INTEGER,
+                created_at DATETIME,
+                FOREIGN KEY(manager_id) REFERENCES users(id)
+            )
+            """
+        )
+
+        // insert single row
+        try db.run("INSERT INTO \"users\" (email, age, admin) values (?, ?, ?)",
+                   "alice@example.com", 1.datatypeValue, false.datatypeValue)
+
+        // prepare a statement and read a single row. This will incremeent the cursor which
+        // prevents the implicit transaction from closing.
+        // https://www.sqlite.org/lang_transaction.html#implicit_versus_explicit_transactions
+        let statement = try db.prepare("SELECT email FROM users")
+        XCTAssert(try statement.step())
+        let blob = statement.row[0] as Blob
+        XCTAssertEqual("alice@example.com", String(bytes: blob.bytes, encoding: .utf8)!)
+
+        // verify that the transaction is not closed, which prevents wal_checkpoints (both explicit and auto)
+        do {
+            try db.run("pragma wal_checkpoint(truncate)")
+            XCTFail("Database should be locked")
+        } catch {
+            // pass
+        }
+
+        // reset the prepared statement, allowing the implicit transaction to close
+        statement.reset()
+
+        // truncate succeeds
+        try db.run("pragma wal_checkpoint(truncate)")
+    }
+
 }

From dd3e813577b8b6ba363b12cff024dd633e9e29ab Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Fri, 22 Jul 2022 12:37:48 +0200
Subject: [PATCH 532/685] Create FUNDING.yml

---
 .github/FUNDING.yml | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 .github/FUNDING.yml

diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 00000000..119ccc65
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1 @@
+github: [stephencelis, jberkel, NathanFallet]

From ac1988c9663e8c5f64d21b255d91c154a30e2f35 Mon Sep 17 00:00:00 2001
From: Adam Wulf <adam.wulf@gmail.com>
Date: Fri, 22 Jul 2022 14:12:11 -0500
Subject: [PATCH 533/685] Test cleanup for statement reset

---
 Tests/SQLiteTests/StatementTests.swift | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/Tests/SQLiteTests/StatementTests.swift b/Tests/SQLiteTests/StatementTests.swift
index 77bc09c1..c12fe8cb 100644
--- a/Tests/SQLiteTests/StatementTests.swift
+++ b/Tests/SQLiteTests/StatementTests.swift
@@ -38,15 +38,13 @@ class StatementTests: SQLiteTestCase {
     /// Check that a statement reset will close the implicit transaction, allowing wal file to checkpoint
     func test_reset_statement() throws {
         // Remove old test db if any
-        let path = "\(NSTemporaryDirectory())/SQLite.swift Tests.sqlite3"
+        let path = temporaryFile() + ".sqlite3"
         try? FileManager.default.removeItem(atPath: path)
         try? FileManager.default.removeItem(atPath: path + "-shm")
         try? FileManager.default.removeItem(atPath: path + "-wal")
 
         // create new db on disk in wal mode
         let db = try Connection(.uri(path))
-        let url = URL(fileURLWithPath: db.description)
-        XCTAssertEqual(url.lastPathComponent, "SQLite.swift Tests.sqlite3")
         try db.run("PRAGMA journal_mode=WAL;")
 
         // create users table

From 012194b271dc32a0a9d1182edb4bea5201d8d59d Mon Sep 17 00:00:00 2001
From: Adam Wulf <adam.wulf@gmail.com>
Date: Fri, 22 Jul 2022 15:43:14 -0500
Subject: [PATCH 534/685] Adding documentation for Statement.reset().

---
 Documentation/Index.md | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index b71cdc4f..ed79f33e 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1872,6 +1872,14 @@ let stmt = try db.prepare("SELECT * FROM attachments WHERE typeConformsTo(UTI, ?
 for row in stmt.bind(kUTTypeImage) { /* ... */ }
 ```
 
+> _Note:_ Prepared queries can be reused, and long lived prepared queries should be `reset()` after each use. Otherwise, the transaction (either implicit or explicit) might be held open until the query is reset or finalized. This can affect performance. Statements are reset automatically during `deinit`.
+> 
+> ```swift
+> someObj.statement = try db.prepare("SELECT * FROM attachments WHERE typeConformsTo(UTI, ?)")
+> for row in someObj.statement.bind(kUTTypeImage) { /* ... */ }
+> someObj.statement.reset()
+> ```
+
 [UTTypeConformsTo]: https://developer.apple.com/documentation/coreservices/1444079-uttypeconformsto
 
 ## Custom Aggregations

From 58fd9dc1b6db7544135af10ced07f720e2dc36ac Mon Sep 17 00:00:00 2001
From: Adam Wulf <adam.wulf@gmail.com>
Date: Fri, 22 Jul 2022 15:43:42 -0500
Subject: [PATCH 535/685] Fix close of markdown code block

---
 Documentation/Index.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index ed79f33e..2a877a71 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -828,7 +828,7 @@ let query = try db.prepare(users)
 for user in query {
     // 💥 can throw an error here
 }
-````
+```
 
 #### Failable iteration
 

From 7b3de3d24b3eaea797a3db1b5a6373196edd4561 Mon Sep 17 00:00:00 2001
From: Adam Wulf <adam.wulf@gmail.com>
Date: Fri, 22 Jul 2022 15:48:15 -0500
Subject: [PATCH 536/685] Add link to relevant sqlite.org documentation page

---
 Documentation/Index.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 2a877a71..29b18c96 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1872,7 +1872,7 @@ let stmt = try db.prepare("SELECT * FROM attachments WHERE typeConformsTo(UTI, ?
 for row in stmt.bind(kUTTypeImage) { /* ... */ }
 ```
 
-> _Note:_ Prepared queries can be reused, and long lived prepared queries should be `reset()` after each use. Otherwise, the transaction (either implicit or explicit) might be held open until the query is reset or finalized. This can affect performance. Statements are reset automatically during `deinit`.
+> _Note:_ Prepared queries can be reused, and long lived prepared queries should be `reset()` after each use. Otherwise, the transaction (either [implicit or explicit](https://www.sqlite.org/lang_transaction.html#implicit_versus_explicit_transactions)) will be held open until the query is reset or finalized. This can affect performance. Statements are reset automatically during `deinit`.
 > 
 > ```swift
 > someObj.statement = try db.prepare("SELECT * FROM attachments WHERE typeConformsTo(UTI, ?)")

From 5a30f299c41f335a0745b0eab773db4f3ee184af Mon Sep 17 00:00:00 2001
From: Adam Wulf <adam.wulf@gmail.com>
Date: Fri, 22 Jul 2022 17:45:52 -0500
Subject: [PATCH 537/685] cleanup test for Statement.reset()

---
 Tests/SQLiteTests/StatementTests.swift | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/Tests/SQLiteTests/StatementTests.swift b/Tests/SQLiteTests/StatementTests.swift
index c12fe8cb..b3048211 100644
--- a/Tests/SQLiteTests/StatementTests.swift
+++ b/Tests/SQLiteTests/StatementTests.swift
@@ -37,13 +37,8 @@ class StatementTests: SQLiteTestCase {
 
     /// Check that a statement reset will close the implicit transaction, allowing wal file to checkpoint
     func test_reset_statement() throws {
-        // Remove old test db if any
-        let path = temporaryFile() + ".sqlite3"
-        try? FileManager.default.removeItem(atPath: path)
-        try? FileManager.default.removeItem(atPath: path + "-shm")
-        try? FileManager.default.removeItem(atPath: path + "-wal")
-
         // create new db on disk in wal mode
+        let path = temporaryFile() + ".sqlite3"
         let db = try Connection(.uri(path))
         try db.run("PRAGMA journal_mode=WAL;")
 
@@ -70,9 +65,7 @@ class StatementTests: SQLiteTestCase {
         // prevents the implicit transaction from closing.
         // https://www.sqlite.org/lang_transaction.html#implicit_versus_explicit_transactions
         let statement = try db.prepare("SELECT email FROM users")
-        XCTAssert(try statement.step())
-        let blob = statement.row[0] as Blob
-        XCTAssertEqual("alice@example.com", String(bytes: blob.bytes, encoding: .utf8)!)
+        _ = try statement.step()
 
         // verify that the transaction is not closed, which prevents wal_checkpoints (both explicit and auto)
         do {

From efa5fcb5c24352d266e9a87075dbfb3e1c5fd7ea Mon Sep 17 00:00:00 2001
From: Adam Wulf <adam.wulf@gmail.com>
Date: Fri, 22 Jul 2022 17:47:46 -0500
Subject: [PATCH 538/685] Better check for throwing error in test

---
 Tests/SQLiteTests/StatementTests.swift | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/Tests/SQLiteTests/StatementTests.swift b/Tests/SQLiteTests/StatementTests.swift
index b3048211..e41fa714 100644
--- a/Tests/SQLiteTests/StatementTests.swift
+++ b/Tests/SQLiteTests/StatementTests.swift
@@ -68,12 +68,7 @@ class StatementTests: SQLiteTestCase {
         _ = try statement.step()
 
         // verify that the transaction is not closed, which prevents wal_checkpoints (both explicit and auto)
-        do {
-            try db.run("pragma wal_checkpoint(truncate)")
-            XCTFail("Database should be locked")
-        } catch {
-            // pass
-        }
+        XCTAssertThrowsError(try db.run("pragma wal_checkpoint(truncate)"))
 
         // reset the prepared statement, allowing the implicit transaction to close
         statement.reset()

From da0cd09219fe02d22c721637bc55d0ce600821ff Mon Sep 17 00:00:00 2001
From: Adam Wulf <adam.wulf@gmail.com>
Date: Fri, 22 Jul 2022 19:25:52 -0500
Subject: [PATCH 539/685] Remove unneeded wal mode

---
 Tests/SQLiteTests/StatementTests.swift | 1 -
 1 file changed, 1 deletion(-)

diff --git a/Tests/SQLiteTests/StatementTests.swift b/Tests/SQLiteTests/StatementTests.swift
index e41fa714..3cc68aca 100644
--- a/Tests/SQLiteTests/StatementTests.swift
+++ b/Tests/SQLiteTests/StatementTests.swift
@@ -40,7 +40,6 @@ class StatementTests: SQLiteTestCase {
         // create new db on disk in wal mode
         let path = temporaryFile() + ".sqlite3"
         let db = try Connection(.uri(path))
-        try db.run("PRAGMA journal_mode=WAL;")
 
         // create users table
         try db.execute("""

From 210303f7b21f829bf82e17f41a8f912742ea2be3 Mon Sep 17 00:00:00 2001
From: Adam Wulf <adam.wulf@gmail.com>
Date: Sat, 23 Jul 2022 15:19:10 -0500
Subject: [PATCH 540/685] Use in memory database from test setup, verify error
 when statement isn't reset, update comments

---
 Tests/SQLiteTests/StatementTests.swift | 46 ++++++++++++--------------
 1 file changed, 21 insertions(+), 25 deletions(-)

diff --git a/Tests/SQLiteTests/StatementTests.swift b/Tests/SQLiteTests/StatementTests.swift
index 3cc68aca..bc100cd2 100644
--- a/Tests/SQLiteTests/StatementTests.swift
+++ b/Tests/SQLiteTests/StatementTests.swift
@@ -1,6 +1,16 @@
 import XCTest
 import SQLite
 
+#if SQLITE_SWIFT_STANDALONE
+import sqlite3
+#elseif SQLITE_SWIFT_SQLCIPHER
+import SQLCipher
+#elseif os(Linux)
+import CSQLite
+#else
+import SQLite3
+#endif
+
 class StatementTests: SQLiteTestCase {
     override func setUpWithError() throws {
         try super.setUpWithError()
@@ -37,28 +47,8 @@ class StatementTests: SQLiteTestCase {
 
     /// Check that a statement reset will close the implicit transaction, allowing wal file to checkpoint
     func test_reset_statement() throws {
-        // create new db on disk in wal mode
-        let path = temporaryFile() + ".sqlite3"
-        let db = try Connection(.uri(path))
-
-        // create users table
-        try db.execute("""
-            CREATE TABLE users (
-                id INTEGER PRIMARY KEY,
-                email TEXT NOT NULL UNIQUE,
-                age INTEGER,
-                salary REAL,
-                admin BOOLEAN NOT NULL DEFAULT 0 CHECK (admin IN (0, 1)),
-                manager_id INTEGER,
-                created_at DATETIME,
-                FOREIGN KEY(manager_id) REFERENCES users(id)
-            )
-            """
-        )
-
         // insert single row
-        try db.run("INSERT INTO \"users\" (email, age, admin) values (?, ?, ?)",
-                   "alice@example.com", 1.datatypeValue, false.datatypeValue)
+        try insertUsers("bob")
 
         // prepare a statement and read a single row. This will incremeent the cursor which
         // prevents the implicit transaction from closing.
@@ -66,14 +56,20 @@ class StatementTests: SQLiteTestCase {
         let statement = try db.prepare("SELECT email FROM users")
         _ = try statement.step()
 
-        // verify that the transaction is not closed, which prevents wal_checkpoints (both explicit and auto)
-        XCTAssertThrowsError(try db.run("pragma wal_checkpoint(truncate)"))
+        // verify implicit transaction is not closed, and the users table is still locked
+        XCTAssertThrowsError(try db.run("DROP TABLE users")) { error in
+            if case let Result.error(_, code, _) = error {
+                XCTAssertEqual(code, SQLITE_LOCKED)
+            } else {
+                XCTFail("unexpected error")
+            }
+        }
 
-        // reset the prepared statement, allowing the implicit transaction to close
+        // reset the prepared statement, unlocking the table and allowing the implicit transaction to close
         statement.reset()
 
         // truncate succeeds
-        try db.run("pragma wal_checkpoint(truncate)")
+        try db.run("DROP TABLE users")
     }
 
 }

From d970a11bd66747fd3b67d8ce072d944fca03b341 Mon Sep 17 00:00:00 2001
From: Adam Wulf <adam.wulf@gmail.com>
Date: Sat, 23 Jul 2022 15:21:03 -0500
Subject: [PATCH 541/685] typo

---
 Tests/SQLiteTests/StatementTests.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Tests/SQLiteTests/StatementTests.swift b/Tests/SQLiteTests/StatementTests.swift
index bc100cd2..eeb513fe 100644
--- a/Tests/SQLiteTests/StatementTests.swift
+++ b/Tests/SQLiteTests/StatementTests.swift
@@ -50,7 +50,7 @@ class StatementTests: SQLiteTestCase {
         // insert single row
         try insertUsers("bob")
 
-        // prepare a statement and read a single row. This will incremeent the cursor which
+        // prepare a statement and read a single row. This will increment the cursor which
         // prevents the implicit transaction from closing.
         // https://www.sqlite.org/lang_transaction.html#implicit_versus_explicit_transactions
         let statement = try db.prepare("SELECT email FROM users")

From 5c66460cb97375d9cdc68364afe8e6db434f6cb9 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 23 Jul 2022 22:21:59 +0200
Subject: [PATCH 542/685] Adds SchemaChanger to perform database schema changes

---
 SQLite.xcodeproj/project.pbxproj              |  70 ++++
 Sources/SQLite/Schema/Connection+Schema.swift | 145 ++++++++
 Sources/SQLite/Schema/SchemaChanger.swift     | 231 ++++++++++++
 Sources/SQLite/Schema/SchemaDefinitions.swift | 336 +++++++++++++++++
 .../Schema/ConnectionSchemaTests.swift        | 139 +++++++
 .../Schema/SchemaChangerTests.swift           |  87 +++++
 .../Schema/SchemaDefinitionsTests.swift       | 342 ++++++++++++++++++
 7 files changed, 1350 insertions(+)
 create mode 100644 Sources/SQLite/Schema/Connection+Schema.swift
 create mode 100644 Sources/SQLite/Schema/SchemaChanger.swift
 create mode 100644 Sources/SQLite/Schema/SchemaDefinitions.swift
 create mode 100644 Tests/SQLiteTests/Schema/ConnectionSchemaTests.swift
 create mode 100644 Tests/SQLiteTests/Schema/SchemaChangerTests.swift
 create mode 100644 Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 2656ed6a..abd69301 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -51,24 +51,33 @@
 		19A170ACC97B19730FB7BA4D /* Connection+Aggregation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */; };
 		19A17152E32A9585831E3FE0 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
 		19A1717B10CC941ACB5533D6 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
+		19A17188B4D96636F9C0C209 /* ConnectionSchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17CA1DF7D0F7C9A94C51C /* ConnectionSchemaTests.swift */; };
 		19A171967CC511C4F6F773C9 /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */; };
 		19A171BE056457F13BFBC4C3 /* FTSIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171FDE4D67879B14ACBDF /* FTSIntegrationTests.swift */; };
 		19A171E6FA242F72A308C594 /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
 		19A171F12AB8B07F2FD7201A /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
 		19A1720B67ED13E6150C6A3D /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */; };
 		19A17254FBA7894891F7297B /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
+		19A1725658E480B9B378F28B /* ConnectionSchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17CA1DF7D0F7C9A94C51C /* ConnectionSchemaTests.swift */; };
 		19A172A9B536D02D4A98AAAD /* QueryIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */; };
 		19A172EB202970561E5C4245 /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */; };
 		19A173668D948AD4DF1F5352 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
 		19A1737286A74F3CF7412906 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
 		19A173EFEF0B3BD0B3ED406C /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17E723300E5ED3771DCB5 /* Result.swift */; };
 		19A17408007B182F884E3A53 /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; };
+		19A1740EACD47904AA24B8DC /* SchemaDefinitions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17268AE67B746B96AC125 /* SchemaDefinitions.swift */; };
+		19A174506543905D71BF0518 /* Connection+Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A170A97B51DC5EE365F3C5 /* Connection+Schema.swift */; };
 		19A17490543609FCED53CACC /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
 		19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
 		19A1750CEE9B05267995CF3D /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
+		19A1750EF4A5F92954A451FF /* Connection+Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A170A97B51DC5EE365F3C5 /* Connection+Schema.swift */; };
 		19A176376CB6A94759F7980A /* Connection+Aggregation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */; };
 		19A176406BDE9D9C80CC9FA3 /* QueryIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */; };
+		19A1766AC10D13C4EFF349AD /* SchemaChangerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17FDB0B0CFB8987906FD0 /* SchemaChangerTests.swift */; };
 		19A1769C1F3A7542BECF50FF /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */; };
+		19A177290558991BCC60E4E3 /* SchemaChanger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171B262DDE8718513CFDA /* SchemaChanger.swift */; };
+		19A1773A335CAB9D0AE14E8E /* SchemaChanger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171B262DDE8718513CFDA /* SchemaChanger.swift */; };
+		19A177C25834473FAB32CF3B /* SchemaChangerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17FDB0B0CFB8987906FD0 /* SchemaChangerTests.swift */; };
 		19A177CC33F2E6A24AF90B02 /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
 		19A178072B371489E6A1E839 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
 		19A17835FD5886FDC5A3228F /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
@@ -78,19 +87,31 @@
 		19A179B59450FE7C4811AB8A /* Connection+Aggregation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */; };
 		19A179CCF9671E345E5A9811 /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
 		19A179E76EA6207669B60C1B /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
+		19A17A33EA026C2E2CEBAF36 /* Connection+Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A170A97B51DC5EE365F3C5 /* Connection+Schema.swift */; };
+		19A17B0DF1DDB6BBC9C95D64 /* SchemaDefinitions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17268AE67B746B96AC125 /* SchemaDefinitions.swift */; };
+		19A17B36ABC6006AB80F693C /* ConnectionSchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17CA1DF7D0F7C9A94C51C /* ConnectionSchemaTests.swift */; };
+		19A17B62A4125AF4F6014CF5 /* SchemaDefinitionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A176174862D0F0139B3987 /* SchemaDefinitionsTests.swift */; };
+		19A17BA13FD35F058787B7D3 /* SchemaDefinitions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17268AE67B746B96AC125 /* SchemaDefinitions.swift */; };
 		19A17C013B00682B70D53DB8 /* FTSIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171FDE4D67879B14ACBDF /* FTSIntegrationTests.swift */; };
 		19A17C4B951CB054EE48AB1C /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
 		19A17C80076860CF7751A056 /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */; };
 		19A17C9407AC0EE104E5CC85 /* FTSIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171FDE4D67879B14ACBDF /* FTSIntegrationTests.swift */; };
 		19A17CB808ACF606726E77A8 /* QueryIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */; };
+		19A17D1BEABA610ABF003D67 /* SchemaDefinitions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17268AE67B746B96AC125 /* SchemaDefinitions.swift */; };
 		19A17DC282E36C4F41AA440B /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
 		19A17DF8D4F13A20F5D2269E /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17E723300E5ED3771DCB5 /* Result.swift */; };
+		19A17DFE05ED8B1F7C45F7EE /* SchemaChanger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171B262DDE8718513CFDA /* SchemaChanger.swift */; };
 		19A17E04C4C0956715C5676A /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
 		19A17E29278A12BC4F542506 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
+		19A17E80F736EEE8EE2AA4CE /* SchemaDefinitionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A176174862D0F0139B3987 /* SchemaDefinitionsTests.swift */; };
 		19A17EC0D68BA8C03288ADF7 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
+		19A17F0BF02896E1664F4090 /* Connection+Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A170A97B51DC5EE365F3C5 /* Connection+Schema.swift */; };
 		19A17F1B3F0A3C96B5ED6D64 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17E723300E5ED3771DCB5 /* Result.swift */; };
 		19A17F60B685636D1F83C2DD /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; };
 		19A17FB80B94E882050AA908 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
+		19A17FC04708C6ED637DDFD4 /* SchemaChangerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17FDB0B0CFB8987906FD0 /* SchemaChangerTests.swift */; };
+		19A17FC07731779C1B8506FA /* SchemaChanger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171B262DDE8718513CFDA /* SchemaChanger.swift */; };
+		19A17FE78A39E86F330420EC /* SchemaDefinitionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A176174862D0F0139B3987 /* SchemaDefinitionsTests.swift */; };
 		19A17FF4A10B44D3937C8CAC /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
 		3717F908221F5D8800B9BD3D /* CustomAggregationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */; };
 		3717F909221F5D8900B9BD3D /* CustomAggregationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */; };
@@ -241,22 +262,28 @@
 		03A65E5A1C6BB0F50062603F /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		03A65E631C6BB0F60062603F /* SQLiteTests tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SQLiteTests tvOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
 		03A65E961C6BB3210062603F /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
+		19A170A97B51DC5EE365F3C5 /* Connection+Schema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Connection+Schema.swift"; sourceTree = "<group>"; };
 		19A1710E73A46D5AC721CDA9 /* Errors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = "<group>"; };
+		19A171B262DDE8718513CFDA /* SchemaChanger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaChanger.swift; sourceTree = "<group>"; };
 		19A171FDE4D67879B14ACBDF /* FTSIntegrationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTSIntegrationTests.swift; sourceTree = "<group>"; };
 		19A1721B8984686B9963B45D /* FTS5Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5Tests.swift; sourceTree = "<group>"; };
+		19A17268AE67B746B96AC125 /* SchemaDefinitions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaDefinitions.swift; sourceTree = "<group>"; };
 		19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAndTimeFunctionTests.swift; sourceTree = "<group>"; };
 		19A1730E4390C775C25677D1 /* FTS5.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5.swift; sourceTree = "<group>"; };
 		19A17399EA9E61235D5D77BF /* CipherTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CipherTests.swift; sourceTree = "<group>"; };
 		19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Connection+Aggregation.swift"; sourceTree = "<group>"; };
 		19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RowTests.swift; sourceTree = "<group>"; };
+		19A176174862D0F0139B3987 /* SchemaDefinitionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaDefinitionsTests.swift; sourceTree = "<group>"; };
 		19A178A39ACA9667A62663CC /* Cipher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cipher.swift; sourceTree = "<group>"; };
 		19A1794B7972D14330A65BBD /* Linux.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Linux.md; sourceTree = "<group>"; };
 		19A1794CC4D7827E997E32A7 /* FoundationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationTests.swift; sourceTree = "<group>"; };
 		19A17B93B48B5560E6E51791 /* Fixtures.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Fixtures.swift; sourceTree = "<group>"; };
 		19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAndTimeFunctions.swift; sourceTree = "<group>"; };
 		19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryIntegrationTests.swift; sourceTree = "<group>"; };
+		19A17CA1DF7D0F7C9A94C51C /* ConnectionSchemaTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectionSchemaTests.swift; sourceTree = "<group>"; };
 		19A17E723300E5ED3771DCB5 /* Result.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Result.swift; sourceTree = "<group>"; };
 		19A17EA3A313F129011B3FA0 /* Release.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Release.md; sourceTree = "<group>"; };
+		19A17FDB0B0CFB8987906FD0 /* SchemaChangerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaChangerTests.swift; sourceTree = "<group>"; };
 		3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomAggregationTests.swift; sourceTree = "<group>"; };
 		3D3C3CCB26E5568800759140 /* SQLite.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = SQLite.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
 		3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.0.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
@@ -381,6 +408,26 @@
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
+		19A1792D261C689FC988A90A /* Schema */ = {
+			isa = PBXGroup;
+			children = (
+				19A171B262DDE8718513CFDA /* SchemaChanger.swift */,
+				19A17268AE67B746B96AC125 /* SchemaDefinitions.swift */,
+				19A170A97B51DC5EE365F3C5 /* Connection+Schema.swift */,
+			);
+			path = Schema;
+			sourceTree = "<group>";
+		};
+		19A17B56FBA20E7245BC8AC0 /* Schema */ = {
+			isa = PBXGroup;
+			children = (
+				19A176174862D0F0139B3987 /* SchemaDefinitionsTests.swift */,
+				19A17FDB0B0CFB8987906FD0 /* SchemaChangerTests.swift */,
+				19A17CA1DF7D0F7C9A94C51C /* ConnectionSchemaTests.swift */,
+			);
+			path = Schema;
+			sourceTree = "<group>";
+		};
 		3D67B3E41DB2469200A4F4C6 /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
@@ -427,6 +474,7 @@
 				EE247AED1C3F06E900AE3E12 /* Core */,
 				EE247AF41C3F06E900AE3E12 /* Extensions */,
 				EE247AF91C3F06E900AE3E12 /* Typed */,
+				19A1792D261C689FC988A90A /* Schema */,
 			);
 			name = SQLite;
 			path = Sources/SQLite;
@@ -463,6 +511,7 @@
 				19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */,
 				19A171FDE4D67879B14ACBDF /* FTSIntegrationTests.swift */,
 				3DF7B78C28842C23005DD8CA /* ResultTests.swift */,
+				19A17B56FBA20E7245BC8AC0 /* Schema */,
 			);
 			name = SQLiteTests;
 			path = Tests/SQLiteTests;
@@ -868,6 +917,9 @@
 				19A17073552293CA063BEA66 /* Result.swift in Sources */,
 				997DF2B0287FC06D00F8DF95 /* Query+with.swift in Sources */,
 				19A179B59450FE7C4811AB8A /* Connection+Aggregation.swift in Sources */,
+				19A17FC07731779C1B8506FA /* SchemaChanger.swift in Sources */,
+				19A1740EACD47904AA24B8DC /* SchemaDefinitions.swift in Sources */,
+				19A1750EF4A5F92954A451FF /* Connection+Schema.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -901,6 +953,9 @@
 				D4DB368E20C09CFD00D5A58E /* SelectTests.swift in Sources */,
 				19A17CB808ACF606726E77A8 /* QueryIntegrationTests.swift in Sources */,
 				19A17C9407AC0EE104E5CC85 /* FTSIntegrationTests.swift in Sources */,
+				19A17B62A4125AF4F6014CF5 /* SchemaDefinitionsTests.swift in Sources */,
+				19A17FC04708C6ED637DDFD4 /* SchemaChangerTests.swift in Sources */,
+				19A17188B4D96636F9C0C209 /* ConnectionSchemaTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -935,6 +990,9 @@
 				19A17DC282E36C4F41AA440B /* Errors.swift in Sources */,
 				19A173668D948AD4DF1F5352 /* DateAndTimeFunctions.swift in Sources */,
 				19A17DF8D4F13A20F5D2269E /* Result.swift in Sources */,
+				19A17DFE05ED8B1F7C45F7EE /* SchemaChanger.swift in Sources */,
+				19A17D1BEABA610ABF003D67 /* SchemaDefinitions.swift in Sources */,
+				19A17A33EA026C2E2CEBAF36 /* Connection+Schema.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -970,6 +1028,9 @@
 				19A173EFEF0B3BD0B3ED406C /* Result.swift in Sources */,
 				997DF2AE287FC06D00F8DF95 /* Query+with.swift in Sources */,
 				19A176376CB6A94759F7980A /* Connection+Aggregation.swift in Sources */,
+				19A1773A335CAB9D0AE14E8E /* SchemaChanger.swift in Sources */,
+				19A17BA13FD35F058787B7D3 /* SchemaDefinitions.swift in Sources */,
+				19A174506543905D71BF0518 /* Connection+Schema.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1003,6 +1064,9 @@
 				D4DB368C20C09CFB00D5A58E /* SelectTests.swift in Sources */,
 				19A172A9B536D02D4A98AAAD /* QueryIntegrationTests.swift in Sources */,
 				19A17C013B00682B70D53DB8 /* FTSIntegrationTests.swift in Sources */,
+				19A17FE78A39E86F330420EC /* SchemaDefinitionsTests.swift in Sources */,
+				19A177C25834473FAB32CF3B /* SchemaChangerTests.swift in Sources */,
+				19A1725658E480B9B378F28B /* ConnectionSchemaTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1038,6 +1102,9 @@
 				19A17F1B3F0A3C96B5ED6D64 /* Result.swift in Sources */,
 				997DF2AF287FC06D00F8DF95 /* Query+with.swift in Sources */,
 				19A170ACC97B19730FB7BA4D /* Connection+Aggregation.swift in Sources */,
+				19A177290558991BCC60E4E3 /* SchemaChanger.swift in Sources */,
+				19A17B0DF1DDB6BBC9C95D64 /* SchemaDefinitions.swift in Sources */,
+				19A17F0BF02896E1664F4090 /* Connection+Schema.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1071,6 +1138,9 @@
 				D4DB368D20C09CFC00D5A58E /* SelectTests.swift in Sources */,
 				19A176406BDE9D9C80CC9FA3 /* QueryIntegrationTests.swift in Sources */,
 				19A171BE056457F13BFBC4C3 /* FTSIntegrationTests.swift in Sources */,
+				19A17E80F736EEE8EE2AA4CE /* SchemaDefinitionsTests.swift in Sources */,
+				19A1766AC10D13C4EFF349AD /* SchemaChangerTests.swift in Sources */,
+				19A17B36ABC6006AB80F693C /* ConnectionSchemaTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/Sources/SQLite/Schema/Connection+Schema.swift b/Sources/SQLite/Schema/Connection+Schema.swift
new file mode 100644
index 00000000..e368bdaf
--- /dev/null
+++ b/Sources/SQLite/Schema/Connection+Schema.swift
@@ -0,0 +1,145 @@
+import Foundation
+
+extension Connection {
+    // Changing the foreign_keys setting affects the execution of all statements prepared using the database
+    // connection, including those prepared before the setting was changed.
+    //
+    // https://sqlite.org/pragma.html#pragma_foreign_keys
+    var foreignKeys: Bool {
+        get { getBoolPragma("foreign_keys") }
+        set { setBoolPragma("foreign_keys", newValue) }
+    }
+
+    var deferForeignKeys: Bool {
+        get { getBoolPragma("defer_foreign_keys") }
+        set { setBoolPragma("defer_foreign_keys", newValue) }
+    }
+
+    // https://sqlite.org/pragma.html#pragma_foreign_key_check
+
+    // There are four columns in each result row.
+    // The first column is the name of the table that
+    // contains the REFERENCES clause.
+    // The second column is the rowid of the row that contains the
+    // invalid REFERENCES clause, or NULL if the child table is a WITHOUT ROWID table.
+    // The third column is the name of the table that is referred to.
+    // The fourth column is the index of the specific foreign key constraint that failed.
+    func foreignKeyCheck() throws -> [ForeignKeyError] {
+        try run("PRAGMA foreign_key_check").compactMap { row -> ForeignKeyError? in
+            guard let table = row[0] as? String,
+                  let rowId = row[1] as? Int64,
+                  let target = row[2] as? String else { return nil }
+
+            return ForeignKeyError(from: table, rowId: rowId, to: target)
+        }
+    }
+
+    // https://sqlite.org/pragma.html#pragma_table_info
+    //
+    // This pragma returns one row for each column in the named table. Columns in the result set include the
+    // column name, data type, whether or not the column can be NULL, and the default value for the column. The
+    // "pk" column in the result set is zero for columns that are not part of the primary key, and is the
+    // index of the column in the primary key for columns that are part of the primary key.
+    func columnInfo(table: String) throws  -> [ColumnDefinition] {
+        func parsePrimaryKey(column: String) throws -> ColumnDefinition.PrimaryKey? {
+            try createTableSQL(name: table).flatMap { .init(sql: $0) }
+        }
+
+        let foreignKeys: [String: [ForeignKeyDefinition]] =
+            Dictionary(grouping: try foreignKeyInfo(table: table), by: { $0.column })
+
+        return try run("PRAGMA table_info(\(table.quote()))").compactMap { row -> ColumnDefinition? in
+            guard let name = row[1] as? String,
+                  let type = row[2] as? String,
+                  let notNull = row[3] as? Int64,
+                  let defaultValue = row[4] as? String?,
+                  let primaryKey = row[5] as? Int64 else { return nil }
+            return ColumnDefinition(name: name,
+                                    primaryKey: primaryKey == 1 ? try parsePrimaryKey(column: name) : nil,
+                                    type: ColumnDefinition.Affinity.from(type),
+                                    null: notNull == 0,
+                                    defaultValue: LiteralValue.from(defaultValue),
+                                    references: foreignKeys[name]?.first)
+        }
+    }
+
+    func indexInfo(table: String) throws -> [IndexDefinition] {
+        func indexSQL(name: String) throws  -> String? {
+            try run("""
+                    SELECT sql FROM sqlite_master WHERE name=? AND type='index'
+                      UNION ALL
+                    SELECT sql FROM sqlite_temp_master WHERE name=? AND type='index'
+                    """, name, name)
+                    .compactMap { row in row[0] as? String }
+                    .first
+        }
+
+        func columns(name: String) throws -> [String] {
+            try run("PRAGMA index_info(\(name.quote()))").compactMap { row in
+                row[2] as? String
+            }
+        }
+
+        return try run("PRAGMA index_list(\(table.quote()))").compactMap { row -> IndexDefinition? in
+            guard let name = row[1] as? String,
+                  let unique = row[2] as? Int64,
+                    // Indexes SQLite creates implicitly for internal use start with "sqlite_".
+                    // See https://www.sqlite.org/fileformat2.html#intschema
+                  !name.starts(with: "sqlite_") else {
+                return nil
+            }
+            return .init(table: table,
+                         name: name,
+                         unique: unique == 1,
+                         columns: try columns(name: name),
+                         indexSQL: try indexSQL(name: name))
+        }
+    }
+
+    func tableInfo() throws -> [String] {
+        try run("SELECT tbl_name FROM sqlite_master WHERE type = 'table'").compactMap { row in
+            if let name = row[0] as? String, !name.starts(with: "sqlite_") {
+                return name
+            } else {
+                return nil
+            }
+        }
+    }
+
+    func foreignKeyInfo(table: String) throws -> [ForeignKeyDefinition] {
+        try run("PRAGMA foreign_key_list(\(table.quote()))").compactMap { row in
+            if let table = row[2] as? String,      // table
+               let column = row[3] as? String,     // from
+               let primaryKey = row[4] as? String, // to
+               let onUpdate = row[5] as? String,
+               let onDelete = row[6] as? String {
+                return ForeignKeyDefinition(table: table, column: column, primaryKey: primaryKey,
+                                            onUpdate: onUpdate == TableBuilder.Dependency.noAction.rawValue ? nil : onUpdate,
+                                            onDelete: onDelete == TableBuilder.Dependency.noAction.rawValue ? nil : onDelete
+                )
+            } else {
+                return nil
+            }
+        }
+    }
+
+    private func createTableSQL(name: String) throws  -> String? {
+        try run("""
+                SELECT sql FROM sqlite_master WHERE name=? AND type='table'
+                  UNION ALL
+                SELECT sql FROM sqlite_temp_master WHERE name=? AND type='table'
+        """, name, name)
+            .compactMap { row in row[0] as? String }
+            .first
+    }
+
+    private func getBoolPragma(_ key: String) -> Bool {
+        guard let binding = try? scalar("PRAGMA \(key)"),
+              let intBinding = binding as? Int64 else { return false }
+        return intBinding == 1
+    }
+
+    private func setBoolPragma(_ key: String, _ newValue: Bool) {
+        _ = try? run("PRAGMA \(key) = \(newValue ? "1" : "0")")
+    }
+}
diff --git a/Sources/SQLite/Schema/SchemaChanger.swift b/Sources/SQLite/Schema/SchemaChanger.swift
new file mode 100644
index 00000000..ff0befc3
--- /dev/null
+++ b/Sources/SQLite/Schema/SchemaChanger.swift
@@ -0,0 +1,231 @@
+import Foundation
+
+/*
+    https://www.sqlite.org/lang_altertable.html
+
+   The only schema altering commands directly supported by SQLite are the "rename table" and "add column"
+   commands shown above.
+
+    (SQLite 3.25.0: RENAME COLUMN)
+    (SQLite 3.35.0: DROP COLUMN)
+
+   However, applications can make other arbitrary changes to the format of a table using a
+   simple sequence of operations. The steps to make arbitrary changes to the schema design of some table X are as follows:
+
+        1. If foreign key constraints are enabled, disable them using PRAGMA foreign_keys=OFF.
+        2. Start a transaction.
+        3. Remember the format of all indexes and triggers associated with table X
+           (SELECT sql FROM sqlite_master WHERE tbl_name='X' AND type='index')
+        4. Use CREATE TABLE to construct a new table "new_X" that is in the desired revised format of table X.
+        5. Transfer content from X into new_X using a statement like: INSERT INTO new_X SELECT ... FROM X.
+        6. Drop the old table X: DROP TABLE X.
+        7. Change the name of new_X to X using: ALTER TABLE new_X RENAME TO X.
+        8. Use CREATE INDEX and CREATE TRIGGER to reconstruct indexes and triggers associated with table X.
+        9. If any views refer to table X in a way that is affected by the schema change, then drop those views using DROP VIEW
+       10. If foreign key constraints were originally enabled then run PRAGMA foreign_key_check
+       11. Commit the transaction started in step 2.
+       12. If foreign keys constraints were originally enabled, reenable them now.
+*/
+public class SchemaChanger: CustomStringConvertible {
+    enum SchemaChangeError: LocalizedError {
+        case foreignKeyError([ForeignKeyError])
+
+        var errorDescription: String? {
+            switch self {
+            case .foreignKeyError(let errors):
+                return "Foreign key errors: \(errors)"
+            }
+        }
+    }
+
+    public enum Operation {
+        case none
+        case add(ColumnDefinition)
+        case remove(String)
+        case renameColumn(String, String)
+        case renameTable(String)
+
+        /// Returns non-nil if the operation can be executed with a simple SQL statement
+        func toSQL(_ table: String) -> String? {
+            switch self {
+            case .add(let definition): return "ALTER TABLE \(table.quote()) ADD COLUMN \(definition.toSQL())"
+            default: return nil
+            }
+        }
+    }
+
+    public class AlterTableDefinition {
+        fileprivate var operations: [Operation] = []
+
+        let name: String
+
+        init(name: String) {
+            self.name = name
+        }
+
+        public func add(_ column: ColumnDefinition) {
+            operations.append(.add(column))
+        }
+
+        public func remove(_ column: String) {
+            operations.append(.remove(column))
+        }
+
+        public func rename(_ column: String, to: String) {
+            operations.append(.renameColumn(column, to))
+        }
+    }
+
+    private let connection: Connection
+    static let tempPrefix = "tmp_"
+    typealias Block = () throws -> Void
+    public typealias AlterTableDefinitionBlock = (AlterTableDefinition) -> Void
+
+    struct Options: OptionSet {
+        let rawValue: Int
+        static let `default`: Options = []
+        static let temp = Options(rawValue: 1)
+    }
+
+    public init(connection: Connection) {
+        self.connection = connection
+    }
+
+    public func alter(table: String, block: AlterTableDefinitionBlock) throws {
+        let alterTableDefinition = AlterTableDefinition(name: table)
+        block(alterTableDefinition)
+
+        for operation in alterTableDefinition.operations {
+            try run(table: table, operation: operation)
+        }
+    }
+
+    public func drop(table: String) throws {
+        try dropTable(table)
+    }
+
+    private func run(table: String, operation: Operation) throws {
+        if let sql = operation.toSQL(table) {
+            try connection.run(sql)
+        } else {
+            try doTheTableDance(table: table, operation: operation)
+        }
+    }
+
+    private func doTheTableDance(table: String, operation: Operation) throws {
+        try connection.transaction {
+            try disableRefIntegrity {
+                let tempTable = "\(SchemaChanger.tempPrefix)\(table)"
+                try moveTable(from: table, to: tempTable, options: [.temp], operation: operation)
+                try moveTable(from: tempTable, to: table)
+                let foreignKeyErrors = try connection.foreignKeyCheck()
+                if foreignKeyErrors.count > 0 {
+                    throw SchemaChangeError.foreignKeyError(foreignKeyErrors)
+                }
+            }
+        }
+    }
+
+    private func disableRefIntegrity(block: Block) throws {
+        let oldForeignKeys = connection.foreignKeys
+        let oldDeferForeignKeys = connection.deferForeignKeys
+
+        connection.deferForeignKeys = true
+        connection.foreignKeys = false
+
+        defer {
+            connection.deferForeignKeys = oldDeferForeignKeys
+            connection.foreignKeys = oldForeignKeys
+        }
+
+        try block()
+    }
+
+    private func moveTable(from: String, to: String, options: Options = .default, operation: Operation = .none) throws {
+        try copyTable(from: from, to: to, options: options, operation: operation)
+        try dropTable(from)
+    }
+
+    private func copyTable(from: String, to: String, options: Options = .default, operation: Operation) throws {
+        let fromDefinition = TableDefinition(
+            name: from,
+            columns: try connection.columnInfo(table: from),
+            indexes: try connection.indexInfo(table: from)
+        )
+        let toDefinition   = fromDefinition.apply(.renameTable(to)).apply(operation)
+
+        try createTable(definition: toDefinition, options: options)
+        try createTableIndexes(definition: toDefinition)
+        if case .remove = operation {
+            try copyTableContents(from: fromDefinition.apply(operation), to: toDefinition)
+        } else {
+            try copyTableContents(from: fromDefinition, to: toDefinition)
+        }
+    }
+
+    private func createTable(definition: TableDefinition, options: Options) throws {
+        try connection.run(definition.toSQL(temporary: options.contains(.temp)))
+    }
+
+    private func createTableIndexes(definition: TableDefinition) throws {
+        for index in definition.indexes {
+            try index.validate()
+            try connection.run(index.toSQL())
+        }
+    }
+
+    private func dropTable(_ table: String) throws {
+        try connection.run("DROP TABLE IF EXISTS \(table.quote())")
+    }
+
+    private func copyTableContents(from: TableDefinition, to: TableDefinition) throws {
+        try connection.run(from.copySQL(to: to))
+    }
+
+    public var description: String {
+        "SQLiteSchemaChanger: \(connection.description)"
+    }
+}
+
+extension IndexDefinition {
+    func renameTable(to: String) -> IndexDefinition {
+        func indexName() -> String {
+            if to.starts(with: SchemaChanger.tempPrefix) {
+                return "\(SchemaChanger.tempPrefix)\(name)"
+            } else if table.starts(with: SchemaChanger.tempPrefix) {
+                return name.replacingOccurrences(of: SchemaChanger.tempPrefix, with: "")
+            } else {
+                return name
+            }
+        }
+        return IndexDefinition(table: to, name: indexName(), unique: unique, columns: columns, where: `where`, orders: orders)
+    }
+
+    func renameColumn(from: String, to: String) -> IndexDefinition {
+        IndexDefinition(table: table, name: name, unique: unique, columns: columns.map {
+            $0 == from ? to : $0
+        }, where: `where`, orders: orders)
+    }
+}
+
+extension TableDefinition {
+    func apply(_ operation: SchemaChanger.Operation) -> TableDefinition {
+        switch operation {
+        case .none: return self
+        case .add: fatalError("Use 'ALTER TABLE ADD COLUMN (...)'")
+        case .remove(let column):
+            return TableDefinition(name: name,
+                columns: columns.filter { $0.name != column },
+                indexes: indexes.filter { !$0.columns.contains(column) }
+            )
+        case .renameColumn(let from, let to):
+            return TableDefinition(
+                name: name,
+                columns: columns.map { $0.rename(from: from, to: to) },
+                indexes: indexes.map { $0.renameColumn(from: from, to: to) }
+        )
+        case .renameTable(let to):
+            return TableDefinition(name: to, columns: columns, indexes: indexes.map { $0.renameTable(to: to) })
+        }
+    }
+}
diff --git a/Sources/SQLite/Schema/SchemaDefinitions.swift b/Sources/SQLite/Schema/SchemaDefinitions.swift
new file mode 100644
index 00000000..563ae331
--- /dev/null
+++ b/Sources/SQLite/Schema/SchemaDefinitions.swift
@@ -0,0 +1,336 @@
+import Foundation
+
+struct TableDefinition: Equatable {
+    let name: String
+    let columns: [ColumnDefinition]
+    let indexes: [IndexDefinition]
+
+    var quotedColumnList: String {
+        columns.map { $0.name.quote() }.joined(separator: ", ")
+    }
+}
+
+// https://sqlite.org/syntax/column-def.html
+// column-name -> type-name -> column-constraint*
+public struct ColumnDefinition: Equatable {
+
+    // The type affinity of a column is the recommended type for data stored in that column.
+    // The important idea here is that the type is recommended, not required. Any column can still
+    // store any type of data. It is just that some columns, given the choice, will prefer to use one
+    // storage class over another. The preferred storage class for a column is called its "affinity".
+    enum Affinity: String, CustomStringConvertible, CaseIterable {
+        case INTEGER
+        case NUMERIC
+        case REAL
+        case TEXT
+        case BLOB
+
+        var description: String {
+            rawValue
+        }
+
+        static func from(_ string: String) -> Affinity {
+            Affinity.allCases.first { $0.rawValue.lowercased() == string.lowercased() } ?? TEXT
+        }
+    }
+
+    enum OnConflict: String, CaseIterable {
+        case ROLLBACK
+        case ABORT
+        case FAIL
+        case IGNORE
+        case REPLACE
+
+        static func from(_ string: String) -> OnConflict? {
+            OnConflict.allCases.first { $0.rawValue == string }
+        }
+    }
+
+    struct PrimaryKey: Equatable {
+        let autoIncrement: Bool
+        let onConflict: OnConflict?
+
+        // swiftlint:disable:next force_try
+        static let pattern = try! NSRegularExpression(pattern: "PRIMARY KEY\\s*(?:ASC|DESC)?\\s*(?:ON CONFLICT (\\w+)?)?\\s*(AUTOINCREMENT)?")
+
+        init(autoIncrement: Bool = true, onConflict: OnConflict? = nil) {
+            self.autoIncrement = autoIncrement
+            self.onConflict = onConflict
+        }
+
+        init?(sql: String) {
+            if let match = PrimaryKey.pattern.firstMatch(in: sql, range: NSRange(location: 0, length: sql.count)) {
+                let conflict = match.range(at: 1)
+                var onConflict: ColumnDefinition.OnConflict?
+                if conflict.location != NSNotFound {
+                    onConflict = .from((sql as NSString).substring(with: conflict))
+                }
+                let autoIncrement = match.range(at: 2).location != NSNotFound
+                self.init(autoIncrement: autoIncrement, onConflict: onConflict)
+            } else {
+                return nil
+            }
+        }
+    }
+
+    let name: String
+    let primaryKey: PrimaryKey?
+    let type: Affinity
+    let null: Bool
+    let defaultValue: LiteralValue
+    let references: ForeignKeyDefinition?
+
+    func rename(from: String, to: String) -> ColumnDefinition {
+        guard from == name else { return self }
+        return ColumnDefinition(name: to, primaryKey: primaryKey, type: type, null: null, defaultValue: defaultValue, references: references)
+    }
+}
+
+enum LiteralValue: Equatable, CustomStringConvertible {
+    // swiftlint:disable force_try
+    private static let singleQuote = try! NSRegularExpression(pattern: "^'(.*)'$")
+    private static let doubleQuote = try! NSRegularExpression(pattern: "^\"(.*)\"$")
+    private static let blob        = try! NSRegularExpression(pattern: "^[xX]\'(.*)\'$")
+    // swiftlint:enable force_try
+
+    case numericLiteral(String)
+    case stringLiteral(String)
+    // BLOB literals are string literals containing hexadecimal data and preceded by a single "x" or "X"
+    // character. Example: X'53514C697465'
+    case blobLiteral(String)
+
+    // If there is no explicit DEFAULT clause attached to a column definition, then the default value of the
+    // column is NULL
+    // swiftlint:disable identifier_name
+    case NULL
+
+    // Beginning with SQLite 3.23.0 (2018-04-02), SQLite recognizes the identifiers "TRUE" and
+    // "FALSE" as boolean literals, if and only if those identifiers are not already used for some other
+    // meaning.
+    //
+    // The boolean identifiers TRUE and FALSE are usually just aliases for the integer values 1 and 0, respectively.
+    case TRUE
+    case FALSE
+    case CURRENT_TIME
+    case CURRENT_DATE
+    case CURRENT_TIMESTAMP
+    // swiftlint:enable identifier_name
+
+    static func from(_ string: String?) -> LiteralValue {
+        func parse(_ value: String) -> LiteralValue {
+            if let match = singleQuote.firstMatch(in: value, range: NSRange(location: 0, length: value.count)) {
+                return stringLiteral((value as NSString).substring(with: match.range(at: 1)).replacingOccurrences(of: "''", with: "'"))
+            } else if let match = doubleQuote.firstMatch(in: value, range: NSRange(location: 0, length: value.count)) {
+                return stringLiteral((value as NSString).substring(with: match.range(at: 1)).replacingOccurrences(of: "\"\"", with: "\""))
+            } else if let match = blob.firstMatch(in: value, range: NSRange(location: 0, length: value.count)) {
+                return blobLiteral((value as NSString).substring(with: match.range(at: 1)))
+            } else {
+                return numericLiteral(value)
+            }
+        }
+        guard let string = string else { return NULL }
+
+        switch string {
+        case "NULL": return NULL
+        case "TRUE": return TRUE
+        case "FALSE": return FALSE
+        case "CURRENT_TIME": return CURRENT_TIME
+        case "CURRENT_TIMESTAMP": return CURRENT_TIMESTAMP
+        case "CURRENT_DATE": return CURRENT_DATE
+        default: return parse(string)
+        }
+    }
+
+    var description: String {
+        switch self {
+        case .NULL: return "NULL"
+        case .TRUE: return "TRUE"
+        case .FALSE: return "FALSE"
+        case .CURRENT_TIMESTAMP: return "CURRENT_TIMESTAMP"
+        case .CURRENT_TIME: return "CURRENT_TIME"
+        case .CURRENT_DATE: return "CURRENT_DATE"
+        case .stringLiteral(let value): return value.quote("'")
+        case .blobLiteral(let value): return "X\(value.quote("'"))"
+        case .numericLiteral(let value): return value
+        }
+    }
+
+    func map<U>(block: (LiteralValue) -> U) -> U? {
+        if self == .NULL {
+            return nil
+        } else {
+            return block(self)
+        }
+    }
+}
+
+// https://sqlite.org/lang_createindex.html
+// schema-name.index-name ON table-name ( indexed-column+ ) WHERE expr
+struct IndexDefinition: Equatable {
+    // SQLite supports index names up to 64 characters.
+    static let maxIndexLength = 64
+
+    // swiftlint:disable force_try
+    static let whereRe = try! NSRegularExpression(pattern: "\\sWHERE\\s+(.+)$")
+    static let orderRe = try! NSRegularExpression(pattern: "\"?(\\w+)\"? DESC")
+    // swiftlint:enable force_try
+
+    enum Order: String { case ASC, DESC }
+
+    init(table: String, name: String, unique: Bool = false, columns: [String], `where`: String? = nil, orders: [String: Order]? = nil) {
+        self.table = table
+        self.name = name
+        self.unique = unique
+        self.columns = columns
+        self.where = `where`
+        self.orders = orders
+    }
+
+    init (table: String, name: String, unique: Bool, columns: [String], indexSQL: String?) {
+        func wherePart(sql: String) -> String? {
+            IndexDefinition.whereRe.firstMatch(in: sql, options: [], range: NSRange(location: 0, length: sql.count)).map {
+                (sql as NSString).substring(with: $0.range(at: 1))
+            }
+        }
+
+        func orders(sql: String) -> [String: IndexDefinition.Order] {
+            IndexDefinition.orderRe.matches(in: sql, range: NSRange(location: 0, length: sql.count))
+                    .reduce([String: IndexDefinition.Order]()) { (memo, result) in
+                        var memo2 = memo
+                        let column = (sql as NSString).substring(with: result.range(at: 1))
+                        memo2[column] = .DESC
+                        return memo2
+            }
+        }
+        self.init(table: table,
+                  name: name,
+                  unique: unique,
+                  columns: columns,
+                  where: indexSQL.flatMap(wherePart),
+                  orders: indexSQL.flatMap(orders))
+    }
+
+    let table: String
+    let name: String
+    let unique: Bool
+    let columns: [String]
+    let `where`: String?
+    let orders: [String: Order]?
+
+    enum IndexError: LocalizedError {
+        case tooLong(String, String)
+
+        var errorDescription: String? {
+            switch self {
+            case .tooLong(let name, let table):
+                return "Index name '\(name)' on table '\(table)' is too long; the limit is " +
+                     "\(IndexDefinition.maxIndexLength) characters"
+            }
+        }
+    }
+
+    func validate() throws {
+        if name.count > IndexDefinition.maxIndexLength {
+            throw IndexError.tooLong(name, table)
+        }
+    }
+}
+
+struct ForeignKeyDefinition: Equatable {
+    let table: String
+    let column: String
+    let primaryKey: String
+    let onUpdate: String?
+    let onDelete: String?
+}
+
+struct ForeignKeyError: CustomStringConvertible {
+    let from: String
+    let rowId: Int64
+    let to: String
+
+    var description: String {
+        "\(from) [\(rowId)] => \(to)"
+    }
+}
+
+extension TableDefinition {
+    func toSQL(temporary: Bool = false) -> String {
+        assert(columns.count > 0, "no columns to create")
+
+        return ([
+            "CREATE",
+            temporary ? "TEMPORARY" : nil,
+            "TABLE",
+            name,
+            "(",
+            columns.map { $0.toSQL() }.joined(separator: ",\n"),
+            ")"
+        ] as [String?]).compactMap { $0 }
+         .joined(separator: " ")
+    }
+
+    func copySQL(to: TableDefinition) -> String {
+        assert(columns.count > 0, "no columns to copy")
+        assert(columns.count == to.columns.count, "column counts don't match")
+        return "INSERT INTO \(to.name.quote()) (\(to.quotedColumnList)) SELECT \(quotedColumnList) FROM \(name.quote())"
+    }
+}
+
+extension ColumnDefinition {
+    func toSQL() -> String {
+        [
+            name.quote(),
+            type.rawValue,
+            defaultValue.map { "DEFAULT \($0)" },
+            primaryKey.map { $0.toSQL() },
+            null ? nil : "NOT NULL",
+            references.map { $0.toSQL() }
+        ].compactMap { $0 }
+         .joined(separator: " ")
+    }
+}
+
+extension IndexDefinition {
+    func toSQL(ifNotExists: Bool = false) -> String {
+        let commaSeparatedColumns = columns.map { (column: String) -> String in
+            column.quote() + (orders?[column].map { " \($0.rawValue)" } ?? "")
+        }.joined(separator: ", ")
+
+        return ([
+            "CREATE",
+            unique ? "UNIQUE" : nil,
+            "INDEX",
+            ifNotExists ? "IF NOT EXISTS" : nil,
+            name.quote(),
+            "ON",
+            table.quote(),
+            "(\(commaSeparatedColumns))",
+            `where`.map { "WHERE \($0)" }
+        ] as [String?]).compactMap { $0 }
+         .joined(separator: " ")
+    }
+}
+
+extension ForeignKeyDefinition {
+    func toSQL() -> String {
+        ([
+            "REFERENCES",
+            table.quote(),
+            "(\(primaryKey.quote()))",
+            onUpdate.map { "ON UPDATE \($0)" },
+            onDelete.map { "ON DELETE \($0)" }
+        ] as [String?]).compactMap { $0 }
+         .joined(separator: " ")
+    }
+}
+
+extension ColumnDefinition.PrimaryKey {
+    func toSQL() -> String {
+        [
+            "PRIMARY KEY",
+            autoIncrement ? "AUTOINCREMENT" : nil,
+            onConflict.map { "ON CONFLICT \($0.rawValue)" }
+        ].compactMap { $0 }.joined(separator: " ")
+    }
+}
diff --git a/Tests/SQLiteTests/Schema/ConnectionSchemaTests.swift b/Tests/SQLiteTests/Schema/ConnectionSchemaTests.swift
new file mode 100644
index 00000000..02321510
--- /dev/null
+++ b/Tests/SQLiteTests/Schema/ConnectionSchemaTests.swift
@@ -0,0 +1,139 @@
+import XCTest
+@testable import SQLite
+
+class ConnectionSchemaTests: SQLiteTestCase {
+
+    override func setUpWithError() throws {
+        try super.setUpWithError()
+        try createUsersTable()
+    }
+
+    func test_column_info() throws {
+        let columns = try db.columnInfo(table: "users")
+        XCTAssertEqual(columns, [
+            ColumnDefinition(name: "id",
+                             primaryKey: .init(autoIncrement: false, onConflict: nil),
+                             type: .INTEGER,
+                             null: true,
+                             defaultValue: .NULL,
+                             references: nil),
+            ColumnDefinition(name: "email",
+                             primaryKey: nil,
+                             type: .TEXT,
+                             null: false,
+                             defaultValue: .NULL,
+                             references: nil),
+            ColumnDefinition(name: "age",
+                             primaryKey: nil,
+                             type: .INTEGER,
+                             null: true,
+                             defaultValue: .NULL,
+                             references: nil),
+            ColumnDefinition(name: "salary",
+                             primaryKey: nil,
+                             type: .REAL,
+                             null: true,
+                             defaultValue: .NULL,
+                             references: nil),
+            ColumnDefinition(name: "admin",
+                             primaryKey: nil,
+                             type: .TEXT,
+                             null: false,
+                             defaultValue: .numericLiteral("0"),
+                             references: nil),
+            ColumnDefinition(name: "manager_id",
+                             primaryKey: nil, type: .INTEGER,
+                             null: true,
+                             defaultValue: .NULL,
+                             references: .init(table: "users", column: "manager_id", primaryKey: "id", onUpdate: nil, onDelete: nil)),
+            ColumnDefinition(name: "created_at",
+                             primaryKey: nil,
+                             type: .TEXT,
+                             null: true,
+                             defaultValue: .NULL,
+                             references: nil)
+        ])
+    }
+
+    func test_column_info_parses_conflict_modifier() throws {
+        try db.run("CREATE TABLE t (\"id\" INTEGER PRIMARY KEY ON CONFLICT IGNORE AUTOINCREMENT)")
+
+        XCTAssertEqual(
+            try db.columnInfo(table: "t"), [
+            ColumnDefinition(
+                name: "id",
+                primaryKey: .init(autoIncrement: true, onConflict: .IGNORE),
+                type: .INTEGER,
+                null: true,
+                defaultValue: .NULL,
+                references: nil)
+            ]
+        )
+    }
+
+    func test_column_info_detects_missing_autoincrement() throws {
+        try db.run("CREATE TABLE t (\"id\" INTEGER PRIMARY KEY)")
+
+        XCTAssertEqual(
+            try db.columnInfo(table: "t"), [
+            ColumnDefinition(
+                    name: "id",
+                    primaryKey: .init(autoIncrement: false),
+                    type: .INTEGER,
+                    null: true,
+                    defaultValue: .NULL,
+                    references: nil)
+            ]
+        )
+    }
+
+    func test_index_info_no_index() throws {
+        let indexes = try db.indexInfo(table: "users")
+        XCTAssertTrue(indexes.isEmpty)
+    }
+
+    func test_index_info_with_index() throws {
+        try db.run("CREATE UNIQUE INDEX index_users ON users (age DESC) WHERE age IS NOT NULL")
+        let indexes = try db.indexInfo(table: "users")
+
+        XCTAssertEqual(indexes, [
+            IndexDefinition(
+                table: "users",
+                name: "index_users",
+                unique: true,
+                columns: ["age"],
+                where: "age IS NOT NULL",
+                orders: ["age": .DESC]
+            )
+        ])
+    }
+
+    func test_table_info_returns_list_of_tables() throws {
+        let tables = try db.tableInfo()
+        XCTAssertEqual(tables, ["users"])
+    }
+
+    func test_foreign_key_info_empty() throws {
+        try db.run("CREATE TABLE t (\"id\" INTEGER PRIMARY KEY)")
+
+        let foreignKeys = try db.foreignKeyInfo(table: "t")
+        XCTAssertTrue(foreignKeys.isEmpty)
+    }
+
+    func test_foreign_key_info() throws {
+        let linkTable = Table("test_links")
+
+        let idColumn = SQLite.Expression<Int64>("id")
+        let testIdColumn = SQLite.Expression<Int64>("test_id")
+
+        try db.run(linkTable.create(block: { definition in
+            definition.column(idColumn, primaryKey: .autoincrement)
+            definition.column(testIdColumn, unique: false, check: nil, references: users, Expression<Int64>("id"))
+        }))
+
+        let foreignKeys = try db.foreignKeyInfo(table: "test_links")
+        XCTAssertEqual(foreignKeys, [
+            ForeignKeyDefinition(table: "users", column: "test_id", primaryKey: "id", onUpdate: nil, onDelete: nil)
+        ])
+    }
+}
diff --git a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
new file mode 100644
index 00000000..21ae6e59
--- /dev/null
+++ b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
@@ -0,0 +1,87 @@
+import XCTest
+@testable import SQLite
+
+class SchemaChangerTests: SQLiteTestCase {
+    var schemaChanger: SchemaChanger!
+
+    override func setUpWithError() throws {
+        try super.setUpWithError()
+        try createUsersTable()
+
+        try insertUsers("bob")
+
+        schemaChanger = SchemaChanger(connection: db)
+    }
+
+    func test_empty_migration_does_not_change_column_definitions() throws {
+        let previous = try db.columnInfo(table: "users")
+        try schemaChanger.alter(table: "users") { _ in
+        }
+        let current = try db.columnInfo(table: "users")
+
+        XCTAssertEqual(previous, current)
+    }
+
+    func test_empty_migration_does_not_change_index_definitions() throws {
+        let previous = try db.indexInfo(table: "users")
+        try schemaChanger.alter(table: "users") { _ in
+        }
+        let current = try db.indexInfo(table: "users")
+
+        XCTAssertEqual(previous, current)
+    }
+
+    func test_empty_migration_does_not_change_foreign_key_definitions() throws {
+        let previous = try db.foreignKeyInfo(table: "users")
+        try schemaChanger.alter(table: "users") { _ in
+        }
+        let current = try db.foreignKeyInfo(table: "users")
+
+        XCTAssertEqual(previous, current)
+    }
+
+    func test_empty_migration_does_not_change_the_row_count() throws {
+        let previous = try db.scalar(users.count)
+        try schemaChanger.alter(table: "users") { _ in
+        }
+        let current = try db.scalar(users.count)
+
+        XCTAssertEqual(previous, current)
+    }
+
+    func test_remove_column() throws {
+        try schemaChanger.alter(table: "users") { table in
+            table.remove("age")
+        }
+        let columns = try db.columnInfo(table: "users").map(\.name)
+        XCTAssertFalse(columns.contains("age"))
+    }
+
+    func test_rename_column() throws {
+        try schemaChanger.alter(table: "users") { table in
+            table.rename("age", to: "age2")
+        }
+
+        let columns = try db.columnInfo(table: "users").map(\.name)
+        XCTAssertFalse(columns.contains("age"))
+        XCTAssertTrue(columns.contains("age2"))
+    }
+
+    func test_add_column() throws {
+        let newColumn = ColumnDefinition(name: "new_column", primaryKey: nil, type: .TEXT, null: true, defaultValue: .NULL, references: nil)
+
+        try schemaChanger.alter(table: "users") { table in
+            table.add(newColumn)
+        }
+
+        let columns = try db.columnInfo(table: "users")
+        XCTAssertTrue(columns.contains(newColumn))
+    }
+
+    func test_drop_table() throws {
+        try schemaChanger.drop(table: "users")
+
+        let tables = try db.tableInfo()
+        XCTAssertFalse(tables.contains("users"))
+    }
+}
diff --git a/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift b/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
new file mode 100644
index 00000000..07fbf371
--- /dev/null
+++ b/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
@@ -0,0 +1,342 @@
+import XCTest
+@testable import SQLite
+
+class ColumnDefinitionTests: XCTestCase {
+    var definition: ColumnDefinition!
+    var expected: String!
+
+    static let definitions: [(ColumnDefinition, String)] = [
+        (ColumnDefinition(name: "id", primaryKey: .init(), type: .INTEGER, null: false, defaultValue: .NULL, references: nil),
+        "\"id\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL"),
+
+        (ColumnDefinition(name: "other_id", primaryKey: nil, type: .INTEGER, null: false, defaultValue: .NULL,
+                          references: ForeignKeyDefinition(table: "other_table", column: "", primaryKey: "some_id", onUpdate: nil, onDelete: nil)),
+        "\"other_id\" INTEGER NOT NULL REFERENCES \"other_table\" (\"some_id\")"),
+
+        (ColumnDefinition(name: "text", primaryKey: nil, type: .TEXT, null: true, defaultValue: .NULL, references: nil),
+        "\"text\" TEXT"),
+
+        (ColumnDefinition(name: "text", primaryKey: nil, type: .TEXT, null: false, defaultValue: .NULL, references: nil),
+        "\"text\" TEXT NOT NULL"),
+
+        (ColumnDefinition(name: "text_column", primaryKey: nil, type: .TEXT, null: true, defaultValue: .stringLiteral("fo\"o"), references: nil),
+        "\"text_column\" TEXT DEFAULT 'fo\"o'"),
+
+        (ColumnDefinition(name: "integer_column", primaryKey: nil, type: .INTEGER, null: true, defaultValue: .numericLiteral("123"), references: nil),
+        "\"integer_column\" INTEGER DEFAULT 123"),
+
+        (ColumnDefinition(name: "real_column", primaryKey: nil, type: .REAL, null: true, defaultValue: .numericLiteral("123.123"), references: nil),
+        "\"real_column\" REAL DEFAULT 123.123")
+    ]
+
+    override class var defaultTestSuite: XCTestSuite {
+        let suite = XCTestSuite(forTestCaseClass: ColumnDefinitionTests.self)
+
+        for (column, expected) in ColumnDefinitionTests.definitions {
+            let test = ColumnDefinitionTests(selector: #selector(verify))
+            test.definition = column
+            test.expected = expected
+            suite.addTest(test)
+        }
+        return suite
+    }
+
+    @objc func verify() {
+        XCTAssertEqual(definition.toSQL(), expected)
+    }
+}
+
+class AffinityTests: XCTestCase {
+    func test_from() {
+        XCTAssertEqual(ColumnDefinition.Affinity.from("TEXT"), .TEXT)
+        XCTAssertEqual(ColumnDefinition.Affinity.from("text"), .TEXT)
+        XCTAssertEqual(ColumnDefinition.Affinity.from("INTEGER"), .INTEGER)
+    }
+
+    func test_returns_TEXT_for_unknown_type() {
+        XCTAssertEqual(ColumnDefinition.Affinity.from("baz"), .TEXT)
+    }
+}
+
+class IndexDefinitionTests: XCTestCase {
+    var definition: IndexDefinition!
+    var expected: String!
+    var ifNotExists: Bool!
+
+    static let definitions: [(IndexDefinition, Bool, String)] = [
+        (IndexDefinition(table: "tests", name: "index_tests",
+                         unique: false,
+                         columns: ["test_column"],
+                         where: nil,
+                         orders: nil),
+        false,
+        "CREATE INDEX \"index_tests\" ON \"tests\" (\"test_column\")"),
+
+        (IndexDefinition(table: "tests", name: "index_tests",
+                         unique: true,
+                         columns: ["test_column"],
+                         where: nil,
+                         orders: nil),
+        false,
+        "CREATE UNIQUE INDEX \"index_tests\" ON \"tests\" (\"test_column\")"),
+
+        (IndexDefinition(table: "tests", name: "index_tests",
+                         unique: true,
+                         columns: ["test_column", "bar_column"],
+                         where: "test_column IS NOT NULL",
+                         orders: nil),
+        false,
+        "CREATE UNIQUE INDEX \"index_tests\" ON \"tests\" (\"test_column\", \"bar_column\") WHERE test_column IS NOT NULL"),
+
+        (IndexDefinition(table: "tests", name: "index_tests",
+                         unique: true,
+                         columns: ["test_column", "bar_column"],
+                         where: nil,
+                         orders: ["test_column": .DESC]),
+        false,
+        "CREATE UNIQUE INDEX \"index_tests\" ON \"tests\" (\"test_column\" DESC, \"bar_column\")"),
+
+        (IndexDefinition(table: "tests", name: "index_tests",
+                         unique: false,
+                         columns: ["test_column"],
+                         where: nil,
+                         orders: nil),
+        true,
+        "CREATE INDEX IF NOT EXISTS \"index_tests\" ON \"tests\" (\"test_column\")")
+    ]
+
+    override class var defaultTestSuite: XCTestSuite {
+        let suite = XCTestSuite(forTestCaseClass: IndexDefinitionTests.self)
+
+        for (column, ifNotExists, expected) in IndexDefinitionTests.definitions {
+            let test = IndexDefinitionTests(selector: #selector(verify))
+            test.definition = column
+            test.expected = expected
+            test.ifNotExists = ifNotExists
+            suite.addTest(test)
+        }
+        return suite
+    }
+
+    @objc func verify() {
+        XCTAssertEqual(definition.toSQL(ifNotExists: ifNotExists), expected)
+    }
+
+    func test_validate() {
+
+        let longIndex = IndexDefinition(
+                table: "tests",
+                name: String(repeating: "x", count: 65),
+                unique: false,
+                columns: ["test_column"],
+                where: nil,
+                orders: nil)
+
+        XCTAssertThrowsError(try longIndex.validate()) { error in
+            XCTAssertEqual(error.localizedDescription,
+                           "Index name 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' " +
+                           "on table 'tests' is too long; the limit is 64 characters")
+        }
+    }
+
+    func test_rename() {
+        let index = IndexDefinition(table: "tests", name: "index_tests_something",
+                                    unique: true,
+                                    columns: ["test_column"],
+                                    where: "test_column IS NOT NULL",
+                                    orders: nil)
+
+        let renamedIndex = index.renameTable(to: "foo")
+
+        XCTAssertEqual(renamedIndex,
+           IndexDefinition(
+                table: "foo",
+                name: "index_tests_something",
+                unique: true,
+                columns: ["test_column"],
+                where: "test_column IS NOT NULL",
+                orders: nil
+           )
+        )
+    }
+}
+
+class ForeignKeyDefinitionTests: XCTestCase {
+    func test_toSQL() {
+        XCTAssertEqual(
+            ForeignKeyDefinition(
+                table: "foo",
+                column: "bar",
+                primaryKey: "bar_id",
+                onUpdate: nil,
+                onDelete: "SET NULL"
+            ).toSQL(), """
+               REFERENCES "foo" ("bar_id") ON DELETE SET NULL
+               """
+        )
+    }
+}
+
+class TableDefinitionTests: XCTestCase {
+    func test_quoted_columnList() {
+        let definition = TableDefinition(name: "foo", columns: [
+            ColumnDefinition(name: "id", primaryKey: .init(), type: .INTEGER, null: false, defaultValue: .NULL, references: nil),
+            ColumnDefinition(name: "baz", primaryKey: nil, type: .INTEGER, null: false, defaultValue: .NULL, references: nil)
+        ], indexes: [])
+
+        XCTAssertEqual(definition.quotedColumnList, """
+                                                    "id", "baz"
+                                                    """)
+    }
+
+    func test_toSQL() {
+        let definition = TableDefinition(name: "foo", columns: [
+            ColumnDefinition(name: "id", primaryKey: .init(), type: .INTEGER, null: false, defaultValue: .NULL, references: nil)
+        ], indexes: [])
+
+        XCTAssertEqual(definition.toSQL(), """
+                                           CREATE TABLE foo ( \"id\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL )
+                                           """)
+    }
+
+    func test_toSQL_temp_table() {
+        let definition = TableDefinition(name: "foo", columns: [
+            ColumnDefinition(name: "id", primaryKey: .init(), type: .INTEGER, null: false, defaultValue: .NULL, references: nil)
+        ], indexes: [])
+
+        XCTAssertEqual(definition.toSQL(temporary: true), """
+                                                          CREATE TEMPORARY TABLE foo ( \"id\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL )
+                                                          """)
+    }
+
+    /*
+    func test_throws_an_error_when_columns_are_empty() {
+        let empty = TableDefinition(name: "empty", columns: [], indexes: [])
+        XCTAssertThrowsError(empty.toSQL())
+    }
+     */
+
+    func test_copySQL() {
+        let from = TableDefinition(name: "from_table", columns: [
+            ColumnDefinition(name: "id", primaryKey: .init(), type: .INTEGER, null: false, defaultValue: .NULL, references: nil)
+        ], indexes: [])
+
+        let to = TableDefinition(name: "to_table", columns: [
+            ColumnDefinition(name: "id", primaryKey: .init(), type: .INTEGER, null: false, defaultValue: .NULL, references: nil)
+        ], indexes: [])
+
+        XCTAssertEqual(from.copySQL(to: to), """
+                                             INSERT INTO "to_table" ("id") SELECT "id" FROM "from_table"
+                                             """)
+    }
+}
+
+class PrimaryKeyTests: XCTestCase {
+    func test_toSQL() {
+        XCTAssertEqual(ColumnDefinition.PrimaryKey(autoIncrement: false).toSQL(),
+                       "PRIMARY KEY")
+    }
+
+    func test_toSQL_autoincrement() {
+        XCTAssertEqual(ColumnDefinition.PrimaryKey(autoIncrement: true).toSQL(),
+                       "PRIMARY KEY AUTOINCREMENT")
+    }
+
+    func test_toSQL_on_conflict() {
+        XCTAssertEqual(ColumnDefinition.PrimaryKey(autoIncrement: false, onConflict: .ROLLBACK).toSQL(),
+                       "PRIMARY KEY ON CONFLICT ROLLBACK")
+    }
+}
+
+class LiteralValueTests: XCTestCase {
+    func test_recognizes_TRUE() {
+        XCTAssertEqual(LiteralValue.from("TRUE"), .TRUE)
+    }
+
+    func test_recognizes_FALSE() {
+        XCTAssertEqual(LiteralValue.from("FALSE"), .FALSE)
+    }
+
+    func test_recognizes_NULL() {
+        XCTAssertEqual(LiteralValue.from("NULL"), .NULL)
+    }
+
+    func test_recognizes_nil() {
+        XCTAssertEqual(LiteralValue.from(nil), .NULL)
+    }
+
+    func test_recognizes_CURRENT_TIME() {
+        XCTAssertEqual(LiteralValue.from("CURRENT_TIME"), .CURRENT_TIME)
+    }
+
+    func test_recognizes_CURRENT_TIMESTAMP() {
+        XCTAssertEqual(LiteralValue.from("CURRENT_TIMESTAMP"), .CURRENT_TIMESTAMP)
+    }
+
+    func test_recognizes_CURRENT_DATE() {
+        XCTAssertEqual(LiteralValue.from("CURRENT_DATE"), .CURRENT_DATE)
+    }
+
+    func test_recognizes_double_quote_string_literals() {
+        XCTAssertEqual(LiteralValue.from("\"foo\""), .stringLiteral("foo"))
+    }
+
+    func test_recognizes_single_quote_string_literals() {
+        XCTAssertEqual(LiteralValue.from("\'foo\'"), .stringLiteral("foo"))
+    }
+
+    func test_unquotes_double_quote_string_literals() {
+        XCTAssertEqual(LiteralValue.from("\"fo\"\"o\""), .stringLiteral("fo\"o"))
+    }
+
+    func test_unquotes_single_quote_string_literals() {
+        XCTAssertEqual(LiteralValue.from("'fo''o'"), .stringLiteral("fo'o"))
+    }
+
+    func test_recognizes_numeric_literals() {
+        XCTAssertEqual(LiteralValue.from("1.2"), .numericLiteral("1.2"))
+        XCTAssertEqual(LiteralValue.from("0xdeadbeef"), .numericLiteral("0xdeadbeef"))
+    }
+
+    func test_recognizes_blob_literals() {
+        XCTAssertEqual(LiteralValue.from("X'deadbeef'"), .blobLiteral("deadbeef"))
+        XCTAssertEqual(LiteralValue.from("x'deadbeef'"), .blobLiteral("deadbeef"))
+    }
+
+    func test_description_TRUE() {
+        XCTAssertEqual(LiteralValue.TRUE.description, "TRUE")
+    }
+
+    func test_description_FALSE() {
+        XCTAssertEqual(LiteralValue.FALSE.description, "FALSE")
+    }
+
+    func test_description_NULL() {
+        XCTAssertEqual(LiteralValue.NULL.description, "NULL")
+    }
+
+    func test_description_CURRENT_TIME() {
+        XCTAssertEqual(LiteralValue.CURRENT_TIME.description, "CURRENT_TIME")
+    }
+
+    func test_description_CURRENT_TIMESTAMP() {
+        XCTAssertEqual(LiteralValue.CURRENT_TIMESTAMP.description, "CURRENT_TIMESTAMP")
+    }
+
+    func test_description_CURRENT_DATE() {
+        XCTAssertEqual(LiteralValue.CURRENT_DATE.description, "CURRENT_DATE")
+    }
+
+    func test_description_string_literal() {
+        XCTAssertEqual(LiteralValue.stringLiteral("foo").description, "'foo'")
+    }
+
+    func test_description_numeric_literal() {
+        XCTAssertEqual(LiteralValue.numericLiteral("1.2").description, "1.2")
+        XCTAssertEqual(LiteralValue.numericLiteral("0xdeadbeef").description, "0xdeadbeef")
+    }
+
+    func test_description_blob_literal() {
+        XCTAssertEqual(LiteralValue.blobLiteral("deadbeef").description, "X'deadbeef'")
+    }
+}

From affcec8494488f155a846dc58c388ca798a239e7 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 24 Jul 2022 02:43:39 +0200
Subject: [PATCH 543/685] Use DROP/RENAME COLUMN when available

---
 Sources/SQLite/Schema/Connection+Schema.swift | 13 +++++++++++
 Sources/SQLite/Schema/SchemaChanger.swift     | 22 +++++++++++++++----
 .../Schema/ConnectionSchemaTests.swift        |  7 ++++++
 .../Schema/SchemaChangerTests.swift           | 22 +++++++++++++++++++
 .../Schema/SchemaDefinitionsTests.swift       |  4 ++++
 5 files changed, 64 insertions(+), 4 deletions(-)

diff --git a/Sources/SQLite/Schema/Connection+Schema.swift b/Sources/SQLite/Schema/Connection+Schema.swift
index e368bdaf..c6cf197f 100644
--- a/Sources/SQLite/Schema/Connection+Schema.swift
+++ b/Sources/SQLite/Schema/Connection+Schema.swift
@@ -1,6 +1,19 @@
 import Foundation
 
 extension Connection {
+    var sqliteVersion: String? {
+        (try? scalar("SELECT sqlite_version()")) as? String
+    }
+
+    var sqliteVersionTriple: (Int, Int, Int) {
+        guard let version = sqliteVersion,
+              let splits = .some(version.split(separator: ".", maxSplits: 3)), splits.count == 3,
+              let major = Int(splits[0]), let minor = Int(splits[1]), let point = Int(splits[2]) else {
+            return (0, 0, 0)
+        }
+        return (major, minor, point)
+    }
+
     // Changing the foreign_keys setting affects the execution of all statements prepared using the database
     // connection, including those prepared before the setting was changed.
     //
diff --git a/Sources/SQLite/Schema/SchemaChanger.swift b/Sources/SQLite/Schema/SchemaChanger.swift
index ff0befc3..cd6b6f25 100644
--- a/Sources/SQLite/Schema/SchemaChanger.swift
+++ b/Sources/SQLite/Schema/SchemaChanger.swift
@@ -27,6 +27,8 @@ import Foundation
        12. If foreign keys constraints were originally enabled, reenable them now.
 */
 public class SchemaChanger: CustomStringConvertible {
+    typealias SQLiteVersion = (Int, Int, Int)
+
     enum SchemaChangeError: LocalizedError {
         case foreignKeyError([ForeignKeyError])
 
@@ -46,9 +48,14 @@ public class SchemaChanger: CustomStringConvertible {
         case renameTable(String)
 
         /// Returns non-nil if the operation can be executed with a simple SQL statement
-        func toSQL(_ table: String) -> String? {
+        func toSQL(_ table: String, version: SQLiteVersion) -> String? {
             switch self {
-            case .add(let definition): return "ALTER TABLE \(table.quote()) ADD COLUMN \(definition.toSQL())"
+            case .add(let definition):
+                return "ALTER TABLE \(table.quote()) ADD COLUMN \(definition.toSQL())"
+            case .renameColumn(let from, let to) where version.0 >= 3 && version.1 >= 25:
+                return "ALTER TABLE \(table.quote()) RENAME COLUMN \(from.quote()) TO \(to.quote())"
+            case .remove(let column) where version.0 >= 3 && version.1 >= 35:
+                return "ALTER TABLE \(table.quote()) DROP COLUMN \(column.quote())"
             default: return nil
             }
         }
@@ -77,6 +84,7 @@ public class SchemaChanger: CustomStringConvertible {
     }
 
     private let connection: Connection
+    private let version: SQLiteVersion
     static let tempPrefix = "tmp_"
     typealias Block = () throws -> Void
     public typealias AlterTableDefinitionBlock = (AlterTableDefinition) -> Void
@@ -87,8 +95,14 @@ public class SchemaChanger: CustomStringConvertible {
         static let temp = Options(rawValue: 1)
     }
 
-    public init(connection: Connection) {
+    public convenience init(connection: Connection) {
+        self.init(connection: connection,
+                  version: connection.sqliteVersionTriple)
+    }
+
+    init(connection: Connection, version: SQLiteVersion) {
         self.connection = connection
+        self.version = version
     }
 
     public func alter(table: String, block: AlterTableDefinitionBlock) throws {
@@ -105,7 +119,7 @@ public class SchemaChanger: CustomStringConvertible {
     }
 
     private func run(table: String, operation: Operation) throws {
-        if let sql = operation.toSQL(table) {
+        if let sql = operation.toSQL(table, version: version) {
             try connection.run(sql)
         } else {
             try doTheTableDance(table: table, operation: operation)
diff --git a/Tests/SQLiteTests/Schema/ConnectionSchemaTests.swift b/Tests/SQLiteTests/Schema/ConnectionSchemaTests.swift
index 02321510..9fbad26c 100644
--- a/Tests/SQLiteTests/Schema/ConnectionSchemaTests.swift
+++ b/Tests/SQLiteTests/Schema/ConnectionSchemaTests.swift
@@ -136,4 +136,11 @@ class ConnectionSchemaTests: SQLiteTestCase {
             ForeignKeyDefinition(table: "users", column: "test_id", primaryKey: "id", onUpdate: nil, onDelete: nil)
         ])
     }
+
+    func test_sqlite_version_triple() {
+        let version = db.sqliteVersionTriple
+        XCTAssertEqual(version.0, 3)
+        XCTAssertGreaterThan(version.1, 0)
+        XCTAssertGreaterThanOrEqual(version.2, 0)
+    }
 }
diff --git a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
index 21ae6e59..165de4a8 100644
--- a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
@@ -57,6 +57,16 @@ class SchemaChangerTests: SQLiteTestCase {
         XCTAssertFalse(columns.contains("age"))
     }
 
+    func test_remove_column_legacy() throws {
+        schemaChanger = .init(connection: db, version: (3, 24, 0)) // DROP COLUMN introduced in 3.35.0
+
+        try schemaChanger.alter(table: "users") { table in
+            table.remove("age")
+        }
+        let columns = try db.columnInfo(table: "users").map(\.name)
+        XCTAssertFalse(columns.contains("age"))
+    }
+
     func test_rename_column() throws {
         try schemaChanger.alter(table: "users") { table in
             table.rename("age", to: "age2")
@@ -67,6 +77,18 @@ class SchemaChangerTests: SQLiteTestCase {
         XCTAssertTrue(columns.contains("age2"))
     }
 
+    func test_rename_column_legacy() throws {
+        schemaChanger = .init(connection: db, version: (3, 24, 0)) // RENAME COLUMN introduced in 3.25.0
+
+        try schemaChanger.alter(table: "users") { table in
+            table.rename("age", to: "age2")
+        }
+
+        let columns = try db.columnInfo(table: "users").map(\.name)
+        XCTAssertFalse(columns.contains("age"))
+        XCTAssertTrue(columns.contains("age2"))
+    }
+
     func test_add_column() throws {
         let newColumn = ColumnDefinition(name: "new_column", primaryKey: nil, type: .TEXT, null: true, defaultValue: .NULL, references: nil)
 
diff --git a/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift b/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
index 07fbf371..c19840bc 100644
--- a/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
@@ -29,6 +29,7 @@ class ColumnDefinitionTests: XCTestCase {
         "\"real_column\" REAL DEFAULT 123.123")
     ]
 
+    #if !os(Linux)
     override class var defaultTestSuite: XCTestSuite {
         let suite = XCTestSuite(forTestCaseClass: ColumnDefinitionTests.self)
 
@@ -44,6 +45,7 @@ class ColumnDefinitionTests: XCTestCase {
     @objc func verify() {
         XCTAssertEqual(definition.toSQL(), expected)
     }
+    #endif
 }
 
 class AffinityTests: XCTestCase {
@@ -105,6 +107,7 @@ class IndexDefinitionTests: XCTestCase {
         "CREATE INDEX IF NOT EXISTS \"index_tests\" ON \"tests\" (\"test_column\")")
     ]
 
+    #if !os(Linux)
     override class var defaultTestSuite: XCTestSuite {
         let suite = XCTestSuite(forTestCaseClass: IndexDefinitionTests.self)
 
@@ -121,6 +124,7 @@ class IndexDefinitionTests: XCTestCase {
     @objc func verify() {
         XCTAssertEqual(definition.toSQL(ifNotExists: ifNotExists), expected)
     }
+    #endif
 
     func test_validate() {
 

From 1b645291774b5d36af7630c8bdd8530373d1368d Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 24 Jul 2022 19:49:41 +0200
Subject: [PATCH 544/685] ColumnDefinition needs to be public

---
 SQLite.xcodeproj/project.pbxproj              | 10 +++
 Sources/SQLite/Core/Connection+Pragmas.swift  | 52 +++++++++++
 Sources/SQLite/Core/Connection.swift          | 11 ---
 Sources/SQLite/Schema/Connection+Schema.swift | 87 ++++++-------------
 Sources/SQLite/Schema/SchemaChanger.swift     |  8 +-
 Sources/SQLite/Schema/SchemaDefinitions.swift | 60 +++++++------
 .../Schema/ConnectionSchemaTests.swift        |  9 +-
 .../Schema/SchemaDefinitionsTests.swift       |  4 +-
 8 files changed, 130 insertions(+), 111 deletions(-)
 create mode 100644 Sources/SQLite/Core/Connection+Pragmas.swift

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index abd69301..a97ef184 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -46,6 +46,7 @@
 		03A65E941C6BB3030062603F /* ValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B331C3F142E00AE3E12 /* ValueTests.swift */; };
 		03A65E951C6BB3030062603F /* TestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B161C3F127200AE3E12 /* TestHelpers.swift */; };
 		03A65E971C6BB3210062603F /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 03A65E961C6BB3210062603F /* libsqlite3.tbd */; };
+		19A17018F250343BD0F9F4B0 /* Connection+Pragmas.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17F285B767BFACD96714B /* Connection+Pragmas.swift */; };
 		19A17073552293CA063BEA66 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17E723300E5ED3771DCB5 /* Result.swift */; };
 		19A1709C3E7A406E62293B2A /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; };
 		19A170ACC97B19730FB7BA4D /* Connection+Aggregation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */; };
@@ -71,6 +72,7 @@
 		19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
 		19A1750CEE9B05267995CF3D /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
 		19A1750EF4A5F92954A451FF /* Connection+Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A170A97B51DC5EE365F3C5 /* Connection+Schema.swift */; };
+		19A1760CE25615CA015E2E5F /* Connection+Pragmas.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17F285B767BFACD96714B /* Connection+Pragmas.swift */; };
 		19A176376CB6A94759F7980A /* Connection+Aggregation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */; };
 		19A176406BDE9D9C80CC9FA3 /* QueryIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */; };
 		19A1766AC10D13C4EFF349AD /* SchemaChangerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17FDB0B0CFB8987906FD0 /* SchemaChangerTests.swift */; };
@@ -82,7 +84,9 @@
 		19A178072B371489E6A1E839 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
 		19A17835FD5886FDC5A3228F /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
 		19A1785195182AF8731A8BDA /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */; };
+		19A178A8B2A34FB6B565DEDA /* Connection+Pragmas.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17F285B767BFACD96714B /* Connection+Pragmas.swift */; };
 		19A1792C0520D4E83C2EB075 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
+		19A17986405D9A875698408F /* Connection+Pragmas.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17F285B767BFACD96714B /* Connection+Pragmas.swift */; };
 		19A179A0C45377CB09BB358C /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
 		19A179B59450FE7C4811AB8A /* Connection+Aggregation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */; };
 		19A179CCF9671E345E5A9811 /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
@@ -283,6 +287,7 @@
 		19A17CA1DF7D0F7C9A94C51C /* ConnectionSchemaTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectionSchemaTests.swift; sourceTree = "<group>"; };
 		19A17E723300E5ED3771DCB5 /* Result.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Result.swift; sourceTree = "<group>"; };
 		19A17EA3A313F129011B3FA0 /* Release.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Release.md; sourceTree = "<group>"; };
+		19A17F285B767BFACD96714B /* Connection+Pragmas.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Connection+Pragmas.swift"; sourceTree = "<group>"; };
 		19A17FDB0B0CFB8987906FD0 /* SchemaChangerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaChangerTests.swift; sourceTree = "<group>"; };
 		3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomAggregationTests.swift; sourceTree = "<group>"; };
 		3D3C3CCB26E5568800759140 /* SQLite.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = SQLite.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
@@ -530,6 +535,7 @@
 				19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */,
 				3DF7B78728842972005DD8CA /* Connection+Attach.swift */,
 				3DF7B790288449BA005DD8CA /* URIQueryParameter.swift */,
+				19A17F285B767BFACD96714B /* Connection+Pragmas.swift */,
 			);
 			path = Core;
 			sourceTree = "<group>";
@@ -920,6 +926,7 @@
 				19A17FC07731779C1B8506FA /* SchemaChanger.swift in Sources */,
 				19A1740EACD47904AA24B8DC /* SchemaDefinitions.swift in Sources */,
 				19A1750EF4A5F92954A451FF /* Connection+Schema.swift in Sources */,
+				19A17986405D9A875698408F /* Connection+Pragmas.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -993,6 +1000,7 @@
 				19A17DFE05ED8B1F7C45F7EE /* SchemaChanger.swift in Sources */,
 				19A17D1BEABA610ABF003D67 /* SchemaDefinitions.swift in Sources */,
 				19A17A33EA026C2E2CEBAF36 /* Connection+Schema.swift in Sources */,
+				19A178A8B2A34FB6B565DEDA /* Connection+Pragmas.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1031,6 +1039,7 @@
 				19A1773A335CAB9D0AE14E8E /* SchemaChanger.swift in Sources */,
 				19A17BA13FD35F058787B7D3 /* SchemaDefinitions.swift in Sources */,
 				19A174506543905D71BF0518 /* Connection+Schema.swift in Sources */,
+				19A17018F250343BD0F9F4B0 /* Connection+Pragmas.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1105,6 +1114,7 @@
 				19A177290558991BCC60E4E3 /* SchemaChanger.swift in Sources */,
 				19A17B0DF1DDB6BBC9C95D64 /* SchemaDefinitions.swift in Sources */,
 				19A17F0BF02896E1664F4090 /* Connection+Schema.swift in Sources */,
+				19A1760CE25615CA015E2E5F /* Connection+Pragmas.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/Sources/SQLite/Core/Connection+Pragmas.swift b/Sources/SQLite/Core/Connection+Pragmas.swift
new file mode 100644
index 00000000..43ff9610
--- /dev/null
+++ b/Sources/SQLite/Core/Connection+Pragmas.swift
@@ -0,0 +1,52 @@
+import Foundation
+
+public typealias UserVersion = Int32
+public typealias SQLiteVersion = (Int, Int, Int)
+
+public extension Connection {
+    /// The user version of the database.
+    /// See SQLite [PRAGMA user_version](https://sqlite.org/pragma.html#pragma_user_version)
+    var userVersion: UserVersion? {
+        get {
+            (try? scalar("PRAGMA user_version") as? Int64).map(Int32.init)
+        }
+        set {
+            _ = try? run("PRAGMA user_version = \(newValue ?? 0)")
+        }
+    }
+
+    /// The version of SQLite.
+    /// See SQLite [sqlite_version()](https://sqlite.org/lang_corefunc.html#sqlite_version)
+    var sqliteVersion: SQLiteVersion {
+        guard let version = (try? scalar("SELECT sqlite_version()")) as? String,
+              let splits = .some(version.split(separator: ".", maxSplits: 3)), splits.count == 3,
+              let major = Int(splits[0]), let minor = Int(splits[1]), let point = Int(splits[2]) else {
+            return (0, 0, 0)
+        }
+        return (major, minor, point)
+    }
+
+    // Changing the foreign_keys setting affects the execution of all statements prepared using the database
+    // connection, including those prepared before the setting was changed.
+    //
+    // https://sqlite.org/pragma.html#pragma_foreign_keys
+    var foreignKeys: Bool {
+        get { getBoolPragma("foreign_keys") }
+        set { setBoolPragma("foreign_keys", newValue) }
+    }
+
+    var deferForeignKeys: Bool {
+        get { getBoolPragma("defer_foreign_keys") }
+        set { setBoolPragma("defer_foreign_keys", newValue) }
+    }
+
+    private func getBoolPragma(_ key: String) -> Bool {
+        guard let binding = try? scalar("PRAGMA \(key)"),
+              let intBinding = binding as? Int64 else { return false }
+        return intBinding == 1
+    }
+
+    private func setBoolPragma(_ key: String, _ newValue: Bool) {
+        _ = try? run("PRAGMA \(key) = \(newValue ? "1" : "0")")
+    }
+}
diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 68b83821..0e51e651 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -156,17 +156,6 @@ public final class Connection {
         Int(sqlite3_total_changes(handle))
     }
 
-    /// The user version of the database.
-    /// See SQLite [PRAGMA user_version](https://sqlite.org/pragma.html#pragma_user_version)
-    public var userVersion: Int32? {
-        get {
-            (try? scalar("PRAGMA user_version") as? Int64).map(Int32.init)
-        }
-        set {
-            _ = try? run("PRAGMA user_version = \(newValue ?? 0)")
-        }
-    }
-
     // MARK: - Execute
 
     /// Executes a batch of SQL statements.
diff --git a/Sources/SQLite/Schema/Connection+Schema.swift b/Sources/SQLite/Schema/Connection+Schema.swift
index c6cf197f..8bd219ed 100644
--- a/Sources/SQLite/Schema/Connection+Schema.swift
+++ b/Sources/SQLite/Schema/Connection+Schema.swift
@@ -1,52 +1,6 @@
 import Foundation
 
 extension Connection {
-    var sqliteVersion: String? {
-        (try? scalar("SELECT sqlite_version()")) as? String
-    }
-
-    var sqliteVersionTriple: (Int, Int, Int) {
-        guard let version = sqliteVersion,
-              let splits = .some(version.split(separator: ".", maxSplits: 3)), splits.count == 3,
-              let major = Int(splits[0]), let minor = Int(splits[1]), let point = Int(splits[2]) else {
-            return (0, 0, 0)
-        }
-        return (major, minor, point)
-    }
-
-    // Changing the foreign_keys setting affects the execution of all statements prepared using the database
-    // connection, including those prepared before the setting was changed.
-    //
-    // https://sqlite.org/pragma.html#pragma_foreign_keys
-    var foreignKeys: Bool {
-        get { getBoolPragma("foreign_keys") }
-        set { setBoolPragma("foreign_keys", newValue) }
-    }
-
-    var deferForeignKeys: Bool {
-        get { getBoolPragma("defer_foreign_keys") }
-        set { setBoolPragma("defer_foreign_keys", newValue) }
-    }
-
-    // https://sqlite.org/pragma.html#pragma_foreign_key_check
-
-    // There are four columns in each result row.
-    // The first column is the name of the table that
-    // contains the REFERENCES clause.
-    // The second column is the rowid of the row that contains the
-    // invalid REFERENCES clause, or NULL if the child table is a WITHOUT ROWID table.
-    // The third column is the name of the table that is referred to.
-    // The fourth column is the index of the specific foreign key constraint that failed.
-    func foreignKeyCheck() throws -> [ForeignKeyError] {
-        try run("PRAGMA foreign_key_check").compactMap { row -> ForeignKeyError? in
-            guard let table = row[0] as? String,
-                  let rowId = row[1] as? Int64,
-                  let target = row[2] as? String else { return nil }
-
-            return ForeignKeyError(from: table, rowId: rowId, to: target)
-        }
-    }
-
     // https://sqlite.org/pragma.html#pragma_table_info
     //
     // This pragma returns one row for each column in the named table. Columns in the result set include the
@@ -58,7 +12,7 @@ extension Connection {
             try createTableSQL(name: table).flatMap { .init(sql: $0) }
         }
 
-        let foreignKeys: [String: [ForeignKeyDefinition]] =
+        let foreignKeys: [String: [ColumnDefinition.ForeignKey]] =
             Dictionary(grouping: try foreignKeyInfo(table: table), by: { $0.column })
 
         return try run("PRAGMA table_info(\(table.quote()))").compactMap { row -> ColumnDefinition? in
@@ -71,7 +25,7 @@ extension Connection {
                                     primaryKey: primaryKey == 1 ? try parsePrimaryKey(column: name) : nil,
                                     type: ColumnDefinition.Affinity.from(type),
                                     null: notNull == 0,
-                                    defaultValue: LiteralValue.from(defaultValue),
+                                    defaultValue: .from(defaultValue),
                                     references: foreignKeys[name]?.first)
         }
     }
@@ -119,16 +73,16 @@ extension Connection {
         }
     }
 
-    func foreignKeyInfo(table: String) throws -> [ForeignKeyDefinition] {
+    func foreignKeyInfo(table: String) throws -> [ColumnDefinition.ForeignKey] {
         try run("PRAGMA foreign_key_list(\(table.quote()))").compactMap { row in
             if let table = row[2] as? String,      // table
                let column = row[3] as? String,     // from
                let primaryKey = row[4] as? String, // to
                let onUpdate = row[5] as? String,
                let onDelete = row[6] as? String {
-                return ForeignKeyDefinition(table: table, column: column, primaryKey: primaryKey,
-                                            onUpdate: onUpdate == TableBuilder.Dependency.noAction.rawValue ? nil : onUpdate,
-                                            onDelete: onDelete == TableBuilder.Dependency.noAction.rawValue ? nil : onDelete
+                return .init(table: table, column: column, primaryKey: primaryKey,
+                             onUpdate: onUpdate == TableBuilder.Dependency.noAction.rawValue ? nil : onUpdate,
+                             onDelete: onDelete == TableBuilder.Dependency.noAction.rawValue ? nil : onDelete
                 )
             } else {
                 return nil
@@ -136,6 +90,25 @@ extension Connection {
         }
     }
 
+    // https://sqlite.org/pragma.html#pragma_foreign_key_check
+
+    // There are four columns in each result row.
+    // The first column is the name of the table that
+    // contains the REFERENCES clause.
+    // The second column is the rowid of the row that contains the
+    // invalid REFERENCES clause, or NULL if the child table is a WITHOUT ROWID table.
+    // The third column is the name of the table that is referred to.
+    // The fourth column is the index of the specific foreign key constraint that failed.
+    func foreignKeyCheck() throws -> [ForeignKeyError] {
+        try run("PRAGMA foreign_key_check").compactMap { row -> ForeignKeyError? in
+            guard let table = row[0] as? String,
+                  let rowId = row[1] as? Int64,
+                  let target = row[2] as? String else { return nil }
+
+            return ForeignKeyError(from: table, rowId: rowId, to: target)
+        }
+    }
+
     private func createTableSQL(name: String) throws  -> String? {
         try run("""
                 SELECT sql FROM sqlite_master WHERE name=? AND type='table'
@@ -145,14 +118,4 @@ extension Connection {
             .compactMap { row in row[0] as? String }
             .first
     }
-
-    private func getBoolPragma(_ key: String) -> Bool {
-        guard let binding = try? scalar("PRAGMA \(key)"),
-              let intBinding = binding as? Int64 else { return false }
-        return intBinding == 1
-    }
-
-    private func setBoolPragma(_ key: String, _ newValue: Bool) {
-        _ = try? run("PRAGMA \(key) = \(newValue ? "1" : "0")")
-    }
 }
diff --git a/Sources/SQLite/Schema/SchemaChanger.swift b/Sources/SQLite/Schema/SchemaChanger.swift
index cd6b6f25..c6529fbe 100644
--- a/Sources/SQLite/Schema/SchemaChanger.swift
+++ b/Sources/SQLite/Schema/SchemaChanger.swift
@@ -27,8 +27,6 @@ import Foundation
        12. If foreign keys constraints were originally enabled, reenable them now.
 */
 public class SchemaChanger: CustomStringConvertible {
-    typealias SQLiteVersion = (Int, Int, Int)
-
     enum SchemaChangeError: LocalizedError {
         case foreignKeyError([ForeignKeyError])
 
@@ -52,9 +50,9 @@ public class SchemaChanger: CustomStringConvertible {
             switch self {
             case .add(let definition):
                 return "ALTER TABLE \(table.quote()) ADD COLUMN \(definition.toSQL())"
-            case .renameColumn(let from, let to) where version.0 >= 3 && version.1 >= 25:
+            case .renameColumn(let from, let to) where version >= (3, 25, 0):
                 return "ALTER TABLE \(table.quote()) RENAME COLUMN \(from.quote()) TO \(to.quote())"
-            case .remove(let column) where version.0 >= 3 && version.1 >= 35:
+            case .remove(let column) where version >= (3, 35, 0):
                 return "ALTER TABLE \(table.quote()) DROP COLUMN \(column.quote())"
             default: return nil
             }
@@ -97,7 +95,7 @@ public class SchemaChanger: CustomStringConvertible {
 
     public convenience init(connection: Connection) {
         self.init(connection: connection,
-                  version: connection.sqliteVersionTriple)
+                  version: connection.sqliteVersion)
     }
 
     init(connection: Connection, version: SQLiteVersion) {
diff --git a/Sources/SQLite/Schema/SchemaDefinitions.swift b/Sources/SQLite/Schema/SchemaDefinitions.swift
index 563ae331..156a06fb 100644
--- a/Sources/SQLite/Schema/SchemaDefinitions.swift
+++ b/Sources/SQLite/Schema/SchemaDefinitions.swift
@@ -18,14 +18,14 @@ public struct ColumnDefinition: Equatable {
     // The important idea here is that the type is recommended, not required. Any column can still
     // store any type of data. It is just that some columns, given the choice, will prefer to use one
     // storage class over another. The preferred storage class for a column is called its "affinity".
-    enum Affinity: String, CustomStringConvertible, CaseIterable {
+    public enum Affinity: String, CustomStringConvertible, CaseIterable {
         case INTEGER
         case NUMERIC
         case REAL
         case TEXT
         case BLOB
 
-        var description: String {
+        public var description: String {
             rawValue
         }
 
@@ -34,7 +34,7 @@ public struct ColumnDefinition: Equatable {
         }
     }
 
-    enum OnConflict: String, CaseIterable {
+    public enum OnConflict: String, CaseIterable {
         case ROLLBACK
         case ABORT
         case FAIL
@@ -46,7 +46,7 @@ public struct ColumnDefinition: Equatable {
         }
     }
 
-    struct PrimaryKey: Equatable {
+    public struct PrimaryKey: Equatable {
         let autoIncrement: Bool
         let onConflict: OnConflict?
 
@@ -73,12 +73,30 @@ public struct ColumnDefinition: Equatable {
         }
     }
 
-    let name: String
-    let primaryKey: PrimaryKey?
-    let type: Affinity
-    let null: Bool
-    let defaultValue: LiteralValue
-    let references: ForeignKeyDefinition?
+    public struct ForeignKey: Equatable {
+        let table: String
+        let column: String
+        let primaryKey: String
+        let onUpdate: String?
+        let onDelete: String?
+    }
+
+    public let name: String
+    public let primaryKey: PrimaryKey?
+    public let type: Affinity
+    public let null: Bool
+    public let defaultValue: LiteralValue
+    public let references: ForeignKey?
+
+    public init(name: String, primaryKey: PrimaryKey?, type: Affinity, null: Bool, defaultValue: LiteralValue,
+                references: ForeignKey?) {
+        self.name = name
+        self.primaryKey = primaryKey
+        self.type = type
+        self.null = null
+        self.defaultValue = defaultValue
+        self.references = references
+    }
 
     func rename(from: String, to: String) -> ColumnDefinition {
         guard from == name else { return self }
@@ -86,7 +104,7 @@ public struct ColumnDefinition: Equatable {
     }
 }
 
-enum LiteralValue: Equatable, CustomStringConvertible {
+public enum LiteralValue: Equatable, CustomStringConvertible {
     // swiftlint:disable force_try
     private static let singleQuote = try! NSRegularExpression(pattern: "^'(.*)'$")
     private static let doubleQuote = try! NSRegularExpression(pattern: "^\"(.*)\"$")
@@ -141,7 +159,7 @@ enum LiteralValue: Equatable, CustomStringConvertible {
         }
     }
 
-    var description: String {
+    public var description: String {
         switch self {
         case .NULL: return "NULL"
         case .TRUE: return "TRUE"
@@ -166,7 +184,7 @@ enum LiteralValue: Equatable, CustomStringConvertible {
 
 // https://sqlite.org/lang_createindex.html
 // schema-name.index-name ON table-name ( indexed-column+ ) WHERE expr
-struct IndexDefinition: Equatable {
+public struct IndexDefinition: Equatable {
     // SQLite supports index names up to 64 characters.
     static let maxIndexLength = 64
 
@@ -175,9 +193,9 @@ struct IndexDefinition: Equatable {
     static let orderRe = try! NSRegularExpression(pattern: "\"?(\\w+)\"? DESC")
     // swiftlint:enable force_try
 
-    enum Order: String { case ASC, DESC }
+    public enum Order: String { case ASC, DESC }
 
-    init(table: String, name: String, unique: Bool = false, columns: [String], `where`: String? = nil, orders: [String: Order]? = nil) {
+    public init(table: String, name: String, unique: Bool = false, columns: [String], `where`: String? = nil, orders: [String: Order]? = nil) {
         self.table = table
         self.name = name
         self.unique = unique
@@ -236,14 +254,6 @@ struct IndexDefinition: Equatable {
     }
 }
 
-struct ForeignKeyDefinition: Equatable {
-    let table: String
-    let column: String
-    let primaryKey: String
-    let onUpdate: String?
-    let onDelete: String?
-}
-
 struct ForeignKeyError: CustomStringConvertible {
     let from: String
     let rowId: Int64
@@ -292,7 +302,7 @@ extension ColumnDefinition {
 }
 
 extension IndexDefinition {
-    func toSQL(ifNotExists: Bool = false) -> String {
+    public func toSQL(ifNotExists: Bool = false) -> String {
         let commaSeparatedColumns = columns.map { (column: String) -> String in
             column.quote() + (orders?[column].map { " \($0.rawValue)" } ?? "")
         }.joined(separator: ", ")
@@ -312,7 +322,7 @@ extension IndexDefinition {
     }
 }
 
-extension ForeignKeyDefinition {
+extension ColumnDefinition.ForeignKey {
     func toSQL() -> String {
         ([
             "REFERENCES",
diff --git a/Tests/SQLiteTests/Schema/ConnectionSchemaTests.swift b/Tests/SQLiteTests/Schema/ConnectionSchemaTests.swift
index 9fbad26c..1c66b761 100644
--- a/Tests/SQLiteTests/Schema/ConnectionSchemaTests.swift
+++ b/Tests/SQLiteTests/Schema/ConnectionSchemaTests.swift
@@ -133,14 +133,11 @@ class ConnectionSchemaTests: SQLiteTestCase {
 
         let foreignKeys = try db.foreignKeyInfo(table: "test_links")
         XCTAssertEqual(foreignKeys, [
-            ForeignKeyDefinition(table: "users", column: "test_id", primaryKey: "id", onUpdate: nil, onDelete: nil)
+            .init(table: "users", column: "test_id", primaryKey: "id", onUpdate: nil, onDelete: nil)
         ])
     }
 
-    func test_sqlite_version_triple() {
-        let version = db.sqliteVersionTriple
-        XCTAssertEqual(version.0, 3)
-        XCTAssertGreaterThan(version.1, 0)
-        XCTAssertGreaterThanOrEqual(version.2, 0)
+    func test_sqlite_version() {
+        XCTAssertTrue(db.sqliteVersion >= (3, 0, 0))
     }
 }
diff --git a/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift b/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
index c19840bc..645bfc34 100644
--- a/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
@@ -10,7 +10,7 @@ class ColumnDefinitionTests: XCTestCase {
         "\"id\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL"),
 
         (ColumnDefinition(name: "other_id", primaryKey: nil, type: .INTEGER, null: false, defaultValue: .NULL,
-                          references: ForeignKeyDefinition(table: "other_table", column: "", primaryKey: "some_id", onUpdate: nil, onDelete: nil)),
+                          references: .init(table: "other_table", column: "", primaryKey: "some_id", onUpdate: nil, onDelete: nil)),
         "\"other_id\" INTEGER NOT NULL REFERENCES \"other_table\" (\"some_id\")"),
 
         (ColumnDefinition(name: "text", primaryKey: nil, type: .TEXT, null: true, defaultValue: .NULL, references: nil),
@@ -168,7 +168,7 @@ class IndexDefinitionTests: XCTestCase {
 class ForeignKeyDefinitionTests: XCTestCase {
     func test_toSQL() {
         XCTAssertEqual(
-            ForeignKeyDefinition(
+            ColumnDefinition.ForeignKey(
                 table: "foo",
                 column: "bar",
                 primaryKey: "bar_id",

From f57c225bad580ddfb22149f8d86e8e12ddca3dbf Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 25 Jul 2022 01:04:28 +0200
Subject: [PATCH 545/685] Move tests into separate directories

---
 SQLite.xcodeproj/project.pbxproj              | 424 ++++++++++--------
 Sources/SQLite/Schema/Connection+Schema.swift |  10 -
 Tests/SQLiteTests/{ => Core}/BlobTests.swift  |   0
 .../Core/Connection+AttachTests.swift         |  62 +++
 .../Core/Connection+PragmaTests.swift         |  42 ++
 .../{ => Core}/ConnectionTests.swift          |  52 ---
 .../{ => Core}/CoreFunctionsTests.swift       |   0
 .../SQLiteTests/{ => Core}/ResultTests.swift  |   0
 .../{ => Core}/StatementTests.swift           |   0
 Tests/SQLiteTests/{ => Core}/ValueTests.swift |   0
 .../{ => Extensions}/CipherTests.swift        |   0
 .../{ => Extensions}/FTS4Tests.swift          |   0
 .../{ => Extensions}/FTS5Tests.swift          |   0
 .../FTSIntegrationTests.swift                 |   0
 .../{ => Extensions}/RTreeTests.swift         |   0
 ...sts.swift => Connection+SchemaTests.swift} |   9 -
 .../Schema/SchemaChangerTests.swift           |  10 +-
 .../{ => Schema}/SchemaTests.swift            |   0
 .../{ => Typed}/AggregateFunctionsTests.swift |   0
 .../{ => Typed}/CustomAggregationTests.swift  |   0
 .../{ => Typed}/CustomFunctionsTests.swift    |   0
 .../DateAndTimeFunctionTests.swift            |   0
 .../{ => Typed}/ExpressionTests.swift         |   0
 .../{ => Typed}/OperatorsTests.swift          |   0
 .../{ => Typed}/QueryIntegrationTests.swift   |   0
 .../SQLiteTests/{ => Typed}/QueryTests.swift  |   0
 Tests/SQLiteTests/{ => Typed}/RowTests.swift  |   0
 .../SQLiteTests/{ => Typed}/SelectTests.swift |   0
 .../SQLiteTests/{ => Typed}/SetterTests.swift |   0
 29 files changed, 343 insertions(+), 266 deletions(-)
 rename Tests/SQLiteTests/{ => Core}/BlobTests.swift (100%)
 create mode 100644 Tests/SQLiteTests/Core/Connection+AttachTests.swift
 create mode 100644 Tests/SQLiteTests/Core/Connection+PragmaTests.swift
 rename Tests/SQLiteTests/{ => Core}/ConnectionTests.swift (90%)
 rename Tests/SQLiteTests/{ => Core}/CoreFunctionsTests.swift (100%)
 rename Tests/SQLiteTests/{ => Core}/ResultTests.swift (100%)
 rename Tests/SQLiteTests/{ => Core}/StatementTests.swift (100%)
 rename Tests/SQLiteTests/{ => Core}/ValueTests.swift (100%)
 rename Tests/SQLiteTests/{ => Extensions}/CipherTests.swift (100%)
 rename Tests/SQLiteTests/{ => Extensions}/FTS4Tests.swift (100%)
 rename Tests/SQLiteTests/{ => Extensions}/FTS5Tests.swift (100%)
 rename Tests/SQLiteTests/{ => Extensions}/FTSIntegrationTests.swift (100%)
 rename Tests/SQLiteTests/{ => Extensions}/RTreeTests.swift (100%)
 rename Tests/SQLiteTests/Schema/{ConnectionSchemaTests.swift => Connection+SchemaTests.swift} (95%)
 rename Tests/SQLiteTests/{ => Schema}/SchemaTests.swift (100%)
 rename Tests/SQLiteTests/{ => Typed}/AggregateFunctionsTests.swift (100%)
 rename Tests/SQLiteTests/{ => Typed}/CustomAggregationTests.swift (100%)
 rename Tests/SQLiteTests/{ => Typed}/CustomFunctionsTests.swift (100%)
 rename Tests/SQLiteTests/{ => Typed}/DateAndTimeFunctionTests.swift (100%)
 rename Tests/SQLiteTests/{ => Typed}/ExpressionTests.swift (100%)
 rename Tests/SQLiteTests/{ => Typed}/OperatorsTests.swift (100%)
 rename Tests/SQLiteTests/{ => Typed}/QueryIntegrationTests.swift (100%)
 rename Tests/SQLiteTests/{ => Typed}/QueryTests.swift (100%)
 rename Tests/SQLiteTests/{ => Typed}/RowTests.swift (100%)
 rename Tests/SQLiteTests/{ => Typed}/SelectTests.swift (100%)
 rename Tests/SQLiteTests/{ => Typed}/SetterTests.swift (100%)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index a97ef184..bc79473e 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -30,96 +30,136 @@
 		03A65E841C6BB2FB0062603F /* Query.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B001C3F06E900AE3E12 /* Query.swift */; };
 		03A65E851C6BB2FB0062603F /* Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B011C3F06E900AE3E12 /* Schema.swift */; };
 		03A65E861C6BB2FB0062603F /* Setter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B021C3F06E900AE3E12 /* Setter.swift */; };
-		03A65E871C6BB3030062603F /* AggregateFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1A1C3F137700AE3E12 /* AggregateFunctionsTests.swift */; };
-		03A65E881C6BB3030062603F /* BlobTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1B1C3F137700AE3E12 /* BlobTests.swift */; };
-		03A65E891C6BB3030062603F /* ConnectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1D1C3F137700AE3E12 /* ConnectionTests.swift */; };
-		03A65E8A1C6BB3030062603F /* CoreFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1E1C3F137700AE3E12 /* CoreFunctionsTests.swift */; };
-		03A65E8B1C6BB3030062603F /* CustomFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1F1C3F137700AE3E12 /* CustomFunctionsTests.swift */; };
-		03A65E8C1C6BB3030062603F /* ExpressionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B201C3F137700AE3E12 /* ExpressionTests.swift */; };
-		03A65E8D1C6BB3030062603F /* FTS4Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B211C3F137700AE3E12 /* FTS4Tests.swift */; };
-		03A65E8E1C6BB3030062603F /* OperatorsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2A1C3F141E00AE3E12 /* OperatorsTests.swift */; };
-		03A65E8F1C6BB3030062603F /* QueryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2B1C3F141E00AE3E12 /* QueryTests.swift */; };
-		03A65E901C6BB3030062603F /* RTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2C1C3F141E00AE3E12 /* RTreeTests.swift */; };
-		03A65E911C6BB3030062603F /* SchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2D1C3F141E00AE3E12 /* SchemaTests.swift */; };
-		03A65E921C6BB3030062603F /* SetterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B181C3F134A00AE3E12 /* SetterTests.swift */; };
-		03A65E931C6BB3030062603F /* StatementTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B321C3F142E00AE3E12 /* StatementTests.swift */; };
-		03A65E941C6BB3030062603F /* ValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B331C3F142E00AE3E12 /* ValueTests.swift */; };
 		03A65E951C6BB3030062603F /* TestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B161C3F127200AE3E12 /* TestHelpers.swift */; };
 		03A65E971C6BB3210062603F /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 03A65E961C6BB3210062603F /* libsqlite3.tbd */; };
 		19A17018F250343BD0F9F4B0 /* Connection+Pragmas.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17F285B767BFACD96714B /* Connection+Pragmas.swift */; };
+		19A17021286A4D8D6C2EF12D /* ConnectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17855BD524FF888265B3C /* ConnectionTests.swift */; };
+		19A17026DCDCDA405B09A229 /* Connection+AttachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A170C08525D3D27CB5F83C /* Connection+AttachTests.swift */; };
 		19A17073552293CA063BEA66 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17E723300E5ED3771DCB5 /* Result.swift */; };
+		19A1708D3D58D7BC1168E55F /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1787E16C8562C09C076F5 /* CipherTests.swift */; };
 		19A1709C3E7A406E62293B2A /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; };
 		19A170ACC97B19730FB7BA4D /* Connection+Aggregation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */; };
+		19A170AEBAA56DC3355A73B3 /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178AEF32ABC8BF2993FB5 /* DateAndTimeFunctionTests.swift */; };
+		19A170C56745F9D722A73D77 /* AggregateFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17613F00A3F4D4A257A04 /* AggregateFunctionsTests.swift */; };
+		19A170D938343E30119EDFB3 /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A174FE5B47A97937A27276 /* RowTests.swift */; };
+		19A1714F7CF964D568AB14E0 /* BlobTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171A2ED4E2640F197F48C /* BlobTests.swift */; };
 		19A17152E32A9585831E3FE0 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
+		19A1716BF8E15F91A6B5CB7A /* CustomFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17F2B5959B212A33C383F /* CustomFunctionsTests.swift */; };
 		19A1717B10CC941ACB5533D6 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
-		19A17188B4D96636F9C0C209 /* ConnectionSchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17CA1DF7D0F7C9A94C51C /* ConnectionSchemaTests.swift */; };
-		19A171967CC511C4F6F773C9 /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */; };
-		19A171BE056457F13BFBC4C3 /* FTSIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171FDE4D67879B14ACBDF /* FTSIntegrationTests.swift */; };
-		19A171E6FA242F72A308C594 /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
+		19A17188B4D96636F9C0C209 /* Connection+SchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17CA1DF7D0F7C9A94C51C /* Connection+SchemaTests.swift */; };
 		19A171F12AB8B07F2FD7201A /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
-		19A1720B67ED13E6150C6A3D /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */; };
-		19A17254FBA7894891F7297B /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
-		19A1725658E480B9B378F28B /* ConnectionSchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17CA1DF7D0F7C9A94C51C /* ConnectionSchemaTests.swift */; };
-		19A172A9B536D02D4A98AAAD /* QueryIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */; };
-		19A172EB202970561E5C4245 /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */; };
+		19A171F243A589C5EBC47937 /* OperatorsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17475DCA068453F787613 /* OperatorsTests.swift */; };
+		19A1725658E480B9B378F28B /* Connection+SchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17CA1DF7D0F7C9A94C51C /* Connection+SchemaTests.swift */; };
+		19A1726002D24C14F876C8FE /* ValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17AE284BB1DF31D1B753E /* ValueTests.swift */; };
+		19A172F71EFD65342072D8D2 /* SchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171A7714C6524093255C5 /* SchemaTests.swift */; };
+		19A173088B85A7E18E8582A7 /* FTSIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BE1CC4AD4036BAB8EE0 /* FTSIntegrationTests.swift */; };
+		19A173389E53CB24DFA8CEDD /* QueryIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17CAE60446607E99C22A6 /* QueryIntegrationTests.swift */; };
+		19A173465F23C64DF3DF469B /* ConnectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17855BD524FF888265B3C /* ConnectionTests.swift */; };
 		19A173668D948AD4DF1F5352 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
 		19A1737286A74F3CF7412906 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
 		19A173EFEF0B3BD0B3ED406C /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17E723300E5ED3771DCB5 /* Result.swift */; };
+		19A173F25449876761347072 /* Connection+AttachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A170C08525D3D27CB5F83C /* Connection+AttachTests.swift */; };
+		19A173F429D7E46289EB2167 /* ResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1745BE8623D8C6808DB3C /* ResultTests.swift */; };
 		19A17408007B182F884E3A53 /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; };
 		19A1740EACD47904AA24B8DC /* SchemaDefinitions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17268AE67B746B96AC125 /* SchemaDefinitions.swift */; };
+		19A17411403D60640467209E /* ExpressionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A170F141BF21946D159083 /* ExpressionTests.swift */; };
+		19A174118D11B93DA5DAAF79 /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178AEF32ABC8BF2993FB5 /* DateAndTimeFunctionTests.swift */; };
+		19A17437659BD7FD787D94A6 /* CustomAggregationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A177EF5E2D91BA86DA4480 /* CustomAggregationTests.swift */; };
+		19A17444861E1443143DEB44 /* FTS4Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1715904F7B6851FCB5EF6 /* FTS4Tests.swift */; };
 		19A174506543905D71BF0518 /* Connection+Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A170A97B51DC5EE365F3C5 /* Connection+Schema.swift */; };
+		19A17457B0461F484AF6BE40 /* CustomFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17F2B5959B212A33C383F /* CustomFunctionsTests.swift */; };
+		19A17482E6FC5E563F3E6A47 /* OperatorsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17475DCA068453F787613 /* OperatorsTests.swift */; };
 		19A17490543609FCED53CACC /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
-		19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
 		19A1750CEE9B05267995CF3D /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
 		19A1750EF4A5F92954A451FF /* Connection+Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A170A97B51DC5EE365F3C5 /* Connection+Schema.swift */; };
+		19A1755C49154C87304C9146 /* FTSIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BE1CC4AD4036BAB8EE0 /* FTSIntegrationTests.swift */; };
 		19A1760CE25615CA015E2E5F /* Connection+Pragmas.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17F285B767BFACD96714B /* Connection+Pragmas.swift */; };
 		19A176376CB6A94759F7980A /* Connection+Aggregation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */; };
-		19A176406BDE9D9C80CC9FA3 /* QueryIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */; };
+		19A1766135CE9786B1878603 /* ValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17AE284BB1DF31D1B753E /* ValueTests.swift */; };
 		19A1766AC10D13C4EFF349AD /* SchemaChangerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17FDB0B0CFB8987906FD0 /* SchemaChangerTests.swift */; };
-		19A1769C1F3A7542BECF50FF /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */; };
+		19A176B3316281F004F92276 /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A174FE5B47A97937A27276 /* RowTests.swift */; };
 		19A177290558991BCC60E4E3 /* SchemaChanger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171B262DDE8718513CFDA /* SchemaChanger.swift */; };
+		19A1772EBE65173EDFB1AFCA /* CustomAggregationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A177EF5E2D91BA86DA4480 /* CustomAggregationTests.swift */; };
+		19A1773155AC2BF2CA86A473 /* SetterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1709D5BDD2691BA160012 /* SetterTests.swift */; };
 		19A1773A335CAB9D0AE14E8E /* SchemaChanger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171B262DDE8718513CFDA /* SchemaChanger.swift */; };
+		19A17746150A815944A6820B /* SelectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17EC0C43015063945D32E /* SelectTests.swift */; };
+		19A1776BD5127DFDF847FF1F /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B96EBD42C878E609CDC /* FTS5Tests.swift */; };
+		19A177909023B7B940C5805E /* FTSIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BE1CC4AD4036BAB8EE0 /* FTSIntegrationTests.swift */; };
+		19A177AA5922527BBDC77CF9 /* QueryIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17CAE60446607E99C22A6 /* QueryIntegrationTests.swift */; };
 		19A177C25834473FAB32CF3B /* SchemaChangerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17FDB0B0CFB8987906FD0 /* SchemaChangerTests.swift */; };
-		19A177CC33F2E6A24AF90B02 /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
+		19A177D5C6542E2D572162E5 /* QueryIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17CAE60446607E99C22A6 /* QueryIntegrationTests.swift */; };
 		19A178072B371489E6A1E839 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
+		19A1781CBA8968ABD3E00877 /* ExpressionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A170F141BF21946D159083 /* ExpressionTests.swift */; };
+		19A1782444437C7FC6B75CBC /* BlobTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171A2ED4E2640F197F48C /* BlobTests.swift */; };
 		19A17835FD5886FDC5A3228F /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
-		19A1785195182AF8731A8BDA /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */; };
+		19A178767223229E61C5066F /* FTS4Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1715904F7B6851FCB5EF6 /* FTS4Tests.swift */; };
+		19A17885B646CB0201BE4BD5 /* QueryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171ED017645C8B04DF9F2 /* QueryTests.swift */; };
 		19A178A8B2A34FB6B565DEDA /* Connection+Pragmas.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17F285B767BFACD96714B /* Connection+Pragmas.swift */; };
+		19A178C041DDCF80B533AD13 /* BlobTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171A2ED4E2640F197F48C /* BlobTests.swift */; };
+		19A178DA2BB5970778CCAF13 /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B96EBD42C878E609CDC /* FTS5Tests.swift */; };
+		19A178DF5A96CFEFF1E271F6 /* AggregateFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17613F00A3F4D4A257A04 /* AggregateFunctionsTests.swift */; };
+		19A178F9008614B8A8425635 /* Connection+PragmaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17C60D3464461057E4D63 /* Connection+PragmaTests.swift */; };
+		19A17900387FDCF578B31E3E /* OperatorsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17475DCA068453F787613 /* OperatorsTests.swift */; };
+		19A17912DB9D3AC8FECF948B /* ResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1745BE8623D8C6808DB3C /* ResultTests.swift */; };
+		19A17923494236793893BF72 /* StatementTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1756EB81E9F7F45B12A78 /* StatementTests.swift */; };
 		19A1792C0520D4E83C2EB075 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
+		19A1793972BDDDB027C113BB /* CustomAggregationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A177EF5E2D91BA86DA4480 /* CustomAggregationTests.swift */; };
+		19A179786A6826D58A70F8BC /* AggregateFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17613F00A3F4D4A257A04 /* AggregateFunctionsTests.swift */; };
 		19A17986405D9A875698408F /* Connection+Pragmas.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17F285B767BFACD96714B /* Connection+Pragmas.swift */; };
-		19A179A0C45377CB09BB358C /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
+		19A1799AF6643CF5081BFA15 /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178AEF32ABC8BF2993FB5 /* DateAndTimeFunctionTests.swift */; };
 		19A179B59450FE7C4811AB8A /* Connection+Aggregation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */; };
+		19A179BB9A6665B2B99DA546 /* CoreFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B55F2409B7031443495 /* CoreFunctionsTests.swift */; };
+		19A179BCD483DEA21661FD37 /* Connection+AttachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A170C08525D3D27CB5F83C /* Connection+AttachTests.swift */; };
 		19A179CCF9671E345E5A9811 /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
 		19A179E76EA6207669B60C1B /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
 		19A17A33EA026C2E2CEBAF36 /* Connection+Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A170A97B51DC5EE365F3C5 /* Connection+Schema.swift */; };
+		19A17A391BF056E3D729E70A /* SchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171A7714C6524093255C5 /* SchemaTests.swift */; };
+		19A17A52BF29D27C9AA229E7 /* QueryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171ED017645C8B04DF9F2 /* QueryTests.swift */; };
+		19A17A7B3E3B7E76364A2AEE /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1787E16C8562C09C076F5 /* CipherTests.swift */; };
+		19A17A7DF99B0379FD3396B1 /* CustomFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17F2B5959B212A33C383F /* CustomFunctionsTests.swift */; };
+		19A17A9520802ACF45907970 /* RTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17162C9861E5C4900455D /* RTreeTests.swift */; };
+		19A17ABCF0EB4808BDC5B5FF /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A174FE5B47A97937A27276 /* RowTests.swift */; };
 		19A17B0DF1DDB6BBC9C95D64 /* SchemaDefinitions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17268AE67B746B96AC125 /* SchemaDefinitions.swift */; };
-		19A17B36ABC6006AB80F693C /* ConnectionSchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17CA1DF7D0F7C9A94C51C /* ConnectionSchemaTests.swift */; };
+		19A17B1D9B5CEBE9CE09280C /* RTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17162C9861E5C4900455D /* RTreeTests.swift */; };
+		19A17B36ABC6006AB80F693C /* Connection+SchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17CA1DF7D0F7C9A94C51C /* Connection+SchemaTests.swift */; };
 		19A17B62A4125AF4F6014CF5 /* SchemaDefinitionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A176174862D0F0139B3987 /* SchemaDefinitionsTests.swift */; };
 		19A17BA13FD35F058787B7D3 /* SchemaDefinitions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17268AE67B746B96AC125 /* SchemaDefinitions.swift */; };
-		19A17C013B00682B70D53DB8 /* FTSIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171FDE4D67879B14ACBDF /* FTSIntegrationTests.swift */; };
-		19A17C4B951CB054EE48AB1C /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
-		19A17C80076860CF7751A056 /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */; };
-		19A17C9407AC0EE104E5CC85 /* FTSIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171FDE4D67879B14ACBDF /* FTSIntegrationTests.swift */; };
-		19A17CB808ACF606726E77A8 /* QueryIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */; };
+		19A17BACF4C032513DE1F879 /* Connection+PragmaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17C60D3464461057E4D63 /* Connection+PragmaTests.swift */; };
+		19A17C74233AFC2EDAFA23DC /* ResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1745BE8623D8C6808DB3C /* ResultTests.swift */; };
+		19A17CA4D7B63D845428A9C5 /* StatementTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1756EB81E9F7F45B12A78 /* StatementTests.swift */; };
+		19A17CA6ADB78A2E545BF836 /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1787E16C8562C09C076F5 /* CipherTests.swift */; };
+		19A17CF65C0196E03BC64519 /* ConnectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17855BD524FF888265B3C /* ConnectionTests.swift */; };
 		19A17D1BEABA610ABF003D67 /* SchemaDefinitions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17268AE67B746B96AC125 /* SchemaDefinitions.swift */; };
+		19A17D6EC40BC35A5DC81BA8 /* StatementTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1756EB81E9F7F45B12A78 /* StatementTests.swift */; };
+		19A17D993398B8215B73E1EA /* CoreFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B55F2409B7031443495 /* CoreFunctionsTests.swift */; };
+		19A17DAD5975D9367EAA46E2 /* RTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17162C9861E5C4900455D /* RTreeTests.swift */; };
 		19A17DC282E36C4F41AA440B /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
+		19A17DD33C2E43DD6EE05A60 /* ExpressionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A170F141BF21946D159083 /* ExpressionTests.swift */; };
+		19A17DE1FCDB5695702AD24D /* SelectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17EC0C43015063945D32E /* SelectTests.swift */; };
+		19A17DE34C477232592A8F6B /* CoreFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B55F2409B7031443495 /* CoreFunctionsTests.swift */; };
 		19A17DF8D4F13A20F5D2269E /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17E723300E5ED3771DCB5 /* Result.swift */; };
 		19A17DFE05ED8B1F7C45F7EE /* SchemaChanger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171B262DDE8718513CFDA /* SchemaChanger.swift */; };
 		19A17E04C4C0956715C5676A /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
+		19A17E0ABA6C415F014CD51C /* SetterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1709D5BDD2691BA160012 /* SetterTests.swift */; };
+		19A17E1DD976D5CE80018749 /* FTS4Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1715904F7B6851FCB5EF6 /* FTS4Tests.swift */; };
 		19A17E29278A12BC4F542506 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
+		19A17E3F47DA087E2B76D087 /* QueryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171ED017645C8B04DF9F2 /* QueryTests.swift */; };
 		19A17E80F736EEE8EE2AA4CE /* SchemaDefinitionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A176174862D0F0139B3987 /* SchemaDefinitionsTests.swift */; };
 		19A17EC0D68BA8C03288ADF7 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
 		19A17F0BF02896E1664F4090 /* Connection+Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A170A97B51DC5EE365F3C5 /* Connection+Schema.swift */; };
 		19A17F1B3F0A3C96B5ED6D64 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17E723300E5ED3771DCB5 /* Result.swift */; };
+		19A17F2096E83A3181E03317 /* SchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171A7714C6524093255C5 /* SchemaTests.swift */; };
 		19A17F60B685636D1F83C2DD /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; };
+		19A17F7977364EC8CD33C3C3 /* SelectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17EC0C43015063945D32E /* SelectTests.swift */; };
+		19A17F907258E524B3CA2FAE /* SetterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1709D5BDD2691BA160012 /* SetterTests.swift */; };
+		19A17FACE8E4D54A50BA934E /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B96EBD42C878E609CDC /* FTS5Tests.swift */; };
 		19A17FB80B94E882050AA908 /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
+		19A17FBAA26953EB854E790D /* Connection+PragmaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17C60D3464461057E4D63 /* Connection+PragmaTests.swift */; };
 		19A17FC04708C6ED637DDFD4 /* SchemaChangerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17FDB0B0CFB8987906FD0 /* SchemaChangerTests.swift */; };
 		19A17FC07731779C1B8506FA /* SchemaChanger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171B262DDE8718513CFDA /* SchemaChanger.swift */; };
+		19A17FD22EF43DF428DD93BA /* ValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17AE284BB1DF31D1B753E /* ValueTests.swift */; };
 		19A17FE78A39E86F330420EC /* SchemaDefinitionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A176174862D0F0139B3987 /* SchemaDefinitionsTests.swift */; };
 		19A17FF4A10B44D3937C8CAC /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
-		3717F908221F5D8800B9BD3D /* CustomAggregationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */; };
-		3717F909221F5D8900B9BD3D /* CustomAggregationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */; };
-		3717F90A221F5D8900B9BD3D /* CustomAggregationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */; };
 		3D67B3E61DB2469200A4F4C6 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */; };
 		3D67B3E71DB246BA00A4F4C6 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
 		3D67B3E81DB246BA00A4F4C6 /* Connection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEF1C3F06E900AE3E12 /* Connection.swift */; };
@@ -144,9 +184,6 @@
 		3DF7B78928842972005DD8CA /* Connection+Attach.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B78728842972005DD8CA /* Connection+Attach.swift */; };
 		3DF7B78A28842972005DD8CA /* Connection+Attach.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B78728842972005DD8CA /* Connection+Attach.swift */; };
 		3DF7B78B28842972005DD8CA /* Connection+Attach.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B78728842972005DD8CA /* Connection+Attach.swift */; };
-		3DF7B78D28842C23005DD8CA /* ResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B78C28842C23005DD8CA /* ResultTests.swift */; };
-		3DF7B78E28842C23005DD8CA /* ResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B78C28842C23005DD8CA /* ResultTests.swift */; };
-		3DF7B78F28842C23005DD8CA /* ResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B78C28842C23005DD8CA /* ResultTests.swift */; };
 		3DF7B791288449BA005DD8CA /* URIQueryParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B790288449BA005DD8CA /* URIQueryParameter.swift */; };
 		3DF7B792288449BA005DD8CA /* URIQueryParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B790288449BA005DD8CA /* URIQueryParameter.swift */; };
 		3DF7B793288449BA005DD8CA /* URIQueryParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B790288449BA005DD8CA /* URIQueryParameter.swift */; };
@@ -162,9 +199,6 @@
 		997DF2AF287FC06D00F8DF95 /* Query+with.swift in Sources */ = {isa = PBXBuildFile; fileRef = 997DF2AD287FC06D00F8DF95 /* Query+with.swift */; };
 		997DF2B0287FC06D00F8DF95 /* Query+with.swift in Sources */ = {isa = PBXBuildFile; fileRef = 997DF2AD287FC06D00F8DF95 /* Query+with.swift */; };
 		997DF2B1287FC06D00F8DF95 /* Query+with.swift in Sources */ = {isa = PBXBuildFile; fileRef = 997DF2AD287FC06D00F8DF95 /* Query+with.swift */; };
-		D4DB368C20C09CFB00D5A58E /* SelectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4DB368A20C09C9B00D5A58E /* SelectTests.swift */; };
-		D4DB368D20C09CFC00D5A58E /* SelectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4DB368A20C09C9B00D5A58E /* SelectTests.swift */; };
-		D4DB368E20C09CFD00D5A58E /* SelectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4DB368A20C09C9B00D5A58E /* SelectTests.swift */; };
 		EE247AD71C3F04ED00AE3E12 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		EE247ADE1C3F04ED00AE3E12 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE247AD31C3F04ED00AE3E12 /* SQLite.framework */; };
 		EE247B031C3F06E900AE3E12 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
@@ -185,35 +219,7 @@
 		EE247B141C3F06E900AE3E12 /* Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B011C3F06E900AE3E12 /* Schema.swift */; };
 		EE247B151C3F06E900AE3E12 /* Setter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B021C3F06E900AE3E12 /* Setter.swift */; };
 		EE247B171C3F127200AE3E12 /* TestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B161C3F127200AE3E12 /* TestHelpers.swift */; };
-		EE247B191C3F134A00AE3E12 /* SetterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B181C3F134A00AE3E12 /* SetterTests.swift */; };
-		EE247B221C3F137700AE3E12 /* AggregateFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1A1C3F137700AE3E12 /* AggregateFunctionsTests.swift */; };
-		EE247B231C3F137700AE3E12 /* BlobTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1B1C3F137700AE3E12 /* BlobTests.swift */; };
-		EE247B251C3F137700AE3E12 /* ConnectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1D1C3F137700AE3E12 /* ConnectionTests.swift */; };
-		EE247B261C3F137700AE3E12 /* CoreFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1E1C3F137700AE3E12 /* CoreFunctionsTests.swift */; };
-		EE247B271C3F137700AE3E12 /* CustomFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1F1C3F137700AE3E12 /* CustomFunctionsTests.swift */; };
-		EE247B281C3F137700AE3E12 /* ExpressionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B201C3F137700AE3E12 /* ExpressionTests.swift */; };
-		EE247B291C3F137700AE3E12 /* FTS4Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B211C3F137700AE3E12 /* FTS4Tests.swift */; };
-		EE247B2E1C3F141E00AE3E12 /* OperatorsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2A1C3F141E00AE3E12 /* OperatorsTests.swift */; };
-		EE247B2F1C3F141E00AE3E12 /* QueryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2B1C3F141E00AE3E12 /* QueryTests.swift */; };
-		EE247B301C3F141E00AE3E12 /* RTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2C1C3F141E00AE3E12 /* RTreeTests.swift */; };
-		EE247B311C3F141E00AE3E12 /* SchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2D1C3F141E00AE3E12 /* SchemaTests.swift */; };
-		EE247B341C3F142E00AE3E12 /* StatementTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B321C3F142E00AE3E12 /* StatementTests.swift */; };
-		EE247B351C3F142E00AE3E12 /* ValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B331C3F142E00AE3E12 /* ValueTests.swift */; };
 		EE247B461C3F3ED000AE3E12 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE247B3C1C3F3ED000AE3E12 /* SQLite.framework */; };
-		EE247B531C3F3FC700AE3E12 /* AggregateFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1A1C3F137700AE3E12 /* AggregateFunctionsTests.swift */; };
-		EE247B541C3F3FC700AE3E12 /* BlobTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1B1C3F137700AE3E12 /* BlobTests.swift */; };
-		EE247B551C3F3FC700AE3E12 /* ConnectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1D1C3F137700AE3E12 /* ConnectionTests.swift */; };
-		EE247B561C3F3FC700AE3E12 /* CoreFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1E1C3F137700AE3E12 /* CoreFunctionsTests.swift */; };
-		EE247B571C3F3FC700AE3E12 /* CustomFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B1F1C3F137700AE3E12 /* CustomFunctionsTests.swift */; };
-		EE247B581C3F3FC700AE3E12 /* ExpressionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B201C3F137700AE3E12 /* ExpressionTests.swift */; };
-		EE247B591C3F3FC700AE3E12 /* FTS4Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B211C3F137700AE3E12 /* FTS4Tests.swift */; };
-		EE247B5A1C3F3FC700AE3E12 /* OperatorsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2A1C3F141E00AE3E12 /* OperatorsTests.swift */; };
-		EE247B5B1C3F3FC700AE3E12 /* QueryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2B1C3F141E00AE3E12 /* QueryTests.swift */; };
-		EE247B5C1C3F3FC700AE3E12 /* RTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2C1C3F141E00AE3E12 /* RTreeTests.swift */; };
-		EE247B5D1C3F3FC700AE3E12 /* SchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B2D1C3F141E00AE3E12 /* SchemaTests.swift */; };
-		EE247B5E1C3F3FC700AE3E12 /* SetterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B181C3F134A00AE3E12 /* SetterTests.swift */; };
-		EE247B5F1C3F3FC700AE3E12 /* StatementTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B321C3F142E00AE3E12 /* StatementTests.swift */; };
-		EE247B601C3F3FC700AE3E12 /* ValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B331C3F142E00AE3E12 /* ValueTests.swift */; };
 		EE247B611C3F3FC700AE3E12 /* TestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B161C3F127200AE3E12 /* TestHelpers.swift */; };
 		EE247B621C3F3FDB00AE3E12 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		EE247B631C3F3FDB00AE3E12 /* Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF71C3F06E900AE3E12 /* Foundation.swift */; };
@@ -266,34 +272,51 @@
 		03A65E5A1C6BB0F50062603F /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		03A65E631C6BB0F60062603F /* SQLiteTests tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SQLiteTests tvOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
 		03A65E961C6BB3210062603F /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
+		19A1709D5BDD2691BA160012 /* SetterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetterTests.swift; sourceTree = "<group>"; };
 		19A170A97B51DC5EE365F3C5 /* Connection+Schema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Connection+Schema.swift"; sourceTree = "<group>"; };
+		19A170C08525D3D27CB5F83C /* Connection+AttachTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Connection+AttachTests.swift"; sourceTree = "<group>"; };
+		19A170F141BF21946D159083 /* ExpressionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExpressionTests.swift; sourceTree = "<group>"; };
 		19A1710E73A46D5AC721CDA9 /* Errors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = "<group>"; };
+		19A1715904F7B6851FCB5EF6 /* FTS4Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS4Tests.swift; sourceTree = "<group>"; };
+		19A17162C9861E5C4900455D /* RTreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RTreeTests.swift; sourceTree = "<group>"; };
+		19A171A2ED4E2640F197F48C /* BlobTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlobTests.swift; sourceTree = "<group>"; };
+		19A171A7714C6524093255C5 /* SchemaTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaTests.swift; sourceTree = "<group>"; };
 		19A171B262DDE8718513CFDA /* SchemaChanger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaChanger.swift; sourceTree = "<group>"; };
-		19A171FDE4D67879B14ACBDF /* FTSIntegrationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTSIntegrationTests.swift; sourceTree = "<group>"; };
-		19A1721B8984686B9963B45D /* FTS5Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5Tests.swift; sourceTree = "<group>"; };
+		19A171ED017645C8B04DF9F2 /* QueryTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryTests.swift; sourceTree = "<group>"; };
 		19A17268AE67B746B96AC125 /* SchemaDefinitions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaDefinitions.swift; sourceTree = "<group>"; };
-		19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAndTimeFunctionTests.swift; sourceTree = "<group>"; };
 		19A1730E4390C775C25677D1 /* FTS5.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5.swift; sourceTree = "<group>"; };
-		19A17399EA9E61235D5D77BF /* CipherTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CipherTests.swift; sourceTree = "<group>"; };
+		19A1745BE8623D8C6808DB3C /* ResultTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResultTests.swift; sourceTree = "<group>"; };
+		19A17475DCA068453F787613 /* OperatorsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperatorsTests.swift; sourceTree = "<group>"; };
+		19A174FE5B47A97937A27276 /* RowTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RowTests.swift; sourceTree = "<group>"; };
+		19A1756EB81E9F7F45B12A78 /* StatementTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatementTests.swift; sourceTree = "<group>"; };
 		19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Connection+Aggregation.swift"; sourceTree = "<group>"; };
-		19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RowTests.swift; sourceTree = "<group>"; };
+		19A17613F00A3F4D4A257A04 /* AggregateFunctionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AggregateFunctionsTests.swift; sourceTree = "<group>"; };
 		19A176174862D0F0139B3987 /* SchemaDefinitionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaDefinitionsTests.swift; sourceTree = "<group>"; };
+		19A177EF5E2D91BA86DA4480 /* CustomAggregationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomAggregationTests.swift; sourceTree = "<group>"; };
+		19A17855BD524FF888265B3C /* ConnectionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectionTests.swift; sourceTree = "<group>"; };
+		19A1787E16C8562C09C076F5 /* CipherTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CipherTests.swift; sourceTree = "<group>"; };
 		19A178A39ACA9667A62663CC /* Cipher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cipher.swift; sourceTree = "<group>"; };
+		19A178AEF32ABC8BF2993FB5 /* DateAndTimeFunctionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAndTimeFunctionTests.swift; sourceTree = "<group>"; };
 		19A1794B7972D14330A65BBD /* Linux.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Linux.md; sourceTree = "<group>"; };
 		19A1794CC4D7827E997E32A7 /* FoundationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationTests.swift; sourceTree = "<group>"; };
+		19A17AE284BB1DF31D1B753E /* ValueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValueTests.swift; sourceTree = "<group>"; };
+		19A17B55F2409B7031443495 /* CoreFunctionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreFunctionsTests.swift; sourceTree = "<group>"; };
 		19A17B93B48B5560E6E51791 /* Fixtures.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Fixtures.swift; sourceTree = "<group>"; };
+		19A17B96EBD42C878E609CDC /* FTS5Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5Tests.swift; sourceTree = "<group>"; };
 		19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAndTimeFunctions.swift; sourceTree = "<group>"; };
-		19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryIntegrationTests.swift; sourceTree = "<group>"; };
-		19A17CA1DF7D0F7C9A94C51C /* ConnectionSchemaTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectionSchemaTests.swift; sourceTree = "<group>"; };
+		19A17BE1CC4AD4036BAB8EE0 /* FTSIntegrationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTSIntegrationTests.swift; sourceTree = "<group>"; };
+		19A17C60D3464461057E4D63 /* Connection+PragmaTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Connection+PragmaTests.swift"; sourceTree = "<group>"; };
+		19A17CA1DF7D0F7C9A94C51C /* Connection+SchemaTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Connection+SchemaTests.swift"; sourceTree = "<group>"; };
+		19A17CAE60446607E99C22A6 /* QueryIntegrationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryIntegrationTests.swift; sourceTree = "<group>"; };
 		19A17E723300E5ED3771DCB5 /* Result.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Result.swift; sourceTree = "<group>"; };
 		19A17EA3A313F129011B3FA0 /* Release.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Release.md; sourceTree = "<group>"; };
+		19A17EC0C43015063945D32E /* SelectTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectTests.swift; sourceTree = "<group>"; };
 		19A17F285B767BFACD96714B /* Connection+Pragmas.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Connection+Pragmas.swift"; sourceTree = "<group>"; };
+		19A17F2B5959B212A33C383F /* CustomFunctionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomFunctionsTests.swift; sourceTree = "<group>"; };
 		19A17FDB0B0CFB8987906FD0 /* SchemaChangerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaChangerTests.swift; sourceTree = "<group>"; };
-		3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomAggregationTests.swift; sourceTree = "<group>"; };
 		3D3C3CCB26E5568800759140 /* SQLite.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = SQLite.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
 		3D67B3E51DB2469200A4F4C6 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.0.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; };
 		3DF7B78728842972005DD8CA /* Connection+Attach.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Connection+Attach.swift"; sourceTree = "<group>"; };
-		3DF7B78C28842C23005DD8CA /* ResultTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultTests.swift; sourceTree = "<group>"; };
 		3DF7B790288449BA005DD8CA /* URIQueryParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URIQueryParameter.swift; sourceTree = "<group>"; };
 		3DF7B79528846FCC005DD8CA /* Resources */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Resources; sourceTree = "<group>"; };
 		3DF7B79A2884C353005DD8CA /* CHANGELOG.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = "<group>"; };
@@ -302,7 +325,6 @@
 		49EB68C31F7B3CB400D89D40 /* Coding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coding.swift; sourceTree = "<group>"; };
 		997DF2AD287FC06D00F8DF95 /* Query+with.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Query+with.swift"; sourceTree = "<group>"; };
 		A121AC451CA35C79005A31D1 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
-		D4DB368A20C09C9B00D5A58E /* SelectTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectTests.swift; sourceTree = "<group>"; };
 		EE247AD31C3F04ED00AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AD61C3F04ED00AE3E12 /* SQLite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLite.h; sourceTree = "<group>"; };
 		EE247AD81C3F04ED00AE3E12 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -326,20 +348,6 @@
 		EE247B011C3F06E900AE3E12 /* Schema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Schema.swift; sourceTree = "<group>"; };
 		EE247B021C3F06E900AE3E12 /* Setter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Setter.swift; sourceTree = "<group>"; };
 		EE247B161C3F127200AE3E12 /* TestHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestHelpers.swift; sourceTree = "<group>"; };
-		EE247B181C3F134A00AE3E12 /* SetterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetterTests.swift; sourceTree = "<group>"; };
-		EE247B1A1C3F137700AE3E12 /* AggregateFunctionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AggregateFunctionsTests.swift; sourceTree = "<group>"; };
-		EE247B1B1C3F137700AE3E12 /* BlobTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlobTests.swift; sourceTree = "<group>"; };
-		EE247B1D1C3F137700AE3E12 /* ConnectionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectionTests.swift; sourceTree = "<group>"; };
-		EE247B1E1C3F137700AE3E12 /* CoreFunctionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreFunctionsTests.swift; sourceTree = "<group>"; };
-		EE247B1F1C3F137700AE3E12 /* CustomFunctionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomFunctionsTests.swift; sourceTree = "<group>"; };
-		EE247B201C3F137700AE3E12 /* ExpressionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExpressionTests.swift; sourceTree = "<group>"; };
-		EE247B211C3F137700AE3E12 /* FTS4Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS4Tests.swift; sourceTree = "<group>"; };
-		EE247B2A1C3F141E00AE3E12 /* OperatorsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperatorsTests.swift; sourceTree = "<group>"; };
-		EE247B2B1C3F141E00AE3E12 /* QueryTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryTests.swift; sourceTree = "<group>"; };
-		EE247B2C1C3F141E00AE3E12 /* RTreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RTreeTests.swift; sourceTree = "<group>"; };
-		EE247B2D1C3F141E00AE3E12 /* SchemaTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaTests.swift; sourceTree = "<group>"; };
-		EE247B321C3F142E00AE3E12 /* StatementTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatementTests.swift; sourceTree = "<group>"; };
-		EE247B331C3F142E00AE3E12 /* ValueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValueTests.swift; sourceTree = "<group>"; };
 		EE247B3C1C3F3ED000AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247B451C3F3ED000AE3E12 /* SQLiteTests Mac.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SQLiteTests Mac.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247B771C3F40D700AE3E12 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
@@ -423,16 +431,62 @@
 			path = Schema;
 			sourceTree = "<group>";
 		};
+		19A1798E3459573BEE50FA34 /* Core */ = {
+			isa = PBXGroup;
+			children = (
+				19A1756EB81E9F7F45B12A78 /* StatementTests.swift */,
+				19A171A2ED4E2640F197F48C /* BlobTests.swift */,
+				19A17855BD524FF888265B3C /* ConnectionTests.swift */,
+				19A17B55F2409B7031443495 /* CoreFunctionsTests.swift */,
+				19A1745BE8623D8C6808DB3C /* ResultTests.swift */,
+				19A17AE284BB1DF31D1B753E /* ValueTests.swift */,
+				19A17C60D3464461057E4D63 /* Connection+PragmaTests.swift */,
+				19A170C08525D3D27CB5F83C /* Connection+AttachTests.swift */,
+			);
+			path = Core;
+			sourceTree = "<group>";
+		};
+		19A17AECBF878B1DAE0AE3DD /* Typed */ = {
+			isa = PBXGroup;
+			children = (
+				19A170F141BF21946D159083 /* ExpressionTests.swift */,
+				19A171ED017645C8B04DF9F2 /* QueryTests.swift */,
+				19A178AEF32ABC8BF2993FB5 /* DateAndTimeFunctionTests.swift */,
+				19A17F2B5959B212A33C383F /* CustomFunctionsTests.swift */,
+				19A17475DCA068453F787613 /* OperatorsTests.swift */,
+				19A17EC0C43015063945D32E /* SelectTests.swift */,
+				19A17CAE60446607E99C22A6 /* QueryIntegrationTests.swift */,
+				19A17613F00A3F4D4A257A04 /* AggregateFunctionsTests.swift */,
+				19A177EF5E2D91BA86DA4480 /* CustomAggregationTests.swift */,
+				19A1709D5BDD2691BA160012 /* SetterTests.swift */,
+				19A174FE5B47A97937A27276 /* RowTests.swift */,
+			);
+			path = Typed;
+			sourceTree = "<group>";
+		};
 		19A17B56FBA20E7245BC8AC0 /* Schema */ = {
 			isa = PBXGroup;
 			children = (
 				19A176174862D0F0139B3987 /* SchemaDefinitionsTests.swift */,
 				19A17FDB0B0CFB8987906FD0 /* SchemaChangerTests.swift */,
-				19A17CA1DF7D0F7C9A94C51C /* ConnectionSchemaTests.swift */,
+				19A17CA1DF7D0F7C9A94C51C /* Connection+SchemaTests.swift */,
+				19A171A7714C6524093255C5 /* SchemaTests.swift */,
 			);
 			path = Schema;
 			sourceTree = "<group>";
 		};
+		19A17E470E4492D287C0D12F /* Extensions */ = {
+			isa = PBXGroup;
+			children = (
+				19A17B96EBD42C878E609CDC /* FTS5Tests.swift */,
+				19A17BE1CC4AD4036BAB8EE0 /* FTSIntegrationTests.swift */,
+				19A1715904F7B6851FCB5EF6 /* FTS4Tests.swift */,
+				19A1787E16C8562C09C076F5 /* CipherTests.swift */,
+				19A17162C9861E5C4900455D /* RTreeTests.swift */,
+			);
+			path = Extensions;
+			sourceTree = "<group>";
+		};
 		3D67B3E41DB2469200A4F4C6 /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
@@ -489,34 +543,14 @@
 			isa = PBXGroup;
 			children = (
 				3DF7B79528846FCC005DD8CA /* Resources */,
-				EE247B1A1C3F137700AE3E12 /* AggregateFunctionsTests.swift */,
-				EE247B1B1C3F137700AE3E12 /* BlobTests.swift */,
-				EE247B1D1C3F137700AE3E12 /* ConnectionTests.swift */,
-				EE247B1E1C3F137700AE3E12 /* CoreFunctionsTests.swift */,
-				EE247B1F1C3F137700AE3E12 /* CustomFunctionsTests.swift */,
-				3717F907221F5D7C00B9BD3D /* CustomAggregationTests.swift */,
-				EE247B201C3F137700AE3E12 /* ExpressionTests.swift */,
-				EE247B211C3F137700AE3E12 /* FTS4Tests.swift */,
-				EE247B2A1C3F141E00AE3E12 /* OperatorsTests.swift */,
-				EE247B2B1C3F141E00AE3E12 /* QueryTests.swift */,
-				EE247B2C1C3F141E00AE3E12 /* RTreeTests.swift */,
-				EE247B2D1C3F141E00AE3E12 /* SchemaTests.swift */,
-				EE247B181C3F134A00AE3E12 /* SetterTests.swift */,
-				EE247B321C3F142E00AE3E12 /* StatementTests.swift */,
-				EE247B331C3F142E00AE3E12 /* ValueTests.swift */,
 				EE247B161C3F127200AE3E12 /* TestHelpers.swift */,
 				EE247AE41C3F04ED00AE3E12 /* Info.plist */,
-				19A1721B8984686B9963B45D /* FTS5Tests.swift */,
 				19A1794CC4D7827E997E32A7 /* FoundationTests.swift */,
-				19A17399EA9E61235D5D77BF /* CipherTests.swift */,
 				19A17B93B48B5560E6E51791 /* Fixtures.swift */,
-				19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */,
-				19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */,
-				D4DB368A20C09C9B00D5A58E /* SelectTests.swift */,
-				19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */,
-				19A171FDE4D67879B14ACBDF /* FTSIntegrationTests.swift */,
-				3DF7B78C28842C23005DD8CA /* ResultTests.swift */,
 				19A17B56FBA20E7245BC8AC0 /* Schema */,
+				19A17E470E4492D287C0D12F /* Extensions */,
+				19A1798E3459573BEE50FA34 /* Core */,
+				19A17AECBF878B1DAE0AE3DD /* Typed */,
 			);
 			name = SQLiteTests;
 			path = Tests/SQLiteTests;
@@ -934,35 +968,37 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				3DF7B78F28842C23005DD8CA /* ResultTests.swift in Sources */,
-				03A65E881C6BB3030062603F /* BlobTests.swift in Sources */,
-				03A65E901C6BB3030062603F /* RTreeTests.swift in Sources */,
-				03A65E941C6BB3030062603F /* ValueTests.swift in Sources */,
-				03A65E8F1C6BB3030062603F /* QueryTests.swift in Sources */,
-				03A65E8B1C6BB3030062603F /* CustomFunctionsTests.swift in Sources */,
-				03A65E871C6BB3030062603F /* AggregateFunctionsTests.swift in Sources */,
-				03A65E921C6BB3030062603F /* SetterTests.swift in Sources */,
-				03A65E891C6BB3030062603F /* ConnectionTests.swift in Sources */,
-				03A65E8A1C6BB3030062603F /* CoreFunctionsTests.swift in Sources */,
-				3717F90A221F5D8900B9BD3D /* CustomAggregationTests.swift in Sources */,
-				03A65E931C6BB3030062603F /* StatementTests.swift in Sources */,
-				03A65E911C6BB3030062603F /* SchemaTests.swift in Sources */,
-				03A65E8D1C6BB3030062603F /* FTS4Tests.swift in Sources */,
-				03A65E8C1C6BB3030062603F /* ExpressionTests.swift in Sources */,
-				03A65E8E1C6BB3030062603F /* OperatorsTests.swift in Sources */,
 				03A65E951C6BB3030062603F /* TestHelpers.swift in Sources */,
-				19A17254FBA7894891F7297B /* FTS5Tests.swift in Sources */,
 				19A17E04C4C0956715C5676A /* FoundationTests.swift in Sources */,
-				19A179A0C45377CB09BB358C /* CipherTests.swift in Sources */,
 				19A17F60B685636D1F83C2DD /* Fixtures.swift in Sources */,
-				19A1785195182AF8731A8BDA /* RowTests.swift in Sources */,
-				19A1769C1F3A7542BECF50FF /* DateAndTimeFunctionTests.swift in Sources */,
-				D4DB368E20C09CFD00D5A58E /* SelectTests.swift in Sources */,
-				19A17CB808ACF606726E77A8 /* QueryIntegrationTests.swift in Sources */,
-				19A17C9407AC0EE104E5CC85 /* FTSIntegrationTests.swift in Sources */,
 				19A17B62A4125AF4F6014CF5 /* SchemaDefinitionsTests.swift in Sources */,
 				19A17FC04708C6ED637DDFD4 /* SchemaChangerTests.swift in Sources */,
-				19A17188B4D96636F9C0C209 /* ConnectionSchemaTests.swift in Sources */,
+				19A17188B4D96636F9C0C209 /* Connection+SchemaTests.swift in Sources */,
+				19A17FACE8E4D54A50BA934E /* FTS5Tests.swift in Sources */,
+				19A177909023B7B940C5805E /* FTSIntegrationTests.swift in Sources */,
+				19A17E1DD976D5CE80018749 /* FTS4Tests.swift in Sources */,
+				19A17411403D60640467209E /* ExpressionTests.swift in Sources */,
+				19A17CA4D7B63D845428A9C5 /* StatementTests.swift in Sources */,
+				19A17885B646CB0201BE4BD5 /* QueryTests.swift in Sources */,
+				19A1708D3D58D7BC1168E55F /* CipherTests.swift in Sources */,
+				19A178C041DDCF80B533AD13 /* BlobTests.swift in Sources */,
+				19A17021286A4D8D6C2EF12D /* ConnectionTests.swift in Sources */,
+				19A17DE34C477232592A8F6B /* CoreFunctionsTests.swift in Sources */,
+				19A1799AF6643CF5081BFA15 /* DateAndTimeFunctionTests.swift in Sources */,
+				19A17457B0461F484AF6BE40 /* CustomFunctionsTests.swift in Sources */,
+				19A17900387FDCF578B31E3E /* OperatorsTests.swift in Sources */,
+				19A17C74233AFC2EDAFA23DC /* ResultTests.swift in Sources */,
+				19A17A9520802ACF45907970 /* RTreeTests.swift in Sources */,
+				19A17A391BF056E3D729E70A /* SchemaTests.swift in Sources */,
+				19A17746150A815944A6820B /* SelectTests.swift in Sources */,
+				19A1766135CE9786B1878603 /* ValueTests.swift in Sources */,
+				19A177D5C6542E2D572162E5 /* QueryIntegrationTests.swift in Sources */,
+				19A178DF5A96CFEFF1E271F6 /* AggregateFunctionsTests.swift in Sources */,
+				19A17437659BD7FD787D94A6 /* CustomAggregationTests.swift in Sources */,
+				19A17F907258E524B3CA2FAE /* SetterTests.swift in Sources */,
+				19A17ABCF0EB4808BDC5B5FF /* RowTests.swift in Sources */,
+				19A17BACF4C032513DE1F879 /* Connection+PragmaTests.swift in Sources */,
+				19A173F25449876761347072 /* Connection+AttachTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1047,35 +1083,37 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				3DF7B78D28842C23005DD8CA /* ResultTests.swift in Sources */,
-				EE247B261C3F137700AE3E12 /* CoreFunctionsTests.swift in Sources */,
-				EE247B291C3F137700AE3E12 /* FTS4Tests.swift in Sources */,
-				EE247B191C3F134A00AE3E12 /* SetterTests.swift in Sources */,
-				EE247B311C3F141E00AE3E12 /* SchemaTests.swift in Sources */,
 				EE247B171C3F127200AE3E12 /* TestHelpers.swift in Sources */,
-				EE247B281C3F137700AE3E12 /* ExpressionTests.swift in Sources */,
-				EE247B271C3F137700AE3E12 /* CustomFunctionsTests.swift in Sources */,
-				EE247B341C3F142E00AE3E12 /* StatementTests.swift in Sources */,
-				EE247B301C3F141E00AE3E12 /* RTreeTests.swift in Sources */,
-				3717F908221F5D8800B9BD3D /* CustomAggregationTests.swift in Sources */,
-				EE247B231C3F137700AE3E12 /* BlobTests.swift in Sources */,
-				EE247B351C3F142E00AE3E12 /* ValueTests.swift in Sources */,
-				EE247B2F1C3F141E00AE3E12 /* QueryTests.swift in Sources */,
-				EE247B221C3F137700AE3E12 /* AggregateFunctionsTests.swift in Sources */,
-				EE247B2E1C3F141E00AE3E12 /* OperatorsTests.swift in Sources */,
-				EE247B251C3F137700AE3E12 /* ConnectionTests.swift in Sources */,
-				19A171E6FA242F72A308C594 /* FTS5Tests.swift in Sources */,
 				19A17FB80B94E882050AA908 /* FoundationTests.swift in Sources */,
-				19A177CC33F2E6A24AF90B02 /* CipherTests.swift in Sources */,
 				19A17408007B182F884E3A53 /* Fixtures.swift in Sources */,
-				19A1720B67ED13E6150C6A3D /* RowTests.swift in Sources */,
-				19A17C80076860CF7751A056 /* DateAndTimeFunctionTests.swift in Sources */,
-				D4DB368C20C09CFB00D5A58E /* SelectTests.swift in Sources */,
-				19A172A9B536D02D4A98AAAD /* QueryIntegrationTests.swift in Sources */,
-				19A17C013B00682B70D53DB8 /* FTSIntegrationTests.swift in Sources */,
 				19A17FE78A39E86F330420EC /* SchemaDefinitionsTests.swift in Sources */,
 				19A177C25834473FAB32CF3B /* SchemaChangerTests.swift in Sources */,
-				19A1725658E480B9B378F28B /* ConnectionSchemaTests.swift in Sources */,
+				19A1725658E480B9B378F28B /* Connection+SchemaTests.swift in Sources */,
+				19A178DA2BB5970778CCAF13 /* FTS5Tests.swift in Sources */,
+				19A1755C49154C87304C9146 /* FTSIntegrationTests.swift in Sources */,
+				19A17444861E1443143DEB44 /* FTS4Tests.swift in Sources */,
+				19A17DD33C2E43DD6EE05A60 /* ExpressionTests.swift in Sources */,
+				19A17D6EC40BC35A5DC81BA8 /* StatementTests.swift in Sources */,
+				19A17E3F47DA087E2B76D087 /* QueryTests.swift in Sources */,
+				19A17A7B3E3B7E76364A2AEE /* CipherTests.swift in Sources */,
+				19A1782444437C7FC6B75CBC /* BlobTests.swift in Sources */,
+				19A17CF65C0196E03BC64519 /* ConnectionTests.swift in Sources */,
+				19A179BB9A6665B2B99DA546 /* CoreFunctionsTests.swift in Sources */,
+				19A174118D11B93DA5DAAF79 /* DateAndTimeFunctionTests.swift in Sources */,
+				19A17A7DF99B0379FD3396B1 /* CustomFunctionsTests.swift in Sources */,
+				19A171F243A589C5EBC47937 /* OperatorsTests.swift in Sources */,
+				19A173F429D7E46289EB2167 /* ResultTests.swift in Sources */,
+				19A17B1D9B5CEBE9CE09280C /* RTreeTests.swift in Sources */,
+				19A172F71EFD65342072D8D2 /* SchemaTests.swift in Sources */,
+				19A17F7977364EC8CD33C3C3 /* SelectTests.swift in Sources */,
+				19A17FD22EF43DF428DD93BA /* ValueTests.swift in Sources */,
+				19A177AA5922527BBDC77CF9 /* QueryIntegrationTests.swift in Sources */,
+				19A179786A6826D58A70F8BC /* AggregateFunctionsTests.swift in Sources */,
+				19A1793972BDDDB027C113BB /* CustomAggregationTests.swift in Sources */,
+				19A1773155AC2BF2CA86A473 /* SetterTests.swift in Sources */,
+				19A176B3316281F004F92276 /* RowTests.swift in Sources */,
+				19A17FBAA26953EB854E790D /* Connection+PragmaTests.swift in Sources */,
+				19A17026DCDCDA405B09A229 /* Connection+AttachTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1122,35 +1160,37 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				3DF7B78E28842C23005DD8CA /* ResultTests.swift in Sources */,
-				EE247B561C3F3FC700AE3E12 /* CoreFunctionsTests.swift in Sources */,
-				EE247B5A1C3F3FC700AE3E12 /* OperatorsTests.swift in Sources */,
-				EE247B541C3F3FC700AE3E12 /* BlobTests.swift in Sources */,
-				EE247B5D1C3F3FC700AE3E12 /* SchemaTests.swift in Sources */,
-				EE247B591C3F3FC700AE3E12 /* FTS4Tests.swift in Sources */,
-				EE247B531C3F3FC700AE3E12 /* AggregateFunctionsTests.swift in Sources */,
-				EE247B5F1C3F3FC700AE3E12 /* StatementTests.swift in Sources */,
-				EE247B5C1C3F3FC700AE3E12 /* RTreeTests.swift in Sources */,
-				EE247B571C3F3FC700AE3E12 /* CustomFunctionsTests.swift in Sources */,
-				3717F909221F5D8900B9BD3D /* CustomAggregationTests.swift in Sources */,
-				EE247B601C3F3FC700AE3E12 /* ValueTests.swift in Sources */,
-				EE247B551C3F3FC700AE3E12 /* ConnectionTests.swift in Sources */,
 				EE247B611C3F3FC700AE3E12 /* TestHelpers.swift in Sources */,
-				EE247B581C3F3FC700AE3E12 /* ExpressionTests.swift in Sources */,
-				EE247B5E1C3F3FC700AE3E12 /* SetterTests.swift in Sources */,
-				EE247B5B1C3F3FC700AE3E12 /* QueryTests.swift in Sources */,
-				19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */,
 				19A178072B371489E6A1E839 /* FoundationTests.swift in Sources */,
-				19A17C4B951CB054EE48AB1C /* CipherTests.swift in Sources */,
 				19A1709C3E7A406E62293B2A /* Fixtures.swift in Sources */,
-				19A171967CC511C4F6F773C9 /* RowTests.swift in Sources */,
-				19A172EB202970561E5C4245 /* DateAndTimeFunctionTests.swift in Sources */,
-				D4DB368D20C09CFC00D5A58E /* SelectTests.swift in Sources */,
-				19A176406BDE9D9C80CC9FA3 /* QueryIntegrationTests.swift in Sources */,
-				19A171BE056457F13BFBC4C3 /* FTSIntegrationTests.swift in Sources */,
 				19A17E80F736EEE8EE2AA4CE /* SchemaDefinitionsTests.swift in Sources */,
 				19A1766AC10D13C4EFF349AD /* SchemaChangerTests.swift in Sources */,
-				19A17B36ABC6006AB80F693C /* ConnectionSchemaTests.swift in Sources */,
+				19A17B36ABC6006AB80F693C /* Connection+SchemaTests.swift in Sources */,
+				19A1776BD5127DFDF847FF1F /* FTS5Tests.swift in Sources */,
+				19A173088B85A7E18E8582A7 /* FTSIntegrationTests.swift in Sources */,
+				19A178767223229E61C5066F /* FTS4Tests.swift in Sources */,
+				19A1781CBA8968ABD3E00877 /* ExpressionTests.swift in Sources */,
+				19A17923494236793893BF72 /* StatementTests.swift in Sources */,
+				19A17A52BF29D27C9AA229E7 /* QueryTests.swift in Sources */,
+				19A17CA6ADB78A2E545BF836 /* CipherTests.swift in Sources */,
+				19A1714F7CF964D568AB14E0 /* BlobTests.swift in Sources */,
+				19A173465F23C64DF3DF469B /* ConnectionTests.swift in Sources */,
+				19A17D993398B8215B73E1EA /* CoreFunctionsTests.swift in Sources */,
+				19A170AEBAA56DC3355A73B3 /* DateAndTimeFunctionTests.swift in Sources */,
+				19A1716BF8E15F91A6B5CB7A /* CustomFunctionsTests.swift in Sources */,
+				19A17482E6FC5E563F3E6A47 /* OperatorsTests.swift in Sources */,
+				19A17912DB9D3AC8FECF948B /* ResultTests.swift in Sources */,
+				19A17DAD5975D9367EAA46E2 /* RTreeTests.swift in Sources */,
+				19A17F2096E83A3181E03317 /* SchemaTests.swift in Sources */,
+				19A17DE1FCDB5695702AD24D /* SelectTests.swift in Sources */,
+				19A1726002D24C14F876C8FE /* ValueTests.swift in Sources */,
+				19A173389E53CB24DFA8CEDD /* QueryIntegrationTests.swift in Sources */,
+				19A170C56745F9D722A73D77 /* AggregateFunctionsTests.swift in Sources */,
+				19A1772EBE65173EDFB1AFCA /* CustomAggregationTests.swift in Sources */,
+				19A17E0ABA6C415F014CD51C /* SetterTests.swift in Sources */,
+				19A170D938343E30119EDFB3 /* RowTests.swift in Sources */,
+				19A178F9008614B8A8425635 /* Connection+PragmaTests.swift in Sources */,
+				19A179BCD483DEA21661FD37 /* Connection+AttachTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/Sources/SQLite/Schema/Connection+Schema.swift b/Sources/SQLite/Schema/Connection+Schema.swift
index 8bd219ed..c3b24f38 100644
--- a/Sources/SQLite/Schema/Connection+Schema.swift
+++ b/Sources/SQLite/Schema/Connection+Schema.swift
@@ -63,16 +63,6 @@ extension Connection {
         }
     }
 
-    func tableInfo() throws -> [String] {
-        try run("SELECT tbl_name FROM sqlite_master WHERE type = 'table'").compactMap { row in
-            if let name = row[0] as? String, !name.starts(with: "sqlite_") {
-                return name
-            } else {
-                return nil
-            }
-        }
-    }
-
     func foreignKeyInfo(table: String) throws -> [ColumnDefinition.ForeignKey] {
         try run("PRAGMA foreign_key_list(\(table.quote()))").compactMap { row in
             if let table = row[2] as? String,      // table
diff --git a/Tests/SQLiteTests/BlobTests.swift b/Tests/SQLiteTests/Core/BlobTests.swift
similarity index 100%
rename from Tests/SQLiteTests/BlobTests.swift
rename to Tests/SQLiteTests/Core/BlobTests.swift
diff --git a/Tests/SQLiteTests/Core/Connection+AttachTests.swift b/Tests/SQLiteTests/Core/Connection+AttachTests.swift
new file mode 100644
index 00000000..940a30ca
--- /dev/null
+++ b/Tests/SQLiteTests/Core/Connection+AttachTests.swift
@@ -0,0 +1,62 @@
+import XCTest
+import Foundation
+@testable import SQLite
+
+#if SQLITE_SWIFT_STANDALONE
+import sqlite3
+#elseif SQLITE_SWIFT_SQLCIPHER
+import SQLCipher
+#elseif os(Linux)
+import CSQLite
+#else
+import SQLite3
+#endif
+
+class ConnectionAttachTests: SQLiteTestCase {
+    func test_attach_detach_memory_database() throws {
+        let schemaName = "test"
+
+        try db.attach(.inMemory, as: schemaName)
+
+        let table = Table("attached_users", database: schemaName)
+        let name = Expression<String>("string")
+
+        // create a table, insert some data
+        try db.run(table.create { builder in
+            builder.column(name)
+        })
+        _ = try db.run(table.insert(name <- "test"))
+
+        // query data
+        let rows = try db.prepare(table.select(name)).map { $0[name] }
+        XCTAssertEqual(["test"], rows)
+
+        try db.detach(schemaName)
+    }
+
+    func test_attach_detach_file_database() throws {
+        let schemaName = "test"
+        let testDb = fixture("test", withExtension: "sqlite")
+
+        try db.attach(.uri(testDb, parameters: [.mode(.readOnly)]), as: schemaName)
+
+        let table = Table("tests", database: schemaName)
+        let email = Expression<String>("email")
+
+        let rows = try db.prepare(table.select(email)).map { $0[email] }
+        XCTAssertEqual(["foo@bar.com"], rows)
+
+        try db.detach(schemaName)
+    }
+
+    func test_detach_invalid_schema_name_errors_with_no_such_database() throws {
+        XCTAssertThrowsError(try db.detach("no-exist")) { error in
+            if case let Result.error(message, code, _) = error {
+                XCTAssertEqual(code, SQLITE_ERROR)
+                XCTAssertEqual("no such database: no-exist", message)
+            } else {
+                XCTFail("unexpected error: \(error)")
+            }
+        }
+    }
+}
diff --git a/Tests/SQLiteTests/Core/Connection+PragmaTests.swift b/Tests/SQLiteTests/Core/Connection+PragmaTests.swift
new file mode 100644
index 00000000..2d0742c9
--- /dev/null
+++ b/Tests/SQLiteTests/Core/Connection+PragmaTests.swift
@@ -0,0 +1,42 @@
+import XCTest
+import Foundation
+@testable import SQLite
+
+#if SQLITE_SWIFT_STANDALONE
+import sqlite3
+#elseif SQLITE_SWIFT_SQLCIPHER
+import SQLCipher
+#elseif os(Linux)
+import CSQLite
+#else
+import SQLite3
+#endif
+
+class ConnectionPragmaTests: SQLiteTestCase {
+    func test_userVersion() {
+        db.userVersion = 2
+        XCTAssertEqual(2, db.userVersion!)
+    }
+
+    func test_sqlite_version() {
+        XCTAssertTrue(db.sqliteVersion >= (3, 0, 0))
+    }
+
+    func test_foreignKeys_defaults_to_false() {
+        XCTAssertFalse(db.foreignKeys)
+    }
+
+    func test_foreignKeys_sets_value() {
+        db.foreignKeys = true
+        XCTAssertTrue(db.foreignKeys)
+    }
+
+    func test_defer_foreignKeys_defaults_to_false() {
+        XCTAssertFalse(db.deferForeignKeys)
+    }
+
+    func test_defer_foreignKeys_sets_value() {
+        db.deferForeignKeys = true
+        XCTAssertTrue(db.deferForeignKeys)
+    }
+}
diff --git a/Tests/SQLiteTests/ConnectionTests.swift b/Tests/SQLiteTests/Core/ConnectionTests.swift
similarity index 90%
rename from Tests/SQLiteTests/ConnectionTests.swift
rename to Tests/SQLiteTests/Core/ConnectionTests.swift
index 347516f5..e9ceff08 100644
--- a/Tests/SQLiteTests/ConnectionTests.swift
+++ b/Tests/SQLiteTests/Core/ConnectionTests.swift
@@ -111,11 +111,6 @@ class ConnectionTests: SQLiteTestCase {
         XCTAssertEqual(2, db.totalChanges)
     }
 
-    func test_userVersion() {
-        db.userVersion = 2
-        XCTAssertEqual(2, db.userVersion!)
-    }
-
     func test_prepare_preparesAndReturnsStatements() throws {
         _ = try db.prepare("SELECT * FROM users WHERE admin = 0")
         _ = try db.prepare("SELECT * FROM users WHERE admin = ?", 0)
@@ -445,51 +440,4 @@ class ConnectionTests: SQLiteTestCase {
         }
         semaphores.forEach { $0.wait() }
     }
-
-    func test_attach_detach_memory_database() throws {
-        let schemaName = "test"
-
-        try db.attach(.inMemory, as: schemaName)
-
-        let table = Table("attached_users", database: schemaName)
-        let name = Expression<String>("string")
-
-        // create a table, insert some data
-        try db.run(table.create { builder in
-            builder.column(name)
-        })
-        _ = try db.run(table.insert(name <- "test"))
-
-        // query data
-        let rows = try db.prepare(table.select(name)).map { $0[name] }
-        XCTAssertEqual(["test"], rows)
-
-        try db.detach(schemaName)
-    }
-
-    func test_attach_detach_file_database() throws {
-        let schemaName = "test"
-        let testDb = fixture("test", withExtension: "sqlite")
-
-        try db.attach(.uri(testDb, parameters: [.mode(.readOnly)]), as: schemaName)
-
-        let table = Table("tests", database: schemaName)
-        let email = Expression<String>("email")
-
-        let rows = try db.prepare(table.select(email)).map { $0[email] }
-        XCTAssertEqual(["foo@bar.com"], rows)
-
-        try db.detach(schemaName)
-    }
-
-    func test_detach_invalid_schema_name_errors_with_no_such_database() throws {
-        XCTAssertThrowsError(try db.detach("no-exist")) { error in
-            if case let Result.error(message, code, _) = error {
-                XCTAssertEqual(code, SQLITE_ERROR)
-                XCTAssertEqual("no such database: no-exist", message)
-            } else {
-                XCTFail("unexpected error: \(error)")
-            }
-        }
-    }
 }
diff --git a/Tests/SQLiteTests/CoreFunctionsTests.swift b/Tests/SQLiteTests/Core/CoreFunctionsTests.swift
similarity index 100%
rename from Tests/SQLiteTests/CoreFunctionsTests.swift
rename to Tests/SQLiteTests/Core/CoreFunctionsTests.swift
diff --git a/Tests/SQLiteTests/ResultTests.swift b/Tests/SQLiteTests/Core/ResultTests.swift
similarity index 100%
rename from Tests/SQLiteTests/ResultTests.swift
rename to Tests/SQLiteTests/Core/ResultTests.swift
diff --git a/Tests/SQLiteTests/StatementTests.swift b/Tests/SQLiteTests/Core/StatementTests.swift
similarity index 100%
rename from Tests/SQLiteTests/StatementTests.swift
rename to Tests/SQLiteTests/Core/StatementTests.swift
diff --git a/Tests/SQLiteTests/ValueTests.swift b/Tests/SQLiteTests/Core/ValueTests.swift
similarity index 100%
rename from Tests/SQLiteTests/ValueTests.swift
rename to Tests/SQLiteTests/Core/ValueTests.swift
diff --git a/Tests/SQLiteTests/CipherTests.swift b/Tests/SQLiteTests/Extensions/CipherTests.swift
similarity index 100%
rename from Tests/SQLiteTests/CipherTests.swift
rename to Tests/SQLiteTests/Extensions/CipherTests.swift
diff --git a/Tests/SQLiteTests/FTS4Tests.swift b/Tests/SQLiteTests/Extensions/FTS4Tests.swift
similarity index 100%
rename from Tests/SQLiteTests/FTS4Tests.swift
rename to Tests/SQLiteTests/Extensions/FTS4Tests.swift
diff --git a/Tests/SQLiteTests/FTS5Tests.swift b/Tests/SQLiteTests/Extensions/FTS5Tests.swift
similarity index 100%
rename from Tests/SQLiteTests/FTS5Tests.swift
rename to Tests/SQLiteTests/Extensions/FTS5Tests.swift
diff --git a/Tests/SQLiteTests/FTSIntegrationTests.swift b/Tests/SQLiteTests/Extensions/FTSIntegrationTests.swift
similarity index 100%
rename from Tests/SQLiteTests/FTSIntegrationTests.swift
rename to Tests/SQLiteTests/Extensions/FTSIntegrationTests.swift
diff --git a/Tests/SQLiteTests/RTreeTests.swift b/Tests/SQLiteTests/Extensions/RTreeTests.swift
similarity index 100%
rename from Tests/SQLiteTests/RTreeTests.swift
rename to Tests/SQLiteTests/Extensions/RTreeTests.swift
diff --git a/Tests/SQLiteTests/Schema/ConnectionSchemaTests.swift b/Tests/SQLiteTests/Schema/Connection+SchemaTests.swift
similarity index 95%
rename from Tests/SQLiteTests/Schema/ConnectionSchemaTests.swift
rename to Tests/SQLiteTests/Schema/Connection+SchemaTests.swift
index 1c66b761..56e79734 100644
--- a/Tests/SQLiteTests/Schema/ConnectionSchemaTests.swift
+++ b/Tests/SQLiteTests/Schema/Connection+SchemaTests.swift
@@ -108,11 +108,6 @@ class ConnectionSchemaTests: SQLiteTestCase {
         ])
     }
 
-    func test_table_info_returns_list_of_tables() throws {
-        let tables = try db.tableInfo()
-        XCTAssertEqual(tables, ["users"])
-    }
-
     func test_foreign_key_info_empty() throws {
         try db.run("CREATE TABLE t (\"id\" INTEGER PRIMARY KEY)")
 
@@ -136,8 +131,4 @@ class ConnectionSchemaTests: SQLiteTestCase {
             .init(table: "users", column: "test_id", primaryKey: "id", onUpdate: nil, onDelete: nil)
         ])
     }
-
-    func test_sqlite_version() {
-        XCTAssertTrue(db.sqliteVersion >= (3, 0, 0))
-    }
 }
diff --git a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
index 165de4a8..4d4f8d50 100644
--- a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
@@ -102,8 +102,12 @@ class SchemaChangerTests: SQLiteTestCase {
 
     func test_drop_table() throws {
         try schemaChanger.drop(table: "users")
-
-        let tables = try db.tableInfo()
-        XCTAssertFalse(tables.contains("users"))
+        XCTAssertThrowsError(try db.scalar(users.count)) { error in
+            if case Result.error(let message, _, _) =  error {
+                XCTAssertEqual(message, "no such table: users")
+            } else {
+                XCTFail("unexpected error \(error)")
+            }
+        }
     }
 }
diff --git a/Tests/SQLiteTests/SchemaTests.swift b/Tests/SQLiteTests/Schema/SchemaTests.swift
similarity index 100%
rename from Tests/SQLiteTests/SchemaTests.swift
rename to Tests/SQLiteTests/Schema/SchemaTests.swift
diff --git a/Tests/SQLiteTests/AggregateFunctionsTests.swift b/Tests/SQLiteTests/Typed/AggregateFunctionsTests.swift
similarity index 100%
rename from Tests/SQLiteTests/AggregateFunctionsTests.swift
rename to Tests/SQLiteTests/Typed/AggregateFunctionsTests.swift
diff --git a/Tests/SQLiteTests/CustomAggregationTests.swift b/Tests/SQLiteTests/Typed/CustomAggregationTests.swift
similarity index 100%
rename from Tests/SQLiteTests/CustomAggregationTests.swift
rename to Tests/SQLiteTests/Typed/CustomAggregationTests.swift
diff --git a/Tests/SQLiteTests/CustomFunctionsTests.swift b/Tests/SQLiteTests/Typed/CustomFunctionsTests.swift
similarity index 100%
rename from Tests/SQLiteTests/CustomFunctionsTests.swift
rename to Tests/SQLiteTests/Typed/CustomFunctionsTests.swift
diff --git a/Tests/SQLiteTests/DateAndTimeFunctionTests.swift b/Tests/SQLiteTests/Typed/DateAndTimeFunctionTests.swift
similarity index 100%
rename from Tests/SQLiteTests/DateAndTimeFunctionTests.swift
rename to Tests/SQLiteTests/Typed/DateAndTimeFunctionTests.swift
diff --git a/Tests/SQLiteTests/ExpressionTests.swift b/Tests/SQLiteTests/Typed/ExpressionTests.swift
similarity index 100%
rename from Tests/SQLiteTests/ExpressionTests.swift
rename to Tests/SQLiteTests/Typed/ExpressionTests.swift
diff --git a/Tests/SQLiteTests/OperatorsTests.swift b/Tests/SQLiteTests/Typed/OperatorsTests.swift
similarity index 100%
rename from Tests/SQLiteTests/OperatorsTests.swift
rename to Tests/SQLiteTests/Typed/OperatorsTests.swift
diff --git a/Tests/SQLiteTests/QueryIntegrationTests.swift b/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
similarity index 100%
rename from Tests/SQLiteTests/QueryIntegrationTests.swift
rename to Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
diff --git a/Tests/SQLiteTests/QueryTests.swift b/Tests/SQLiteTests/Typed/QueryTests.swift
similarity index 100%
rename from Tests/SQLiteTests/QueryTests.swift
rename to Tests/SQLiteTests/Typed/QueryTests.swift
diff --git a/Tests/SQLiteTests/RowTests.swift b/Tests/SQLiteTests/Typed/RowTests.swift
similarity index 100%
rename from Tests/SQLiteTests/RowTests.swift
rename to Tests/SQLiteTests/Typed/RowTests.swift
diff --git a/Tests/SQLiteTests/SelectTests.swift b/Tests/SQLiteTests/Typed/SelectTests.swift
similarity index 100%
rename from Tests/SQLiteTests/SelectTests.swift
rename to Tests/SQLiteTests/Typed/SelectTests.swift
diff --git a/Tests/SQLiteTests/SetterTests.swift b/Tests/SQLiteTests/Typed/SetterTests.swift
similarity index 100%
rename from Tests/SQLiteTests/SetterTests.swift
rename to Tests/SQLiteTests/Typed/SetterTests.swift

From a6e6e687b47944b4c338e23bb054fd925998222e Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 26 Jul 2022 00:44:55 +0200
Subject: [PATCH 546/685] WIP

---
 Sources/SQLite/Schema/Connection+Schema.swift |  2 +-
 Sources/SQLite/Schema/SchemaChanger.swift     | 73 ++++++++++++++-----
 Sources/SQLite/Schema/SchemaDefinitions.swift | 20 +++--
 .../Schema/Connection+SchemaTests.swift       | 18 ++---
 .../Schema/SchemaChangerTests.swift           | 30 +++++++-
 .../Schema/SchemaDefinitionsTests.swift       | 26 +++----
 6 files changed, 119 insertions(+), 50 deletions(-)

diff --git a/Sources/SQLite/Schema/Connection+Schema.swift b/Sources/SQLite/Schema/Connection+Schema.swift
index c3b24f38..378fad68 100644
--- a/Sources/SQLite/Schema/Connection+Schema.swift
+++ b/Sources/SQLite/Schema/Connection+Schema.swift
@@ -24,7 +24,7 @@ extension Connection {
             return ColumnDefinition(name: name,
                                     primaryKey: primaryKey == 1 ? try parsePrimaryKey(column: name) : nil,
                                     type: ColumnDefinition.Affinity.from(type),
-                                    null: notNull == 0,
+                                    nullable: notNull == 0,
                                     defaultValue: .from(defaultValue),
                                     references: foreignKeys[name]?.first)
         }
diff --git a/Sources/SQLite/Schema/SchemaChanger.swift b/Sources/SQLite/Schema/SchemaChanger.swift
index c6529fbe..daba2f60 100644
--- a/Sources/SQLite/Schema/SchemaChanger.swift
+++ b/Sources/SQLite/Schema/SchemaChanger.swift
@@ -27,36 +27,63 @@ import Foundation
        12. If foreign keys constraints were originally enabled, reenable them now.
 */
 public class SchemaChanger: CustomStringConvertible {
-    enum SchemaChangeError: LocalizedError {
+    public enum Error: LocalizedError {
+        case invalidColumnDefinition(String)
         case foreignKeyError([ForeignKeyError])
 
-        var errorDescription: String? {
+        public var errorDescription: String? {
             switch self {
             case .foreignKeyError(let errors):
                 return "Foreign key errors: \(errors)"
+            case .invalidColumnDefinition(let message):
+                return "Invalid column definition: \(message)"
             }
         }
     }
 
     public enum Operation {
-        case none
-        case add(ColumnDefinition)
-        case remove(String)
+        case addColumn(ColumnDefinition)
+        case dropColumn(String)
         case renameColumn(String, String)
         case renameTable(String)
 
         /// Returns non-nil if the operation can be executed with a simple SQL statement
         func toSQL(_ table: String, version: SQLiteVersion) -> String? {
             switch self {
-            case .add(let definition):
+            case .addColumn(let definition):
                 return "ALTER TABLE \(table.quote()) ADD COLUMN \(definition.toSQL())"
             case .renameColumn(let from, let to) where version >= (3, 25, 0):
                 return "ALTER TABLE \(table.quote()) RENAME COLUMN \(from.quote()) TO \(to.quote())"
-            case .remove(let column) where version >= (3, 35, 0):
+            case .dropColumn(let column) where version >= (3, 35, 0):
                 return "ALTER TABLE \(table.quote()) DROP COLUMN \(column.quote())"
             default: return nil
             }
         }
+
+        func validate() throws {
+            switch self {
+            case .addColumn(let definition):
+                // The new column may take any of the forms permissible in a CREATE TABLE statement, with the following restrictions:
+                // - The column may not have a PRIMARY KEY or UNIQUE constraint.
+                // - The column may not have a default value of CURRENT_TIME, CURRENT_DATE, CURRENT_TIMESTAMP, or an expression in parentheses
+                // - If a NOT NULL constraint is specified, then the column must have a default value other than NULL.
+                guard definition.primaryKey == nil else {
+                    throw Error.invalidColumnDefinition("can not add primary key column")
+                }
+                let invalidValues: [LiteralValue] = [.CURRENT_TIME, .CURRENT_DATE, .CURRENT_TIMESTAMP]
+                if invalidValues.contains(definition.defaultValue) {
+                    throw Error.invalidColumnDefinition("Invalid default value")
+                }
+                if !definition.nullable && definition.defaultValue == .NULL {
+                    throw Error.invalidColumnDefinition("NOT NULL columns must have a default value other than NULL")
+                }
+            case .dropColumn:
+                // The DROP COLUMN command only works if the column is not referenced by any other parts of the schema
+                // and is not a PRIMARY KEY and does not have a UNIQUE constraint
+                break
+            default: break
+            }
+        }
     }
 
     public class AlterTableDefinition {
@@ -69,11 +96,11 @@ public class SchemaChanger: CustomStringConvertible {
         }
 
         public func add(_ column: ColumnDefinition) {
-            operations.append(.add(column))
+            operations.append(.addColumn(column))
         }
 
         public func remove(_ column: String) {
-            operations.append(.remove(column))
+            operations.append(.dropColumn(column))
         }
 
         public func rename(_ column: String, to: String) {
@@ -116,7 +143,15 @@ public class SchemaChanger: CustomStringConvertible {
         try dropTable(table)
     }
 
+    // Beginning with release 3.25.0 (2018-09-15), references to the table within trigger bodies and
+    // view definitions are also renamed.
+    public func rename(table: String, to: String) throws {
+        try connection.run("ALTER TABLE \(table.quote()) RENAME TO \(to.quote())")
+    }
+
     private func run(table: String, operation: Operation) throws {
+        try operation.validate()
+
         if let sql = operation.toSQL(table, version: version) {
             try connection.run(sql)
         } else {
@@ -129,10 +164,10 @@ public class SchemaChanger: CustomStringConvertible {
             try disableRefIntegrity {
                 let tempTable = "\(SchemaChanger.tempPrefix)\(table)"
                 try moveTable(from: table, to: tempTable, options: [.temp], operation: operation)
-                try moveTable(from: tempTable, to: table)
+                try rename(table: tempTable, to: table)
                 let foreignKeyErrors = try connection.foreignKeyCheck()
                 if foreignKeyErrors.count > 0 {
-                    throw SchemaChangeError.foreignKeyError(foreignKeyErrors)
+                    throw Error.foreignKeyError(foreignKeyErrors)
                 }
             }
         }
@@ -153,22 +188,24 @@ public class SchemaChanger: CustomStringConvertible {
         try block()
     }
 
-    private func moveTable(from: String, to: String, options: Options = .default, operation: Operation = .none) throws {
+    private func moveTable(from: String, to: String, options: Options = .default, operation: Operation? = nil) throws {
         try copyTable(from: from, to: to, options: options, operation: operation)
         try dropTable(from)
     }
 
-    private func copyTable(from: String, to: String, options: Options = .default, operation: Operation) throws {
+    private func copyTable(from: String, to: String, options: Options = .default, operation: Operation?) throws {
         let fromDefinition = TableDefinition(
             name: from,
             columns: try connection.columnInfo(table: from),
             indexes: try connection.indexInfo(table: from)
         )
-        let toDefinition   = fromDefinition.apply(.renameTable(to)).apply(operation)
+        let toDefinition   = fromDefinition
+                .apply(.renameTable(to))
+                .apply(operation)
 
         try createTable(definition: toDefinition, options: options)
         try createTableIndexes(definition: toDefinition)
-        if case .remove = operation {
+        if case .dropColumn = operation {
             try copyTableContents(from: fromDefinition.apply(operation), to: toDefinition)
         } else {
             try copyTableContents(from: fromDefinition, to: toDefinition)
@@ -221,11 +258,11 @@ extension IndexDefinition {
 }
 
 extension TableDefinition {
-    func apply(_ operation: SchemaChanger.Operation) -> TableDefinition {
+    func apply(_ operation: SchemaChanger.Operation?) -> TableDefinition {
         switch operation {
         case .none: return self
-        case .add: fatalError("Use 'ALTER TABLE ADD COLUMN (...)'")
-        case .remove(let column):
+        case .addColumn: fatalError("Use 'ALTER TABLE ADD COLUMN (...)'")
+        case .dropColumn(let column):
             return TableDefinition(name: name,
                 columns: columns.filter { $0.name != column },
                 indexes: indexes.filter { !$0.columns.contains(column) }
diff --git a/Sources/SQLite/Schema/SchemaDefinitions.swift b/Sources/SQLite/Schema/SchemaDefinitions.swift
index 156a06fb..a06487b2 100644
--- a/Sources/SQLite/Schema/SchemaDefinitions.swift
+++ b/Sources/SQLite/Schema/SchemaDefinitions.swift
@@ -84,23 +84,27 @@ public struct ColumnDefinition: Equatable {
     public let name: String
     public let primaryKey: PrimaryKey?
     public let type: Affinity
-    public let null: Bool
+    public let nullable: Bool
     public let defaultValue: LiteralValue
     public let references: ForeignKey?
 
-    public init(name: String, primaryKey: PrimaryKey?, type: Affinity, null: Bool, defaultValue: LiteralValue,
-                references: ForeignKey?) {
+    public init(name: String,
+                primaryKey: PrimaryKey? = nil,
+                type: Affinity,
+                nullable: Bool = false,
+                defaultValue: LiteralValue = .NULL,
+                references: ForeignKey? = nil) {
         self.name = name
         self.primaryKey = primaryKey
         self.type = type
-        self.null = null
+        self.nullable = nullable
         self.defaultValue = defaultValue
         self.references = references
     }
 
     func rename(from: String, to: String) -> ColumnDefinition {
         guard from == name else { return self }
-        return ColumnDefinition(name: to, primaryKey: primaryKey, type: type, null: null, defaultValue: defaultValue, references: references)
+        return ColumnDefinition(name: to, primaryKey: primaryKey, type: type, nullable: nullable, defaultValue: defaultValue, references: references)
     }
 }
 
@@ -254,12 +258,12 @@ public struct IndexDefinition: Equatable {
     }
 }
 
-struct ForeignKeyError: CustomStringConvertible {
+public struct ForeignKeyError: CustomStringConvertible {
     let from: String
     let rowId: Int64
     let to: String
 
-    var description: String {
+    public var description: String {
         "\(from) [\(rowId)] => \(to)"
     }
 }
@@ -294,7 +298,7 @@ extension ColumnDefinition {
             type.rawValue,
             defaultValue.map { "DEFAULT \($0)" },
             primaryKey.map { $0.toSQL() },
-            null ? nil : "NOT NULL",
+            nullable ? nil : "NOT NULL",
             references.map { $0.toSQL() }
         ].compactMap { $0 }
          .joined(separator: " ")
diff --git a/Tests/SQLiteTests/Schema/Connection+SchemaTests.swift b/Tests/SQLiteTests/Schema/Connection+SchemaTests.swift
index 56e79734..6eded6b2 100644
--- a/Tests/SQLiteTests/Schema/Connection+SchemaTests.swift
+++ b/Tests/SQLiteTests/Schema/Connection+SchemaTests.swift
@@ -14,42 +14,42 @@ class ConnectionSchemaTests: SQLiteTestCase {
             ColumnDefinition(name: "id",
                              primaryKey: .init(autoIncrement: false, onConflict: nil),
                              type: .INTEGER,
-                             null: true,
+                             nullable: true,
                              defaultValue: .NULL,
                              references: nil),
             ColumnDefinition(name: "email",
                              primaryKey: nil,
                              type: .TEXT,
-                             null: false,
+                             nullable: false,
                              defaultValue: .NULL,
                              references: nil),
             ColumnDefinition(name: "age",
                              primaryKey: nil,
                              type: .INTEGER,
-                             null: true,
+                             nullable: true,
                              defaultValue: .NULL,
                              references: nil),
             ColumnDefinition(name: "salary",
                              primaryKey: nil,
                              type: .REAL,
-                             null: true,
+                             nullable: true,
                              defaultValue: .NULL,
                              references: nil),
             ColumnDefinition(name: "admin",
                              primaryKey: nil,
                              type: .TEXT,
-                             null: false,
+                             nullable: false,
                              defaultValue: .numericLiteral("0"),
                              references: nil),
             ColumnDefinition(name: "manager_id",
                              primaryKey: nil, type: .INTEGER,
-                             null: true,
+                             nullable: true,
                              defaultValue: .NULL,
                              references: .init(table: "users", column: "manager_id", primaryKey: "id", onUpdate: nil, onDelete: nil)),
             ColumnDefinition(name: "created_at",
                              primaryKey: nil,
                              type: .TEXT,
-                             null: true,
+                             nullable: true,
                              defaultValue: .NULL,
                              references: nil)
         ])
@@ -64,7 +64,7 @@ class ConnectionSchemaTests: SQLiteTestCase {
                 name: "id",
                 primaryKey: .init(autoIncrement: true, onConflict: .IGNORE),
                 type: .INTEGER,
-                null: true,
+                nullable: true,
                 defaultValue: .NULL,
                 references: nil)
             ]
@@ -80,7 +80,7 @@ class ConnectionSchemaTests: SQLiteTestCase {
                     name: "id",
                     primaryKey: .init(autoIncrement: false),
                     type: .INTEGER,
-                    null: true,
+                    nullable: true,
                     defaultValue: .NULL,
                     references: nil)
             ]
diff --git a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
index 4d4f8d50..038a8844 100644
--- a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
@@ -90,7 +90,11 @@ class SchemaChangerTests: SQLiteTestCase {
     }
 
     func test_add_column() throws {
-        let newColumn = ColumnDefinition(name: "new_column", primaryKey: nil, type: .TEXT, null: true, defaultValue: .NULL, references: nil)
+        let column = Expression<String>("new_column")
+        let newColumn = ColumnDefinition(name: "new_column",
+                                         type: .TEXT,
+                                         nullable: true,
+                                         defaultValue: .stringLiteral("foo"))
 
         try schemaChanger.alter(table: "users") { table in
             table.add(newColumn)
@@ -98,6 +102,24 @@ class SchemaChangerTests: SQLiteTestCase {
 
         let columns = try db.columnInfo(table: "users")
         XCTAssertTrue(columns.contains(newColumn))
+
+        XCTAssertEqual(try db.pluck(users.select(column))?[column], "foo")
+    }
+
+    func test_add_column_primary_key_fails() throws {
+        let newColumn = ColumnDefinition(name: "new_column",
+                                         primaryKey: .init(autoIncrement: false, onConflict: nil),
+                                         type: .TEXT)
+
+        XCTAssertThrowsError(try schemaChanger.alter(table: "users") { table in
+            table.add(newColumn)
+        }) { error in
+            if case SchemaChanger.Error.invalidColumnDefinition(_) = error {
+                XCTAssertEqual("Invalid column definition: can not add primary key column", error.localizedDescription)
+            } else {
+                XCTFail("invalid error: \(error)")
+            }
+        }
     }
 
     func test_drop_table() throws {
@@ -110,4 +132,10 @@ class SchemaChangerTests: SQLiteTestCase {
             }
         }
     }
+
+    func test_rename_table() throws {
+        try schemaChanger.rename(table: "users", to: "users_new")
+        let users_new = Table("users_new")
+        XCTAssertEqual((try db.scalar(users_new.count)) as Int, 1)
+    }
 }
diff --git a/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift b/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
index 645bfc34..9c8c3041 100644
--- a/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
@@ -6,26 +6,26 @@ class ColumnDefinitionTests: XCTestCase {
     var expected: String!
 
     static let definitions: [(ColumnDefinition, String)] = [
-        (ColumnDefinition(name: "id", primaryKey: .init(), type: .INTEGER, null: false, defaultValue: .NULL, references: nil),
+        (ColumnDefinition(name: "id", primaryKey: .init(), type: .INTEGER, nullable: false, defaultValue: .NULL, references: nil),
         "\"id\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL"),
 
-        (ColumnDefinition(name: "other_id", primaryKey: nil, type: .INTEGER, null: false, defaultValue: .NULL,
+        (ColumnDefinition(name: "other_id", primaryKey: nil, type: .INTEGER, nullable: false, defaultValue: .NULL,
                           references: .init(table: "other_table", column: "", primaryKey: "some_id", onUpdate: nil, onDelete: nil)),
         "\"other_id\" INTEGER NOT NULL REFERENCES \"other_table\" (\"some_id\")"),
 
-        (ColumnDefinition(name: "text", primaryKey: nil, type: .TEXT, null: true, defaultValue: .NULL, references: nil),
+        (ColumnDefinition(name: "text", primaryKey: nil, type: .TEXT, nullable: true, defaultValue: .NULL, references: nil),
         "\"text\" TEXT"),
 
-        (ColumnDefinition(name: "text", primaryKey: nil, type: .TEXT, null: false, defaultValue: .NULL, references: nil),
+        (ColumnDefinition(name: "text", primaryKey: nil, type: .TEXT, nullable: false, defaultValue: .NULL, references: nil),
         "\"text\" TEXT NOT NULL"),
 
-        (ColumnDefinition(name: "text_column", primaryKey: nil, type: .TEXT, null: true, defaultValue: .stringLiteral("fo\"o"), references: nil),
+        (ColumnDefinition(name: "text_column", primaryKey: nil, type: .TEXT, nullable: true, defaultValue: .stringLiteral("fo\"o"), references: nil),
         "\"text_column\" TEXT DEFAULT 'fo\"o'"),
 
-        (ColumnDefinition(name: "integer_column", primaryKey: nil, type: .INTEGER, null: true, defaultValue: .numericLiteral("123"), references: nil),
+        (ColumnDefinition(name: "integer_column", primaryKey: nil, type: .INTEGER, nullable: true, defaultValue: .numericLiteral("123"), references: nil),
         "\"integer_column\" INTEGER DEFAULT 123"),
 
-        (ColumnDefinition(name: "real_column", primaryKey: nil, type: .REAL, null: true, defaultValue: .numericLiteral("123.123"), references: nil),
+        (ColumnDefinition(name: "real_column", primaryKey: nil, type: .REAL, nullable: true, defaultValue: .numericLiteral("123.123"), references: nil),
         "\"real_column\" REAL DEFAULT 123.123")
     ]
 
@@ -184,8 +184,8 @@ class ForeignKeyDefinitionTests: XCTestCase {
 class TableDefinitionTests: XCTestCase {
     func test_quoted_columnList() {
         let definition = TableDefinition(name: "foo", columns: [
-            ColumnDefinition(name: "id", primaryKey: .init(), type: .INTEGER, null: false, defaultValue: .NULL, references: nil),
-            ColumnDefinition(name: "baz", primaryKey: nil, type: .INTEGER, null: false, defaultValue: .NULL, references: nil)
+            ColumnDefinition(name: "id", primaryKey: .init(), type: .INTEGER, nullable: false, defaultValue: .NULL, references: nil),
+            ColumnDefinition(name: "baz", primaryKey: nil, type: .INTEGER, nullable: false, defaultValue: .NULL, references: nil)
         ], indexes: [])
 
         XCTAssertEqual(definition.quotedColumnList, """
@@ -195,7 +195,7 @@ class TableDefinitionTests: XCTestCase {
 
     func test_toSQL() {
         let definition = TableDefinition(name: "foo", columns: [
-            ColumnDefinition(name: "id", primaryKey: .init(), type: .INTEGER, null: false, defaultValue: .NULL, references: nil)
+            ColumnDefinition(name: "id", primaryKey: .init(), type: .INTEGER, nullable: false, defaultValue: .NULL, references: nil)
         ], indexes: [])
 
         XCTAssertEqual(definition.toSQL(), """
@@ -205,7 +205,7 @@ class TableDefinitionTests: XCTestCase {
 
     func test_toSQL_temp_table() {
         let definition = TableDefinition(name: "foo", columns: [
-            ColumnDefinition(name: "id", primaryKey: .init(), type: .INTEGER, null: false, defaultValue: .NULL, references: nil)
+            ColumnDefinition(name: "id", primaryKey: .init(), type: .INTEGER, nullable: false, defaultValue: .NULL, references: nil)
         ], indexes: [])
 
         XCTAssertEqual(definition.toSQL(temporary: true), """
@@ -222,11 +222,11 @@ class TableDefinitionTests: XCTestCase {
 
     func test_copySQL() {
         let from = TableDefinition(name: "from_table", columns: [
-            ColumnDefinition(name: "id", primaryKey: .init(), type: .INTEGER, null: false, defaultValue: .NULL, references: nil)
+            ColumnDefinition(name: "id", primaryKey: .init(), type: .INTEGER, nullable: false, defaultValue: .NULL, references: nil)
         ], indexes: [])
 
         let to = TableDefinition(name: "to_table", columns: [
-            ColumnDefinition(name: "id", primaryKey: .init(), type: .INTEGER, null: false, defaultValue: .NULL, references: nil)
+            ColumnDefinition(name: "id", primaryKey: .init(), type: .INTEGER, nullable: false, defaultValue: .NULL, references: nil)
         ], indexes: [])
 
         XCTAssertEqual(from.copySQL(to: to), """

From 17a2cb8985b7188a61ddee5af1f9d549b23ab54d Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 26 Jul 2022 00:47:57 +0200
Subject: [PATCH 547/685] Lint

---
 Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift b/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
index 9c8c3041..75321440 100644
--- a/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
@@ -22,10 +22,12 @@ class ColumnDefinitionTests: XCTestCase {
         (ColumnDefinition(name: "text_column", primaryKey: nil, type: .TEXT, nullable: true, defaultValue: .stringLiteral("fo\"o"), references: nil),
         "\"text_column\" TEXT DEFAULT 'fo\"o'"),
 
-        (ColumnDefinition(name: "integer_column", primaryKey: nil, type: .INTEGER, nullable: true, defaultValue: .numericLiteral("123"), references: nil),
+        (ColumnDefinition(name: "integer_column", primaryKey: nil, type: .INTEGER, nullable: true,
+                          defaultValue: .numericLiteral("123"), references: nil),
         "\"integer_column\" INTEGER DEFAULT 123"),
 
-        (ColumnDefinition(name: "real_column", primaryKey: nil, type: .REAL, nullable: true, defaultValue: .numericLiteral("123.123"), references: nil),
+        (ColumnDefinition(name: "real_column", primaryKey: nil, type: .REAL, nullable: true,
+                          defaultValue: .numericLiteral("123.123"), references: nil),
         "\"real_column\" REAL DEFAULT 123.123")
     ]
 

From b5a83033d5727fb7a201e3700baa678e2e861bca Mon Sep 17 00:00:00 2001
From: Andrew Vanderbilt <105957236+a-vanderbilt@users.noreply.github.com>
Date: Fri, 29 Jul 2022 20:12:52 -0400
Subject: [PATCH 548/685] Fixed typo and added/clarified code comment.

Small typo fix (iff -> if). Added code comment, then modified existing code comment to make the intent of the code clearer.
---
 Documentation/Index.md | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 29b18c96..80f8d9f9 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -288,11 +288,13 @@ On macOS, you can use your app’s **Application Support** directory:
 
 
 ```swift
+
+// set the path corresponding to application support.
 var path = NSSearchPathForDirectoriesInDomains(
     .applicationSupportDirectory, .userDomainMask, true
 ).first! + "/" + Bundle.main.bundleIdentifier!
 
-// create parent directory iff it doesn’t exist
+// create parent directory inside application support if it doesn’t exist
 try FileManager.default.createDirectory(
 atPath: path, withIntermediateDirectories: true, attributes: nil
 )

From f2609b9e520c4dcf23b5f57e5b1e9dd1a12db147 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Sat, 30 Jul 2022 09:09:59 +0200
Subject: [PATCH 549/685] Quick update

---
 Documentation/Index.md | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 80f8d9f9..f90b5960 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -288,8 +288,7 @@ On macOS, you can use your app’s **Application Support** directory:
 
 
 ```swift
-
-// set the path corresponding to application support.
+// set the path corresponding to application support
 var path = NSSearchPathForDirectoriesInDomains(
     .applicationSupportDirectory, .userDomainMask, true
 ).first! + "/" + Bundle.main.bundleIdentifier!

From 607a37aca433adffc83cc1c10ddd07a09774b322 Mon Sep 17 00:00:00 2001
From: Goban <gobanest@gmail.com>
Date: Tue, 30 Aug 2022 12:04:13 +0900
Subject: [PATCH 550/685] Update Index.md

'pathForResource(_:ofType:)' has been renamed to 'path(forResource:ofType:)'
---
 Documentation/Index.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index f90b5960..d6374e6e 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -308,7 +308,7 @@ into your Xcode project and added it to your application target), you can
 establish a _read-only_ connection to it.
 
 ```swift
-let path = Bundle.main.pathForResource("db", ofType: "sqlite3")!
+let path = Bundle.main.path(forResource: "db", ofType: "sqlite3")!
 
 let db = try Connection(path, readonly: true)
 ```

From 6a02c202c34c4dc81272a3e792025ee6257bdee9 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Tue, 30 Aug 2022 09:06:19 +0200
Subject: [PATCH 551/685] Fix linting

---
 Sources/SQLite/Typed/Query.swift | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index cfa7544e..7cb2aef3 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -1035,11 +1035,9 @@ extension Connection {
                 select.clauses.select = (false, [Expression<Void>(literal: "*") as Expressible])
                 let queries = [select] + query.clauses.join.map { $0.query }
                 if !namespace.isEmpty {
-                    for q in queries {
-                        if q.tableName().expression.template == namespace {
-                            try expandGlob(true)(q)
-                            continue column
-                        }
+                    for q in queries where q.tableName().expression.template == namespace {
+                        try expandGlob(true)(q)
+                        continue column
                     }
                     throw QueryError.noSuchTable(name: namespace)
                 }

From f25798f3d047a923976d55f4ba9b8ab9e25e0428 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 18 Sep 2022 23:51:49 +0200
Subject: [PATCH 552/685] SQLiteVersion type

---
 SQLite.xcodeproj/project.pbxproj              | 10 +++++++++
 Sources/SQLite/Core/Connection+Pragmas.swift  |  5 ++---
 Sources/SQLite/Core/SQLiteVersion.swift       | 22 +++++++++++++++++++
 Sources/SQLite/Schema/Connection+Schema.swift | 16 ++++++++++++++
 Sources/SQLite/Schema/SchemaChanger.swift     |  4 ++--
 .../Core/Connection+PragmaTests.swift         |  2 +-
 .../Schema/SchemaChangerTests.swift           |  4 ++--
 7 files changed, 55 insertions(+), 8 deletions(-)
 create mode 100644 Sources/SQLite/Core/SQLiteVersion.swift

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index bc79473e..d2005575 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -199,6 +199,10 @@
 		997DF2AF287FC06D00F8DF95 /* Query+with.swift in Sources */ = {isa = PBXBuildFile; fileRef = 997DF2AD287FC06D00F8DF95 /* Query+with.swift */; };
 		997DF2B0287FC06D00F8DF95 /* Query+with.swift in Sources */ = {isa = PBXBuildFile; fileRef = 997DF2AD287FC06D00F8DF95 /* Query+with.swift */; };
 		997DF2B1287FC06D00F8DF95 /* Query+with.swift in Sources */ = {isa = PBXBuildFile; fileRef = 997DF2AD287FC06D00F8DF95 /* Query+with.swift */; };
+		DB7C5DA628D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
+		DB7C5DA728D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
+		DB7C5DA828D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
+		DB7C5DA928D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
 		EE247AD71C3F04ED00AE3E12 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		EE247ADE1C3F04ED00AE3E12 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE247AD31C3F04ED00AE3E12 /* SQLite.framework */; };
 		EE247B031C3F06E900AE3E12 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
@@ -325,6 +329,7 @@
 		49EB68C31F7B3CB400D89D40 /* Coding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coding.swift; sourceTree = "<group>"; };
 		997DF2AD287FC06D00F8DF95 /* Query+with.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Query+with.swift"; sourceTree = "<group>"; };
 		A121AC451CA35C79005A31D1 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SQLiteVersion.swift; sourceTree = "<group>"; };
 		EE247AD31C3F04ED00AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AD61C3F04ED00AE3E12 /* SQLite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLite.h; sourceTree = "<group>"; };
 		EE247AD81C3F04ED00AE3E12 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -569,6 +574,7 @@
 				19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */,
 				3DF7B78728842972005DD8CA /* Connection+Attach.swift */,
 				3DF7B790288449BA005DD8CA /* URIQueryParameter.swift */,
+				DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */,
 				19A17F285B767BFACD96714B /* Connection+Pragmas.swift */,
 			);
 			path = Core;
@@ -954,6 +960,7 @@
 				02A43A9A22738CF100FEC494 /* Backup.swift in Sources */,
 				19A17FF4A10B44D3937C8CAC /* Errors.swift in Sources */,
 				19A1737286A74F3CF7412906 /* DateAndTimeFunctions.swift in Sources */,
+				DB7C5DA828D7C9B6006395CF /* SQLiteVersion.swift in Sources */,
 				19A17073552293CA063BEA66 /* Result.swift in Sources */,
 				997DF2B0287FC06D00F8DF95 /* Query+with.swift in Sources */,
 				19A179B59450FE7C4811AB8A /* Connection+Aggregation.swift in Sources */,
@@ -1012,6 +1019,7 @@
 				3D67B3F71DB246D700A4F4C6 /* Foundation.swift in Sources */,
 				3D67B3F81DB246D700A4F4C6 /* Helpers.swift in Sources */,
 				3D67B3E91DB246D100A4F4C6 /* Statement.swift in Sources */,
+				DB7C5DA928D7C9B6006395CF /* SQLiteVersion.swift in Sources */,
 				3D67B3EA1DB246D100A4F4C6 /* Value.swift in Sources */,
 				3D67B3EB1DB246D100A4F4C6 /* FTS4.swift in Sources */,
 				3D67B3EC1DB246D100A4F4C6 /* RTree.swift in Sources */,
@@ -1069,6 +1077,7 @@
 				02A43A9822738CF100FEC494 /* Backup.swift in Sources */,
 				19A1792C0520D4E83C2EB075 /* Errors.swift in Sources */,
 				19A17E29278A12BC4F542506 /* DateAndTimeFunctions.swift in Sources */,
+				DB7C5DA628D7C9B6006395CF /* SQLiteVersion.swift in Sources */,
 				19A173EFEF0B3BD0B3ED406C /* Result.swift in Sources */,
 				997DF2AE287FC06D00F8DF95 /* Query+with.swift in Sources */,
 				19A176376CB6A94759F7980A /* Connection+Aggregation.swift in Sources */,
@@ -1146,6 +1155,7 @@
 				02A43A9922738CF100FEC494 /* Backup.swift in Sources */,
 				19A17490543609FCED53CACC /* Errors.swift in Sources */,
 				19A17152E32A9585831E3FE0 /* DateAndTimeFunctions.swift in Sources */,
+				DB7C5DA728D7C9B6006395CF /* SQLiteVersion.swift in Sources */,
 				19A17F1B3F0A3C96B5ED6D64 /* Result.swift in Sources */,
 				997DF2AF287FC06D00F8DF95 /* Query+with.swift in Sources */,
 				19A170ACC97B19730FB7BA4D /* Connection+Aggregation.swift in Sources */,
diff --git a/Sources/SQLite/Core/Connection+Pragmas.swift b/Sources/SQLite/Core/Connection+Pragmas.swift
index 43ff9610..8f6d854b 100644
--- a/Sources/SQLite/Core/Connection+Pragmas.swift
+++ b/Sources/SQLite/Core/Connection+Pragmas.swift
@@ -1,7 +1,6 @@
 import Foundation
 
 public typealias UserVersion = Int32
-public typealias SQLiteVersion = (Int, Int, Int)
 
 public extension Connection {
     /// The user version of the database.
@@ -21,9 +20,9 @@ public extension Connection {
         guard let version = (try? scalar("SELECT sqlite_version()")) as? String,
               let splits = .some(version.split(separator: ".", maxSplits: 3)), splits.count == 3,
               let major = Int(splits[0]), let minor = Int(splits[1]), let point = Int(splits[2]) else {
-            return (0, 0, 0)
+            return .zero
         }
-        return (major, minor, point)
+        return .init(major: major, minor: minor, point: point)
     }
 
     // Changing the foreign_keys setting affects the execution of all statements prepared using the database
diff --git a/Sources/SQLite/Core/SQLiteVersion.swift b/Sources/SQLite/Core/SQLiteVersion.swift
new file mode 100644
index 00000000..fa7358da
--- /dev/null
+++ b/Sources/SQLite/Core/SQLiteVersion.swift
@@ -0,0 +1,22 @@
+import Foundation
+
+public struct SQLiteVersion: Comparable, CustomStringConvertible {
+    public let major: Int
+    public let minor: Int
+    public var point: Int = 0
+
+    public var description: String {
+        "SQLite \(major).\(minor).\(point)"
+    }
+
+    public static func <(lhs: SQLiteVersion, rhs: SQLiteVersion) -> Bool {
+        lhs.tuple < rhs.tuple
+    }
+
+    public static func ==(lhs: SQLiteVersion, rhs: SQLiteVersion) -> Bool {
+        lhs.tuple == rhs.tuple
+    }
+
+    static var zero: SQLiteVersion = .init(major: 0, minor: 0)
+    private var tuple: (Int, Int, Int) { (major, minor, point) }
+}
diff --git a/Sources/SQLite/Schema/Connection+Schema.swift b/Sources/SQLite/Schema/Connection+Schema.swift
index 378fad68..d92236ee 100644
--- a/Sources/SQLite/Schema/Connection+Schema.swift
+++ b/Sources/SQLite/Schema/Connection+Schema.swift
@@ -80,6 +80,16 @@ extension Connection {
         }
     }
 
+    func tableInfo() throws -> [String] {
+        try run("SELECT tbl_name FROM sqlite_master WHERE type = 'table'").compactMap { row in
+            if let name = row[0] as? String, !name.starts(with: "sqlite_") {
+                return name
+            } else {
+                return nil
+            }
+        }
+    }
+
     // https://sqlite.org/pragma.html#pragma_foreign_key_check
 
     // There are four columns in each result row.
@@ -99,6 +109,12 @@ extension Connection {
         }
     }
 
+    // https://sqlite.org/pragma.html#pragma_integrity_check
+    func integrityCheck() throws -> [String] {
+        try run("PRAGMA integrity_check").compactMap { $0[0] as? String }.filter { $0 != "ok" }
+    }
+
+
     private func createTableSQL(name: String) throws  -> String? {
         try run("""
                 SELECT sql FROM sqlite_master WHERE name=? AND type='table'
diff --git a/Sources/SQLite/Schema/SchemaChanger.swift b/Sources/SQLite/Schema/SchemaChanger.swift
index daba2f60..991e3338 100644
--- a/Sources/SQLite/Schema/SchemaChanger.swift
+++ b/Sources/SQLite/Schema/SchemaChanger.swift
@@ -52,9 +52,9 @@ public class SchemaChanger: CustomStringConvertible {
             switch self {
             case .addColumn(let definition):
                 return "ALTER TABLE \(table.quote()) ADD COLUMN \(definition.toSQL())"
-            case .renameColumn(let from, let to) where version >= (3, 25, 0):
+            case .renameColumn(let from, let to) where version >= .init(major: 3, minor: 25):
                 return "ALTER TABLE \(table.quote()) RENAME COLUMN \(from.quote()) TO \(to.quote())"
-            case .dropColumn(let column) where version >= (3, 35, 0):
+            case .dropColumn(let column) where version >= .init(major: 3, minor: 35):
                 return "ALTER TABLE \(table.quote()) DROP COLUMN \(column.quote())"
             default: return nil
             }
diff --git a/Tests/SQLiteTests/Core/Connection+PragmaTests.swift b/Tests/SQLiteTests/Core/Connection+PragmaTests.swift
index 2d0742c9..2bcdb6af 100644
--- a/Tests/SQLiteTests/Core/Connection+PragmaTests.swift
+++ b/Tests/SQLiteTests/Core/Connection+PragmaTests.swift
@@ -19,7 +19,7 @@ class ConnectionPragmaTests: SQLiteTestCase {
     }
 
     func test_sqlite_version() {
-        XCTAssertTrue(db.sqliteVersion >= (3, 0, 0))
+        XCTAssertTrue(db.sqliteVersion >= .init(major: 3, minor: 0))
     }
 
     func test_foreignKeys_defaults_to_false() {
diff --git a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
index 038a8844..738588fd 100644
--- a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
@@ -58,7 +58,7 @@ class SchemaChangerTests: SQLiteTestCase {
     }
 
     func test_remove_column_legacy() throws {
-        schemaChanger = .init(connection: db, version: (3, 24, 0)) // DROP COLUMN introduced in 3.35.0
+        schemaChanger = .init(connection: db, version: .init(major: 3, minor: 24)) // DROP COLUMN introduced in 3.35.0
 
         try schemaChanger.alter(table: "users") { table in
             table.remove("age")
@@ -78,7 +78,7 @@ class SchemaChangerTests: SQLiteTestCase {
     }
 
     func test_rename_column_legacy() throws {
-        schemaChanger = .init(connection: db, version: (3, 24, 0)) // RENAME COLUMN introduced in 3.25.0
+        schemaChanger = .init(connection: db, version: .init(major: 3, minor: 24)) // RENAME COLUMN introduced in 3.25.0
 
         try schemaChanger.alter(table: "users") { table in
             table.rename("age", to: "age2")

From ec35c7ea060f08a3f36382564f2a69206da7aa2b Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 18 Sep 2022 23:57:43 +0200
Subject: [PATCH 553/685] Lint

---
 Sources/SQLite/Schema/Connection+Schema.swift | 1 -
 Sources/SQLite/Typed/Query.swift              | 8 +++-----
 2 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/Sources/SQLite/Schema/Connection+Schema.swift b/Sources/SQLite/Schema/Connection+Schema.swift
index d92236ee..9c945e18 100644
--- a/Sources/SQLite/Schema/Connection+Schema.swift
+++ b/Sources/SQLite/Schema/Connection+Schema.swift
@@ -114,7 +114,6 @@ extension Connection {
         try run("PRAGMA integrity_check").compactMap { $0[0] as? String }.filter { $0 != "ok" }
     }
 
-
     private func createTableSQL(name: String) throws  -> String? {
         try run("""
                 SELECT sql FROM sqlite_master WHERE name=? AND type='table'
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index cfa7544e..7cb2aef3 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -1035,11 +1035,9 @@ extension Connection {
                 select.clauses.select = (false, [Expression<Void>(literal: "*") as Expressible])
                 let queries = [select] + query.clauses.join.map { $0.query }
                 if !namespace.isEmpty {
-                    for q in queries {
-                        if q.tableName().expression.template == namespace {
-                            try expandGlob(true)(q)
-                            continue column
-                        }
+                    for q in queries where q.tableName().expression.template == namespace {
+                        try expandGlob(true)(q)
+                        continue column
                     }
                     throw QueryError.noSuchTable(name: namespace)
                 }

From 00a86686c4cf88caf09cde6ad0f50d4064a8b653 Mon Sep 17 00:00:00 2001
From: Michael Henry Pantaleon <me@iamkel.net>
Date: Wed, 12 Oct 2022 23:20:23 +1100
Subject: [PATCH 554/685] Fix playground example as the prepare func can throw
 an error

---
 SQLite.playground/Contents.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/SQLite.playground/Contents.swift b/SQLite.playground/Contents.swift
index c089076d..945adb50 100644
--- a/SQLite.playground/Contents.swift
+++ b/SQLite.playground/Contents.swift
@@ -99,5 +99,5 @@ db.createAggregation("customConcat",
                      initialValue: "users:",
                      reduce: reduce,
                      result: { $0 })
-let result = db.prepare("SELECT customConcat(email) FROM users").scalar() as! String
+let result = try db.prepare("SELECT customConcat(email) FROM users").scalar() as! String
 print(result)

From d7c26353330ea851691f3f0359aa13e7dbedced5 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 16 Oct 2022 02:24:31 +0200
Subject: [PATCH 555/685] Split into classes, improve queries

---
 Makefile                                      |   2 +
 SQLite.xcodeproj/project.pbxproj              |  10 +
 Sources/SQLite/Schema/Connection+Schema.swift | 129 ++-----------
 Sources/SQLite/Schema/SchemaChanger.swift     |   6 +-
 Sources/SQLite/Schema/SchemaDefinitions.swift | 107 ++++++----
 Sources/SQLite/Schema/SchemaReader.swift      | 182 ++++++++++++++++++
 Sources/SQLite/Typed/Query.swift              |  17 ++
 Tests/SQLiteTests/Core/ConnectionTests.swift  |   2 +-
 .../Schema/Connection+SchemaTests.swift       | 140 +++-----------
 .../Schema/SchemaChangerTests.swift           |  24 +--
 .../Schema/SchemaDefinitionsTests.swift       | 132 ++++++++-----
 .../Schema/SchemaReaderTests.swift            | 180 +++++++++++++++++
 12 files changed, 603 insertions(+), 328 deletions(-)
 create mode 100644 Sources/SQLite/Schema/SchemaReader.swift
 create mode 100644 Tests/SQLiteTests/Schema/SchemaReaderTests.swift

diff --git a/Makefile b/Makefile
index c62da000..74bf5d18 100644
--- a/Makefile
+++ b/Makefile
@@ -18,6 +18,8 @@ build:
 
 lint:
 	swiftlint --strict
+lint-fix:
+	swiftlint lint fix
 
 test:
 ifdef XCPRETTY
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index d2005575..a58e0887 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -199,6 +199,10 @@
 		997DF2AF287FC06D00F8DF95 /* Query+with.swift in Sources */ = {isa = PBXBuildFile; fileRef = 997DF2AD287FC06D00F8DF95 /* Query+with.swift */; };
 		997DF2B0287FC06D00F8DF95 /* Query+with.swift in Sources */ = {isa = PBXBuildFile; fileRef = 997DF2AD287FC06D00F8DF95 /* Query+with.swift */; };
 		997DF2B1287FC06D00F8DF95 /* Query+with.swift in Sources */ = {isa = PBXBuildFile; fileRef = 997DF2AD287FC06D00F8DF95 /* Query+with.swift */; };
+		DB58B21128FB864300F8EEA4 /* SchemaReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB58B21028FB864300F8EEA4 /* SchemaReader.swift */; };
+		DB58B21228FB864300F8EEA4 /* SchemaReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB58B21028FB864300F8EEA4 /* SchemaReader.swift */; };
+		DB58B21328FB864300F8EEA4 /* SchemaReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB58B21028FB864300F8EEA4 /* SchemaReader.swift */; };
+		DB58B21428FB864300F8EEA4 /* SchemaReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB58B21028FB864300F8EEA4 /* SchemaReader.swift */; };
 		DB7C5DA628D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
 		DB7C5DA728D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
 		DB7C5DA828D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
@@ -329,6 +333,7 @@
 		49EB68C31F7B3CB400D89D40 /* Coding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coding.swift; sourceTree = "<group>"; };
 		997DF2AD287FC06D00F8DF95 /* Query+with.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Query+with.swift"; sourceTree = "<group>"; };
 		A121AC451CA35C79005A31D1 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		DB58B21028FB864300F8EEA4 /* SchemaReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaReader.swift; sourceTree = "<group>"; };
 		DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SQLiteVersion.swift; sourceTree = "<group>"; };
 		EE247AD31C3F04ED00AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AD61C3F04ED00AE3E12 /* SQLite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLite.h; sourceTree = "<group>"; };
@@ -429,6 +434,7 @@
 		19A1792D261C689FC988A90A /* Schema */ = {
 			isa = PBXGroup;
 			children = (
+				DB58B21028FB864300F8EEA4 /* SchemaReader.swift */,
 				19A171B262DDE8718513CFDA /* SchemaChanger.swift */,
 				19A17268AE67B746B96AC125 /* SchemaDefinitions.swift */,
 				19A170A97B51DC5EE365F3C5 /* Connection+Schema.swift */,
@@ -968,6 +974,7 @@
 				19A1740EACD47904AA24B8DC /* SchemaDefinitions.swift in Sources */,
 				19A1750EF4A5F92954A451FF /* Connection+Schema.swift in Sources */,
 				19A17986405D9A875698408F /* Connection+Pragmas.swift in Sources */,
+				DB58B21328FB864300F8EEA4 /* SchemaReader.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1018,6 +1025,7 @@
 				997DF2B1287FC06D00F8DF95 /* Query+with.swift in Sources */,
 				3D67B3F71DB246D700A4F4C6 /* Foundation.swift in Sources */,
 				3D67B3F81DB246D700A4F4C6 /* Helpers.swift in Sources */,
+				DB58B21428FB864300F8EEA4 /* SchemaReader.swift in Sources */,
 				3D67B3E91DB246D100A4F4C6 /* Statement.swift in Sources */,
 				DB7C5DA928D7C9B6006395CF /* SQLiteVersion.swift in Sources */,
 				3D67B3EA1DB246D100A4F4C6 /* Value.swift in Sources */,
@@ -1085,6 +1093,7 @@
 				19A17BA13FD35F058787B7D3 /* SchemaDefinitions.swift in Sources */,
 				19A174506543905D71BF0518 /* Connection+Schema.swift in Sources */,
 				19A17018F250343BD0F9F4B0 /* Connection+Pragmas.swift in Sources */,
+				DB58B21128FB864300F8EEA4 /* SchemaReader.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1163,6 +1172,7 @@
 				19A17B0DF1DDB6BBC9C95D64 /* SchemaDefinitions.swift in Sources */,
 				19A17F0BF02896E1664F4090 /* Connection+Schema.swift in Sources */,
 				19A1760CE25615CA015E2E5F /* Connection+Pragmas.swift in Sources */,
+				DB58B21228FB864300F8EEA4 /* SchemaReader.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/Sources/SQLite/Schema/Connection+Schema.swift b/Sources/SQLite/Schema/Connection+Schema.swift
index 9c945e18..868b40d5 100644
--- a/Sources/SQLite/Schema/Connection+Schema.swift
+++ b/Sources/SQLite/Schema/Connection+Schema.swift
@@ -1,96 +1,7 @@
 import Foundation
 
-extension Connection {
-    // https://sqlite.org/pragma.html#pragma_table_info
-    //
-    // This pragma returns one row for each column in the named table. Columns in the result set include the
-    // column name, data type, whether or not the column can be NULL, and the default value for the column. The
-    // "pk" column in the result set is zero for columns that are not part of the primary key, and is the
-    // index of the column in the primary key for columns that are part of the primary key.
-    func columnInfo(table: String) throws  -> [ColumnDefinition] {
-        func parsePrimaryKey(column: String) throws -> ColumnDefinition.PrimaryKey? {
-            try createTableSQL(name: table).flatMap { .init(sql: $0) }
-        }
-
-        let foreignKeys: [String: [ColumnDefinition.ForeignKey]] =
-            Dictionary(grouping: try foreignKeyInfo(table: table), by: { $0.column })
-
-        return try run("PRAGMA table_info(\(table.quote()))").compactMap { row -> ColumnDefinition? in
-            guard let name = row[1] as? String,
-                  let type = row[2] as? String,
-                  let notNull = row[3] as? Int64,
-                  let defaultValue = row[4] as? String?,
-                  let primaryKey = row[5] as? Int64 else { return nil }
-            return ColumnDefinition(name: name,
-                                    primaryKey: primaryKey == 1 ? try parsePrimaryKey(column: name) : nil,
-                                    type: ColumnDefinition.Affinity.from(type),
-                                    nullable: notNull == 0,
-                                    defaultValue: .from(defaultValue),
-                                    references: foreignKeys[name]?.first)
-        }
-    }
-
-    func indexInfo(table: String) throws -> [IndexDefinition] {
-        func indexSQL(name: String) throws  -> String? {
-            try run("""
-                    SELECT sql FROM sqlite_master WHERE name=? AND type='index'
-                      UNION ALL
-                    SELECT sql FROM sqlite_temp_master WHERE name=? AND type='index'
-                    """, name, name)
-                    .compactMap { row in row[0] as? String }
-                    .first
-        }
-
-        func columns(name: String) throws -> [String] {
-            try run("PRAGMA index_info(\(name.quote()))").compactMap { row in
-                row[2] as? String
-            }
-        }
-
-        return try run("PRAGMA index_list(\(table.quote()))").compactMap { row -> IndexDefinition? in
-            guard let name = row[1] as? String,
-                  let unique = row[2] as? Int64,
-                    // Indexes SQLite creates implicitly for internal use start with "sqlite_".
-                    // See https://www.sqlite.org/fileformat2.html#intschema
-                  !name.starts(with: "sqlite_") else {
-                return nil
-            }
-            return .init(table: table,
-                         name: name,
-                         unique: unique == 1,
-                         columns: try columns(name: name),
-                         indexSQL: try indexSQL(name: name))
-        }
-    }
-
-    func foreignKeyInfo(table: String) throws -> [ColumnDefinition.ForeignKey] {
-        try run("PRAGMA foreign_key_list(\(table.quote()))").compactMap { row in
-            if let table = row[2] as? String,      // table
-               let column = row[3] as? String,     // from
-               let primaryKey = row[4] as? String, // to
-               let onUpdate = row[5] as? String,
-               let onDelete = row[6] as? String {
-                return .init(table: table, column: column, primaryKey: primaryKey,
-                             onUpdate: onUpdate == TableBuilder.Dependency.noAction.rawValue ? nil : onUpdate,
-                             onDelete: onDelete == TableBuilder.Dependency.noAction.rawValue ? nil : onDelete
-                )
-            } else {
-                return nil
-            }
-        }
-    }
-
-    func tableInfo() throws -> [String] {
-        try run("SELECT tbl_name FROM sqlite_master WHERE type = 'table'").compactMap { row in
-            if let name = row[0] as? String, !name.starts(with: "sqlite_") {
-                return name
-            } else {
-                return nil
-            }
-        }
-    }
-
-    // https://sqlite.org/pragma.html#pragma_foreign_key_check
+public extension Connection {
+    var schemaReader: SchemaReader { SchemaReader(connection: self) }
 
     // There are four columns in each result row.
     // The first column is the name of the table that
@@ -99,28 +10,24 @@ extension Connection {
     // invalid REFERENCES clause, or NULL if the child table is a WITHOUT ROWID table.
     // The third column is the name of the table that is referred to.
     // The fourth column is the index of the specific foreign key constraint that failed.
-    func foreignKeyCheck() throws -> [ForeignKeyError] {
-        try run("PRAGMA foreign_key_check").compactMap { row -> ForeignKeyError? in
-            guard let table = row[0] as? String,
-                  let rowId = row[1] as? Int64,
-                  let target = row[2] as? String else { return nil }
-
-            return ForeignKeyError(from: table, rowId: rowId, to: target)
-        }
+    //
+    // https://sqlite.org/pragma.html#pragma_foreign_key_check
+    func foreignKeyCheck(table: String? = nil) throws -> [ForeignKeyError] {
+        try run("PRAGMA foreign_key_check" + (table.map { "(\($0.quote()))" } ?? ""))
+            .compactMap { row -> ForeignKeyError? in
+                guard let table = row[0] as? String,
+                      let rowId = row[1] as? Int64,
+                      let target = row[2] as? String else { return nil }
+
+                return ForeignKeyError(from: table, rowId: rowId, to: target)
+            }
     }
 
+    // This pragma does a low-level formatting and consistency check of the database.
     // https://sqlite.org/pragma.html#pragma_integrity_check
-    func integrityCheck() throws -> [String] {
-        try run("PRAGMA integrity_check").compactMap { $0[0] as? String }.filter { $0 != "ok" }
-    }
-
-    private func createTableSQL(name: String) throws  -> String? {
-        try run("""
-                SELECT sql FROM sqlite_master WHERE name=? AND type='table'
-                  UNION ALL
-                SELECT sql FROM sqlite_temp_master WHERE name=? AND type='table'
-        """, name, name)
-            .compactMap { row in row[0] as? String }
-            .first
+    func integrityCheck(table: String? = nil, maxErrors: Int? = nil) throws -> [String] {
+        try run("PRAGMA integrity_check" + (table.map { "(\($0.quote()))" } ?? ""))
+            .compactMap { $0[0] as? String }
+            .filter { $0 != "ok" }
     }
 }
diff --git a/Sources/SQLite/Schema/SchemaChanger.swift b/Sources/SQLite/Schema/SchemaChanger.swift
index 991e3338..b557da0a 100644
--- a/Sources/SQLite/Schema/SchemaChanger.swift
+++ b/Sources/SQLite/Schema/SchemaChanger.swift
@@ -109,6 +109,7 @@ public class SchemaChanger: CustomStringConvertible {
     }
 
     private let connection: Connection
+    private let schemaReader: SchemaReader
     private let version: SQLiteVersion
     static let tempPrefix = "tmp_"
     typealias Block = () throws -> Void
@@ -127,6 +128,7 @@ public class SchemaChanger: CustomStringConvertible {
 
     init(connection: Connection, version: SQLiteVersion) {
         self.connection = connection
+        schemaReader = connection.schemaReader
         self.version = version
     }
 
@@ -196,8 +198,8 @@ public class SchemaChanger: CustomStringConvertible {
     private func copyTable(from: String, to: String, options: Options = .default, operation: Operation?) throws {
         let fromDefinition = TableDefinition(
             name: from,
-            columns: try connection.columnInfo(table: from),
-            indexes: try connection.indexInfo(table: from)
+            columns: try schemaReader.columnDefinitions(table: from),
+            indexes: try schemaReader.indexDefinitions(table: from)
         )
         let toDefinition   = fromDefinition
                 .apply(.renameTable(to))
diff --git a/Sources/SQLite/Schema/SchemaDefinitions.swift b/Sources/SQLite/Schema/SchemaDefinitions.swift
index a06487b2..fe2e3931 100644
--- a/Sources/SQLite/Schema/SchemaDefinitions.swift
+++ b/Sources/SQLite/Schema/SchemaDefinitions.swift
@@ -10,6 +10,29 @@ struct TableDefinition: Equatable {
     }
 }
 
+// https://sqlite.org/schematab.html#interpretation_of_the_schema_table
+public struct ObjectDefinition: Equatable {
+    public enum ObjectType: String {
+        case table, index, view, trigger
+    }
+    public let type: ObjectType
+
+    // The name of the object
+    public let name: String
+
+    // The name of a table or view that the object is associated with.
+    //  * For a table or view, a copy of the name column.
+    //  * For an index, the name of the table that is indexed
+    //  * For a trigger, the column stores the name of the table or view that causes the trigger to fire.
+    public let tableName: String
+
+    // The page number of the root b-tree page for tables and indexes, otherwise 0 or NULL
+    public let rootpage: Int64
+
+    // SQL text that describes the object (NULL for the internal indexes)
+    public let sql: String?
+}
+
 // https://sqlite.org/syntax/column-def.html
 // column-name -> type-name -> column-constraint*
 public struct ColumnDefinition: Equatable {
@@ -29,8 +52,8 @@ public struct ColumnDefinition: Equatable {
             rawValue
         }
 
-        static func from(_ string: String) -> Affinity {
-            Affinity.allCases.first { $0.rawValue.lowercased() == string.lowercased() } ?? TEXT
+        init(_ string: String) {
+            self = Affinity.allCases.first { $0.rawValue.lowercased() == string.lowercased() } ?? .TEXT
         }
     }
 
@@ -41,8 +64,9 @@ public struct ColumnDefinition: Equatable {
         case IGNORE
         case REPLACE
 
-        static func from(_ string: String) -> OnConflict? {
-            OnConflict.allCases.first { $0.rawValue == string }
+        init?(_ string: String) {
+            guard let value = (OnConflict.allCases.first { $0.rawValue == string }) else { return nil }
+            self = value
         }
     }
 
@@ -59,17 +83,20 @@ public struct ColumnDefinition: Equatable {
         }
 
         init?(sql: String) {
-            if let match = PrimaryKey.pattern.firstMatch(in: sql, range: NSRange(location: 0, length: sql.count)) {
-                let conflict = match.range(at: 1)
-                var onConflict: ColumnDefinition.OnConflict?
-                if conflict.location != NSNotFound {
-                    onConflict = .from((sql as NSString).substring(with: conflict))
-                }
-                let autoIncrement = match.range(at: 2).location != NSNotFound
-                self.init(autoIncrement: autoIncrement, onConflict: onConflict)
-            } else {
+            guard let match = PrimaryKey.pattern.firstMatch(
+                in: sql,
+                range: NSRange(location: 0, length: sql.count)) else {
                 return nil
             }
+            let conflict = match.range(at: 1)
+            let onConflict: ColumnDefinition.OnConflict?
+            if conflict.location != NSNotFound {
+                onConflict = OnConflict((sql as NSString).substring(with: conflict))
+            } else {
+                onConflict = nil
+            }
+            let autoIncrement = match.range(at: 2).location != NSNotFound
+            self.init(autoIncrement: autoIncrement, onConflict: onConflict)
         }
     }
 
@@ -138,28 +165,19 @@ public enum LiteralValue: Equatable, CustomStringConvertible {
     case CURRENT_TIMESTAMP
     // swiftlint:enable identifier_name
 
-    static func from(_ string: String?) -> LiteralValue {
-        func parse(_ value: String) -> LiteralValue {
-            if let match = singleQuote.firstMatch(in: value, range: NSRange(location: 0, length: value.count)) {
-                return stringLiteral((value as NSString).substring(with: match.range(at: 1)).replacingOccurrences(of: "''", with: "'"))
-            } else if let match = doubleQuote.firstMatch(in: value, range: NSRange(location: 0, length: value.count)) {
-                return stringLiteral((value as NSString).substring(with: match.range(at: 1)).replacingOccurrences(of: "\"\"", with: "\""))
-            } else if let match = blob.firstMatch(in: value, range: NSRange(location: 0, length: value.count)) {
-                return blobLiteral((value as NSString).substring(with: match.range(at: 1)))
-            } else {
-                return numericLiteral(value)
-            }
+    init(_ string: String?) {
+        guard let string = string else {
+            self = .NULL
+            return
         }
-        guard let string = string else { return NULL }
-
         switch string {
-        case "NULL": return NULL
-        case "TRUE": return TRUE
-        case "FALSE": return FALSE
-        case "CURRENT_TIME": return CURRENT_TIME
-        case "CURRENT_TIMESTAMP": return CURRENT_TIMESTAMP
-        case "CURRENT_DATE": return CURRENT_DATE
-        default: return parse(string)
+        case "NULL": self = .NULL
+        case "TRUE": self = .TRUE
+        case "FALSE": self = .FALSE
+        case "CURRENT_TIME": self = .CURRENT_TIME
+        case "CURRENT_TIMESTAMP": self = .CURRENT_TIMESTAMP
+        case "CURRENT_DATE": self = .CURRENT_DATE
+        default: self = LiteralValue.parse(string)
         }
     }
 
@@ -184,6 +202,17 @@ public enum LiteralValue: Equatable, CustomStringConvertible {
             return block(self)
         }
     }
+    private static func parse(_ string: String) -> LiteralValue {
+        if let match = LiteralValue.singleQuote.firstMatch(in: string, range: NSRange(location: 0, length: string.count)) {
+            return .stringLiteral((string as NSString).substring(with: match.range(at: 1)).replacingOccurrences(of: "''", with: "'"))
+        } else if let match = LiteralValue.doubleQuote.firstMatch(in: string, range: NSRange(location: 0, length: string.count)) {
+            return .stringLiteral((string as NSString).substring(with: match.range(at: 1)).replacingOccurrences(of: "\"\"", with: "\""))
+        } else if let match = LiteralValue.blob.firstMatch(in: string, range: NSRange(location: 0, length: string.count)) {
+            return .blobLiteral((string as NSString).substring(with: match.range(at: 1)))
+        } else {
+            return .numericLiteral(string)
+        }
+    }
 }
 
 // https://sqlite.org/lang_createindex.html
@@ -259,9 +288,9 @@ public struct IndexDefinition: Equatable {
 }
 
 public struct ForeignKeyError: CustomStringConvertible {
-    let from: String
-    let rowId: Int64
-    let to: String
+    public let from: String
+    public let rowId: Int64
+    public let to: String
 
     public var description: String {
         "\(from) [\(rowId)] => \(to)"
@@ -270,7 +299,7 @@ public struct ForeignKeyError: CustomStringConvertible {
 
 extension TableDefinition {
     func toSQL(temporary: Bool = false) -> String {
-        assert(columns.count > 0, "no columns to create")
+        precondition(columns.count > 0, "no columns to create")
 
         return ([
             "CREATE",
@@ -285,8 +314,8 @@ extension TableDefinition {
     }
 
     func copySQL(to: TableDefinition) -> String {
-        assert(columns.count > 0, "no columns to copy")
-        assert(columns.count == to.columns.count, "column counts don't match")
+        precondition(columns.count > 0)
+        precondition(columns.count == to.columns.count, "column counts don't match")
         return "INSERT INTO \(to.name.quote()) (\(to.quotedColumnList)) SELECT \(quotedColumnList) FROM \(name.quote())"
     }
 }
diff --git a/Sources/SQLite/Schema/SchemaReader.swift b/Sources/SQLite/Schema/SchemaReader.swift
new file mode 100644
index 00000000..3f02eeae
--- /dev/null
+++ b/Sources/SQLite/Schema/SchemaReader.swift
@@ -0,0 +1,182 @@
+import Foundation
+
+public class SchemaReader {
+    private let connection: Connection
+
+    init(connection: Connection) {
+        self.connection = connection
+    }
+
+    // https://sqlite.org/pragma.html#pragma_table_info
+    //
+    // This pragma returns one row for each column in the named table. Columns in the result set include the
+    // column name, data type, whether or not the column can be NULL, and the default value for the column. The
+    // "pk" column in the result set is zero for columns that are not part of the primary key, and is the
+    // index of the column in the primary key for columns that are part of the primary key.
+    public func columnDefinitions(table: String) throws  -> [ColumnDefinition] {
+        func parsePrimaryKey(column: String) throws -> ColumnDefinition.PrimaryKey? {
+            try createTableSQL(name: table).flatMap { .init(sql: $0) }
+        }
+
+        let foreignKeys: [String: [ColumnDefinition.ForeignKey]] =
+            Dictionary(grouping: try foreignKeys(table: table), by: { $0.column })
+
+        return try connection.prepareRowIterator("PRAGMA table_info(\(table.quote()))")
+            .map { (row: Row) -> ColumnDefinition in
+                ColumnDefinition(
+                    name: row[TableInfoTable.nameColumn],
+                    primaryKey: row[TableInfoTable.primaryKeyColumn] == 1 ?
+                        try parsePrimaryKey(column: row[TableInfoTable.nameColumn]) : nil,
+                    type: ColumnDefinition.Affinity(row[TableInfoTable.typeColumn]),
+                    nullable: row[TableInfoTable.notNullColumn] == 0,
+                    defaultValue: LiteralValue(row[TableInfoTable.defaultValueColumn]),
+                    references: foreignKeys[row[TableInfoTable.nameColumn]]?.first
+                )
+            }
+    }
+
+    public func objectDefinitions(name: String? = nil,
+                                  type: ObjectDefinition.ObjectType? = nil,
+                                  temp: Bool = false) throws -> [ObjectDefinition] {
+        var query: QueryType = temp ? SchemaTable.tempName : SchemaTable.name
+        if let name = name {
+            query = query.where(SchemaTable.nameColumn == name)
+        }
+        if let type = type {
+            query = query.where(SchemaTable.typeColumn == type.rawValue)
+        }
+        return try connection.prepare(query).map { row -> ObjectDefinition in
+            guard let type = ObjectDefinition.ObjectType(rawValue: row[SchemaTable.typeColumn]) else {
+                fatalError("unexpected type")
+            }
+            return ObjectDefinition(
+                type: type,
+                name: row[SchemaTable.nameColumn],
+                tableName: row[SchemaTable.nameColumn],
+                rootpage: row[SchemaTable.rootPageColumn] ?? 0,
+                sql: row[SchemaTable.sqlColumn]
+            )
+        }
+    }
+
+    public func indexDefinitions(table: String) throws -> [IndexDefinition] {
+        func indexSQL(name: String) throws -> String? {
+            try objectDefinitions(name: name, type: .index)
+                .compactMap(\.sql)
+                .first
+        }
+
+        func columns(name: String) throws -> [String] {
+            try connection.prepareRowIterator("PRAGMA index_info(\(name.quote()))")
+                .compactMap { row in
+                    row[IndexInfoTable.nameColumn]
+                }
+        }
+
+        return try connection.prepareRowIterator("PRAGMA index_list(\(table.quote()))")
+            .compactMap { row -> IndexDefinition? in
+                let name = row[IndexListTable.nameColumn]
+                guard !name.starts(with: "sqlite_") else {
+                    // Indexes SQLite creates implicitly for internal use start with "sqlite_".
+                    // See https://www.sqlite.org/fileformat2.html#intschema
+                    return nil
+                }
+                return IndexDefinition(
+                    table: table,
+                    name: name,
+                    unique: row[IndexListTable.uniqueColumn] == 1,
+                    columns: try columns(name: name),
+                    indexSQL: try indexSQL(name: name)
+                )
+            }
+    }
+
+    func foreignKeys(table: String) throws -> [ColumnDefinition.ForeignKey] {
+        try connection.prepareRowIterator("PRAGMA foreign_key_list(\(table.quote()))")
+            .map { row in
+                ColumnDefinition.ForeignKey(
+                    table: row[ForeignKeyListTable.tableColumn],
+                    column: row[ForeignKeyListTable.fromColumn],
+                    primaryKey: row[ForeignKeyListTable.toColumn],
+                    onUpdate: row[ForeignKeyListTable.onUpdateColumn] == TableBuilder.Dependency.noAction.rawValue
+                            ? nil : row[ForeignKeyListTable.onUpdateColumn],
+                    onDelete: row[ForeignKeyListTable.onDeleteColumn] == TableBuilder.Dependency.noAction.rawValue
+                            ? nil : row[ForeignKeyListTable.onDeleteColumn]
+                )
+            }
+    }
+
+    func tableDefinitions() throws -> [TableDefinition] {
+        try objectDefinitions(type: .table)
+                .map { table in
+                    TableDefinition(
+                            name: table.name,
+                            columns: try columnDefinitions(table: table.name),
+                            indexes: try indexDefinitions(table: table.name)
+                    )
+                }
+    }
+
+    private func createTableSQL(name: String) throws -> String? {
+        try (
+            objectDefinitions(name: name, type: .table) +
+            objectDefinitions(name: name, type: .table, temp: true)
+        ).compactMap(\.sql).first
+    }
+}
+
+private class SchemaTable {
+    internal static let name = Table("sqlite_schema", database: "main")
+    internal static let tempName = Table("sqlite_schema", database: "temp")
+
+    static let typeColumn = Expression<String>("type")
+    static let nameColumn = Expression<String>("name")
+    static let tableNameColumn = Expression<String>("tbl_name")
+    static let rootPageColumn = Expression<Int64?>("rootpage")
+    static let sqlColumn = Expression<String?>("sql")
+}
+
+private class TableInfoTable {
+    static let idColumn = Expression<Int64>("cid")
+    static let nameColumn = Expression<String>("name")
+    static let typeColumn = Expression<String>("type")
+    static let notNullColumn = Expression<Int64>("notnull")
+    static let defaultValueColumn = Expression<String?>("dflt_value")
+    static let primaryKeyColumn = Expression<Int64?>("pk")
+}
+
+private class IndexInfoTable {
+    // The rank of the column within the index. (0 means left-most.)
+    static let seqnoColumn = Expression<Int64>("seqno")
+    // The rank of the column within the table being indexed.
+    // A value of -1 means rowid and a value of -2 means that an expression is being used.
+    static let cidColumn = Expression<Int64>("cid")
+    // The name of the column being indexed. This columns is NULL if the column is the rowid or an expression.
+    static let nameColumn = Expression<String?>("name")
+}
+
+private class IndexListTable {
+    // A sequence number assigned to each index for internal tracking purposes.
+    static let seqColumn = Expression<Int64>("seq")
+    // The name of the index
+    static let nameColumn = Expression<String>("name")
+    // "1" if the index is UNIQUE and "0" if not.
+    static let uniqueColumn = Expression<Int64>("unique")
+    // "c" if the index was created by a CREATE INDEX statement,
+    // "u" if the index was created by a UNIQUE constraint, or
+    // "pk" if the index was created by a PRIMARY KEY constraint.
+    static let originColumn = Expression<String>("origin")
+    // "1" if the index is a partial index and "0" if not.
+    static let partialColumn = Expression<Int64>("partial")
+}
+
+private class ForeignKeyListTable {
+    static let idColumn = Expression<Int64>("id")
+    static let seqColumn = Expression<Int64>("seq")
+    static let tableColumn = Expression<String>("table")
+    static let fromColumn = Expression<String>("from")
+    static let toColumn = Expression<String>("to")
+    static let onUpdateColumn = Expression<String>("on_update")
+    static let onDeleteColumn = Expression<String>("on_delete")
+    static let matchColumn = Expression<String>("match")
+}
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index 7cb2aef3..04665f39 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -991,6 +991,15 @@ public struct RowIterator: FailableIterator {
         }
         return elements
     }
+
+    public func compactMap<T>(_ transform: (Element) throws -> T?) throws -> [T] {
+        var elements = [T]()
+        while let row = try failableNext() {
+            guard let element = try transform(row) else { continue }
+            elements.append(element)
+        }
+        return elements
+    }
 }
 
 extension Connection {
@@ -1012,6 +1021,14 @@ extension Connection {
         return RowIterator(statement: statement, columnNames: try columnNamesForQuery(query))
     }
 
+    public func prepareRowIterator(_ statement: String, bindings: Binding?...) throws -> RowIterator {
+        try prepare(statement, bindings).prepareRowIterator()
+    }
+
+    public func prepareRowIterator(_ statement: String, bindings: [Binding?]) throws -> RowIterator {
+        try prepare(statement, bindings).prepareRowIterator()
+    }
+
     private func columnNamesForQuery(_ query: QueryType) throws -> [String: Int] {
         var (columnNames, idx) = ([String: Int](), 0)
         column: for each in query.clauses.select.columns {
diff --git a/Tests/SQLiteTests/Core/ConnectionTests.swift b/Tests/SQLiteTests/Core/ConnectionTests.swift
index e9ceff08..9d623f3f 100644
--- a/Tests/SQLiteTests/Core/ConnectionTests.swift
+++ b/Tests/SQLiteTests/Core/ConnectionTests.swift
@@ -399,7 +399,7 @@ class ConnectionTests: SQLiteTestCase {
         XCTAssertEqual(1, try db.scalar("SELECT ? = ? COLLATE \"NO DIACRITIC\"", "cafe", "café") as? Int64)
     }
 
-    func test_interrupt_interruptsLongRunningQuery() throws {
+    func XXX_test_interrupt_interruptsLongRunningQuery() throws {
         let semaphore = DispatchSemaphore(value: 0)
         db.createFunction("sleep") { _ in
             DispatchQueue.global(qos: .background).async {
diff --git a/Tests/SQLiteTests/Schema/Connection+SchemaTests.swift b/Tests/SQLiteTests/Schema/Connection+SchemaTests.swift
index 6eded6b2..96300529 100644
--- a/Tests/SQLiteTests/Schema/Connection+SchemaTests.swift
+++ b/Tests/SQLiteTests/Schema/Connection+SchemaTests.swift
@@ -8,127 +8,43 @@ class ConnectionSchemaTests: SQLiteTestCase {
         try createUsersTable()
     }
 
-    func test_column_info() throws {
-        let columns = try db.columnInfo(table: "users")
-        XCTAssertEqual(columns, [
-            ColumnDefinition(name: "id",
-                             primaryKey: .init(autoIncrement: false, onConflict: nil),
-                             type: .INTEGER,
-                             nullable: true,
-                             defaultValue: .NULL,
-                             references: nil),
-            ColumnDefinition(name: "email",
-                             primaryKey: nil,
-                             type: .TEXT,
-                             nullable: false,
-                             defaultValue: .NULL,
-                             references: nil),
-            ColumnDefinition(name: "age",
-                             primaryKey: nil,
-                             type: .INTEGER,
-                             nullable: true,
-                             defaultValue: .NULL,
-                             references: nil),
-            ColumnDefinition(name: "salary",
-                             primaryKey: nil,
-                             type: .REAL,
-                             nullable: true,
-                             defaultValue: .NULL,
-                             references: nil),
-            ColumnDefinition(name: "admin",
-                             primaryKey: nil,
-                             type: .TEXT,
-                             nullable: false,
-                             defaultValue: .numericLiteral("0"),
-                             references: nil),
-            ColumnDefinition(name: "manager_id",
-                             primaryKey: nil, type: .INTEGER,
-                             nullable: true,
-                             defaultValue: .NULL,
-                             references: .init(table: "users", column: "manager_id", primaryKey: "id", onUpdate: nil, onDelete: nil)),
-            ColumnDefinition(name: "created_at",
-                             primaryKey: nil,
-                             type: .TEXT,
-                             nullable: true,
-                             defaultValue: .NULL,
-                             references: nil)
-        ])
+    func test_foreignKeyCheck() throws {
+        let errors = try db.foreignKeyCheck()
+        XCTAssert(errors.isEmpty)
     }
 
-    func test_column_info_parses_conflict_modifier() throws {
-        try db.run("CREATE TABLE t (\"id\" INTEGER PRIMARY KEY ON CONFLICT IGNORE AUTOINCREMENT)")
-
-        XCTAssertEqual(
-            try db.columnInfo(table: "t"), [
-            ColumnDefinition(
-                name: "id",
-                primaryKey: .init(autoIncrement: true, onConflict: .IGNORE),
-                type: .INTEGER,
-                nullable: true,
-                defaultValue: .NULL,
-                references: nil)
-            ]
-        )
+    func test_foreignKeyCheck_with_table() throws {
+        let errors = try db.foreignKeyCheck(table: "users")
+        XCTAssert(errors.isEmpty)
     }
 
-    func test_column_info_detects_missing_autoincrement() throws {
-        try db.run("CREATE TABLE t (\"id\" INTEGER PRIMARY KEY)")
-
-        XCTAssertEqual(
-            try db.columnInfo(table: "t"), [
-            ColumnDefinition(
-                    name: "id",
-                    primaryKey: .init(autoIncrement: false),
-                    type: .INTEGER,
-                    nullable: true,
-                    defaultValue: .NULL,
-                    references: nil)
-            ]
-        )
+    func test_foreignKeyCheck_table_not_found() throws {
+        XCTAssertThrowsError(try db.foreignKeyCheck(table: "xxx")) { error in
+            guard case Result.error(let message, _, _) = error else {
+                assertionFailure("invalid error type")
+                return
+            }
+            XCTAssertEqual(message, "no such table: xxx")
+        }
     }
 
-    func test_index_info_no_index() throws {
-        let indexes = try db.indexInfo(table: "users")
-        XCTAssertTrue(indexes.isEmpty)
+    func test_integrityCheck_global() throws {
+        let results = try db.integrityCheck()
+        XCTAssert(results.isEmpty)
     }
 
-    func test_index_info_with_index() throws {
-        try db.run("CREATE UNIQUE INDEX index_users ON users (age DESC) WHERE age IS NOT NULL")
-        let indexes = try db.indexInfo(table: "users")
-
-        XCTAssertEqual(indexes, [
-            IndexDefinition(
-                table: "users",
-                name: "index_users",
-                unique: true,
-                columns: ["age"],
-                where: "age IS NOT NULL",
-                orders: ["age": .DESC]
-            )
-        ])
+    func test_integrityCheck_table() throws {
+        let results = try db.integrityCheck(table: "users")
+        XCTAssert(results.isEmpty)
     }
 
-    func test_foreign_key_info_empty() throws {
-        try db.run("CREATE TABLE t (\"id\" INTEGER PRIMARY KEY)")
-
-        let foreignKeys = try db.foreignKeyInfo(table: "t")
-        XCTAssertTrue(foreignKeys.isEmpty)
-    }
-
-    func test_foreign_key_info() throws {
-        let linkTable = Table("test_links")
-
-        let idColumn = SQLite.Expression<Int64>("id")
-        let testIdColumn = SQLite.Expression<Int64>("test_id")
-
-        try db.run(linkTable.create(block: { definition in
-            definition.column(idColumn, primaryKey: .autoincrement)
-            definition.column(testIdColumn, unique: false, check: nil, references: users, Expression<Int64>("id"))
-        }))
-
-        let foreignKeys = try db.foreignKeyInfo(table: "test_links")
-        XCTAssertEqual(foreignKeys, [
-            .init(table: "users", column: "test_id", primaryKey: "id", onUpdate: nil, onDelete: nil)
-        ])
+    func test_integrityCheck_table_not_found() throws {
+        XCTAssertThrowsError(try db.integrityCheck(table: "xxx")) { error in
+            guard case Result.error(let message, _, _) = error else {
+                assertionFailure("invalid error type")
+                return
+            }
+            XCTAssertEqual(message, "no such table: xxx")
+        }
     }
 }
diff --git a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
index 738588fd..af8b6565 100644
--- a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
@@ -3,6 +3,7 @@ import XCTest
 
 class SchemaChangerTests: SQLiteTestCase {
     var schemaChanger: SchemaChanger!
+    var schemaReader: SchemaReader!
 
     override func setUpWithError() throws {
         try super.setUpWithError()
@@ -10,32 +11,33 @@ class SchemaChangerTests: SQLiteTestCase {
 
         try insertUsers("bob")
 
+        schemaReader = SchemaReader(connection: db)
         schemaChanger = SchemaChanger(connection: db)
     }
 
     func test_empty_migration_does_not_change_column_definitions() throws {
-        let previous = try db.columnInfo(table: "users")
+        let previous = try schemaReader.columnDefinitions(table: "users")
         try schemaChanger.alter(table: "users") { _ in
         }
-        let current = try db.columnInfo(table: "users")
+        let current = try schemaReader.columnDefinitions(table: "users")
 
         XCTAssertEqual(previous, current)
     }
 
     func test_empty_migration_does_not_change_index_definitions() throws {
-        let previous = try db.indexInfo(table: "users")
+        let previous = try schemaReader.indexDefinitions(table: "users")
         try schemaChanger.alter(table: "users") { _ in
         }
-        let current = try db.indexInfo(table: "users")
+        let current = try schemaReader.indexDefinitions(table: "users")
 
         XCTAssertEqual(previous, current)
     }
 
     func test_empty_migration_does_not_change_foreign_key_definitions() throws {
-        let previous = try db.foreignKeyInfo(table: "users")
+        let previous = try schemaReader.foreignKeys(table: "users")
         try schemaChanger.alter(table: "users") { _ in
         }
-        let current = try db.foreignKeyInfo(table: "users")
+        let current = try schemaReader.foreignKeys(table: "users")
 
         XCTAssertEqual(previous, current)
     }
@@ -53,7 +55,7 @@ class SchemaChangerTests: SQLiteTestCase {
         try schemaChanger.alter(table: "users") { table in
             table.remove("age")
         }
-        let columns = try db.columnInfo(table: "users").map(\.name)
+        let columns = try schemaReader.columnDefinitions(table: "users").map(\.name)
         XCTAssertFalse(columns.contains("age"))
     }
 
@@ -63,7 +65,7 @@ class SchemaChangerTests: SQLiteTestCase {
         try schemaChanger.alter(table: "users") { table in
             table.remove("age")
         }
-        let columns = try db.columnInfo(table: "users").map(\.name)
+        let columns = try schemaReader.columnDefinitions(table: "users").map(\.name)
         XCTAssertFalse(columns.contains("age"))
     }
 
@@ -72,7 +74,7 @@ class SchemaChangerTests: SQLiteTestCase {
             table.rename("age", to: "age2")
         }
 
-        let columns = try db.columnInfo(table: "users").map(\.name)
+        let columns = try schemaReader.columnDefinitions(table: "users").map(\.name)
         XCTAssertFalse(columns.contains("age"))
         XCTAssertTrue(columns.contains("age2"))
     }
@@ -84,7 +86,7 @@ class SchemaChangerTests: SQLiteTestCase {
             table.rename("age", to: "age2")
         }
 
-        let columns = try db.columnInfo(table: "users").map(\.name)
+        let columns = try schemaReader.columnDefinitions(table: "users").map(\.name)
         XCTAssertFalse(columns.contains("age"))
         XCTAssertTrue(columns.contains("age2"))
     }
@@ -100,7 +102,7 @@ class SchemaChangerTests: SQLiteTestCase {
             table.add(newColumn)
         }
 
-        let columns = try db.columnInfo(table: "users")
+        let columns = try schemaReader.columnDefinitions(table: "users")
         XCTAssertTrue(columns.contains(newColumn))
 
         XCTAssertEqual(try db.pluck(users.select(column))?[column], "foo")
diff --git a/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift b/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
index 75321440..384aab3f 100644
--- a/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
@@ -5,37 +5,38 @@ class ColumnDefinitionTests: XCTestCase {
     var definition: ColumnDefinition!
     var expected: String!
 
-    static let definitions: [(ColumnDefinition, String)] = [
-        (ColumnDefinition(name: "id", primaryKey: .init(), type: .INTEGER, nullable: false, defaultValue: .NULL, references: nil),
-        "\"id\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL"),
+    static let definitions: [(String, ColumnDefinition)] = [
+        ("\"id\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL",
+        ColumnDefinition(name: "id", primaryKey: .init(), type: .INTEGER, nullable: false, defaultValue: .NULL, references: nil)),
 
-        (ColumnDefinition(name: "other_id", primaryKey: nil, type: .INTEGER, nullable: false, defaultValue: .NULL,
-                          references: .init(table: "other_table", column: "", primaryKey: "some_id", onUpdate: nil, onDelete: nil)),
-        "\"other_id\" INTEGER NOT NULL REFERENCES \"other_table\" (\"some_id\")"),
+        ("\"other_id\" INTEGER NOT NULL REFERENCES \"other_table\" (\"some_id\")",
+        ColumnDefinition(name: "other_id", primaryKey: nil, type: .INTEGER, nullable: false, defaultValue: .NULL,
+                         references: .init(table: "other_table", column: "", primaryKey: "some_id", onUpdate: nil, onDelete: nil))),
 
-        (ColumnDefinition(name: "text", primaryKey: nil, type: .TEXT, nullable: true, defaultValue: .NULL, references: nil),
-        "\"text\" TEXT"),
+        ("\"text\" TEXT",
+        ColumnDefinition(name: "text", primaryKey: nil, type: .TEXT, nullable: true, defaultValue: .NULL, references: nil)),
 
-        (ColumnDefinition(name: "text", primaryKey: nil, type: .TEXT, nullable: false, defaultValue: .NULL, references: nil),
-        "\"text\" TEXT NOT NULL"),
+        ("\"text\" TEXT NOT NULL",
+        ColumnDefinition(name: "text", primaryKey: nil, type: .TEXT, nullable: false, defaultValue: .NULL, references: nil)),
 
-        (ColumnDefinition(name: "text_column", primaryKey: nil, type: .TEXT, nullable: true, defaultValue: .stringLiteral("fo\"o"), references: nil),
-        "\"text_column\" TEXT DEFAULT 'fo\"o'"),
+        ("\"text_column\" TEXT DEFAULT 'fo\"o'",
+        ColumnDefinition(name: "text_column", primaryKey: nil, type: .TEXT, nullable: true,
+        defaultValue: .stringLiteral("fo\"o"), references: nil)),
 
-        (ColumnDefinition(name: "integer_column", primaryKey: nil, type: .INTEGER, nullable: true,
-                          defaultValue: .numericLiteral("123"), references: nil),
-        "\"integer_column\" INTEGER DEFAULT 123"),
+        ("\"integer_column\" INTEGER DEFAULT 123",
+        ColumnDefinition(name: "integer_column", primaryKey: nil, type: .INTEGER, nullable: true,
+                          defaultValue: .numericLiteral("123"), references: nil)),
 
-        (ColumnDefinition(name: "real_column", primaryKey: nil, type: .REAL, nullable: true,
-                          defaultValue: .numericLiteral("123.123"), references: nil),
-        "\"real_column\" REAL DEFAULT 123.123")
+        ("\"real_column\" REAL DEFAULT 123.123",
+        ColumnDefinition(name: "real_column", primaryKey: nil, type: .REAL, nullable: true,
+                          defaultValue: .numericLiteral("123.123"), references: nil))
     ]
 
     #if !os(Linux)
     override class var defaultTestSuite: XCTestSuite {
         let suite = XCTestSuite(forTestCaseClass: ColumnDefinitionTests.self)
 
-        for (column, expected) in ColumnDefinitionTests.definitions {
+        for (expected, column) in ColumnDefinitionTests.definitions {
             let test = ColumnDefinitionTests(selector: #selector(verify))
             test.definition = column
             test.expected = expected
@@ -51,14 +52,17 @@ class ColumnDefinitionTests: XCTestCase {
 }
 
 class AffinityTests: XCTestCase {
-    func test_from() {
-        XCTAssertEqual(ColumnDefinition.Affinity.from("TEXT"), .TEXT)
-        XCTAssertEqual(ColumnDefinition.Affinity.from("text"), .TEXT)
-        XCTAssertEqual(ColumnDefinition.Affinity.from("INTEGER"), .INTEGER)
+    func test_init() {
+        XCTAssertEqual(ColumnDefinition.Affinity("TEXT"), .TEXT)
+        XCTAssertEqual(ColumnDefinition.Affinity("text"), .TEXT)
+        XCTAssertEqual(ColumnDefinition.Affinity("INTEGER"), .INTEGER)
+        XCTAssertEqual(ColumnDefinition.Affinity("BLOB"), .BLOB)
+        XCTAssertEqual(ColumnDefinition.Affinity("REAL"), .REAL)
+        XCTAssertEqual(ColumnDefinition.Affinity("NUMERIC"), .NUMERIC)
     }
 
     func test_returns_TEXT_for_unknown_type() {
-        XCTAssertEqual(ColumnDefinition.Affinity.from("baz"), .TEXT)
+        XCTAssertEqual(ColumnDefinition.Affinity("baz"), .TEXT)
     }
 }
 
@@ -215,13 +219,6 @@ class TableDefinitionTests: XCTestCase {
                                                           """)
     }
 
-    /*
-    func test_throws_an_error_when_columns_are_empty() {
-        let empty = TableDefinition(name: "empty", columns: [], indexes: [])
-        XCTAssertThrowsError(empty.toSQL())
-    }
-     */
-
     func test_copySQL() {
         let from = TableDefinition(name: "from_table", columns: [
             ColumnDefinition(name: "id", primaryKey: .init(), type: .INTEGER, nullable: false, defaultValue: .NULL, references: nil)
@@ -239,74 +236,105 @@ class TableDefinitionTests: XCTestCase {
 
 class PrimaryKeyTests: XCTestCase {
     func test_toSQL() {
-        XCTAssertEqual(ColumnDefinition.PrimaryKey(autoIncrement: false).toSQL(),
-                       "PRIMARY KEY")
+        XCTAssertEqual(
+            ColumnDefinition.PrimaryKey(autoIncrement: false).toSQL(),
+            "PRIMARY KEY"
+        )
     }
 
     func test_toSQL_autoincrement() {
-        XCTAssertEqual(ColumnDefinition.PrimaryKey(autoIncrement: true).toSQL(),
-                       "PRIMARY KEY AUTOINCREMENT")
+        XCTAssertEqual(
+            ColumnDefinition.PrimaryKey(autoIncrement: true).toSQL(),
+            "PRIMARY KEY AUTOINCREMENT"
+        )
     }
 
     func test_toSQL_on_conflict() {
-        XCTAssertEqual(ColumnDefinition.PrimaryKey(autoIncrement: false, onConflict: .ROLLBACK).toSQL(),
-                       "PRIMARY KEY ON CONFLICT ROLLBACK")
+        XCTAssertEqual(
+            ColumnDefinition.PrimaryKey(autoIncrement: false, onConflict: .ROLLBACK).toSQL(),
+            "PRIMARY KEY ON CONFLICT ROLLBACK"
+        )
+    }
+
+    func test_fromSQL() {
+        XCTAssertEqual(
+            ColumnDefinition.PrimaryKey(sql: "PRIMARY KEY"),
+            ColumnDefinition.PrimaryKey(autoIncrement: false)
+        )
+    }
+
+    func test_fromSQL_invalid_sql_is_nil() {
+        XCTAssertNil(ColumnDefinition.PrimaryKey(sql: "FOO"))
+    }
+
+    func test_fromSQL_autoincrement() {
+        XCTAssertEqual(
+            ColumnDefinition.PrimaryKey(sql: "PRIMARY KEY AUTOINCREMENT"),
+            ColumnDefinition.PrimaryKey(autoIncrement: true)
+        )
+    }
+
+    func test_fromSQL_on_conflict() {
+        XCTAssertEqual(
+            ColumnDefinition.PrimaryKey(sql: "PRIMARY KEY ON CONFLICT ROLLBACK"),
+            ColumnDefinition.PrimaryKey(autoIncrement: false, onConflict: .ROLLBACK)
+        )
     }
 }
 
 class LiteralValueTests: XCTestCase {
     func test_recognizes_TRUE() {
-        XCTAssertEqual(LiteralValue.from("TRUE"), .TRUE)
+        XCTAssertEqual(LiteralValue("TRUE"), .TRUE)
     }
 
     func test_recognizes_FALSE() {
-        XCTAssertEqual(LiteralValue.from("FALSE"), .FALSE)
+        XCTAssertEqual(LiteralValue("FALSE"), .FALSE)
     }
 
     func test_recognizes_NULL() {
-        XCTAssertEqual(LiteralValue.from("NULL"), .NULL)
+        XCTAssertEqual(LiteralValue("NULL"), .NULL)
     }
 
     func test_recognizes_nil() {
-        XCTAssertEqual(LiteralValue.from(nil), .NULL)
+        XCTAssertEqual(LiteralValue(nil), .NULL)
     }
 
     func test_recognizes_CURRENT_TIME() {
-        XCTAssertEqual(LiteralValue.from("CURRENT_TIME"), .CURRENT_TIME)
+        XCTAssertEqual(LiteralValue("CURRENT_TIME"), .CURRENT_TIME)
     }
 
     func test_recognizes_CURRENT_TIMESTAMP() {
-        XCTAssertEqual(LiteralValue.from("CURRENT_TIMESTAMP"), .CURRENT_TIMESTAMP)
+        XCTAssertEqual(LiteralValue("CURRENT_TIMESTAMP"), .CURRENT_TIMESTAMP)
     }
 
     func test_recognizes_CURRENT_DATE() {
-        XCTAssertEqual(LiteralValue.from("CURRENT_DATE"), .CURRENT_DATE)
+        XCTAssertEqual(LiteralValue("CURRENT_DATE"), .CURRENT_DATE)
     }
 
     func test_recognizes_double_quote_string_literals() {
-        XCTAssertEqual(LiteralValue.from("\"foo\""), .stringLiteral("foo"))
+        XCTAssertEqual(LiteralValue("\"foo\""), .stringLiteral("foo"))
     }
 
     func test_recognizes_single_quote_string_literals() {
-        XCTAssertEqual(LiteralValue.from("\'foo\'"), .stringLiteral("foo"))
+        XCTAssertEqual(LiteralValue("\'foo\'"), .stringLiteral("foo"))
     }
 
     func test_unquotes_double_quote_string_literals() {
-        XCTAssertEqual(LiteralValue.from("\"fo\"\"o\""), .stringLiteral("fo\"o"))
+        XCTAssertEqual(LiteralValue("\"fo\"\"o\""), .stringLiteral("fo\"o"))
     }
 
     func test_unquotes_single_quote_string_literals() {
-        XCTAssertEqual(LiteralValue.from("'fo''o'"), .stringLiteral("fo'o"))
+        XCTAssertEqual(LiteralValue("'fo''o'"), .stringLiteral("fo'o"))
     }
 
     func test_recognizes_numeric_literals() {
-        XCTAssertEqual(LiteralValue.from("1.2"), .numericLiteral("1.2"))
-        XCTAssertEqual(LiteralValue.from("0xdeadbeef"), .numericLiteral("0xdeadbeef"))
+        XCTAssertEqual(LiteralValue("1.2"), .numericLiteral("1.2"))
+        XCTAssertEqual(LiteralValue("0xdeadbeef"), .numericLiteral("0xdeadbeef"))
     }
 
     func test_recognizes_blob_literals() {
-        XCTAssertEqual(LiteralValue.from("X'deadbeef'"), .blobLiteral("deadbeef"))
-        XCTAssertEqual(LiteralValue.from("x'deadbeef'"), .blobLiteral("deadbeef"))
+        XCTAssertEqual(LiteralValue("X'deadbeef'"), .blobLiteral("deadbeef"))
+        XCTAssertEqual(LiteralValue("x'deadbeef'"), .blobLiteral("deadbeef"))
     }
 
     func test_description_TRUE() {
diff --git a/Tests/SQLiteTests/Schema/SchemaReaderTests.swift b/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
new file mode 100644
index 00000000..165dbc28
--- /dev/null
+++ b/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
@@ -0,0 +1,180 @@
+import XCTest
+@testable import SQLite
+
+class SchemaReaderTests: SQLiteTestCase {
+    private var schemaReader: SchemaReader!
+
+    override func setUpWithError() throws {
+        try super.setUpWithError()
+        try createUsersTable()
+
+        schemaReader = db.schemaReader
+    }
+
+    func test_columnDefinitions() throws {
+        let columns = try schemaReader.columnDefinitions(table: "users")
+        XCTAssertEqual(columns, [
+            ColumnDefinition(name: "id",
+                             primaryKey: .init(autoIncrement: false, onConflict: nil),
+                             type: .INTEGER,
+                             nullable: true,
+                             defaultValue: .NULL,
+                             references: nil),
+            ColumnDefinition(name: "email",
+                             primaryKey: nil,
+                             type: .TEXT,
+                             nullable: false,
+                             defaultValue: .NULL,
+                             references: nil),
+            ColumnDefinition(name: "age",
+                             primaryKey: nil,
+                             type: .INTEGER,
+                             nullable: true,
+                             defaultValue: .NULL,
+                             references: nil),
+            ColumnDefinition(name: "salary",
+                             primaryKey: nil,
+                             type: .REAL,
+                             nullable: true,
+                             defaultValue: .NULL,
+                             references: nil),
+            ColumnDefinition(name: "admin",
+                             primaryKey: nil,
+                             type: .TEXT,
+                             nullable: false,
+                             defaultValue: .numericLiteral("0"),
+                             references: nil),
+            ColumnDefinition(name: "manager_id",
+                             primaryKey: nil, type: .INTEGER,
+                             nullable: true,
+                             defaultValue: .NULL,
+                             references: .init(table: "users", column: "manager_id", primaryKey: "id", onUpdate: nil, onDelete: nil)),
+            ColumnDefinition(name: "created_at",
+                             primaryKey: nil,
+                             type: .TEXT,
+                             nullable: true,
+                             defaultValue: .NULL,
+                             references: nil)
+        ])
+    }
+
+    func test_columnDefinitions_parses_conflict_modifier() throws {
+        try db.run("CREATE TABLE t (\"id\" INTEGER PRIMARY KEY ON CONFLICT IGNORE AUTOINCREMENT)")
+
+        XCTAssertEqual(
+            try schemaReader.columnDefinitions(table: "t"), [
+            ColumnDefinition(
+                name: "id",
+                primaryKey: .init(autoIncrement: true, onConflict: .IGNORE),
+                type: .INTEGER,
+                nullable: true,
+                defaultValue: .NULL,
+                references: nil)
+            ]
+        )
+    }
+
+    func test_columnDefinitions_detects_missing_autoincrement() throws {
+        try db.run("CREATE TABLE t (\"id\" INTEGER PRIMARY KEY)")
+
+        XCTAssertEqual(
+            try schemaReader.columnDefinitions(table: "t"), [
+            ColumnDefinition(
+                    name: "id",
+                    primaryKey: .init(autoIncrement: false),
+                    type: .INTEGER,
+                    nullable: true,
+                    defaultValue: .NULL,
+                    references: nil)
+            ]
+        )
+    }
+
+    func test_indexDefinitions_no_index() throws {
+        let indexes = try schemaReader.indexDefinitions(table: "users")
+        XCTAssertTrue(indexes.isEmpty)
+    }
+
+    func test_indexDefinitions_with_index() throws {
+        try db.run("CREATE UNIQUE INDEX index_users ON users (age DESC) WHERE age IS NOT NULL")
+        let indexes = try schemaReader.indexDefinitions(table: "users")
+
+        XCTAssertEqual(indexes, [
+            IndexDefinition(
+                table: "users",
+                name: "index_users",
+                unique: true,
+                columns: ["age"],
+                where: "age IS NOT NULL",
+                orders: ["age": .DESC]
+            )
+        ])
+    }
+
+    func test_foreignKeys_info_empty() throws {
+        try db.run("CREATE TABLE t (\"id\" INTEGER PRIMARY KEY)")
+
+        let foreignKeys = try schemaReader.foreignKeys(table: "t")
+        XCTAssertTrue(foreignKeys.isEmpty)
+    }
+
+    func test_foreignKeys() throws {
+        let linkTable = Table("test_links")
+
+        let idColumn = SQLite.Expression<Int64>("id")
+        let testIdColumn = SQLite.Expression<Int64>("test_id")
+
+        try db.run(linkTable.create(block: { definition in
+            definition.column(idColumn, primaryKey: .autoincrement)
+            definition.column(testIdColumn, unique: false, check: nil, references: users, Expression<Int64>("id"))
+        }))
+
+        let foreignKeys = try schemaReader.foreignKeys(table: "test_links")
+        XCTAssertEqual(foreignKeys, [
+            .init(table: "users", column: "test_id", primaryKey: "id", onUpdate: nil, onDelete: nil)
+        ])
+    }
+
+    func test_tableDefinitions() throws {
+        let tables = try schemaReader.tableDefinitions()
+        XCTAssertEqual(tables.count, 1)
+        XCTAssertEqual(tables.first?.name, "users")
+    }
+
+    func test_objectDefinitions() throws {
+        let tables = try schemaReader.objectDefinitions()
+
+        XCTAssertEqual(tables.map { table in [table.name, table.tableName, table.type.rawValue]}, [
+            ["users", "users", "table"],
+            ["sqlite_autoindex_users_1", "sqlite_autoindex_users_1", "index"]
+        ])
+    }
+
+    func test_objectDefinitions_temporary() throws {
+        let tables = try schemaReader.objectDefinitions(temp: true)
+        XCTAssert(tables.isEmpty)
+
+        try db.run("CREATE TEMPORARY TABLE foo (bar TEXT)")
+
+        let tables2 = try schemaReader.objectDefinitions(temp: true)
+        XCTAssertEqual(tables2.map { table in [table.name, table.tableName, table.type.rawValue]}, [
+            ["foo", "foo", "table"]
+        ])
+    }
+
+    func test_objectDefinitionsFilterByType() throws {
+        let tables = try schemaReader.objectDefinitions(type: .table)
+
+        XCTAssertEqual(tables.map { table in [table.name, table.tableName, table.type.rawValue]}, [
+            ["users", "users", "table"]
+        ])
+    }
+
+    func test_objectDefinitionsFilterByName() throws {
+        let tables = try schemaReader.objectDefinitions(name: "users")
+
+        XCTAssertEqual(tables.map { table in [table.name, table.tableName, table.type.rawValue]}, [
+            ["users", "users", "table"]
+        ])
+    }
+}

From 2fc0decf41a26787c4d3b2b23ef07786b44f801b Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 16 Oct 2022 19:54:06 +0200
Subject: [PATCH 556/685] Fix tests on older version of SQLite

---
 .swiftlint.yml                                |  1 +
 SQLite.xcodeproj/project.pbxproj              | 10 +++++++
 Sources/SQLite/Core/SQLiteFeature.swift       | 19 ++++++++++++++
 Sources/SQLite/Schema/Connection+Schema.swift |  6 +++--
 Sources/SQLite/Schema/SchemaReader.swift      | 26 ++++++++++++++-----
 .../Schema/Connection+SchemaTests.swift       |  4 ++-
 6 files changed, 57 insertions(+), 9 deletions(-)
 create mode 100644 Sources/SQLite/Core/SQLiteFeature.swift

diff --git a/.swiftlint.yml b/.swiftlint.yml
index 34bb253b..d40be28e 100644
--- a/.swiftlint.yml
+++ b/.swiftlint.yml
@@ -3,6 +3,7 @@ disabled_rules: # rule identifiers to exclude from running
   - operator_whitespace
   - large_tuple
   - closure_parameter_position
+  - inclusive_language  # sqlite_master etc.
 included: # paths to include during linting. `--path` is ignored if present. takes precendence over `excluded`.
   - Sources
   - Tests
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index a58e0887..6fe89283 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -203,6 +203,10 @@
 		DB58B21228FB864300F8EEA4 /* SchemaReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB58B21028FB864300F8EEA4 /* SchemaReader.swift */; };
 		DB58B21328FB864300F8EEA4 /* SchemaReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB58B21028FB864300F8EEA4 /* SchemaReader.swift */; };
 		DB58B21428FB864300F8EEA4 /* SchemaReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB58B21028FB864300F8EEA4 /* SchemaReader.swift */; };
+		DB58B21628FC7C4600F8EEA4 /* SQLiteFeature.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB58B21528FC7C4600F8EEA4 /* SQLiteFeature.swift */; };
+		DB58B21728FC7C4600F8EEA4 /* SQLiteFeature.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB58B21528FC7C4600F8EEA4 /* SQLiteFeature.swift */; };
+		DB58B21828FC7C4600F8EEA4 /* SQLiteFeature.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB58B21528FC7C4600F8EEA4 /* SQLiteFeature.swift */; };
+		DB58B21928FC7C4600F8EEA4 /* SQLiteFeature.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB58B21528FC7C4600F8EEA4 /* SQLiteFeature.swift */; };
 		DB7C5DA628D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
 		DB7C5DA728D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
 		DB7C5DA828D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
@@ -334,6 +338,7 @@
 		997DF2AD287FC06D00F8DF95 /* Query+with.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Query+with.swift"; sourceTree = "<group>"; };
 		A121AC451CA35C79005A31D1 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		DB58B21028FB864300F8EEA4 /* SchemaReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaReader.swift; sourceTree = "<group>"; };
+		DB58B21528FC7C4600F8EEA4 /* SQLiteFeature.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SQLiteFeature.swift; sourceTree = "<group>"; };
 		DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SQLiteVersion.swift; sourceTree = "<group>"; };
 		EE247AD31C3F04ED00AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AD61C3F04ED00AE3E12 /* SQLite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLite.h; sourceTree = "<group>"; };
@@ -580,6 +585,7 @@
 				19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */,
 				3DF7B78728842972005DD8CA /* Connection+Attach.swift */,
 				3DF7B790288449BA005DD8CA /* URIQueryParameter.swift */,
+				DB58B21528FC7C4600F8EEA4 /* SQLiteFeature.swift */,
 				DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */,
 				19A17F285B767BFACD96714B /* Connection+Pragmas.swift */,
 			);
@@ -970,6 +976,7 @@
 				19A17073552293CA063BEA66 /* Result.swift in Sources */,
 				997DF2B0287FC06D00F8DF95 /* Query+with.swift in Sources */,
 				19A179B59450FE7C4811AB8A /* Connection+Aggregation.swift in Sources */,
+				DB58B21828FC7C4600F8EEA4 /* SQLiteFeature.swift in Sources */,
 				19A17FC07731779C1B8506FA /* SchemaChanger.swift in Sources */,
 				19A1740EACD47904AA24B8DC /* SchemaDefinitions.swift in Sources */,
 				19A1750EF4A5F92954A451FF /* Connection+Schema.swift in Sources */,
@@ -1030,6 +1037,7 @@
 				DB7C5DA928D7C9B6006395CF /* SQLiteVersion.swift in Sources */,
 				3D67B3EA1DB246D100A4F4C6 /* Value.swift in Sources */,
 				3D67B3EB1DB246D100A4F4C6 /* FTS4.swift in Sources */,
+				DB58B21928FC7C4600F8EEA4 /* SQLiteFeature.swift in Sources */,
 				3D67B3EC1DB246D100A4F4C6 /* RTree.swift in Sources */,
 				3D67B3ED1DB246D100A4F4C6 /* FTS5.swift in Sources */,
 				3D67B3EE1DB246D100A4F4C6 /* AggregateFunctions.swift in Sources */,
@@ -1089,6 +1097,7 @@
 				19A173EFEF0B3BD0B3ED406C /* Result.swift in Sources */,
 				997DF2AE287FC06D00F8DF95 /* Query+with.swift in Sources */,
 				19A176376CB6A94759F7980A /* Connection+Aggregation.swift in Sources */,
+				DB58B21628FC7C4600F8EEA4 /* SQLiteFeature.swift in Sources */,
 				19A1773A335CAB9D0AE14E8E /* SchemaChanger.swift in Sources */,
 				19A17BA13FD35F058787B7D3 /* SchemaDefinitions.swift in Sources */,
 				19A174506543905D71BF0518 /* Connection+Schema.swift in Sources */,
@@ -1168,6 +1177,7 @@
 				19A17F1B3F0A3C96B5ED6D64 /* Result.swift in Sources */,
 				997DF2AF287FC06D00F8DF95 /* Query+with.swift in Sources */,
 				19A170ACC97B19730FB7BA4D /* Connection+Aggregation.swift in Sources */,
+				DB58B21728FC7C4600F8EEA4 /* SQLiteFeature.swift in Sources */,
 				19A177290558991BCC60E4E3 /* SchemaChanger.swift in Sources */,
 				19A17B0DF1DDB6BBC9C95D64 /* SchemaDefinitions.swift in Sources */,
 				19A17F0BF02896E1664F4090 /* Connection+Schema.swift in Sources */,
diff --git a/Sources/SQLite/Core/SQLiteFeature.swift b/Sources/SQLite/Core/SQLiteFeature.swift
new file mode 100644
index 00000000..36b5b31b
--- /dev/null
+++ b/Sources/SQLite/Core/SQLiteFeature.swift
@@ -0,0 +1,19 @@
+import Foundation
+
+enum SQLiteFeature {
+    case partialIntegrityCheck      // PRAGMA integrity_check(table)
+    case sqliteSchemaTable          // sqlite_master => sqlite_schema
+
+    func isSupported(by version: SQLiteVersion) -> Bool {
+        switch self {
+        case .partialIntegrityCheck, .sqliteSchemaTable:
+            return version > SQLiteVersion(major: 3, minor: 33)
+        }
+    }
+}
+
+extension Connection {
+    func supports(_ feature: SQLiteFeature) -> Bool {
+        feature.isSupported(by: sqliteVersion)
+    }
+}
diff --git a/Sources/SQLite/Schema/Connection+Schema.swift b/Sources/SQLite/Schema/Connection+Schema.swift
index 868b40d5..d36812eb 100644
--- a/Sources/SQLite/Schema/Connection+Schema.swift
+++ b/Sources/SQLite/Schema/Connection+Schema.swift
@@ -25,8 +25,10 @@ public extension Connection {
 
     // This pragma does a low-level formatting and consistency check of the database.
     // https://sqlite.org/pragma.html#pragma_integrity_check
-    func integrityCheck(table: String? = nil, maxErrors: Int? = nil) throws -> [String] {
-        try run("PRAGMA integrity_check" + (table.map { "(\($0.quote()))" } ?? ""))
+    func integrityCheck(table: String? = nil) throws -> [String] {
+        precondition(table == nil || supports(.partialIntegrityCheck), "partial integrity check not supported")
+
+        return try run("PRAGMA integrity_check" + (table.map { "(\($0.quote()))" } ?? ""))
             .compactMap { $0[0] as? String }
             .filter { $0 != "ok" }
     }
diff --git a/Sources/SQLite/Schema/SchemaReader.swift b/Sources/SQLite/Schema/SchemaReader.swift
index 3f02eeae..bfa2e887 100644
--- a/Sources/SQLite/Schema/SchemaReader.swift
+++ b/Sources/SQLite/Schema/SchemaReader.swift
@@ -38,7 +38,7 @@ public class SchemaReader {
     public func objectDefinitions(name: String? = nil,
                                   type: ObjectDefinition.ObjectType? = nil,
                                   temp: Bool = false) throws -> [ObjectDefinition] {
-        var query: QueryType = temp ? SchemaTable.tempName : SchemaTable.name
+        var query: QueryType = connection.schemaTable(temp: temp)
         if let name = name {
             query = query.where(SchemaTable.nameColumn == name)
         }
@@ -99,9 +99,9 @@ public class SchemaReader {
                     column: row[ForeignKeyListTable.fromColumn],
                     primaryKey: row[ForeignKeyListTable.toColumn],
                     onUpdate: row[ForeignKeyListTable.onUpdateColumn] == TableBuilder.Dependency.noAction.rawValue
-                            ? nil : row[ForeignKeyListTable.onUpdateColumn],
+                        ? nil : row[ForeignKeyListTable.onUpdateColumn],
                     onDelete: row[ForeignKeyListTable.onDeleteColumn] == TableBuilder.Dependency.noAction.rawValue
-                            ? nil : row[ForeignKeyListTable.onDeleteColumn]
+                        ? nil : row[ForeignKeyListTable.onDeleteColumn]
                 )
             }
     }
@@ -110,9 +110,9 @@ public class SchemaReader {
         try objectDefinitions(type: .table)
                 .map { table in
                     TableDefinition(
-                            name: table.name,
-                            columns: try columnDefinitions(table: table.name),
-                            indexes: try indexDefinitions(table: table.name)
+                        name: table.name,
+                        columns: try columnDefinitions(table: table.name),
+                        indexes: try indexDefinitions(table: table.name)
                     )
                 }
     }
@@ -129,6 +129,10 @@ private class SchemaTable {
     internal static let name = Table("sqlite_schema", database: "main")
     internal static let tempName = Table("sqlite_schema", database: "temp")
 
+    // legacy table names
+    internal static let masterName = Table("sqlite_master")
+    internal static let tempMasterName = Table("sqlite_temp_master")
+
     static let typeColumn = Expression<String>("type")
     static let nameColumn = Expression<String>("name")
     static let tableNameColumn = Expression<String>("tbl_name")
@@ -180,3 +184,13 @@ private class ForeignKeyListTable {
     static let onDeleteColumn = Expression<String>("on_delete")
     static let matchColumn = Expression<String>("match")
 }
+
+private extension Connection {
+    func schemaTable(temp: Bool = false) -> Table {
+        if supports(.sqliteSchemaTable) {
+            return temp ? SchemaTable.tempName : SchemaTable.name
+        } else {
+            return temp ? SchemaTable.tempMasterName : SchemaTable.masterName
+        }
+    }
+}
diff --git a/Tests/SQLiteTests/Schema/Connection+SchemaTests.swift b/Tests/SQLiteTests/Schema/Connection+SchemaTests.swift
index 96300529..57e2726b 100644
--- a/Tests/SQLiteTests/Schema/Connection+SchemaTests.swift
+++ b/Tests/SQLiteTests/Schema/Connection+SchemaTests.swift
@@ -33,12 +33,14 @@ class ConnectionSchemaTests: SQLiteTestCase {
         XCTAssert(results.isEmpty)
     }
 
-    func test_integrityCheck_table() throws {
+    func test_partial_integrityCheck_table() throws {
+        guard db.supports(.partialIntegrityCheck) else { return }
         let results = try db.integrityCheck(table: "users")
         XCTAssert(results.isEmpty)
     }
 
     func test_integrityCheck_table_not_found() throws {
+        guard db.supports(.partialIntegrityCheck) else { return }
         XCTAssertThrowsError(try db.integrityCheck(table: "xxx")) { error in
             guard case Result.error(let message, _, _) = error else {
                 assertionFailure("invalid error type")

From a6a151b3395c83f845d6d88d7d7565df824ef239 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 16 Oct 2022 20:57:25 +0200
Subject: [PATCH 557/685] Reuse SQLiteFeature in SchemaChanger

---
 Sources/SQLite/Core/SQLiteFeature.swift       |  8 +++-
 Sources/SQLite/Schema/Connection+Schema.swift |  4 +-
 Sources/SQLite/Schema/SchemaChanger.swift     |  6 +--
 Sources/SQLite/Schema/SchemaDefinitions.swift |  5 ++-
 Sources/SQLite/Schema/SchemaReader.swift      | 40 +++++++++----------
 .../Schema/SchemaReaderTests.swift            |  4 +-
 6 files changed, 37 insertions(+), 30 deletions(-)

diff --git a/Sources/SQLite/Core/SQLiteFeature.swift b/Sources/SQLite/Core/SQLiteFeature.swift
index 36b5b31b..50d910a3 100644
--- a/Sources/SQLite/Core/SQLiteFeature.swift
+++ b/Sources/SQLite/Core/SQLiteFeature.swift
@@ -3,11 +3,17 @@ import Foundation
 enum SQLiteFeature {
     case partialIntegrityCheck      // PRAGMA integrity_check(table)
     case sqliteSchemaTable          // sqlite_master => sqlite_schema
+    case renameColumn               // ALTER TABLE ... RENAME COLUMN
+    case dropColumn                 // ALTER TABLE ... DROP COLUMN
 
     func isSupported(by version: SQLiteVersion) -> Bool {
         switch self {
         case .partialIntegrityCheck, .sqliteSchemaTable:
-            return version > SQLiteVersion(major: 3, minor: 33)
+            return version >= .init(major: 3, minor: 33)
+        case .renameColumn:
+            return version >= .init(major: 3, minor: 25)
+        case .dropColumn:
+            return version >= .init(major: 3, minor: 35)
         }
     }
 }
diff --git a/Sources/SQLite/Schema/Connection+Schema.swift b/Sources/SQLite/Schema/Connection+Schema.swift
index d36812eb..2977af17 100644
--- a/Sources/SQLite/Schema/Connection+Schema.swift
+++ b/Sources/SQLite/Schema/Connection+Schema.swift
@@ -1,7 +1,7 @@
 import Foundation
 
 public extension Connection {
-    var schemaReader: SchemaReader { SchemaReader(connection: self) }
+    var schema: SchemaReader { SchemaReader(connection: self) }
 
     // There are four columns in each result row.
     // The first column is the name of the table that
@@ -14,7 +14,7 @@ public extension Connection {
     // https://sqlite.org/pragma.html#pragma_foreign_key_check
     func foreignKeyCheck(table: String? = nil) throws -> [ForeignKeyError] {
         try run("PRAGMA foreign_key_check" + (table.map { "(\($0.quote()))" } ?? ""))
-            .compactMap { row -> ForeignKeyError? in
+            .compactMap { (row: [Binding?]) -> ForeignKeyError? in
                 guard let table = row[0] as? String,
                       let rowId = row[1] as? Int64,
                       let target = row[2] as? String else { return nil }
diff --git a/Sources/SQLite/Schema/SchemaChanger.swift b/Sources/SQLite/Schema/SchemaChanger.swift
index b557da0a..4e1b42c5 100644
--- a/Sources/SQLite/Schema/SchemaChanger.swift
+++ b/Sources/SQLite/Schema/SchemaChanger.swift
@@ -52,9 +52,9 @@ public class SchemaChanger: CustomStringConvertible {
             switch self {
             case .addColumn(let definition):
                 return "ALTER TABLE \(table.quote()) ADD COLUMN \(definition.toSQL())"
-            case .renameColumn(let from, let to) where version >= .init(major: 3, minor: 25):
+            case .renameColumn(let from, let to) where SQLiteFeature.renameColumn.isSupported(by: version):
                 return "ALTER TABLE \(table.quote()) RENAME COLUMN \(from.quote()) TO \(to.quote())"
-            case .dropColumn(let column) where version >= .init(major: 3, minor: 35):
+            case .dropColumn(let column) where SQLiteFeature.dropColumn.isSupported(by: version):
                 return "ALTER TABLE \(table.quote()) DROP COLUMN \(column.quote())"
             default: return nil
             }
@@ -128,7 +128,7 @@ public class SchemaChanger: CustomStringConvertible {
 
     init(connection: Connection, version: SQLiteVersion) {
         self.connection = connection
-        schemaReader = connection.schemaReader
+        schemaReader = connection.schema
         self.version = version
     }
 
diff --git a/Sources/SQLite/Schema/SchemaDefinitions.swift b/Sources/SQLite/Schema/SchemaDefinitions.swift
index fe2e3931..4159b35b 100644
--- a/Sources/SQLite/Schema/SchemaDefinitions.swift
+++ b/Sources/SQLite/Schema/SchemaDefinitions.swift
@@ -245,8 +245,9 @@ public struct IndexDefinition: Equatable {
         }
 
         func orders(sql: String) -> [String: IndexDefinition.Order] {
-            IndexDefinition.orderRe.matches(in: sql, range: NSRange(location: 0, length: sql.count))
-                    .reduce([String: IndexDefinition.Order]()) { (memo, result) in
+            IndexDefinition.orderRe
+                .matches(in: sql, range: NSRange(location: 0, length: sql.count))
+                .reduce([String: IndexDefinition.Order]()) { (memo, result) in
                         var memo2 = memo
                         let column = (sql as NSString).substring(with: result.range(at: 1))
                         memo2[column] = .DESC
diff --git a/Sources/SQLite/Schema/SchemaReader.swift b/Sources/SQLite/Schema/SchemaReader.swift
index bfa2e887..b1292471 100644
--- a/Sources/SQLite/Schema/SchemaReader.swift
+++ b/Sources/SQLite/Schema/SchemaReader.swift
@@ -38,7 +38,7 @@ public class SchemaReader {
     public func objectDefinitions(name: String? = nil,
                                   type: ObjectDefinition.ObjectType? = nil,
                                   temp: Bool = false) throws -> [ObjectDefinition] {
-        var query: QueryType = connection.schemaTable(temp: temp)
+        var query: QueryType = SchemaTable.get(for: connection, temp: temp)
         if let name = name {
             query = query.where(SchemaTable.nameColumn == name)
         }
@@ -125,14 +125,22 @@ public class SchemaReader {
     }
 }
 
-private class SchemaTable {
-    internal static let name = Table("sqlite_schema", database: "main")
-    internal static let tempName = Table("sqlite_schema", database: "temp")
+private enum SchemaTable {
+    private static let name = Table("sqlite_schema", database: "main")
+    private static let tempName = Table("sqlite_schema", database: "temp")
+    // legacy names (< 3.33.0)
+    private static let masterName = Table("sqlite_master")
+    private static let tempMasterName = Table("sqlite_temp_master")
 
-    // legacy table names
-    internal static let masterName = Table("sqlite_master")
-    internal static let tempMasterName = Table("sqlite_temp_master")
+    static func get(for connection: Connection, temp: Bool = false) -> Table {
+        if connection.supports(.sqliteSchemaTable) {
+            return temp ? SchemaTable.tempName : SchemaTable.name
+        } else {
+            return temp ? SchemaTable.tempMasterName : SchemaTable.masterName
+        }
+    }
 
+    // columns
     static let typeColumn = Expression<String>("type")
     static let nameColumn = Expression<String>("name")
     static let tableNameColumn = Expression<String>("tbl_name")
@@ -140,7 +148,7 @@ private class SchemaTable {
     static let sqlColumn = Expression<String?>("sql")
 }
 
-private class TableInfoTable {
+private enum TableInfoTable {
     static let idColumn = Expression<Int64>("cid")
     static let nameColumn = Expression<String>("name")
     static let typeColumn = Expression<String>("type")
@@ -149,7 +157,7 @@ private class TableInfoTable {
     static let primaryKeyColumn = Expression<Int64?>("pk")
 }
 
-private class IndexInfoTable {
+private enum IndexInfoTable {
     // The rank of the column within the index. (0 means left-most.)
     static let seqnoColumn = Expression<Int64>("seqno")
     // The rank of the column within the table being indexed.
@@ -159,7 +167,7 @@ private class IndexInfoTable {
     static let nameColumn = Expression<String?>("name")
 }
 
-private class IndexListTable {
+private enum IndexListTable {
     // A sequence number assigned to each index for internal tracking purposes.
     static let seqColumn = Expression<Int64>("seq")
     // The name of the index
@@ -174,7 +182,7 @@ private class IndexListTable {
     static let partialColumn = Expression<Int64>("partial")
 }
 
-private class ForeignKeyListTable {
+private enum ForeignKeyListTable {
     static let idColumn = Expression<Int64>("id")
     static let seqColumn = Expression<Int64>("seq")
     static let tableColumn = Expression<String>("table")
@@ -184,13 +192,3 @@ private class ForeignKeyListTable {
     static let onDeleteColumn = Expression<String>("on_delete")
     static let matchColumn = Expression<String>("match")
 }
-
-private extension Connection {
-    func schemaTable(temp: Bool = false) -> Table {
-        if supports(.sqliteSchemaTable) {
-            return temp ? SchemaTable.tempName : SchemaTable.name
-        } else {
-            return temp ? SchemaTable.tempMasterName : SchemaTable.masterName
-        }
-    }
-}
diff --git a/Tests/SQLiteTests/Schema/SchemaReaderTests.swift b/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
index 165dbc28..95dba921 100644
--- a/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
@@ -8,7 +8,7 @@ class SchemaReaderTests: SQLiteTestCase {
         try super.setUpWithError()
         try createUsersTable()
 
-        schemaReader = db.schemaReader
+        schemaReader = db.schema
     }
 
     func test_columnDefinitions() throws {
@@ -168,6 +168,7 @@ class SchemaReaderTests: SQLiteTestCase {
         XCTAssertEqual(tables.map { table in [table.name, table.tableName, table.type.rawValue]}, [
             ["users", "users", "table"]
         ])
+        XCTAssertTrue((try schemaReader.objectDefinitions(type: .trigger)).isEmpty)
     }
 
     func test_objectDefinitionsFilterByName() throws {
@@ -176,5 +177,6 @@ class SchemaReaderTests: SQLiteTestCase {
         XCTAssertEqual(tables.map { table in [table.name, table.tableName, table.type.rawValue]}, [
             ["users", "users", "table"]
         ])
+        XCTAssertTrue((try schemaReader.objectDefinitions(name: "xxx")).isEmpty)
     }
 }

From 0f6c3e30245d09bdd1fd50d5e0ac0d162131426c Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 18 Oct 2022 01:11:08 +0200
Subject: [PATCH 558/685] Add documentation

---
 Documentation/Index.md                        | 82 ++++++++++++++++++-
 Sources/SQLite/Schema/SchemaChanger.swift     |  2 +-
 Sources/SQLite/Schema/SchemaDefinitions.swift |  4 +
 Sources/SQLite/Schema/SchemaReader.swift      |  2 +-
 .../Schema/SchemaChangerTests.swift           | 34 ++++----
 .../Schema/SchemaReaderTests.swift            | 34 +++++++-
 6 files changed, 134 insertions(+), 24 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 29b18c96..e40f786d 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1371,6 +1371,37 @@ try db.transaction {
 
 > _Note:_ Transactions run in a serial queue.
 
+## Querying the Schema
+
+We can obtain generic information about objects in the current schema with a `SchemaReader`:
+
+```swift
+let schema = db.schema
+```
+
+To query the data:
+
+```swift
+let indexes = try schema.objectDefinitions(type: .index)
+let tables = try schema.objectDefinitions(type: .table)
+let triggers = try schema.objectDefinitions(type: .trigger)
+```
+
+### Indexes and Columns
+
+Specialized methods are available to get more detailed information:
+
+```swift
+let indexes = try schema.indexDefinitions("users")
+let columns = try schema.columnDefinitions("users")
+
+for index in indexes {
+    print("\(index.name) columns:\(index.columns))")
+}
+for column in columns {
+    print("\(column.name) pk:\(column.primaryKey) nullable: \(column.nullable)")
+}
+```
 
 ## Altering the Schema
 
@@ -1454,11 +1485,56 @@ tables](#creating-a-table).
 
 ### Renaming Columns
 
-Added in SQLite 3.25.0, not exposed yet. [#1073](https://github.com/stephencelis/SQLite.swift/issues/1073)
+We can rename columns with the help of the `SchemaChanger` class:
+
+```swift
+let schemaChanger = SchemaChanger(connection: db)
+try schemaChanger.alter(table: "users") { table in
+    table.rename("old_name", to: "new_name")
+}
+```
 
 ### Dropping Columns
 
-Added in SQLite 3.35.0, not exposed yet. [#1073](https://github.com/stephencelis/SQLite.swift/issues/1073)
+```swift
+let schemaChanger = SchemaChanger(connection: db)
+try schemaChanger.alter(table: "users") { table in
+    table.drop("column")
+}
+```
+
+These operations will work with all versions of SQLite and use modern SQL
+operations such as `DROP COLUMN` when available.
+
+### Adding Columns (SchemaChanger)
+
+The `SchemaChanger` provides an alternative API to add new columns:
+
+```swift
+let newColumn = ColumnDefinition(
+    name: "new_text_column",
+    type: .TEXT,
+    nullable: true, 
+    defaultValue: .stringLiteral("foo")
+)
+
+let schemaChanger = SchemaChanger(connection: db)
+
+try schemaChanger.alter(table: "users") { table in
+    table.add(newColumn)
+}
+```
+
+### Renaming/dropping Tables (SchemaChanger)
+
+The `SchemaChanger` provides an alternative API to rename and drop tables:
+
+```swift
+let schemaChanger = SchemaChanger(connection: db)
+
+try schemaChanger.rename(table: "users", to: "users_new")
+try schemaChanger.drop(table: "emails")
+```
 
 ### Indexes
 
@@ -1515,7 +1591,6 @@ try db.run(users.dropIndex(email, ifExists: true))
 // DROP INDEX IF EXISTS "index_users_on_email"
 ```
 
-
 ### Dropping Tables
 
 We can build
@@ -1535,7 +1610,6 @@ try db.run(users.drop(ifExists: true))
 // DROP TABLE IF EXISTS "users"
 ```
 
-
 ### Migrations and Schema Versioning
 
 You can use the convenience property on `Connection` to query and set the
diff --git a/Sources/SQLite/Schema/SchemaChanger.swift b/Sources/SQLite/Schema/SchemaChanger.swift
index 4e1b42c5..d2ada22c 100644
--- a/Sources/SQLite/Schema/SchemaChanger.swift
+++ b/Sources/SQLite/Schema/SchemaChanger.swift
@@ -99,7 +99,7 @@ public class SchemaChanger: CustomStringConvertible {
             operations.append(.addColumn(column))
         }
 
-        public func remove(_ column: String) {
+        public func drop(_ column: String) {
             operations.append(.dropColumn(column))
         }
 
diff --git a/Sources/SQLite/Schema/SchemaDefinitions.swift b/Sources/SQLite/Schema/SchemaDefinitions.swift
index 4159b35b..a2700dd2 100644
--- a/Sources/SQLite/Schema/SchemaDefinitions.swift
+++ b/Sources/SQLite/Schema/SchemaDefinitions.swift
@@ -31,6 +31,10 @@ public struct ObjectDefinition: Equatable {
 
     // SQL text that describes the object (NULL for the internal indexes)
     public let sql: String?
+
+    public var isInternal: Bool {
+        name.starts(with: "sqlite_") || sql == nil
+    }
 }
 
 // https://sqlite.org/syntax/column-def.html
diff --git a/Sources/SQLite/Schema/SchemaReader.swift b/Sources/SQLite/Schema/SchemaReader.swift
index b1292471..1c26fdd6 100644
--- a/Sources/SQLite/Schema/SchemaReader.swift
+++ b/Sources/SQLite/Schema/SchemaReader.swift
@@ -52,7 +52,7 @@ public class SchemaReader {
             return ObjectDefinition(
                 type: type,
                 name: row[SchemaTable.nameColumn],
-                tableName: row[SchemaTable.nameColumn],
+                tableName: row[SchemaTable.tableNameColumn],
                 rootpage: row[SchemaTable.rootPageColumn] ?? 0,
                 sql: row[SchemaTable.sqlColumn]
             )
diff --git a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
index af8b6565..d023b8e5 100644
--- a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
@@ -3,7 +3,7 @@ import XCTest
 
 class SchemaChangerTests: SQLiteTestCase {
     var schemaChanger: SchemaChanger!
-    var schemaReader: SchemaReader!
+    var schema: SchemaReader!
 
     override func setUpWithError() throws {
         try super.setUpWithError()
@@ -11,33 +11,33 @@ class SchemaChangerTests: SQLiteTestCase {
 
         try insertUsers("bob")
 
-        schemaReader = SchemaReader(connection: db)
+        schema = SchemaReader(connection: db)
         schemaChanger = SchemaChanger(connection: db)
     }
 
     func test_empty_migration_does_not_change_column_definitions() throws {
-        let previous = try schemaReader.columnDefinitions(table: "users")
+        let previous = try schema.columnDefinitions(table: "users")
         try schemaChanger.alter(table: "users") { _ in
         }
-        let current = try schemaReader.columnDefinitions(table: "users")
+        let current = try schema.columnDefinitions(table: "users")
 
         XCTAssertEqual(previous, current)
     }
 
     func test_empty_migration_does_not_change_index_definitions() throws {
-        let previous = try schemaReader.indexDefinitions(table: "users")
+        let previous = try schema.indexDefinitions(table: "users")
         try schemaChanger.alter(table: "users") { _ in
         }
-        let current = try schemaReader.indexDefinitions(table: "users")
+        let current = try schema.indexDefinitions(table: "users")
 
         XCTAssertEqual(previous, current)
     }
 
     func test_empty_migration_does_not_change_foreign_key_definitions() throws {
-        let previous = try schemaReader.foreignKeys(table: "users")
+        let previous = try schema.foreignKeys(table: "users")
         try schemaChanger.alter(table: "users") { _ in
         }
-        let current = try schemaReader.foreignKeys(table: "users")
+        let current = try schema.foreignKeys(table: "users")
 
         XCTAssertEqual(previous, current)
     }
@@ -51,21 +51,21 @@ class SchemaChangerTests: SQLiteTestCase {
         XCTAssertEqual(previous, current)
     }
 
-    func test_remove_column() throws {
+    func test_drop_column() throws {
         try schemaChanger.alter(table: "users") { table in
-            table.remove("age")
+            table.drop("age")
         }
-        let columns = try schemaReader.columnDefinitions(table: "users").map(\.name)
+        let columns = try schema.columnDefinitions(table: "users").map(\.name)
         XCTAssertFalse(columns.contains("age"))
     }
 
-    func test_remove_column_legacy() throws {
+    func test_drop_column_legacy() throws {
         schemaChanger = .init(connection: db, version: .init(major: 3, minor: 24)) // DROP COLUMN introduced in 3.35.0
 
         try schemaChanger.alter(table: "users") { table in
-            table.remove("age")
+            table.drop("age")
         }
-        let columns = try schemaReader.columnDefinitions(table: "users").map(\.name)
+        let columns = try schema.columnDefinitions(table: "users").map(\.name)
         XCTAssertFalse(columns.contains("age"))
     }
 
@@ -74,7 +74,7 @@ class SchemaChangerTests: SQLiteTestCase {
             table.rename("age", to: "age2")
         }
 
-        let columns = try schemaReader.columnDefinitions(table: "users").map(\.name)
+        let columns = try schema.columnDefinitions(table: "users").map(\.name)
         XCTAssertFalse(columns.contains("age"))
         XCTAssertTrue(columns.contains("age2"))
     }
@@ -86,7 +86,7 @@ class SchemaChangerTests: SQLiteTestCase {
             table.rename("age", to: "age2")
         }
 
-        let columns = try schemaReader.columnDefinitions(table: "users").map(\.name)
+        let columns = try schema.columnDefinitions(table: "users").map(\.name)
         XCTAssertFalse(columns.contains("age"))
         XCTAssertTrue(columns.contains("age2"))
     }
@@ -102,7 +102,7 @@ class SchemaChangerTests: SQLiteTestCase {
             table.add(newColumn)
         }
 
-        let columns = try schemaReader.columnDefinitions(table: "users")
+        let columns = try schema.columnDefinitions(table: "users")
         XCTAssertTrue(columns.contains(newColumn))
 
         XCTAssertEqual(try db.pluck(users.select(column))?[column], "foo")
diff --git a/Tests/SQLiteTests/Schema/SchemaReaderTests.swift b/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
index 95dba921..dd5ae103 100644
--- a/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
@@ -146,7 +146,7 @@ class SchemaReaderTests: SQLiteTestCase {
 
         XCTAssertEqual(tables.map { table in [table.name, table.tableName, table.type.rawValue]}, [
             ["users", "users", "table"],
-            ["sqlite_autoindex_users_1", "sqlite_autoindex_users_1", "index"]
+            ["sqlite_autoindex_users_1", "users", "index"]
         ])
     }
 
@@ -162,6 +162,38 @@ class SchemaReaderTests: SQLiteTestCase {
         ])
     }
 
+    func test_objectDefinitions_indexes() throws {
+        let emailIndex = users.createIndex(Expression<String>("email"), unique: false, ifNotExists: true)
+        try db.run(emailIndex)
+
+        let indexes = try schemaReader.objectDefinitions(type: .index)
+            .filter { !$0.isInternal }
+
+        XCTAssertEqual(indexes.map { index in [index.name, index.tableName, index.type.rawValue, index.sql]}, [
+            ["index_users_on_email",
+             "users",
+             "index",
+             "CREATE INDEX \"index_users_on_email\" ON \"users\" (\"email\")"]
+        ])
+    }
+
+    func test_objectDefinitions_triggers() throws {
+        let trigger = """
+        CREATE TRIGGER test_trigger
+            AFTER INSERT ON users BEGIN
+                UPDATE USERS SET name = "update" WHERE id = NEW.rowid;
+            END;
+        """
+
+        try db.run(trigger)
+
+        let triggers = try schemaReader.objectDefinitions(type: .trigger)
+
+        XCTAssertEqual(triggers.map { trigger in [trigger.name, trigger.tableName, trigger.type.rawValue]}, [
+            ["test_trigger", "users", "trigger"]
+        ])
+    }
+
     func test_objectDefinitionsFilterByType() throws {
         let tables = try schemaReader.objectDefinitions(type: .table)
 

From 137788e332f07e04d0a7d07150a043cc04c0d5e5 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 18 Oct 2022 01:17:31 +0200
Subject: [PATCH 559/685] Named param for rename/drop

---
 Documentation/Index.md                            | 4 ++--
 Sources/SQLite/Schema/SchemaChanger.swift         | 4 ++--
 Tests/SQLiteTests/Schema/SchemaChangerTests.swift | 8 ++++----
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index e40f786d..68e66457 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1490,7 +1490,7 @@ We can rename columns with the help of the `SchemaChanger` class:
 ```swift
 let schemaChanger = SchemaChanger(connection: db)
 try schemaChanger.alter(table: "users") { table in
-    table.rename("old_name", to: "new_name")
+    table.rename(column: "old_name", to: "new_name")
 }
 ```
 
@@ -1499,7 +1499,7 @@ try schemaChanger.alter(table: "users") { table in
 ```swift
 let schemaChanger = SchemaChanger(connection: db)
 try schemaChanger.alter(table: "users") { table in
-    table.drop("column")
+    table.drop(column: "email")
 }
 ```
 
diff --git a/Sources/SQLite/Schema/SchemaChanger.swift b/Sources/SQLite/Schema/SchemaChanger.swift
index d2ada22c..67f2b0d3 100644
--- a/Sources/SQLite/Schema/SchemaChanger.swift
+++ b/Sources/SQLite/Schema/SchemaChanger.swift
@@ -99,11 +99,11 @@ public class SchemaChanger: CustomStringConvertible {
             operations.append(.addColumn(column))
         }
 
-        public func drop(_ column: String) {
+        public func drop(column: String) {
             operations.append(.dropColumn(column))
         }
 
-        public func rename(_ column: String, to: String) {
+        public func rename(column: String, to: String) {
             operations.append(.renameColumn(column, to))
         }
     }
diff --git a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
index d023b8e5..2894e5ce 100644
--- a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
@@ -53,7 +53,7 @@ class SchemaChangerTests: SQLiteTestCase {
 
     func test_drop_column() throws {
         try schemaChanger.alter(table: "users") { table in
-            table.drop("age")
+            table.drop(column: "age")
         }
         let columns = try schema.columnDefinitions(table: "users").map(\.name)
         XCTAssertFalse(columns.contains("age"))
@@ -63,7 +63,7 @@ class SchemaChangerTests: SQLiteTestCase {
         schemaChanger = .init(connection: db, version: .init(major: 3, minor: 24)) // DROP COLUMN introduced in 3.35.0
 
         try schemaChanger.alter(table: "users") { table in
-            table.drop("age")
+            table.drop(column: "age")
         }
         let columns = try schema.columnDefinitions(table: "users").map(\.name)
         XCTAssertFalse(columns.contains("age"))
@@ -71,7 +71,7 @@ class SchemaChangerTests: SQLiteTestCase {
 
     func test_rename_column() throws {
         try schemaChanger.alter(table: "users") { table in
-            table.rename("age", to: "age2")
+            table.rename(column: "age", to: "age2")
         }
 
         let columns = try schema.columnDefinitions(table: "users").map(\.name)
@@ -83,7 +83,7 @@ class SchemaChangerTests: SQLiteTestCase {
         schemaChanger = .init(connection: db, version: .init(major: 3, minor: 24)) // RENAME COLUMN introduced in 3.25.0
 
         try schemaChanger.alter(table: "users") { table in
-            table.rename("age", to: "age2")
+            table.rename(column: "age", to: "age2")
         }
 
         let columns = try schema.columnDefinitions(table: "users").map(\.name)

From f2c8bdaf71c57a5087efabf447da33f874ae5787 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 18 Oct 2022 01:25:48 +0200
Subject: [PATCH 560/685] Changelog

---
 CHANGELOG.md           | 4 ++++
 Documentation/Index.md | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7b3f78b4..3a12f377 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
 0.14.0 (tbd), [diff][diff-0.14.0]
 ========================================
 
+* Support more complex schema changes and queries ([#1073][], [#1146][] [#1148][])
 * Support `ATTACH`/`DETACH` ([#30][], [#1142][])
 * Support `WITH` clause ([#1139][])
 * Add `Value` conformance for `NSURL` ([#1110][], [#1141][])
@@ -160,6 +161,7 @@
 [#866]: https://github.com/stephencelis/SQLite.swift/pull/866
 [#881]: https://github.com/stephencelis/SQLite.swift/pull/881
 [#919]: https://github.com/stephencelis/SQLite.swift/pull/919
+[#1073]: https://github.com/stephencelis/SQLite.swift/issues/1073
 [#1075]: https://github.com/stephencelis/SQLite.swift/pull/1075
 [#1077]: https://github.com/stephencelis/SQLite.swift/issues/1077
 [#1094]: https://github.com/stephencelis/SQLite.swift/pull/1094
@@ -185,3 +187,5 @@
 [#1141]: https://github.com/stephencelis/SQLite.swift/pull/1141
 [#1142]: https://github.com/stephencelis/SQLite.swift/pull/1142
 [#1144]: https://github.com/stephencelis/SQLite.swift/pull/1144
+[#1146]: https://github.com/stephencelis/SQLite.swift/pull/1146
+[#1148]: https://github.com/stephencelis/SQLite.swift/pull/1148
diff --git a/Documentation/Index.md b/Documentation/Index.md
index 68e66457..d275db8e 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1514,7 +1514,7 @@ The `SchemaChanger` provides an alternative API to add new columns:
 let newColumn = ColumnDefinition(
     name: "new_text_column",
     type: .TEXT,
-    nullable: true, 
+    nullable: true,
     defaultValue: .stringLiteral("foo")
 )
 

From 140134d68fd82190972f30232e33363c8ae58a79 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 18 Oct 2022 02:06:21 +0200
Subject: [PATCH 561/685] Add playground examples

---
 SQLite.playground/Contents.swift              | 30 ++++++++++++++++++-
 Sources/SQLite/Schema/SchemaDefinitions.swift |  2 +-
 .../Schema/SchemaDefinitionsTests.swift       | 10 +++++++
 3 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/SQLite.playground/Contents.swift b/SQLite.playground/Contents.swift
index c089076d..73091735 100644
--- a/SQLite.playground/Contents.swift
+++ b/SQLite.playground/Contents.swift
@@ -99,5 +99,33 @@ db.createAggregation("customConcat",
                      initialValue: "users:",
                      reduce: reduce,
                      result: { $0 })
-let result = db.prepare("SELECT customConcat(email) FROM users").scalar() as! String
+let result = try db.prepare("SELECT customConcat(email) FROM users").scalar() as! String
 print(result)
+
+/// schema queries
+let schema = db.schema
+let objects = try schema.objectDefinitions()
+print(objects)
+
+let columns = try schema.columnDefinitions(table: "users")
+print(columns)
+
+/// schema alteration
+
+let schemaChanger = SchemaChanger(connection: db)
+try schemaChanger.alter(table: "users") { table in
+    table.add(.init(name: "age", type: .INTEGER))
+    table.rename(column: "email", to: "electronic_mail")
+    table.drop(column: "name")
+}
+
+let changedColumns = try schema.columnDefinitions(table: "users")
+print(changedColumns)
+
+let age = Expression<Int?>("age")
+let electronicMail = Expression<String>("electronic_mail")
+
+let newRowid = try db.run(users.insert(
+    electronicMail <- "carol@mac.com",
+    age <- 33
+))
diff --git a/Sources/SQLite/Schema/SchemaDefinitions.swift b/Sources/SQLite/Schema/SchemaDefinitions.swift
index a2700dd2..b06ddfc7 100644
--- a/Sources/SQLite/Schema/SchemaDefinitions.swift
+++ b/Sources/SQLite/Schema/SchemaDefinitions.swift
@@ -122,7 +122,7 @@ public struct ColumnDefinition: Equatable {
     public init(name: String,
                 primaryKey: PrimaryKey? = nil,
                 type: Affinity,
-                nullable: Bool = false,
+                nullable: Bool = true,
                 defaultValue: LiteralValue = .NULL,
                 references: ForeignKey? = nil) {
         self.name = name
diff --git a/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift b/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
index 384aab3f..ef97b981 100644
--- a/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
@@ -49,6 +49,16 @@ class ColumnDefinitionTests: XCTestCase {
         XCTAssertEqual(definition.toSQL(), expected)
     }
     #endif
+
+    func testNullableByDefault() {
+        let test = ColumnDefinition(name: "test", type: .REAL)
+        XCTAssertEqual(test.name, "test")
+        XCTAssertTrue(test.nullable)
+        XCTAssertEqual(test.defaultValue, .NULL)
+        XCTAssertEqual(test.type, .REAL)
+        XCTAssertNil(test.references)
+        XCTAssertNil(test.primaryKey)
+    }
 }
 
 class AffinityTests: XCTestCase {

From 020ec7aabbda32a384d29fcc4ecf42e52ef48190 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 18 Oct 2022 02:40:18 +0200
Subject: [PATCH 562/685] Better example

---
 SQLite.playground/Contents.swift              | 2 +-
 Sources/SQLite/Schema/SchemaDefinitions.swift | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/SQLite.playground/Contents.swift b/SQLite.playground/Contents.swift
index 73091735..5a7ea379 100644
--- a/SQLite.playground/Contents.swift
+++ b/SQLite.playground/Contents.swift
@@ -114,7 +114,7 @@ print(columns)
 
 let schemaChanger = SchemaChanger(connection: db)
 try schemaChanger.alter(table: "users") { table in
-    table.add(.init(name: "age", type: .INTEGER))
+    table.add(ColumnDefinition(name: "age", type: .INTEGER))
     table.rename(column: "email", to: "electronic_mail")
     table.drop(column: "name")
 }
diff --git a/Sources/SQLite/Schema/SchemaDefinitions.swift b/Sources/SQLite/Schema/SchemaDefinitions.swift
index b06ddfc7..284fc4c3 100644
--- a/Sources/SQLite/Schema/SchemaDefinitions.swift
+++ b/Sources/SQLite/Schema/SchemaDefinitions.swift
@@ -154,7 +154,6 @@ public enum LiteralValue: Equatable, CustomStringConvertible {
 
     // If there is no explicit DEFAULT clause attached to a column definition, then the default value of the
     // column is NULL
-    // swiftlint:disable identifier_name
     case NULL
 
     // Beginning with SQLite 3.23.0 (2018-04-02), SQLite recognizes the identifiers "TRUE" and
@@ -164,6 +163,7 @@ public enum LiteralValue: Equatable, CustomStringConvertible {
     // The boolean identifiers TRUE and FALSE are usually just aliases for the integer values 1 and 0, respectively.
     case TRUE
     case FALSE
+    // swiftlint:disable identifier_name
     case CURRENT_TIME
     case CURRENT_DATE
     case CURRENT_TIMESTAMP

From 773ac2611faaeeb16cedd83406ed3b281ffcf8ea Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 23 Oct 2022 21:39:32 +0200
Subject: [PATCH 563/685] Reactivate #416

---
 Sources/SQLite/Core/Blob.swift              | 51 ++++++++++++++++-----
 Sources/SQLite/Core/Connection.swift        |  2 +-
 Sources/SQLite/Core/Statement.swift         |  2 +-
 Sources/SQLite/Foundation.swift             |  6 +--
 Tests/SQLiteTests/Core/BlobTests.swift      | 10 +++-
 Tests/SQLiteTests/Core/StatementTests.swift |  4 +-
 Tests/SQLiteTests/FoundationTests.swift     |  2 +-
 7 files changed, 55 insertions(+), 22 deletions(-)

diff --git a/Sources/SQLite/Core/Blob.swift b/Sources/SQLite/Core/Blob.swift
index cd31483b..e1ce5d9c 100644
--- a/Sources/SQLite/Core/Blob.swift
+++ b/Sources/SQLite/Core/Blob.swift
@@ -21,26 +21,55 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 //
+import Foundation
 
-public struct Blob {
+public final class Blob {
 
-    public let bytes: [UInt8]
+    public let data: NSData
 
-    public init(bytes: [UInt8]) {
-        self.bytes = bytes
+    public var bytes: UnsafeRawPointer {
+        data.bytes
     }
 
-    public init(bytes: UnsafeRawPointer, length: Int) {
-        let i8bufptr = UnsafeBufferPointer(start: bytes.assumingMemoryBound(to: UInt8.self), count: length)
-        self.init(bytes: [UInt8](i8bufptr))
+    public var length: Int {
+        data.count
     }
 
-    public func toHex() -> String {
-        bytes.map {
-            ($0 < 16 ? "0" : "") + String($0, radix: 16, uppercase: false)
-        }.joined(separator: "")
+    public convenience init(bytes: [UInt8]) {
+        let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bytes.count)
+        for idx in 0..<bytes.count {
+            buffer.advanced(by: idx).pointee = bytes[idx]
+        }
+
+        let data = NSData(
+            bytesNoCopy: UnsafeMutableRawPointer(buffer),
+            length: bytes.count,
+            freeWhenDone: true
+        )
+        self.init(data: data)
     }
 
+    public convenience init(bytes: UnsafeRawPointer, length: Int) {
+        self.init(data: NSData(bytes: bytes, length: length))
+    }
+
+    public init(data: NSData) {
+        self.data = data
+    }
+
+    public func toHex() -> String {
+        let bytes = bytes.assumingMemoryBound(to: UInt8.self)
+
+        var hex = ""
+        for idx in 0..<length {
+            let byte = bytes.advanced(by: idx).pointee
+            if byte < 16 {
+                hex += "0"
+            }
+            hex += String(byte, radix: 16, uppercase: false)
+        }
+        return hex
+    }
 }
 
 extension Blob: CustomStringConvertible {
diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 0e51e651..2a7ec487 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -741,7 +741,7 @@ extension Context {
     func set(result: Binding?) {
         switch result {
         case let blob as Blob:
-            sqlite3_result_blob(self, blob.bytes, Int32(blob.bytes.count), nil)
+            sqlite3_result_blob(self, blob.bytes, Int32(blob.length), nil)
         case let double as Double:
             sqlite3_result_double(self, double)
         case let int as Int64:
diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index 7ba4026c..ec06a5bb 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -103,7 +103,7 @@ public final class Statement {
         if value == nil {
             sqlite3_bind_null(handle, Int32(idx))
         } else if let value = value as? Blob {
-            sqlite3_bind_blob(handle, Int32(idx), value.bytes, Int32(value.bytes.count), SQLITE_TRANSIENT)
+            sqlite3_bind_blob(handle, Int32(idx), value.bytes, Int32(value.length), SQLITE_TRANSIENT)
         } else if let value = value as? Double {
             sqlite3_bind_double(handle, Int32(idx), value)
         } else if let value = value as? Int64 {
diff --git a/Sources/SQLite/Foundation.swift b/Sources/SQLite/Foundation.swift
index 44a31736..e81c4964 100644
--- a/Sources/SQLite/Foundation.swift
+++ b/Sources/SQLite/Foundation.swift
@@ -31,13 +31,11 @@ extension Data: Value {
     }
 
     public static func fromDatatypeValue(_ dataValue: Blob) -> Data {
-        Data(dataValue.bytes)
+        dataValue.data as Data
     }
 
     public var datatypeValue: Blob {
-        withUnsafeBytes { (pointer: UnsafeRawBufferPointer) -> Blob in
-            Blob(bytes: pointer.baseAddress!, length: count)
-        }
+        Blob(data: self as NSData)
     }
 
 }
diff --git a/Tests/SQLiteTests/Core/BlobTests.swift b/Tests/SQLiteTests/Core/BlobTests.swift
index 87eb5709..463ef10a 100644
--- a/Tests/SQLiteTests/Core/BlobTests.swift
+++ b/Tests/SQLiteTests/Core/BlobTests.swift
@@ -11,13 +11,19 @@ class BlobTests: XCTestCase {
 
     func test_init_array() {
         let blob = Blob(bytes: [42, 42, 42])
-        XCTAssertEqual(blob.bytes, [42, 42, 42])
+        XCTAssertEqual(blob.byteArray, [42, 42, 42])
     }
 
     func test_init_unsafeRawPointer() {
         let pointer = UnsafeMutablePointer<UInt8>.allocate(capacity: 3)
         pointer.initialize(repeating: 42, count: 3)
         let blob = Blob(bytes: pointer, length: 3)
-        XCTAssertEqual(blob.bytes, [42, 42, 42])
+        XCTAssertEqual(blob.byteArray, [42, 42, 42])
+    }
+}
+
+extension Blob {
+    var byteArray: [UInt8] {
+        [UInt8](data)
     }
 }
diff --git a/Tests/SQLiteTests/Core/StatementTests.swift b/Tests/SQLiteTests/Core/StatementTests.swift
index eeb513fe..28772ae1 100644
--- a/Tests/SQLiteTests/Core/StatementTests.swift
+++ b/Tests/SQLiteTests/Core/StatementTests.swift
@@ -22,7 +22,7 @@ class StatementTests: SQLiteTestCase {
         let statement = try db.prepare("SELECT email FROM users")
         XCTAssert(try statement.step())
         let blob = statement.row[0] as Blob
-        XCTAssertEqual("alice@example.com", String(bytes: blob.bytes, encoding: .utf8)!)
+        XCTAssertEqual("alice@example.com", String(data: blob.data as Data, encoding: .utf8)!)
     }
 
     func test_zero_sized_blob_returns_null() throws {
@@ -31,7 +31,7 @@ class StatementTests: SQLiteTestCase {
         try db.run(blobs.create { $0.column(blobColumn) })
         try db.run(blobs.insert(blobColumn <- Blob(bytes: [])))
         let blobValue = try db.scalar(blobs.select(blobColumn).limit(1, offset: 0))
-        XCTAssertEqual([], blobValue.bytes)
+        XCTAssertEqual([], blobValue.byteArray)
     }
 
     func test_prepareRowIterator() throws {
diff --git a/Tests/SQLiteTests/FoundationTests.swift b/Tests/SQLiteTests/FoundationTests.swift
index 453febcd..cca15cc1 100644
--- a/Tests/SQLiteTests/FoundationTests.swift
+++ b/Tests/SQLiteTests/FoundationTests.swift
@@ -5,7 +5,7 @@ class FoundationTests: XCTestCase {
     func testDataFromBlob() {
         let data = Data([1, 2, 3])
         let blob = data.datatypeValue
-        XCTAssertEqual([1, 2, 3], blob.bytes)
+        XCTAssertEqual([1, 2, 3], blob.byteArray)
     }
 
     func testBlobToData() {

From 3b91a00c71b34cc3f4343b2c622bf400717a7c3d Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 23 Oct 2022 22:13:21 +0200
Subject: [PATCH 564/685] Fix test

---
 Sources/SQLite/Core/Statement.swift | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index ec06a5bb..df4ceebf 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -100,21 +100,24 @@ public final class Statement {
     }
 
     fileprivate func bind(_ value: Binding?, atIndex idx: Int) {
-        if value == nil {
+        switch value {
+        case .none:
             sqlite3_bind_null(handle, Int32(idx))
-        } else if let value = value as? Blob {
+        case let value as Blob where value.length == 0:
+            sqlite3_bind_zeroblob(handle, Int32(idx), 0)
+        case let value as Blob:
             sqlite3_bind_blob(handle, Int32(idx), value.bytes, Int32(value.length), SQLITE_TRANSIENT)
-        } else if let value = value as? Double {
+        case let value as Double:
             sqlite3_bind_double(handle, Int32(idx), value)
-        } else if let value = value as? Int64 {
+        case let value as Int64:
             sqlite3_bind_int64(handle, Int32(idx), value)
-        } else if let value = value as? String {
+        case let value as String:
             sqlite3_bind_text(handle, Int32(idx), value, -1, SQLITE_TRANSIENT)
-        } else if let value = value as? Int {
+        case let value as Int:
             self.bind(value.datatypeValue, atIndex: idx)
-        } else if let value = value as? Bool {
+        case let value as Bool:
             self.bind(value.datatypeValue, atIndex: idx)
-        } else if let value = value {
+        case .some(let value):
             fatalError("tried to bind unexpected value \(value)")
         }
     }

From 0715e9512daf86fe42e592b54eb633a049adb4b7 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 23 Oct 2022 22:26:46 +0200
Subject: [PATCH 565/685] Fix blob equality

---
 Sources/SQLite/Core/Blob.swift         |  8 +++++++-
 Tests/SQLiteTests/Core/BlobTests.swift | 16 +++++++++++++++-
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/Sources/SQLite/Core/Blob.swift b/Sources/SQLite/Core/Blob.swift
index e1ce5d9c..83b78c2c 100644
--- a/Sources/SQLite/Core/Blob.swift
+++ b/Sources/SQLite/Core/Blob.swift
@@ -36,6 +36,10 @@ public final class Blob {
     }
 
     public convenience init(bytes: [UInt8]) {
+        guard bytes.count > 0 else {
+            self.init(data: NSData())
+            return
+        }
         let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bytes.count)
         for idx in 0..<bytes.count {
             buffer.advanced(by: idx).pointee = bytes[idx]
@@ -54,10 +58,12 @@ public final class Blob {
     }
 
     public init(data: NSData) {
+        precondition(!(data is NSMutableData), "Blob cannot be initialized with mutable data")
         self.data = data
     }
 
     public func toHex() -> String {
+        guard length > 0 else { return "" }
         let bytes = bytes.assumingMemoryBound(to: UInt8.self)
 
         var hex = ""
@@ -85,5 +91,5 @@ extension Blob: Equatable {
 }
 
 public func ==(lhs: Blob, rhs: Blob) -> Bool {
-    lhs.bytes == rhs.bytes
+    lhs.data == rhs.data
 }
diff --git a/Tests/SQLiteTests/Core/BlobTests.swift b/Tests/SQLiteTests/Core/BlobTests.swift
index 463ef10a..9c8700cc 100644
--- a/Tests/SQLiteTests/Core/BlobTests.swift
+++ b/Tests/SQLiteTests/Core/BlobTests.swift
@@ -5,10 +5,14 @@ class BlobTests: XCTestCase {
 
     func test_toHex() {
         let blob = Blob(bytes: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 150, 250, 255])
-
         XCTAssertEqual(blob.toHex(), "000a141e28323c46505a6496faff")
     }
 
+    func test_toHex_empty() {
+        let blob = Blob(bytes: [])
+        XCTAssertEqual(blob.toHex(), "")
+    }
+
     func test_init_array() {
         let blob = Blob(bytes: [42, 42, 42])
         XCTAssertEqual(blob.byteArray, [42, 42, 42])
@@ -20,6 +24,16 @@ class BlobTests: XCTestCase {
         let blob = Blob(bytes: pointer, length: 3)
         XCTAssertEqual(blob.byteArray, [42, 42, 42])
     }
+
+    func test_equality() {
+        let blob1 = Blob(bytes: [42, 42, 42])
+        let blob2 = Blob(bytes: [42, 42, 42])
+        let blob3 = Blob(bytes: [42, 42, 43])
+
+        XCTAssertEqual(Blob(bytes: []), Blob(bytes: []))
+        XCTAssertEqual(blob1, blob2)
+        XCTAssertNotEqual(blob1, blob3)
+    }
 }
 
 extension Blob {

From 0ce78d92aebea37bc68585ae4d0ead17641d86b1 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 23 Oct 2022 22:29:40 +0200
Subject: [PATCH 566/685] Remove helper

---
 Tests/SQLiteTests/Core/BlobTests.swift      | 10 ++--------
 Tests/SQLiteTests/Core/StatementTests.swift |  3 +--
 Tests/SQLiteTests/FoundationTests.swift     |  2 +-
 3 files changed, 4 insertions(+), 11 deletions(-)

diff --git a/Tests/SQLiteTests/Core/BlobTests.swift b/Tests/SQLiteTests/Core/BlobTests.swift
index 9c8700cc..01f38197 100644
--- a/Tests/SQLiteTests/Core/BlobTests.swift
+++ b/Tests/SQLiteTests/Core/BlobTests.swift
@@ -15,14 +15,14 @@ class BlobTests: XCTestCase {
 
     func test_init_array() {
         let blob = Blob(bytes: [42, 42, 42])
-        XCTAssertEqual(blob.byteArray, [42, 42, 42])
+        XCTAssertEqual([UInt8](blob.data), [42, 42, 42])
     }
 
     func test_init_unsafeRawPointer() {
         let pointer = UnsafeMutablePointer<UInt8>.allocate(capacity: 3)
         pointer.initialize(repeating: 42, count: 3)
         let blob = Blob(bytes: pointer, length: 3)
-        XCTAssertEqual(blob.byteArray, [42, 42, 42])
+        XCTAssertEqual([UInt8](blob.data), [42, 42, 42])
     }
 
     func test_equality() {
@@ -35,9 +35,3 @@ class BlobTests: XCTestCase {
         XCTAssertNotEqual(blob1, blob3)
     }
 }
-
-extension Blob {
-    var byteArray: [UInt8] {
-        [UInt8](data)
-    }
-}
diff --git a/Tests/SQLiteTests/Core/StatementTests.swift b/Tests/SQLiteTests/Core/StatementTests.swift
index 28772ae1..2ab84c09 100644
--- a/Tests/SQLiteTests/Core/StatementTests.swift
+++ b/Tests/SQLiteTests/Core/StatementTests.swift
@@ -31,7 +31,7 @@ class StatementTests: SQLiteTestCase {
         try db.run(blobs.create { $0.column(blobColumn) })
         try db.run(blobs.insert(blobColumn <- Blob(bytes: [])))
         let blobValue = try db.scalar(blobs.select(blobColumn).limit(1, offset: 0))
-        XCTAssertEqual([], blobValue.byteArray)
+        XCTAssertEqual([], [UInt8](blobValue.data))
     }
 
     func test_prepareRowIterator() throws {
@@ -71,5 +71,4 @@ class StatementTests: SQLiteTestCase {
         // truncate succeeds
         try db.run("DROP TABLE users")
     }
-
 }
diff --git a/Tests/SQLiteTests/FoundationTests.swift b/Tests/SQLiteTests/FoundationTests.swift
index cca15cc1..ffd3fae1 100644
--- a/Tests/SQLiteTests/FoundationTests.swift
+++ b/Tests/SQLiteTests/FoundationTests.swift
@@ -5,7 +5,7 @@ class FoundationTests: XCTestCase {
     func testDataFromBlob() {
         let data = Data([1, 2, 3])
         let blob = data.datatypeValue
-        XCTAssertEqual([1, 2, 3], blob.byteArray)
+        XCTAssertEqual([1, 2, 3], [UInt8](blob.data))
     }
 
     func testBlobToData() {

From 932d580deae26f04004bcd0aefa536ef021219c8 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 23 Oct 2022 23:08:55 +0200
Subject: [PATCH 567/685] Fix SQLCipher subspec

---
 Sources/SQLite/Core/Blob.swift         | 5 ++---
 Sources/SQLite/Extensions/Cipher.swift | 6 +++---
 Tests/SQLiteTests/Core/BlobTests.swift | 4 ++++
 3 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/Sources/SQLite/Core/Blob.swift b/Sources/SQLite/Core/Blob.swift
index 83b78c2c..fb7ab11b 100644
--- a/Sources/SQLite/Core/Blob.swift
+++ b/Sources/SQLite/Core/Blob.swift
@@ -27,8 +27,8 @@ public final class Blob {
 
     public let data: NSData
 
-    public var bytes: UnsafeRawPointer {
-        data.bytes
+    public var bytes: UnsafePointer<UInt8> {
+        data.bytes.assumingMemoryBound(to: UInt8.self)
     }
 
     public var length: Int {
@@ -64,7 +64,6 @@ public final class Blob {
 
     public func toHex() -> String {
         guard length > 0 else { return "" }
-        let bytes = bytes.assumingMemoryBound(to: UInt8.self)
 
         var hex = ""
         for idx in 0..<length {
diff --git a/Sources/SQLite/Extensions/Cipher.swift b/Sources/SQLite/Extensions/Cipher.swift
index 8af04df9..71889ae5 100644
--- a/Sources/SQLite/Extensions/Cipher.swift
+++ b/Sources/SQLite/Extensions/Cipher.swift
@@ -32,7 +32,7 @@ extension Connection {
     }
 
     public func key(_ key: Blob, db: String = "main") throws {
-        try _key_v2(db: db, keyPointer: key.bytes, keySize: key.bytes.count)
+        try _key_v2(db: db, keyPointer: key.bytes, keySize: key.length)
     }
 
     /// Same as `key(_ key: String, db: String = "main")`, running "PRAGMA cipher_migrate;"
@@ -53,7 +53,7 @@ extension Connection {
 
     /// Same as `[`keyAndMigrate(_ key: String, db: String = "main")` accepting byte array as key
     public func keyAndMigrate(_ key: Blob, db: String = "main") throws {
-        try _key_v2(db: db, keyPointer: key.bytes, keySize: key.bytes.count, migrate: true)
+        try _key_v2(db: db, keyPointer: key.bytes, keySize: key.length, migrate: true)
     }
 
     /// Change the key on an open database. NB: only works if the database is already encrypted.
@@ -68,7 +68,7 @@ extension Connection {
     }
 
     public func rekey(_ key: Blob, db: String = "main") throws {
-        try _rekey_v2(db: db, keyPointer: key.bytes, keySize: key.bytes.count)
+        try _rekey_v2(db: db, keyPointer: key.bytes, keySize: key.length)
     }
 
     /// Converts a non-encrypted database to an encrypted one.
diff --git a/Tests/SQLiteTests/Core/BlobTests.swift b/Tests/SQLiteTests/Core/BlobTests.swift
index 01f38197..d7ed1211 100644
--- a/Tests/SQLiteTests/Core/BlobTests.swift
+++ b/Tests/SQLiteTests/Core/BlobTests.swift
@@ -34,4 +34,8 @@ class BlobTests: XCTestCase {
         XCTAssertEqual(blob1, blob2)
         XCTAssertNotEqual(blob1, blob3)
     }
+
+    func XXX_test_init_with_mutable_data_fails() {
+        _ = Blob(data: NSMutableData())
+    }
 }

From b3a21cab601e22e750e6d46ea526c643f7625b5a Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 23 Oct 2022 23:47:17 +0200
Subject: [PATCH 568/685] Avoid NSMutableData

---
 Tests/SQLiteTests/Extensions/CipherTests.swift | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/Tests/SQLiteTests/Extensions/CipherTests.swift b/Tests/SQLiteTests/Extensions/CipherTests.swift
index cc43272e..bd7f2042 100644
--- a/Tests/SQLiteTests/Extensions/CipherTests.swift
+++ b/Tests/SQLiteTests/Extensions/CipherTests.swift
@@ -19,7 +19,7 @@ class CipherTests: XCTestCase {
 
         // db2
         let key2 = keyData()
-        try db2.key(Blob(bytes: key2.bytes, length: key2.length))
+        try db2.key(Blob(data: key2))
 
         try db2.run("CREATE TABLE foo (bar TEXT)")
         try db2.run("INSERT INTO foo (bar) VALUES ('world')")
@@ -47,7 +47,7 @@ class CipherTests: XCTestCase {
 
     func test_data_rekey() throws {
         let newKey = keyData()
-        try db2.rekey(Blob(bytes: newKey.bytes, length: newKey.length))
+        try db2.rekey(Blob(data: newKey))
         XCTAssertEqual(1, try db2.scalar("SELECT count(*) FROM foo") as? Int64)
     }
 
@@ -108,12 +108,12 @@ class CipherTests: XCTestCase {
         XCTAssertEqual(1, try conn.scalar("SELECT count(*) FROM foo") as? Int64)
     }
 
-    private func keyData(length: Int = 64) -> NSMutableData {
+    private func keyData(length: Int = 64) -> NSData {
         let keyData = NSMutableData(length: length)!
         let result  = SecRandomCopyBytes(kSecRandomDefault, length,
                                          keyData.mutableBytes.assumingMemoryBound(to: UInt8.self))
         XCTAssertEqual(0, result)
-        return keyData
+        return NSData(data: keyData)
     }
 }
 #endif

From bf021c503067675295a18f69ecfc6eb3903c8195 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 23 Oct 2022 23:51:43 +0200
Subject: [PATCH 569/685] Update changelog

---
 CHANGELOG.md | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3a12f377..49590fbe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,7 +10,8 @@
 * Fix `insertMany([Encodable])` ([#1130][], [#1138][])
 * Fix incorrect spelling of `remove_diacritics` ([#1128][])
 * Fix project build order ([#1131][])
-* Performance improvements ([#1109][], [#1115][], [#1132][])
+* Blob performance improvements ([#416][], [#1167][])
+* Various performance improvements ([#1109][], [#1115][], [#1132][])
 * Removed FTS3/4 tokenizer integration (`registerTokenizer`, [#1104][], [#1144][])
 
 0.13.3 (27-03-2022), [diff][diff-0.13.3]
@@ -130,6 +131,7 @@
 [#30]: https://github.com/stephencelis/SQLite.swift/issues/30
 [#142]: https://github.com/stephencelis/SQLite.swift/issues/142
 [#315]: https://github.com/stephencelis/SQLite.swift/issues/315
+[#416]: https://github.com/stephencelis/SQLite.swift/pull/416
 [#426]: https://github.com/stephencelis/SQLite.swift/pull/426
 [#481]: https://github.com/stephencelis/SQLite.swift/pull/481
 [#532]: https://github.com/stephencelis/SQLite.swift/issues/532
@@ -189,3 +191,4 @@
 [#1144]: https://github.com/stephencelis/SQLite.swift/pull/1144
 [#1146]: https://github.com/stephencelis/SQLite.swift/pull/1146
 [#1148]: https://github.com/stephencelis/SQLite.swift/pull/1148
+[#1167]: https://github.com/stephencelis/SQLite.swift/pull/1167

From 06e55e794ffb49eda3f97e0ca627fb76ed2f98f6 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 24 Oct 2022 12:10:54 +0200
Subject: [PATCH 570/685] Simplify

---
 Sources/SQLite/Core/Blob.swift         | 12 +-----------
 Tests/SQLiteTests/Core/BlobTests.swift | 14 ++++++++++++--
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/Sources/SQLite/Core/Blob.swift b/Sources/SQLite/Core/Blob.swift
index fb7ab11b..c8bd2c15 100644
--- a/Sources/SQLite/Core/Blob.swift
+++ b/Sources/SQLite/Core/Blob.swift
@@ -40,17 +40,7 @@ public final class Blob {
             self.init(data: NSData())
             return
         }
-        let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bytes.count)
-        for idx in 0..<bytes.count {
-            buffer.advanced(by: idx).pointee = bytes[idx]
-        }
-
-        let data = NSData(
-            bytesNoCopy: UnsafeMutableRawPointer(buffer),
-            length: bytes.count,
-            freeWhenDone: true
-        )
-        self.init(data: data)
+        self.init(data: NSData(bytes: bytes, length: bytes.count))
     }
 
     public convenience init(bytes: UnsafeRawPointer, length: Int) {
diff --git a/Tests/SQLiteTests/Core/BlobTests.swift b/Tests/SQLiteTests/Core/BlobTests.swift
index d7ed1211..bef4bb83 100644
--- a/Tests/SQLiteTests/Core/BlobTests.swift
+++ b/Tests/SQLiteTests/Core/BlobTests.swift
@@ -13,9 +13,19 @@ class BlobTests: XCTestCase {
         XCTAssertEqual(blob.toHex(), "")
     }
 
+    func test_description() {
+        let blob = Blob(bytes: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 150, 250, 255])
+        XCTAssertEqual(blob.description, "x'000a141e28323c46505a6496faff'")
+    }
+
+    func test_description_empty() {
+        let blob = Blob(bytes: [])
+        XCTAssertEqual(blob.description, "x''")
+    }
+
     func test_init_array() {
-        let blob = Blob(bytes: [42, 42, 42])
-        XCTAssertEqual([UInt8](blob.data), [42, 42, 42])
+        let blob = Blob(bytes: [42, 43, 44])
+        XCTAssertEqual([UInt8](blob.data), [42, 43, 44])
     }
 
     func test_init_unsafeRawPointer() {

From 570efefb451ff021aa5d19414f9a30d357042a96 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 26 Oct 2022 01:04:29 +0200
Subject: [PATCH 571/685] prepareRowIterator should be internal

---
 Documentation/Index.md                      | 8 --------
 Sources/SQLite/Core/Statement.swift         | 4 ++--
 Tests/SQLiteTests/Core/StatementTests.swift | 2 +-
 3 files changed, 3 insertions(+), 11 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 3d0639b3..fa91f7b7 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -2125,15 +2125,7 @@ using the following functions.
         }
     }
     ```
-    Statements with results may be iterated over, using a `RowIterator` if
-    useful.
     
-    ```swift
-    let emailColumn = Expression<String>("email")
-    let stmt = try db.prepare("SELECT id, email FROM users")
-    let emails = try! stmt.prepareRowIterator().map { $0[emailColumn] }
-    ```
-
   - `run` prepares a single `Statement` object from a SQL string, optionally
     binds values to it (using the statement’s `bind` function), executes,
     and returns the statement.
diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index df4ceebf..80450258 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -236,8 +236,8 @@ extension Statement: FailableIterator {
 }
 
 extension Statement {
-    public func prepareRowIterator() -> RowIterator {
-        return RowIterator(statement: self, columnNames: self.columnNameMap)
+    func prepareRowIterator() -> RowIterator {
+        RowIterator(statement: self, columnNames: columnNameMap)
     }
 
     var columnNameMap: [String: Int] {
diff --git a/Tests/SQLiteTests/Core/StatementTests.swift b/Tests/SQLiteTests/Core/StatementTests.swift
index 2ab84c09..0d82e890 100644
--- a/Tests/SQLiteTests/Core/StatementTests.swift
+++ b/Tests/SQLiteTests/Core/StatementTests.swift
@@ -1,5 +1,5 @@
 import XCTest
-import SQLite
+@testable import SQLite
 
 #if SQLITE_SWIFT_STANDALONE
 import sqlite3

From 11bfa260eef892b0a187a6b77ffe8a94d4e97641 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 18 Oct 2022 23:50:13 +0200
Subject: [PATCH 572/685] Mention query parameter in changelog

---
 CHANGELOG.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 49590fbe..01b7de5a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,7 @@
 
 * Support more complex schema changes and queries ([#1073][], [#1146][] [#1148][])
 * Support `ATTACH`/`DETACH` ([#30][], [#1142][])
+* Expose connection flags (via `URIQueryParameter`) to open db ([#1074][]))
 * Support `WITH` clause ([#1139][])
 * Add `Value` conformance for `NSURL` ([#1110][], [#1141][])
 * Add decoding for `UUID` ([#1137][])
@@ -164,6 +165,7 @@
 [#881]: https://github.com/stephencelis/SQLite.swift/pull/881
 [#919]: https://github.com/stephencelis/SQLite.swift/pull/919
 [#1073]: https://github.com/stephencelis/SQLite.swift/issues/1073
+[#1074]: https://github.com/stephencelis/SQLite.swift/issues/1074
 [#1075]: https://github.com/stephencelis/SQLite.swift/pull/1075
 [#1077]: https://github.com/stephencelis/SQLite.swift/issues/1077
 [#1094]: https://github.com/stephencelis/SQLite.swift/pull/1094

From ff3c4a2d4cc8533c45addba6bbd2d0d90e8833d8 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 21 Oct 2022 12:20:24 +0200
Subject: [PATCH 573/685] Remove outdated/unavailable project refs

---
 README.md | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/README.md b/README.md
index 1b04c7c8..cdc11dd5 100644
--- a/README.md
+++ b/README.md
@@ -267,19 +267,14 @@ These projects enhance or use SQLite.swift:
 
  - [SQLiteMigrationManager.swift][] (inspired by
    [FMDBMigrationManager][])
- - [Delta: Math helper](https://apps.apple.com/app/delta-math-helper/id1436506800)
-   (see [Delta/Utils/Database.swift](https://github.com/GroupeMINASTE/Delta-iOS/blob/master/Delta/Utils/Database.swift) for production implementation example)
-
 
 ## Alternatives
 
 Looking for something else? Try another Swift wrapper (or [FMDB][]):
 
- - [Camembert](https://github.com/remirobert/Camembert)
  - [GRDB](https://github.com/groue/GRDB.swift)
  - [SQLiteDB](https://github.com/FahimF/SQLiteDB)
  - [Squeal](https://github.com/nerdyc/Squeal)
- - [SwiftData](https://github.com/ryanfowler/SwiftData)
 
 [Swift]: https://swift.org/
 [SQLite3]: https://www.sqlite.org

From dad179a555d0d2714ab1fcf69ba938073d17ff54 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 21 Oct 2022 18:47:32 +0200
Subject: [PATCH 574/685] Bump version number

---
 Documentation/Index.md                | 12 ++++++------
 README.md                             |  8 ++++----
 SQLite.swift.podspec                  |  2 +-
 SQLite.xcodeproj/project.pbxproj      |  4 ++--
 Sources/SQLite/Typed/Expression.swift |  3 +--
 Tests/SPM/Package.swift               |  2 +-
 6 files changed, 15 insertions(+), 16 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index fa91f7b7..65cf5114 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -83,7 +83,7 @@ process of downloading, compiling, and linking dependencies.
 
   ```swift
   dependencies: [
-    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.13.3")
+    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.0")
   ]
   ```
 
@@ -104,7 +104,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.13.3
+    github "stephencelis/SQLite.swift" ~> 0.14.0
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -134,7 +134,7 @@ install SQLite.swift with Carthage:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.13.3'
+        pod 'SQLite.swift', '~> 0.14.0'
     end
     ```
 
@@ -148,7 +148,7 @@ with the OS you can require the `standalone` subspec:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.13.3'
+  pod 'SQLite.swift/standalone', '~> 0.14.0'
 end
 ```
 
@@ -158,7 +158,7 @@ dependency to sqlite3 or one of its subspecs:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.13.3'
+  pod 'SQLite.swift/standalone', '~> 0.14.0'
   pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
 end
 ```
@@ -174,7 +174,7 @@ If you want to use [SQLCipher][] with SQLite.swift you can require the
 target 'YourAppTargetName' do
   # Make sure you only require the subspec, otherwise you app might link against
   # the system SQLite, which means the SQLCipher-specific methods won't work.
-  pod 'SQLite.swift/SQLCipher', '~> 0.13.3'
+  pod 'SQLite.swift/SQLCipher', '~> 0.14.0'
 end
 ```
 
diff --git a/README.md b/README.md
index cdc11dd5..ab1b67f5 100644
--- a/README.md
+++ b/README.md
@@ -136,7 +136,7 @@ Swift code.
 
   ```swift
   dependencies: [
-      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.13.3")
+      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.0")
   ]
   ```
 
@@ -160,7 +160,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.13.3
+    github "stephencelis/SQLite.swift" ~> 0.14.0
     ```
 
  3. Run `carthage update` and
@@ -191,7 +191,7 @@ SQLite.swift with CocoaPods:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.13.3'
+        pod 'SQLite.swift', '~> 0.14.0'
     end
     ```
 
@@ -250,7 +250,7 @@ device:
 [Submit a pull request]: https://github.com/stephencelis/SQLite.swift/fork
 
 
-## Author
+## Original author
 
  - [Stephen Celis](mailto:stephen@stephencelis.com)
    ([@stephencelis](https://twitter.com/stephencelis))
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index d36d0330..c30aa765 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.13.3"
+  s.version          = "0.14.0"
   s.summary          = "A type-safe, Swift-language layer over SQLite3."
 
   s.description      = <<-DESC
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 6fe89283..3d62e980 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1497,7 +1497,7 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
-				MARKETING_VERSION = 0.13.3;
+				MARKETING_VERSION = 0.14.0;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
@@ -1520,7 +1520,7 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
-				MARKETING_VERSION = 0.13.3;
+				MARKETING_VERSION = 0.14.0;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
diff --git a/Sources/SQLite/Typed/Expression.swift b/Sources/SQLite/Typed/Expression.swift
index 95cdd3b9..de5afe2e 100644
--- a/Sources/SQLite/Typed/Expression.swift
+++ b/Sources/SQLite/Typed/Expression.swift
@@ -73,8 +73,7 @@ public protocol Expressible {
 extension Expressible {
 
     // naïve compiler for statements that can’t be bound, e.g., CREATE TABLE
-    // FIXME: make internal (0.13.0)
-    public func asSQL() -> String {
+    func asSQL() -> String {
         let expressed = expression
         var idx = 0
         return expressed.template.reduce("") { template, character in
diff --git a/Tests/SPM/Package.swift b/Tests/SPM/Package.swift
index dd1cd45c..d5d2e9ff 100644
--- a/Tests/SPM/Package.swift
+++ b/Tests/SPM/Package.swift
@@ -15,7 +15,7 @@ let package = Package(
         // for testing from same repository
         .package(path: "../..")
         // normally this would be:
-        // .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.13.0")
+        // .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.0")
     ],
     targets: [
         .target(

From 136a5c5c07d0084d459bb6fa466eba1e564c3e9f Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 22 Oct 2022 23:51:34 +0200
Subject: [PATCH 575/685] Add ExpressionTests

---
 Sources/SQLite/Typed/Expression.swift         | 20 +++++++-------
 Tests/SQLiteTests/TestHelpers.swift           |  2 +-
 Tests/SQLiteTests/Typed/ExpressionTests.swift | 27 ++++++++++++++++++-
 .../Typed/QueryIntegrationTests.swift         |  7 ++++-
 4 files changed, 43 insertions(+), 13 deletions(-)

diff --git a/Sources/SQLite/Typed/Expression.swift b/Sources/SQLite/Typed/Expression.swift
index de5afe2e..af125cc2 100644
--- a/Sources/SQLite/Typed/Expression.swift
+++ b/Sources/SQLite/Typed/Expression.swift
@@ -64,31 +64,31 @@ public struct Expression<Datatype>: ExpressionType {
 
 }
 
-public protocol Expressible {
+public protocol Expressible: CustomStringConvertible {
 
     var expression: Expression<Void> { get }
 
 }
 
 extension Expressible {
+    public var description: String {
+        asSQL()
+    }
 
     // naïve compiler for statements that can’t be bound, e.g., CREATE TABLE
     func asSQL() -> String {
         let expressed = expression
-        var idx = 0
-        return expressed.template.reduce("") { template, character in
-            let transcoded: String
+        return expressed.template.reduce(("", 0)) { memo, character in
+            let (template, index) = memo
 
             if character == "?" {
-                transcoded = transcode(expressed.bindings[idx])
-                idx += 1
+                precondition(index < expressed.bindings.count, "not enough bindings for expression")
+                return (template + transcode(expressed.bindings[index]), index + 1)
             } else {
-                transcoded = String(character)
+                return (template + String(character), index)
             }
-            return template + transcoded
-        }
+        }.0
     }
-
 }
 
 extension ExpressionType {
diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index 2a8c7e39..65cff8bb 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -12,7 +12,7 @@ class SQLiteTestCase: XCTestCase {
         trace = [String: Int]()
 
         db.trace { SQL in
-            print(SQL)
+            // print("SQL: \(SQL)")
             self.trace[SQL, default: 0] += 1
         }
     }
diff --git a/Tests/SQLiteTests/Typed/ExpressionTests.swift b/Tests/SQLiteTests/Typed/ExpressionTests.swift
index 32100d4d..9155a45c 100644
--- a/Tests/SQLiteTests/Typed/ExpressionTests.swift
+++ b/Tests/SQLiteTests/Typed/ExpressionTests.swift
@@ -1,5 +1,30 @@
 import XCTest
-import SQLite
+@testable import SQLite
 
 class ExpressionTests: XCTestCase {
+
+    func test_asSQL_expression_bindings() {
+        let expression = Expression<String>("foo ? bar", ["baz"])
+        XCTAssertEqual(expression.asSQL(), "foo 'baz' bar")
+    }
+
+    func test_asSQL_expression_bindings_quoting() {
+        let expression = Expression<String>("foo ? bar", ["'baz'"])
+        XCTAssertEqual(expression.asSQL(), "foo '''baz''' bar")
+    }
+
+    func test_expression_custom_string_convertible() {
+        let expression = Expression<String>("foo ? bar", ["baz"])
+        XCTAssertEqual(expression.asSQL(), expression.description)
+    }
+
+    func test_init_literal() {
+        let expression = Expression<String>(literal: "literal")
+        XCTAssertEqual(expression.template, "literal")
+    }
+
+    func test_init_identifier() {
+        let expression = Expression<String>("identifier")
+        XCTAssertEqual(expression.template, "\"identifier\"")
+    }
 }
diff --git a/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift b/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
index 27b78c0a..3fd388e9 100644
--- a/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
+++ b/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
@@ -192,7 +192,12 @@ class QueryIntegrationTests: SQLiteTestCase {
         let query3 = users.select(users[*], Expression<Int>(literal: "1 AS weight")).filter(email == "sally@example.com")
         let query4 = users.select(users[*], Expression<Int>(literal: "2 AS weight")).filter(email == "alice@example.com")
 
-        print(query3.union(query4).order(Expression<Int>(literal: "weight")).asSQL())
+        let sql = query3.union(query4).order(Expression<Int>(literal: "weight")).asSQL()
+        XCTAssertEqual(sql,
+        """
+        SELECT "users".*, 1 AS weight FROM "users" WHERE ("email" = 'sally@example.com') UNION \
+        SELECT "users".*, 2 AS weight FROM "users" WHERE ("email" = 'alice@example.com') ORDER BY weight
+        """)
 
         let orderedIDs = try db.prepare(query3.union(query4).order(Expression<Int>(literal: "weight"), email)).map { $0[id] }
         XCTAssertEqual(Array(expectedIDs.reversed()), orderedIDs)

From fc8f8df40b8434337338633fc5ae853736c1adad Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 24 Oct 2022 10:40:21 +0200
Subject: [PATCH 576/685] Remove outdated docs/links

---
 README.md | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/README.md b/README.md
index ab1b67f5..0d9396c6 100644
--- a/README.md
+++ b/README.md
@@ -19,6 +19,7 @@ syntax _and_ intent.
  - [Well-documented][See Documentation]
  - Extensively tested
  - [SQLCipher][] support via CocoaPods
+ - [Schema query/migration][]
  - Works on [Linux](Documentation/Linux.md) (with some limitations)
  - Active support at
    [StackOverflow](https://stackoverflow.com/questions/tagged/sqlite.swift),
@@ -27,6 +28,7 @@ syntax _and_ intent.
 
 [SQLCipher]: https://www.zetetic.net/sqlcipher/
 [Full-text search]: Documentation/Index.md#full-text-search
+[Schema query/migration]: Documentation/Index.md#querying-the-schema
 [See Documentation]: Documentation/Index.md#sqliteswift-documentation
 
 
@@ -115,17 +117,10 @@ interactively, from the Xcode project’s playground.
 
 ![SQLite.playground Screen Shot](Documentation/Resources/playground@2x.png)
 
-For a more comprehensive example, see
-[this article][Create a Data Access Layer with SQLite.swift and Swift 2]
-and the [companion repository][SQLiteDataAccessLayer2].
-
-
-[Create a Data Access Layer with SQLite.swift and Swift 2]: https://masteringswift.blogspot.com/2015/09/create-data-access-layer-with.html
-[SQLiteDataAccessLayer2]: https://github.com/hoffmanjon/SQLiteDataAccessLayer2/tree/master
-
 ## Installation
 
-> _Note:_ Version 0.11.6 and later requires Swift 5 (and [Xcode](https://developer.apple.com/xcode/downloads/) 10.2) or greater. Version 0.11.5 requires Swift 4.2 (and [Xcode](https://developer.apple.com/xcode/downloads/) 10.1) or greater.
+> _Note:_ Version 0.11.6 and later requires Swift 5 (and [Xcode](https://developer.apple.com/xcode/downloads/) 10.2) or greater.
+> Version 0.11.5 requires Swift 4.2 (and [Xcode](https://developer.apple.com/xcode/downloads/) 10.1) or greater.
 
 ### Swift Package Manager
 

From 0eb58d8fa82e864d1071c92a2fc88747484d3f48 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 26 Oct 2022 23:34:17 +0200
Subject: [PATCH 577/685] Doc updates

---
 CHANGELOG.md                                  |  1 +
 Documentation/Index.md                        | 90 +++++++++----------
 Documentation/Release.md                      |  1 +
 Documentation/Upgrading.md                    | 11 +++
 SQLite.playground/Contents.swift              |  1 +
 Sources/SQLite/Schema/SchemaChanger.swift     | 10 +--
 .../Schema/SchemaChangerTests.swift           | 14 +++
 7 files changed, 78 insertions(+), 50 deletions(-)
 create mode 100644 Documentation/Upgrading.md

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 01b7de5a..92c89e9d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,6 @@
 0.14.0 (tbd), [diff][diff-0.14.0]
 ========================================
+For breaking changes, see [Upgrading.md](Documentation/Upgrading.md).
 
 * Support more complex schema changes and queries ([#1073][], [#1146][] [#1148][])
 * Support `ATTACH`/`DETACH` ([#30][], [#1142][])
diff --git a/Documentation/Index.md b/Documentation/Index.md
index 65cf5114..bdd1da28 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -41,14 +41,19 @@
   - [Updating Rows](#updating-rows)
   - [Deleting Rows](#deleting-rows)
   - [Transactions and Savepoints](#transactions-and-savepoints)
+  - [Querying the Schema](#querying-the-schema)
   - [Altering the Schema](#altering-the-schema)
     - [Renaming Tables](#renaming-tables)
+    - [Dropping Tables](#dropping-tables)
     - [Adding Columns](#adding-columns)
       - [Added Column Constraints](#added-column-constraints)
+    - [Schema Changer](#schemachanger)
+      - [Renaming Columns](#renaming-columns)
+      - [Dropping Columns](#dropping-columns)
+      - [Renaming/dropping tables](#renamingdropping-tables)
     - [Indexes](#indexes)
       - [Creating Indexes](#creating-indexes)
       - [Dropping Indexes](#dropping-indexes)
-    - [Dropping Tables](#dropping-tables)
     - [Migrations and Schema Versioning](#migrations-and-schema-versioning)
   - [Custom Types](#custom-types)
     - [Date-Time Values](#date-time-values)
@@ -1409,7 +1414,6 @@ for column in columns {
 SQLite.swift comes with several functions (in addition to `Table.create`) for
 altering a database schema in a type-safe manner.
 
-
 ### Renaming Tables
 
 We can build an `ALTER TABLE … RENAME TO` statement by calling the `rename`
@@ -1420,6 +1424,24 @@ try db.run(users.rename(Table("users_old")))
 // ALTER TABLE "users" RENAME TO "users_old"
 ```
 
+### Dropping Tables
+
+We can build
+[`DROP TABLE` statements](https://www.sqlite.org/lang_droptable.html)
+by calling the `dropTable` function on a `SchemaType`.
+
+```swift
+try db.run(users.drop())
+// DROP TABLE "users"
+```
+
+The `drop` function has one additional parameter, `ifExists`, which (when
+`true`) adds an `IF EXISTS` clause to the statement.
+
+```swift
+try db.run(users.drop(ifExists: true))
+// DROP TABLE IF EXISTS "users"
+```
 
 ### Adding Columns
 
@@ -1484,57 +1506,54 @@ tables](#creating-a-table).
     // ALTER TABLE "posts" ADD COLUMN "user_id" INTEGER REFERENCES "users" ("id")
     ```
 
-### Renaming Columns
+### SchemaChanger
 
-We can rename columns with the help of the `SchemaChanger` class:
+Version 0.14.0 introduces `SchemaChanger`, an alternative API to perform more complex
+migrations such as renaming columns. These operations work with all versions of
+SQLite but use SQL statements such as `ALTER TABLE RENAME COLUMN` when available.
+
+#### Adding Columns
 
 ```swift
+let newColumn = ColumnDefinition(
+    name: "new_text_column",
+    type: .TEXT,
+    nullable: true,
+    defaultValue: .stringLiteral("foo")
+)
+
 let schemaChanger = SchemaChanger(connection: db)
+
 try schemaChanger.alter(table: "users") { table in
-    table.rename(column: "old_name", to: "new_name")
+    table.add(newColumn)
 }
 ```
 
-### Dropping Columns
+#### Renaming Columns
 
 ```swift
 let schemaChanger = SchemaChanger(connection: db)
 try schemaChanger.alter(table: "users") { table in
-    table.drop(column: "email")
+    table.rename(column: "old_name", to: "new_name")
 }
 ```
 
-These operations will work with all versions of SQLite and use modern SQL
-operations such as `DROP COLUMN` when available.
-
-### Adding Columns (SchemaChanger)
-
-The `SchemaChanger` provides an alternative API to add new columns:
+#### Dropping Columns
 
 ```swift
-let newColumn = ColumnDefinition(
-    name: "new_text_column",
-    type: .TEXT,
-    nullable: true,
-    defaultValue: .stringLiteral("foo")
-)
-
 let schemaChanger = SchemaChanger(connection: db)
-
 try schemaChanger.alter(table: "users") { table in
-    table.add(newColumn)
+    table.drop(column: "email")
 }
 ```
 
-### Renaming/dropping Tables (SchemaChanger)
-
-The `SchemaChanger` provides an alternative API to rename and drop tables:
+#### Renaming/dropping Tables
 
 ```swift
 let schemaChanger = SchemaChanger(connection: db)
 
 try schemaChanger.rename(table: "users", to: "users_new")
-try schemaChanger.drop(table: "emails")
+try schemaChanger.drop(table: "emails", ifExists: false)
 ```
 
 ### Indexes
@@ -1592,25 +1611,6 @@ try db.run(users.dropIndex(email, ifExists: true))
 // DROP INDEX IF EXISTS "index_users_on_email"
 ```
 
-### Dropping Tables
-
-We can build
-[`DROP TABLE` statements](https://www.sqlite.org/lang_droptable.html)
-by calling the `dropTable` function on a `SchemaType`.
-
-```swift
-try db.run(users.drop())
-// DROP TABLE "users"
-```
-
-The `drop` function has one additional parameter, `ifExists`, which (when
-`true`) adds an `IF EXISTS` clause to the statement.
-
-```swift
-try db.run(users.drop(ifExists: true))
-// DROP TABLE IF EXISTS "users"
-```
-
 ### Migrations and Schema Versioning
 
 You can use the convenience property on `Connection` to query and set the
diff --git a/Documentation/Release.md b/Documentation/Release.md
index 87d715f6..8ec67970 100644
--- a/Documentation/Release.md
+++ b/Documentation/Release.md
@@ -3,6 +3,7 @@
 * [ ] Make sure current master branch has a green build
 * [ ] Make sure `SQLite.playground` runs without errors
 * [ ] Make sure `CHANGELOG.md` is up-to-date
+* [ ] Add content to `Documentation/Upgrading.md` if needed
 * [ ] Update the version number in `SQLite.swift.podspec`
 * [ ] Run `pod lib lint` locally
 * [ ] Update the version numbers mentioned in `README.md`, `Documentation/Index.md`
diff --git a/Documentation/Upgrading.md b/Documentation/Upgrading.md
new file mode 100644
index 00000000..8c398467
--- /dev/null
+++ b/Documentation/Upgrading.md
@@ -0,0 +1,11 @@
+# Upgrading
+
+## 0.13 → 0.14
+
+- `Expression.asSQL()` is no longer available. Expressions now implement `CustomStringConvertible`,
+  where `description` returns the SQL.
+- `Statement.prepareRowIterator()` is now longer available. Instead, use the methods
+  of the same name on `Connection`.
+- `Blob` no longer wraps byte arrays and now uses `NSData`, which enables memory and
+ performance improvements.
+- `Connection.registerTokenizer` is no longer available to register custom FTS4 tokenizers.
diff --git a/SQLite.playground/Contents.swift b/SQLite.playground/Contents.swift
index 5a7ea379..0eafdd0d 100644
--- a/SQLite.playground/Contents.swift
+++ b/SQLite.playground/Contents.swift
@@ -52,6 +52,7 @@ for user in try Array(rowIterator) {
 
 /// also with `map()`
 let mapRowIterator = try db.prepareRowIterator(users)
+
 let userIds = try mapRowIterator.map { $0[id] }
 
 /// using `failableNext()` on `RowIterator`
diff --git a/Sources/SQLite/Schema/SchemaChanger.swift b/Sources/SQLite/Schema/SchemaChanger.swift
index 67f2b0d3..af710908 100644
--- a/Sources/SQLite/Schema/SchemaChanger.swift
+++ b/Sources/SQLite/Schema/SchemaChanger.swift
@@ -141,8 +141,8 @@ public class SchemaChanger: CustomStringConvertible {
         }
     }
 
-    public func drop(table: String) throws {
-        try dropTable(table)
+    public func drop(table: String, ifExists: Bool = true) throws {
+        try dropTable(table, ifExists: ifExists)
     }
 
     // Beginning with release 3.25.0 (2018-09-15), references to the table within trigger bodies and
@@ -192,7 +192,7 @@ public class SchemaChanger: CustomStringConvertible {
 
     private func moveTable(from: String, to: String, options: Options = .default, operation: Operation? = nil) throws {
         try copyTable(from: from, to: to, options: options, operation: operation)
-        try dropTable(from)
+        try dropTable(from, ifExists: true)
     }
 
     private func copyTable(from: String, to: String, options: Options = .default, operation: Operation?) throws {
@@ -225,8 +225,8 @@ public class SchemaChanger: CustomStringConvertible {
         }
     }
 
-    private func dropTable(_ table: String) throws {
-        try connection.run("DROP TABLE IF EXISTS \(table.quote())")
+    private func dropTable(_ table: String, ifExists: Bool) throws {
+        try connection.run("DROP TABLE \(ifExists ? "IF EXISTS" : "") \(table.quote())")
     }
 
     private func copyTableContents(from: TableDefinition, to: TableDefinition) throws {
diff --git a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
index 2894e5ce..40f65b62 100644
--- a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
@@ -135,6 +135,20 @@ class SchemaChangerTests: SQLiteTestCase {
         }
     }
 
+    func test_drop_table_if_exists_true() throws {
+        try schemaChanger.drop(table: "xxx", ifExists: true)
+    }
+
+    func test_drop_table_if_exists_false() throws {
+        XCTAssertThrowsError(try schemaChanger.drop(table: "xxx", ifExists: false)) { error in
+            if case Result.error(let message, _, _) =  error {
+                XCTAssertEqual(message, "no such table: xxx")
+            } else {
+                XCTFail("unexpected error \(error)")
+            }
+        }
+    }
+
     func test_rename_table() throws {
         try schemaChanger.rename(table: "users", to: "users_new")
         let users_new = Table("users_new")

From 25708c9804d906d039a293538e45877e9262d433 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 26 Oct 2022 23:48:00 +0200
Subject: [PATCH 578/685] Updates

---
 CHANGELOG.md           | 2 +-
 Documentation/Index.md | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 92c89e9d..2783a67d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,4 @@
-0.14.0 (tbd), [diff][diff-0.14.0]
+0.14.0 (27-10-2022), [diff][diff-0.14.0]
 ========================================
 For breaking changes, see [Upgrading.md](Documentation/Upgrading.md).
 
diff --git a/Documentation/Index.md b/Documentation/Index.md
index bdd1da28..20469037 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -50,7 +50,7 @@
     - [Schema Changer](#schemachanger)
       - [Renaming Columns](#renaming-columns)
       - [Dropping Columns](#dropping-columns)
-      - [Renaming/dropping tables](#renamingdropping-tables)
+      - [Renaming/dropping Tables](#renamingdropping-tables)
     - [Indexes](#indexes)
       - [Creating Indexes](#creating-indexes)
       - [Dropping Indexes](#dropping-indexes)
@@ -173,7 +173,7 @@ See the [sqlite3 podspec][sqlite3pod] for more details.
 #### Using SQLite.swift with SQLCipher
 
 If you want to use [SQLCipher][] with SQLite.swift you can require the
-`SQLCipher` subspec in your Podfile:
+`SQLCipher` subspec in your Podfile (SPM is not supported yet, see [#1084](/issues/1084)):
 
 ```ruby
 target 'YourAppTargetName' do
@@ -2183,7 +2183,7 @@ try db.detach("external")
 // DETACH DATABASE 'external'
 ```
 
-When compiled for SQLCipher, you can additionally pass a `key` parameter to `attach`:
+When compiled for SQLCipher, we can additionally pass a `key` parameter to `attach`:
 
 ```swift
 try db.attach(.uri("encrypted.sqlite"), as: "encrypted", key: "secret")

From ac09389994bb6549a3f978d996f2d3a06b5a0071 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 27 Oct 2022 00:04:22 +0200
Subject: [PATCH 579/685] Mention group container problems

Closes #1042
---
 Documentation/Index.md | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 20469037..363443d6 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -9,6 +9,7 @@
     - [Connecting to a Database](#connecting-to-a-database)
       - [Read-Write Databases](#read-write-databases)
       - [Read-Only Databases](#read-only-databases)
+      - [In a Shared Group Container](#in-a-shared-group-container)
       - [In-Memory Databases](#in-memory-databases)
       - [URI parameters](#uri-parameters)
       - [Thread-Safety](#thread-safety)
@@ -173,7 +174,7 @@ See the [sqlite3 podspec][sqlite3pod] for more details.
 #### Using SQLite.swift with SQLCipher
 
 If you want to use [SQLCipher][] with SQLite.swift you can require the
-`SQLCipher` subspec in your Podfile (SPM is not supported yet, see [#1084](/issues/1084)):
+`SQLCipher` subspec in your Podfile (SPM is not supported yet, see [#1084](https://github.com/stephencelis/SQLite.swift/issues/1084)):
 
 ```ruby
 target 'YourAppTargetName' do
@@ -330,6 +331,13 @@ let db = try Connection(path, readonly: true)
 > We welcome changes to the above sample code to show how to successfully copy and use a bundled "seed"
 > database for writing in an app.
 
+#### In a shared group container
+
+It is not recommend to store databases in a [shared group container],
+some users have reported crashes ([#1042](https://github.com/stephencelis/SQLite.swift/issues/1042)).
+
+[shared group container]: https://developer.apple.com/documentation/foundation/filemanager/1412643-containerurl#
+
 #### In-Memory Databases
 
 If you omit the path, SQLite.swift will provision an [in-memory

From 194d99addcfbf76795d00c072470623b4ded5ad8 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 27 Oct 2022 00:51:19 +0200
Subject: [PATCH 580/685] Fix ambiguous use of description

---
 Sources/SQLite/Extensions/FTS4.swift          | 50 ++++++++-----------
 Sources/SQLite/Extensions/FTS5.swift          | 18 +++----
 Sources/SQLite/Typed/Expression.swift         | 10 ++--
 Tests/SQLiteTests/Typed/ExpressionTests.swift |  5 ++
 4 files changed, 39 insertions(+), 44 deletions(-)

diff --git a/Sources/SQLite/Extensions/FTS4.swift b/Sources/SQLite/Extensions/FTS4.swift
index e9e65746..8e91e453 100644
--- a/Sources/SQLite/Extensions/FTS4.swift
+++ b/Sources/SQLite/Extensions/FTS4.swift
@@ -117,7 +117,7 @@ public struct Tokenizer {
 
     // https://sqlite.org/fts5.html#the_experimental_trigram_tokenizer
     public static func Trigram(caseSensitive: Bool = false) -> Tokenizer {
-        return Tokenizer("trigram", ["case_sensitive", caseSensitive ? "1" : "0"])
+        Tokenizer("trigram", ["case_sensitive", caseSensitive ? "1" : "0"])
     }
 
     public static func Custom(_ name: String) -> Tokenizer {
@@ -236,18 +236,12 @@ open class FTSConfig {
             }
         }
 
-        @discardableResult mutating func append(_ key: String, value: CustomStringConvertible?) -> Options {
-            append(key, value: value?.description)
+        @discardableResult mutating func append(_ key: String, value: String) -> Options {
+            append(key, value: Expression<String>(value))
         }
 
-        @discardableResult mutating func append(_ key: String, value: String?) -> Options {
-            append(key, value: value.map { Expression<String>($0) })
-        }
-
-        @discardableResult mutating func append(_ key: String, value: Expressible?) -> Options {
-            if let value = value {
-                arguments.append("=".join([Expression<Void>(literal: key), value]))
-            }
+        @discardableResult mutating func append(_ key: String, value: Expressible) -> Options {
+            arguments.append("=".join([Expression<Void>(literal: key), value]))
             return self
         }
     }
@@ -256,26 +250,16 @@ open class FTSConfig {
 /// Configuration for the [FTS4](https://www.sqlite.org/fts3.html) extension.
 open class FTS4Config: FTSConfig {
     /// [The matchinfo= option](https://www.sqlite.org/fts3.html#section_6_4)
-    public enum MatchInfo: CustomStringConvertible {
+    public enum MatchInfo: String {
         case fts3
-        public var description: String {
-            "fts3"
-        }
     }
 
     /// [FTS4 options](https://www.sqlite.org/fts3.html#fts4_options)
-    public enum Order: CustomStringConvertible {
+    public enum Order: String {
         /// Data structures are optimized for returning results in ascending order by docid (default)
         case asc
         /// FTS4 stores its data in such a way as to optimize returning results in descending order by docid.
         case desc
-
-        public var description: String {
-            switch self {
-            case .asc: return "asc"
-            case .desc: return "desc"
-            }
-        }
     }
 
     var compressFunction: String?
@@ -322,11 +306,21 @@ open class FTS4Config: FTSConfig {
         for (column, _) in (columnDefinitions.filter { $0.options.contains(.unindexed) }) {
             options.append("notindexed", value: column)
         }
-        options.append("languageid", value: languageId)
-        options.append("compress", value: compressFunction)
-        options.append("uncompress", value: uncompressFunction)
-        options.append("matchinfo", value: matchInfo)
-        options.append("order", value: order)
+        if let languageId = languageId {
+            options.append("languageid", value: languageId)
+        }
+        if let compressFunction = compressFunction {
+            options.append("compress", value: compressFunction)
+        }
+        if let uncompressFunction = uncompressFunction {
+            options.append("uncompress", value: uncompressFunction)
+        }
+        if let matchInfo = matchInfo {
+            options.append("matchinfo", value: matchInfo.rawValue)
+        }
+        if let order = order {
+            options.append("order", value: order.rawValue)
+        }
         return options
     }
 }
diff --git a/Sources/SQLite/Extensions/FTS5.swift b/Sources/SQLite/Extensions/FTS5.swift
index f108bbec..2e4f65fb 100644
--- a/Sources/SQLite/Extensions/FTS5.swift
+++ b/Sources/SQLite/Extensions/FTS5.swift
@@ -33,21 +33,13 @@ extension Module {
 /// **Note:** this is currently only applicable when using SQLite.swift together with a FTS5-enabled version
 /// of SQLite.
 open class FTS5Config: FTSConfig {
-    public enum Detail: CustomStringConvertible {
+    public enum Detail: String {
         /// store rowid, column number, term offset
         case full
         /// store rowid, column number
         case column
         /// store rowid
         case none
-
-        public var description: String {
-            switch self {
-            case .full: return "full"
-            case .column: return "column"
-            case .none: return "none"
-            }
-        }
     }
 
     var detail: Detail?
@@ -77,11 +69,15 @@ open class FTS5Config: FTSConfig {
 
     override func options() -> Options {
         var options = super.options()
-        options.append("content_rowid", value: contentRowId)
+        if let contentRowId = contentRowId {
+            options.append("content_rowid", value: contentRowId)
+        }
         if let columnSize = columnSize {
             options.append("columnsize", value: Expression<Int>(value: columnSize))
         }
-        options.append("detail", value: detail)
+        if let detail = detail {
+            options.append("detail", value: detail.rawValue)
+        }
         return options
     }
 
diff --git a/Sources/SQLite/Typed/Expression.swift b/Sources/SQLite/Typed/Expression.swift
index af125cc2..dcc44fe4 100644
--- a/Sources/SQLite/Typed/Expression.swift
+++ b/Sources/SQLite/Typed/Expression.swift
@@ -22,7 +22,7 @@
 // THE SOFTWARE.
 //
 
-public protocol ExpressionType: Expressible { // extensions cannot have inheritance clauses
+public protocol ExpressionType: Expressible, CustomStringConvertible { // extensions cannot have inheritance clauses
 
     associatedtype UnderlyingType = Void
 
@@ -47,6 +47,9 @@ extension ExpressionType {
         self.init(expression.template, expression.bindings)
     }
 
+    public var description: String {
+        asSQL()
+    }
 }
 
 /// An `Expression` represents a raw SQL fragment and any associated bindings.
@@ -64,16 +67,13 @@ public struct Expression<Datatype>: ExpressionType {
 
 }
 
-public protocol Expressible: CustomStringConvertible {
+public protocol Expressible {
 
     var expression: Expression<Void> { get }
 
 }
 
 extension Expressible {
-    public var description: String {
-        asSQL()
-    }
 
     // naïve compiler for statements that can’t be bound, e.g., CREATE TABLE
     func asSQL() -> String {
diff --git a/Tests/SQLiteTests/Typed/ExpressionTests.swift b/Tests/SQLiteTests/Typed/ExpressionTests.swift
index 9155a45c..147d62e9 100644
--- a/Tests/SQLiteTests/Typed/ExpressionTests.swift
+++ b/Tests/SQLiteTests/Typed/ExpressionTests.swift
@@ -18,6 +18,11 @@ class ExpressionTests: XCTestCase {
         XCTAssertEqual(expression.asSQL(), expression.description)
     }
 
+    func test_builtin_unambiguously_custom_string_convertible() {
+        let integer: Int = 45
+        XCTAssertEqual(integer.description, "45")
+    }
+
     func test_init_literal() {
         let expression = Expression<String>(literal: "literal")
         XCTAssertEqual(expression.template, "literal")

From 367f6aaee8228f71eedcfcc34e1433e79c46c632 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 27 Oct 2022 10:17:46 +0200
Subject: [PATCH 581/685] add(_ column:) => add(column:)

---
 Documentation/Index.md                            | 2 +-
 SQLite.playground/Contents.swift                  | 2 +-
 Sources/SQLite/Schema/SchemaChanger.swift         | 2 +-
 Tests/SQLiteTests/Schema/SchemaChangerTests.swift | 4 ++--
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 363443d6..c518c739 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1533,7 +1533,7 @@ let newColumn = ColumnDefinition(
 let schemaChanger = SchemaChanger(connection: db)
 
 try schemaChanger.alter(table: "users") { table in
-    table.add(newColumn)
+    table.add(column: newColumn)
 }
 ```
 
diff --git a/SQLite.playground/Contents.swift b/SQLite.playground/Contents.swift
index 0eafdd0d..f651cbc1 100644
--- a/SQLite.playground/Contents.swift
+++ b/SQLite.playground/Contents.swift
@@ -115,7 +115,7 @@ print(columns)
 
 let schemaChanger = SchemaChanger(connection: db)
 try schemaChanger.alter(table: "users") { table in
-    table.add(ColumnDefinition(name: "age", type: .INTEGER))
+    table.add(column: ColumnDefinition(name: "age", type: .INTEGER))
     table.rename(column: "email", to: "electronic_mail")
     table.drop(column: "name")
 }
diff --git a/Sources/SQLite/Schema/SchemaChanger.swift b/Sources/SQLite/Schema/SchemaChanger.swift
index af710908..af7b5e27 100644
--- a/Sources/SQLite/Schema/SchemaChanger.swift
+++ b/Sources/SQLite/Schema/SchemaChanger.swift
@@ -95,7 +95,7 @@ public class SchemaChanger: CustomStringConvertible {
             self.name = name
         }
 
-        public func add(_ column: ColumnDefinition) {
+        public func add(column: ColumnDefinition) {
             operations.append(.addColumn(column))
         }
 
diff --git a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
index 40f65b62..9f8e21f4 100644
--- a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
@@ -99,7 +99,7 @@ class SchemaChangerTests: SQLiteTestCase {
                                          defaultValue: .stringLiteral("foo"))
 
         try schemaChanger.alter(table: "users") { table in
-            table.add(newColumn)
+            table.add(column: newColumn)
         }
 
         let columns = try schema.columnDefinitions(table: "users")
@@ -114,7 +114,7 @@ class SchemaChangerTests: SQLiteTestCase {
                                          type: .TEXT)
 
         XCTAssertThrowsError(try schemaChanger.alter(table: "users") { table in
-            table.add(newColumn)
+            table.add(column: newColumn)
         }) { error in
             if case SchemaChanger.Error.invalidColumnDefinition(_) = error {
                 XCTAssertEqual("Invalid column definition: can not add primary key column", error.localizedDescription)

From 2c4af8526e112e3a23df141e988d08a28e475ecd Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 27 Oct 2022 10:21:13 +0200
Subject: [PATCH 582/685] Update docs

---
 Documentation/Index.md | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index c518c739..ada9b7c3 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -49,9 +49,10 @@
     - [Adding Columns](#adding-columns)
       - [Added Column Constraints](#added-column-constraints)
     - [Schema Changer](#schemachanger)
+      - [Adding Columns](#adding-columns)
       - [Renaming Columns](#renaming-columns)
       - [Dropping Columns](#dropping-columns)
-      - [Renaming/dropping Tables](#renamingdropping-tables)
+      - [Renaming/Dropping Tables](#renamingdropping-tables)
     - [Indexes](#indexes)
       - [Creating Indexes](#creating-indexes)
       - [Dropping Indexes](#dropping-indexes)
@@ -1555,7 +1556,7 @@ try schemaChanger.alter(table: "users") { table in
 }
 ```
 
-#### Renaming/dropping Tables
+#### Renaming/Dropping Tables
 
 ```swift
 let schemaChanger = SchemaChanger(connection: db)

From 3161f06acd378ff3e5e91c0c590c9dc2edba1ce5 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 27 Oct 2022 12:06:14 +0200
Subject: [PATCH 583/685] Use direct links

---
 README.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 0d9396c6..ac0c2a7a 100644
--- a/README.md
+++ b/README.md
@@ -277,10 +277,10 @@ Looking for something else? Try another Swift wrapper (or [FMDB][]):
 
 [GitHubActionBadge]: https://img.shields.io/github/workflow/status/stephencelis/SQLite.swift/Build%20and%20test
 
-[CocoaPodsVersionBadge]: https://cocoapod-badges.herokuapp.com/v/SQLite.swift/badge.png
+[CocoaPodsVersionBadge]: https://img.shields.io/cocoapods/v/SQLite.swift.svg?style=flat
 [CocoaPodsVersionLink]: https://cocoapods.org/pods/SQLite.swift
 
-[PlatformBadge]: https://cocoapod-badges.herokuapp.com/p/SQLite.swift/badge.png
+[PlatformBadge]: https://img.shields.io/cocoapods/p/SQLite.swift.svg?style=flat
 [PlatformLink]: https://cocoapods.org/pods/SQLite.swift
 
 [CartagheBadge]: https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat

From 1235d44cd3e8596e842a47c03efbcbdb61797024 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 1 Nov 2022 22:28:21 +0100
Subject: [PATCH 584/685] Revert changes to Blob

---
 CHANGELOG.md                                  |  6 +++
 Documentation/Index.md                        | 12 ++---
 README.md                                     |  4 +-
 SQLite.swift.podspec                          |  2 +-
 Sources/SQLite/Core/Blob.swift                | 50 ++++---------------
 Sources/SQLite/Core/Connection.swift          |  2 +-
 Sources/SQLite/Core/Statement.swift           |  4 +-
 Sources/SQLite/Extensions/Cipher.swift        |  6 +--
 Sources/SQLite/Foundation.swift               |  6 ++-
 Tests/SPM/Package.swift                       |  2 +-
 Tests/SQLiteTests/Core/BlobTests.swift        |  8 +--
 Tests/SQLiteTests/Core/StatementTests.swift   |  4 +-
 .../SQLiteTests/Extensions/CipherTests.swift  | 11 ++--
 Tests/SQLiteTests/FoundationTests.swift       |  2 +-
 14 files changed, 47 insertions(+), 72 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2783a67d..fc759118 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+0.14.1 (01-11-2022), [diff][diff-0.14.1]
+========================================
+
+* Reverted `Blob` changes (See [#1167][] for rationale).
+
 0.14.0 (27-10-2022), [diff][diff-0.14.0]
 ========================================
 For breaking changes, see [Upgrading.md](Documentation/Upgrading.md).
@@ -129,6 +134,7 @@ For breaking changes, see [Upgrading.md](Documentation/Upgrading.md).
 [diff-0.13.2]: https://github.com/stephencelis/SQLite.swift/compare/0.13.1...0.13.2
 [diff-0.13.3]: https://github.com/stephencelis/SQLite.swift/compare/0.13.2...0.13.3
 [diff-0.14.0]: https://github.com/stephencelis/SQLite.swift/compare/0.13.3...0.14.0
+[diff-0.14.1]: https://github.com/stephencelis/SQLite.swift/compare/0.14.0...0.14.1
 
 [#30]: https://github.com/stephencelis/SQLite.swift/issues/30
 [#142]: https://github.com/stephencelis/SQLite.swift/issues/142
diff --git a/Documentation/Index.md b/Documentation/Index.md
index ada9b7c3..730fe30b 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -90,7 +90,7 @@ process of downloading, compiling, and linking dependencies.
 
   ```swift
   dependencies: [
-    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.0")
+    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.1")
   ]
   ```
 
@@ -111,7 +111,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.14.0
+    github "stephencelis/SQLite.swift" ~> 0.14.1
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -141,7 +141,7 @@ install SQLite.swift with Carthage:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.14.0'
+        pod 'SQLite.swift', '~> 0.14.1'
     end
     ```
 
@@ -155,7 +155,7 @@ with the OS you can require the `standalone` subspec:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.14.0'
+  pod 'SQLite.swift/standalone', '~> 0.14.1'
 end
 ```
 
@@ -165,7 +165,7 @@ dependency to sqlite3 or one of its subspecs:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.14.0'
+  pod 'SQLite.swift/standalone', '~> 0.14.1'
   pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
 end
 ```
@@ -181,7 +181,7 @@ If you want to use [SQLCipher][] with SQLite.swift you can require the
 target 'YourAppTargetName' do
   # Make sure you only require the subspec, otherwise you app might link against
   # the system SQLite, which means the SQLCipher-specific methods won't work.
-  pod 'SQLite.swift/SQLCipher', '~> 0.14.0'
+  pod 'SQLite.swift/SQLCipher', '~> 0.14.1'
 end
 ```
 
diff --git a/README.md b/README.md
index ac0c2a7a..4cf72d03 100644
--- a/README.md
+++ b/README.md
@@ -131,7 +131,7 @@ Swift code.
 
   ```swift
   dependencies: [
-      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.0")
+      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.1")
   ]
   ```
 
@@ -155,7 +155,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.14.0
+    github "stephencelis/SQLite.swift" ~> 0.14.1
     ```
 
  3. Run `carthage update` and
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index c30aa765..f32282d3 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.14.0"
+  s.version          = "0.14.1"
   s.summary          = "A type-safe, Swift-language layer over SQLite3."
 
   s.description      = <<-DESC
diff --git a/Sources/SQLite/Core/Blob.swift b/Sources/SQLite/Core/Blob.swift
index c8bd2c15..a709fb42 100644
--- a/Sources/SQLite/Core/Blob.swift
+++ b/Sources/SQLite/Core/Blob.swift
@@ -21,64 +21,36 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 //
-import Foundation
 
-public final class Blob {
+public struct Blob {
 
-    public let data: NSData
+    public let bytes: [UInt8]
 
-    public var bytes: UnsafePointer<UInt8> {
-        data.bytes.assumingMemoryBound(to: UInt8.self)
+    public init(bytes: [UInt8]) {
+        self.bytes = bytes
     }
 
-    public var length: Int {
-        data.count
-    }
-
-    public convenience init(bytes: [UInt8]) {
-        guard bytes.count > 0 else {
-            self.init(data: NSData())
-            return
-        }
-        self.init(data: NSData(bytes: bytes, length: bytes.count))
-    }
-
-    public convenience init(bytes: UnsafeRawPointer, length: Int) {
-        self.init(data: NSData(bytes: bytes, length: length))
-    }
-
-    public init(data: NSData) {
-        precondition(!(data is NSMutableData), "Blob cannot be initialized with mutable data")
-        self.data = data
+    public init(bytes: UnsafeRawPointer, length: Int) {
+        let i8bufptr = UnsafeBufferPointer(start: bytes.assumingMemoryBound(to: UInt8.self), count: length)
+        self.init(bytes: [UInt8](i8bufptr))
     }
 
     public func toHex() -> String {
-        guard length > 0 else { return "" }
-
-        var hex = ""
-        for idx in 0..<length {
-            let byte = bytes.advanced(by: idx).pointee
-            if byte < 16 {
-                hex += "0"
-            }
-            hex += String(byte, radix: 16, uppercase: false)
-        }
-        return hex
+        bytes.map {
+           ($0 < 16 ? "0" : "") + String($0, radix: 16, uppercase: false)
+        }.joined(separator: "")
     }
 }
 
 extension Blob: CustomStringConvertible {
-
     public var description: String {
         "x'\(toHex())'"
     }
-
 }
 
 extension Blob: Equatable {
-
 }
 
 public func ==(lhs: Blob, rhs: Blob) -> Bool {
-    lhs.data == rhs.data
+    lhs.bytes == rhs.bytes
 }
diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 2a7ec487..0e51e651 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -741,7 +741,7 @@ extension Context {
     func set(result: Binding?) {
         switch result {
         case let blob as Blob:
-            sqlite3_result_blob(self, blob.bytes, Int32(blob.length), nil)
+            sqlite3_result_blob(self, blob.bytes, Int32(blob.bytes.count), nil)
         case let double as Double:
             sqlite3_result_double(self, double)
         case let int as Int64:
diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index 80450258..6cb2e5d3 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -103,10 +103,10 @@ public final class Statement {
         switch value {
         case .none:
             sqlite3_bind_null(handle, Int32(idx))
-        case let value as Blob where value.length == 0:
+        case let value as Blob where value.bytes.count == 0:
             sqlite3_bind_zeroblob(handle, Int32(idx), 0)
         case let value as Blob:
-            sqlite3_bind_blob(handle, Int32(idx), value.bytes, Int32(value.length), SQLITE_TRANSIENT)
+            sqlite3_bind_blob(handle, Int32(idx), value.bytes, Int32(value.bytes.count), SQLITE_TRANSIENT)
         case let value as Double:
             sqlite3_bind_double(handle, Int32(idx), value)
         case let value as Int64:
diff --git a/Sources/SQLite/Extensions/Cipher.swift b/Sources/SQLite/Extensions/Cipher.swift
index 71889ae5..8af04df9 100644
--- a/Sources/SQLite/Extensions/Cipher.swift
+++ b/Sources/SQLite/Extensions/Cipher.swift
@@ -32,7 +32,7 @@ extension Connection {
     }
 
     public func key(_ key: Blob, db: String = "main") throws {
-        try _key_v2(db: db, keyPointer: key.bytes, keySize: key.length)
+        try _key_v2(db: db, keyPointer: key.bytes, keySize: key.bytes.count)
     }
 
     /// Same as `key(_ key: String, db: String = "main")`, running "PRAGMA cipher_migrate;"
@@ -53,7 +53,7 @@ extension Connection {
 
     /// Same as `[`keyAndMigrate(_ key: String, db: String = "main")` accepting byte array as key
     public func keyAndMigrate(_ key: Blob, db: String = "main") throws {
-        try _key_v2(db: db, keyPointer: key.bytes, keySize: key.length, migrate: true)
+        try _key_v2(db: db, keyPointer: key.bytes, keySize: key.bytes.count, migrate: true)
     }
 
     /// Change the key on an open database. NB: only works if the database is already encrypted.
@@ -68,7 +68,7 @@ extension Connection {
     }
 
     public func rekey(_ key: Blob, db: String = "main") throws {
-        try _rekey_v2(db: db, keyPointer: key.bytes, keySize: key.length)
+        try _rekey_v2(db: db, keyPointer: key.bytes, keySize: key.bytes.count)
     }
 
     /// Converts a non-encrypted database to an encrypted one.
diff --git a/Sources/SQLite/Foundation.swift b/Sources/SQLite/Foundation.swift
index e81c4964..44a31736 100644
--- a/Sources/SQLite/Foundation.swift
+++ b/Sources/SQLite/Foundation.swift
@@ -31,11 +31,13 @@ extension Data: Value {
     }
 
     public static func fromDatatypeValue(_ dataValue: Blob) -> Data {
-        dataValue.data as Data
+        Data(dataValue.bytes)
     }
 
     public var datatypeValue: Blob {
-        Blob(data: self as NSData)
+        withUnsafeBytes { (pointer: UnsafeRawBufferPointer) -> Blob in
+            Blob(bytes: pointer.baseAddress!, length: count)
+        }
     }
 
 }
diff --git a/Tests/SPM/Package.swift b/Tests/SPM/Package.swift
index d5d2e9ff..3e329552 100644
--- a/Tests/SPM/Package.swift
+++ b/Tests/SPM/Package.swift
@@ -15,7 +15,7 @@ let package = Package(
         // for testing from same repository
         .package(path: "../..")
         // normally this would be:
-        // .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.0")
+        // .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.1")
     ],
     targets: [
         .target(
diff --git a/Tests/SQLiteTests/Core/BlobTests.swift b/Tests/SQLiteTests/Core/BlobTests.swift
index bef4bb83..f2e9435e 100644
--- a/Tests/SQLiteTests/Core/BlobTests.swift
+++ b/Tests/SQLiteTests/Core/BlobTests.swift
@@ -25,14 +25,14 @@ class BlobTests: XCTestCase {
 
     func test_init_array() {
         let blob = Blob(bytes: [42, 43, 44])
-        XCTAssertEqual([UInt8](blob.data), [42, 43, 44])
+        XCTAssertEqual(blob.bytes, [42, 43, 44])
     }
 
     func test_init_unsafeRawPointer() {
         let pointer = UnsafeMutablePointer<UInt8>.allocate(capacity: 3)
         pointer.initialize(repeating: 42, count: 3)
         let blob = Blob(bytes: pointer, length: 3)
-        XCTAssertEqual([UInt8](blob.data), [42, 42, 42])
+        XCTAssertEqual(blob.bytes, [42, 42, 42])
     }
 
     func test_equality() {
@@ -44,8 +44,4 @@ class BlobTests: XCTestCase {
         XCTAssertEqual(blob1, blob2)
         XCTAssertNotEqual(blob1, blob3)
     }
-
-    func XXX_test_init_with_mutable_data_fails() {
-        _ = Blob(data: NSMutableData())
-    }
 }
diff --git a/Tests/SQLiteTests/Core/StatementTests.swift b/Tests/SQLiteTests/Core/StatementTests.swift
index 0d82e890..5f212505 100644
--- a/Tests/SQLiteTests/Core/StatementTests.swift
+++ b/Tests/SQLiteTests/Core/StatementTests.swift
@@ -22,7 +22,7 @@ class StatementTests: SQLiteTestCase {
         let statement = try db.prepare("SELECT email FROM users")
         XCTAssert(try statement.step())
         let blob = statement.row[0] as Blob
-        XCTAssertEqual("alice@example.com", String(data: blob.data as Data, encoding: .utf8)!)
+        XCTAssertEqual("alice@example.com", String(bytes: blob.bytes, encoding: .utf8)!)
     }
 
     func test_zero_sized_blob_returns_null() throws {
@@ -31,7 +31,7 @@ class StatementTests: SQLiteTestCase {
         try db.run(blobs.create { $0.column(blobColumn) })
         try db.run(blobs.insert(blobColumn <- Blob(bytes: [])))
         let blobValue = try db.scalar(blobs.select(blobColumn).limit(1, offset: 0))
-        XCTAssertEqual([], [UInt8](blobValue.data))
+        XCTAssertEqual([], blobValue.bytes)
     }
 
     func test_prepareRowIterator() throws {
diff --git a/Tests/SQLiteTests/Extensions/CipherTests.swift b/Tests/SQLiteTests/Extensions/CipherTests.swift
index bd7f2042..bc89cfa2 100644
--- a/Tests/SQLiteTests/Extensions/CipherTests.swift
+++ b/Tests/SQLiteTests/Extensions/CipherTests.swift
@@ -19,7 +19,7 @@ class CipherTests: XCTestCase {
 
         // db2
         let key2 = keyData()
-        try db2.key(Blob(data: key2))
+        try db2.key(Blob(bytes: key2.bytes, length: key2.length))
 
         try db2.run("CREATE TABLE foo (bar TEXT)")
         try db2.run("INSERT INTO foo (bar) VALUES ('world')")
@@ -47,7 +47,7 @@ class CipherTests: XCTestCase {
 
     func test_data_rekey() throws {
         let newKey = keyData()
-        try db2.rekey(Blob(data: newKey))
+        try db2.rekey(Blob(bytes: newKey.bytes, length: newKey.length))
         XCTAssertEqual(1, try db2.scalar("SELECT count(*) FROM foo") as? Int64)
     }
 
@@ -79,12 +79,11 @@ class CipherTests: XCTestCase {
         // sqlite> CREATE TABLE foo (bar TEXT);
         // sqlite> INSERT INTO foo (bar) VALUES ('world');
         guard let cipherVersion: String = db1.cipherVersion,
-            cipherVersion.starts(with: "3.") || cipherVersion.starts(with: "4.")
-            else { return }
+            cipherVersion.starts(with: "3.") || cipherVersion.starts(with: "4.") else { return }
 
         let encryptedFile = cipherVersion.starts(with: "3.") ?
-            fixture("encrypted-3.x", withExtension: "sqlite") :
-            fixture("encrypted-4.x", withExtension: "sqlite")
+                fixture("encrypted-3.x", withExtension: "sqlite") :
+                fixture("encrypted-4.x", withExtension: "sqlite")
 
         try FileManager.default.setAttributes([FileAttributeKey.immutable: 1], ofItemAtPath: encryptedFile)
         XCTAssertFalse(FileManager.default.isWritableFile(atPath: encryptedFile))
diff --git a/Tests/SQLiteTests/FoundationTests.swift b/Tests/SQLiteTests/FoundationTests.swift
index ffd3fae1..453febcd 100644
--- a/Tests/SQLiteTests/FoundationTests.swift
+++ b/Tests/SQLiteTests/FoundationTests.swift
@@ -5,7 +5,7 @@ class FoundationTests: XCTestCase {
     func testDataFromBlob() {
         let data = Data([1, 2, 3])
         let blob = data.datatypeValue
-        XCTAssertEqual([1, 2, 3], [UInt8](blob.data))
+        XCTAssertEqual([1, 2, 3], blob.bytes)
     }
 
     func testBlobToData() {

From f06b8df5bc0fb73d6ac46adaf5f047fded953f79 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 2 Nov 2022 09:04:08 +0100
Subject: [PATCH 585/685] Removed

---
 Documentation/Upgrading.md | 2 --
 1 file changed, 2 deletions(-)

diff --git a/Documentation/Upgrading.md b/Documentation/Upgrading.md
index 8c398467..f2cc2ecb 100644
--- a/Documentation/Upgrading.md
+++ b/Documentation/Upgrading.md
@@ -6,6 +6,4 @@
   where `description` returns the SQL.
 - `Statement.prepareRowIterator()` is now longer available. Instead, use the methods
   of the same name on `Connection`.
-- `Blob` no longer wraps byte arrays and now uses `NSData`, which enables memory and
- performance improvements.
 - `Connection.registerTokenizer` is no longer available to register custom FTS4 tokenizers.

From d926517c090042ee3268048f1d46020f94b39d0c Mon Sep 17 00:00:00 2001
From: Geoff MacDonald <geoffmacd@gmail.com>
Date: Tue, 20 Dec 2022 12:18:53 -0800
Subject: [PATCH 586/685] adds support for extended error codes

---
 Sources/SQLite/Core/Connection.swift          |  7 ++++++
 Sources/SQLite/Core/Result.swift              | 24 ++++++++++++++++++-
 Tests/SQLiteTests/Core/ConnectionTests.swift  |  4 ++++
 Tests/SQLiteTests/Core/ResultTests.swift      | 13 ++++++++++
 .../Typed/QueryIntegrationTests.swift         | 13 ++++++++++
 5 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 0e51e651..f74ed82c 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -156,6 +156,13 @@ public final class Connection {
         Int(sqlite3_total_changes(handle))
     }
 
+    /// Whether or not the database will return extended error codes when errors are handled.
+    public var usesExtendedErrorCodes: Bool = false {
+        didSet {
+            sqlite3_extended_result_codes(handle, usesExtendedErrorCodes ? 1 : 0)
+        }
+    }
+    
     // MARK: - Execute
 
     /// Executes a batch of SQL statements.
diff --git a/Sources/SQLite/Core/Result.swift b/Sources/SQLite/Core/Result.swift
index 3de4d25d..06f9cc74 100644
--- a/Sources/SQLite/Core/Result.swift
+++ b/Sources/SQLite/Core/Result.swift
@@ -21,11 +21,27 @@ public enum Result: Error {
     /// - statement: the statement which produced the error
     case error(message: String, code: Int32, statement: Statement?)
 
+    /// Represents a SQLite specific [extended error code] (https://sqlite.org/rescode.html#primary_result_codes_versus_extended_result_codes)
+    ///
+    /// - message: English-language text that describes the error
+    ///
+    /// - extendedCode: SQLite [extended error code](https://sqlite.org/rescode.html#extended_result_code_list)
+    ///
+    /// - statement: the statement which produced the error
+    case extendedError(message: String, extendedCode: Int32, statement: Statement?)
+
     init?(errorCode: Int32, connection: Connection, statement: Statement? = nil) {
         guard !Result.successCodes.contains(errorCode) else { return nil }
 
         let message = String(cString: sqlite3_errmsg(connection.handle))
-        self = .error(message: message, code: errorCode, statement: statement)
+
+        guard connection.usesExtendedErrorCodes else {
+            self = .error(message: message, code: errorCode, statement: statement)
+            return
+        }
+
+        let extendedErrorCode = sqlite3_extended_errcode(connection.handle)
+        self = .extendedError(message: message, extendedCode: extendedErrorCode, statement: statement)
     }
 
 }
@@ -40,6 +56,12 @@ extension Result: CustomStringConvertible {
             } else {
                 return "\(message) (code: \(errorCode))"
             }
+        case let .extendedError(message,  extendedCode, statement):
+            if let statement = statement {
+                return "\(message) (\(statement)) (extended code: \(extendedCode))"
+            } else {
+                return "\(message) (extended code: \(extendedCode))"
+            }
         }
     }
 }
diff --git a/Tests/SQLiteTests/Core/ConnectionTests.swift b/Tests/SQLiteTests/Core/ConnectionTests.swift
index 9d623f3f..6a1d94ae 100644
--- a/Tests/SQLiteTests/Core/ConnectionTests.swift
+++ b/Tests/SQLiteTests/Core/ConnectionTests.swift
@@ -111,6 +111,10 @@ class ConnectionTests: SQLiteTestCase {
         XCTAssertEqual(2, db.totalChanges)
     }
 
+    func test_useExtendedErrorCodes_returnsFalseDefault() throws {
+        XCTAssertFalse(db.usesExtendedErrorCodes)
+    }
+
     func test_prepare_preparesAndReturnsStatements() throws {
         _ = try db.prepare("SELECT * FROM users WHERE admin = 0")
         _ = try db.prepare("SELECT * FROM users WHERE admin = ?", 0)
diff --git a/Tests/SQLiteTests/Core/ResultTests.swift b/Tests/SQLiteTests/Core/ResultTests.swift
index fab4a0bb..d3c8bb1f 100644
--- a/Tests/SQLiteTests/Core/ResultTests.swift
+++ b/Tests/SQLiteTests/Core/ResultTests.swift
@@ -53,4 +53,17 @@ class ResultTests: XCTestCase {
         XCTAssertEqual("not an error (SELECT 1) (code: 21)",
             Result(errorCode: SQLITE_MISUSE, connection: connection, statement: statement)?.description)
     }
+
+    func test_init_extended_with_other_code_returns_error() {
+        connection.usesExtendedErrorCodes = true
+        if case .some(.extendedError(let message, let extendedCode, let statement)) =
+            Result(errorCode: SQLITE_MISUSE, connection: connection, statement: nil) {
+            XCTAssertEqual("not an error", message)
+            XCTAssertEqual(extendedCode, 0)
+            XCTAssertNil(statement)
+            XCTAssert(connection === connection)
+        } else {
+            XCTFail("no error")
+        }
+    }
 }
diff --git a/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift b/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
index 3fd388e9..a86708ec 100644
--- a/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
+++ b/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
@@ -229,6 +229,19 @@ class QueryIntegrationTests: SQLiteTestCase {
         }
     }
 
+    func test_extendedErrorCodes_catchConstraintError() throws {
+        db.usesExtendedErrorCodes = true
+        try db.run(users.insert(email <- "alice@example.com"))
+        do {
+            try db.run(users.insert(email <- "alice@example.com"))
+            XCTFail("expected error")
+        } catch let Result.extendedError(_,  extendedCode, _) where extendedCode == 2_067 {
+            // SQLITE_CONSTRAINT_UNIQUE expected
+        } catch let error {
+            XCTFail("unexpected error: \(error)")
+        }
+    }
+
     // https://github.com/stephencelis/SQLite.swift/issues/285
     func test_order_by_random() throws {
         try insertUsers(["a", "b", "c'"])

From 0fc4b7b223e5402fd497c5929e220bbec02608d5 Mon Sep 17 00:00:00 2001
From: Geoff MacDonald <geoffmacd@gmail.com>
Date: Tue, 20 Dec 2022 12:21:24 -0800
Subject: [PATCH 587/685] lint

---
 Sources/SQLite/Core/Connection.swift                | 2 +-
 Sources/SQLite/Core/Result.swift                    | 2 +-
 Tests/SQLiteTests/Typed/QueryIntegrationTests.swift | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index f74ed82c..26cadea4 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -162,7 +162,7 @@ public final class Connection {
             sqlite3_extended_result_codes(handle, usesExtendedErrorCodes ? 1 : 0)
         }
     }
-    
+
     // MARK: - Execute
 
     /// Executes a batch of SQL statements.
diff --git a/Sources/SQLite/Core/Result.swift b/Sources/SQLite/Core/Result.swift
index 06f9cc74..9fe47ada 100644
--- a/Sources/SQLite/Core/Result.swift
+++ b/Sources/SQLite/Core/Result.swift
@@ -56,7 +56,7 @@ extension Result: CustomStringConvertible {
             } else {
                 return "\(message) (code: \(errorCode))"
             }
-        case let .extendedError(message,  extendedCode, statement):
+        case let .extendedError(message, extendedCode, statement):
             if let statement = statement {
                 return "\(message) (\(statement)) (extended code: \(extendedCode))"
             } else {
diff --git a/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift b/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
index a86708ec..3b973fa0 100644
--- a/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
+++ b/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
@@ -235,7 +235,7 @@ class QueryIntegrationTests: SQLiteTestCase {
         do {
             try db.run(users.insert(email <- "alice@example.com"))
             XCTFail("expected error")
-        } catch let Result.extendedError(_,  extendedCode, _) where extendedCode == 2_067 {
+        } catch let Result.extendedError(_, extendedCode, _) where extendedCode == 2_067 {
             // SQLITE_CONSTRAINT_UNIQUE expected
         } catch let error {
             XCTFail("unexpected error: \(error)")

From 4b9ea97872a241fad38c221afad7a701fc987868 Mon Sep 17 00:00:00 2001
From: Matthew Jee <matthew@marmphco.com>
Date: Fri, 23 Dec 2022 00:37:03 -0800
Subject: [PATCH 588/685] Fix incorrect column names for SELECT * preceded by a
 WITH

In  #1139 I introduced support for the `WITH` clause. My implementation contains a bug: the statement preparer doesn't produce the correct result column names for queries containing a `SELECT *` preceded by a `WITH`.

For example, consider the following statement:

```
WITH temp AS ( SELECT id, email from users) SELECT * from temp
```

An error would be thrown when preparing this statement because the glob expansion procedure would try to look up the column names for the result by looking up the column names for the query `SELECT * from temp`. This does not work because `temp` is a temporary view defined in the `WITH` clause.

To fix this, I modified the glob expansion procedure to include the `WITH` clause in the query used to look up the result column names.
---
 Sources/SQLite/Typed/Query.swift              | 19 +++++++++++
 .../Typed/QueryIntegrationTests.swift         | 33 +++++++++++++++++++
 2 files changed, 52 insertions(+)

diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index 04665f39..feff2f69 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -1036,10 +1036,29 @@ extension Connection {
             let column = names.removeLast()
             let namespace = names.joined(separator: ".")
 
+            // Return a copy of the input "with" clause stripping all subclauses besides "select", "join", and "with".
+            func strip(_ with: WithClauses) -> WithClauses {
+                var stripped = WithClauses()
+                stripped.recursive = with.recursive
+                for subclause in with.clauses {
+                    let query = subclause.query
+                    var strippedQuery = type(of: query).init(query.clauses.from.name, database: query.clauses.from.database)
+                    strippedQuery.clauses.select = query.clauses.select
+                    strippedQuery.clauses.join = query.clauses.join
+                    strippedQuery.clauses.with = strip(query.clauses.with)
+
+                    var strippedSubclause = WithClauses.Clause(alias: subclause.alias, query: strippedQuery)
+                    strippedSubclause.columns = subclause.columns
+                    stripped.clauses.append(strippedSubclause)
+                }
+                return stripped
+            }
+
             func expandGlob(_ namespace: Bool) -> (QueryType) throws -> Void {
                 { (queryType: QueryType) throws -> Void in
                     var query = type(of: queryType).init(queryType.clauses.from.name, database: queryType.clauses.from.database)
                     query.clauses.select = queryType.clauses.select
+                    query.clauses.with = strip(queryType.clauses.with)
                     let expression = query.expression
                     var names = try self.prepare(expression.template, expression.bindings).columnNames.map { $0.quote() }
                     if namespace { names = names.map { "\(queryType.tableName().expression.template).\($0)" } }
diff --git a/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift b/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
index 3fd388e9..d99b8457 100644
--- a/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
+++ b/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
@@ -276,6 +276,39 @@ class QueryIntegrationTests: SQLiteTestCase {
 
         XCTAssertEqual(21, sum)
     }
+
+    /// Verify that `*` is properly expanded in a SELECT statement following a WITH clause.
+    func test_with_glob_expansion() throws {
+        let names = Table("names")
+        let name = Expression<String>("name")
+        try db.run(names.create { builder in
+            builder.column(email)
+            builder.column(name)
+        })
+
+        try db.run(users.insert(email <- "alice@example.com"))
+        try db.run(names.insert(email <- "alice@example.com", name <- "Alice"))
+
+        // WITH intermediate AS ( SELECT ... ) SELECT * FROM intermediate
+        let intermediate = Table("intermediate")
+        let rows = try db.prepare(
+            intermediate
+                .with(intermediate,
+                      as: users
+                        .select([id, users[email], name])
+                        .join(names, on: names[email] == users[email])
+                        .where(users[email] == "alice@example.com")
+                     ))
+
+        // There should be at least one row in the result.
+        let row = try XCTUnwrap(rows.makeIterator().next())
+        
+        // Verify the column names
+        XCTAssertEqual(row.columnNames.count, 3)
+        XCTAssertNotNil(row[id])
+        XCTAssertNotNil(row[name])
+        XCTAssertNotNil(row[email])
+    }
 }
 
 extension Connection {

From bdc3be7fdf9b6289ee0e0ea5c28002839d8cf54d Mon Sep 17 00:00:00 2001
From: Matthew Jee <matthew@marmphco.com>
Date: Fri, 23 Dec 2022 00:45:34 -0800
Subject: [PATCH 589/685] linter error

---
 Tests/SQLiteTests/Typed/QueryIntegrationTests.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift b/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
index d99b8457..f5105a09 100644
--- a/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
+++ b/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
@@ -302,7 +302,7 @@ class QueryIntegrationTests: SQLiteTestCase {
 
         // There should be at least one row in the result.
         let row = try XCTUnwrap(rows.makeIterator().next())
-        
+
         // Verify the column names
         XCTAssertEqual(row.columnNames.count, 3)
         XCTAssertNotNil(row[id])

From b7c6fd6f94eedf6995ff607ae1625f71041377aa Mon Sep 17 00:00:00 2001
From: Dimitris Apostolou <dimitris.apostolou@icloud.com>
Date: Sun, 8 Jan 2023 14:07:12 +0200
Subject: [PATCH 590/685] Fix typos

---
 Documentation/Index.md                 | 2 +-
 SQLite.playground/Contents.swift       | 2 +-
 Sources/SQLite/Extensions/Cipher.swift | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 730fe30b..583d5def 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -691,7 +691,7 @@ do {
 }
 ```
 
-Multiple rows can be inserted at once by similarily calling `insertMany` with an array of
+Multiple rows can be inserted at once by similarly calling `insertMany` with an array of
 per-row [setters](#setters).
 
 ```swift
diff --git a/SQLite.playground/Contents.swift b/SQLite.playground/Contents.swift
index f651cbc1..d893e696 100644
--- a/SQLite.playground/Contents.swift
+++ b/SQLite.playground/Contents.swift
@@ -65,7 +65,7 @@ do {
     // Handle error
 }
 
-/// define a virtual tabe for the FTS index
+/// define a virtual table for the FTS index
 let emails = VirtualTable("emails")
 
 let subject = Expression<String>("subject")
diff --git a/Sources/SQLite/Extensions/Cipher.swift b/Sources/SQLite/Extensions/Cipher.swift
index 8af04df9..03194ef1 100644
--- a/Sources/SQLite/Extensions/Cipher.swift
+++ b/Sources/SQLite/Extensions/Cipher.swift
@@ -93,7 +93,7 @@ extension Connection {
             // per recommendation of SQLCipher authors
             let migrateResult = try scalar("PRAGMA cipher_migrate;")
             if (migrateResult as? String) != "0" {
-                // "0" is the result of successfull migration
+                // "0" is the result of successful migration
                 throw Result.error(message: "Error in cipher migration, result \(migrateResult.debugDescription)", code: 1, statement: nil)
             }
         }

From 0d905d788e386854effc7133f1faf31fe9a3c9e2 Mon Sep 17 00:00:00 2001
From: "Pongsakorn Onsri(Ken)" <pongsakorn.onsri@nanameue.jp>
Date: Fri, 17 Mar 2023 17:21:31 +0700
Subject: [PATCH 591/685] fix Xcode build error

---
 Sources/SQLite/Core/Connection+Pragmas.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Sources/SQLite/Core/Connection+Pragmas.swift b/Sources/SQLite/Core/Connection+Pragmas.swift
index 8f6d854b..2c4f0efb 100644
--- a/Sources/SQLite/Core/Connection+Pragmas.swift
+++ b/Sources/SQLite/Core/Connection+Pragmas.swift
@@ -7,7 +7,7 @@ public extension Connection {
     /// See SQLite [PRAGMA user_version](https://sqlite.org/pragma.html#pragma_user_version)
     var userVersion: UserVersion? {
         get {
-            (try? scalar("PRAGMA user_version") as? Int64).map(Int32.init)
+            (try? scalar("PRAGMA user_version") as? Int64)?.map(Int32.init)
         }
         set {
             _ = try? run("PRAGMA user_version = \(newValue ?? 0)")

From 5f96ca46c1843f26c040b467d9f87519f03a0888 Mon Sep 17 00:00:00 2001
From: Stefan Saasen <stefan@ohoj-software.com>
Date: Fri, 7 Apr 2023 15:41:11 +0200
Subject: [PATCH 592/685] Make ithe IndexDefinition properties public

The [documentation](https://github.com/stephencelis/SQLite.swift/blob/master/Documentation/Index.md#querying-the-schema)
suggests that the index schema information can be queried. That requires
the `IndexDefinition` properties to be public.
---
 Sources/SQLite/Schema/SchemaDefinitions.swift | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/Sources/SQLite/Schema/SchemaDefinitions.swift b/Sources/SQLite/Schema/SchemaDefinitions.swift
index 284fc4c3..b314e5c0 100644
--- a/Sources/SQLite/Schema/SchemaDefinitions.swift
+++ b/Sources/SQLite/Schema/SchemaDefinitions.swift
@@ -266,12 +266,12 @@ public struct IndexDefinition: Equatable {
                   orders: indexSQL.flatMap(orders))
     }
 
-    let table: String
-    let name: String
-    let unique: Bool
-    let columns: [String]
-    let `where`: String?
-    let orders: [String: Order]?
+    public let table: String
+    public let name: String
+    public let unique: Bool
+    public let columns: [String]
+    public let `where`: String?
+    public let orders: [String: Order]?
 
     enum IndexError: LocalizedError {
         case tooLong(String, String)

From 0718088b7885dfb08f8930111e13aa12fa9a55c6 Mon Sep 17 00:00:00 2001
From: fwcd <fwcdmail@gmail.com>
Date: Fri, 21 Apr 2023 16:10:41 +0200
Subject: [PATCH 593/685] Fix GitHub Actions build badge

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 4cf72d03..90333b16 100644
--- a/README.md
+++ b/README.md
@@ -275,7 +275,7 @@ Looking for something else? Try another Swift wrapper (or [FMDB][]):
 [SQLite3]: https://www.sqlite.org
 [SQLite.swift]: https://github.com/stephencelis/SQLite.swift
 
-[GitHubActionBadge]: https://img.shields.io/github/workflow/status/stephencelis/SQLite.swift/Build%20and%20test
+[GitHubActionBadge]: https://img.shields.io/github/actions/workflow/status/stephencelis/SQLite.swift/build.yml?branch=master
 
 [CocoaPodsVersionBadge]: https://img.shields.io/cocoapods/v/SQLite.swift.svg?style=flat
 [CocoaPodsVersionLink]: https://cocoapods.org/pods/SQLite.swift

From 481b531c6906e11d8efcc7c36ea89b7e572e6ce7 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 18 Oct 2022 22:14:04 +0200
Subject: [PATCH 594/685] Run on macOS 12

Bump deployment targets

Disable watchOS validation

CocoaPods/CocoaPods#11558

Adjust deployment targets for Xcode 14
---
 .github/workflows/build.yml      |  4 ++--
 Package.swift                    |  8 ++++----
 SQLite.swift.podspec             |  8 ++++----
 SQLite.xcodeproj/project.pbxproj | 30 ++++++++++++++++++++++--------
 Tests/SPM/Package.swift          |  8 ++++----
 run-tests.sh                     |  4 ++--
 6 files changed, 38 insertions(+), 24 deletions(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index d1659d9d..beec5ca2 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -2,10 +2,10 @@ name: Build and test
 on: [push, pull_request]
 env:
   IOS_SIMULATOR: iPhone 12
-  IOS_VERSION: "15.2"
+  IOS_VERSION: "16.0"
 jobs:
   build:
-    runs-on: macos-11
+    runs-on: macos-12
     steps:
     - uses: actions/checkout@v2
     - name: Install
diff --git a/Package.swift b/Package.swift
index 9664e99a..de40367a 100644
--- a/Package.swift
+++ b/Package.swift
@@ -4,10 +4,10 @@ import PackageDescription
 let package = Package(
     name: "SQLite.swift",
     platforms: [
-        .iOS(.v9),
-        .macOS(.v10_10),
-        .watchOS(.v3),
-        .tvOS(.v9)
+        .iOS(.v11),
+        .macOS(.v10_13),
+        .watchOS(.v4),
+        .tvOS(.v11)
     ],
     products: [
         .library(
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index f32282d3..4edddd67 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -18,10 +18,10 @@ Pod::Spec.new do |s|
   s.default_subspec  = 'standard'
   s.swift_versions = ['5']
 
-  ios_deployment_target = '9.0'
-  tvos_deployment_target = '9.1'
-  osx_deployment_target = '10.10'
-  watchos_deployment_target = '3.0'
+  ios_deployment_target = '11.0'
+  tvos_deployment_target = '11.0'
+  osx_deployment_target = '10.13'
+  watchos_deployment_target = '4.0'
 
   s.ios.deployment_target = ios_deployment_target
   s.tvos.deployment_target = tvos_deployment_target
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 3d62e980..def32855 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1263,6 +1263,7 @@
 				SDKROOT = appletvos;
 				SKIP_INSTALL = YES;
 				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
+				TVOS_DEPLOYMENT_TARGET = 11.0;
 			};
 			name = Debug;
 		};
@@ -1284,6 +1285,7 @@
 				SDKROOT = appletvos;
 				SKIP_INSTALL = YES;
 				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
+				TVOS_DEPLOYMENT_TARGET = 11.0;
 			};
 			name = Release;
 		};
@@ -1297,6 +1299,7 @@
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = appletvos;
 				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
+				TVOS_DEPLOYMENT_TARGET = 11.0;
 			};
 			name = Debug;
 		};
@@ -1310,6 +1313,7 @@
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = appletvos;
 				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
+				TVOS_DEPLOYMENT_TARGET = 11.0;
 			};
 			name = Release;
 		};
@@ -1333,6 +1337,7 @@
 				SKIP_INSTALL = YES;
 				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
 				TARGETED_DEVICE_FAMILY = 4;
+				WATCHOS_DEPLOYMENT_TARGET = 4.0;
 			};
 			name = Debug;
 		};
@@ -1356,6 +1361,7 @@
 				SKIP_INSTALL = YES;
 				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
 				TARGETED_DEVICE_FAMILY = 4;
+				WATCHOS_DEPLOYMENT_TARGET = 4.0;
 			};
 			name = Release;
 		};
@@ -1408,8 +1414,8 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
-				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+				MACOSX_DEPLOYMENT_TARGET = 10.13;
 				MTL_ENABLE_DEBUG_INFO = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				PRODUCT_NAME = "";
@@ -1417,10 +1423,10 @@
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
 				SWIFT_VERSION = 5.0;
 				TARGETED_DEVICE_FAMILY = "1,2,3";
-				TVOS_DEPLOYMENT_TARGET = 9.1;
+				TVOS_DEPLOYMENT_TARGET = 11.0;
 				VERSIONING_SYSTEM = "apple-generic";
 				VERSION_INFO_PREFIX = "";
-				WATCHOS_DEPLOYMENT_TARGET = 3.0;
+				WATCHOS_DEPLOYMENT_TARGET = 4.0;
 			};
 			name = Debug;
 		};
@@ -1467,19 +1473,19 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
-				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+				MACOSX_DEPLOYMENT_TARGET = 10.13;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				PRODUCT_NAME = "";
 				SDKROOT = iphoneos;
 				SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
 				SWIFT_VERSION = 5.0;
 				TARGETED_DEVICE_FAMILY = "1,2,3";
-				TVOS_DEPLOYMENT_TARGET = 9.1;
+				TVOS_DEPLOYMENT_TARGET = 11.0;
 				VALIDATE_PRODUCT = YES;
 				VERSIONING_SYSTEM = "apple-generic";
 				VERSION_INFO_PREFIX = "";
-				WATCHOS_DEPLOYMENT_TARGET = 3.0;
+				WATCHOS_DEPLOYMENT_TARGET = 4.0;
 			};
 			name = Release;
 		};
@@ -1496,6 +1502,7 @@
 				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				MARKETING_VERSION = 0.14.0;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
@@ -1519,6 +1526,7 @@
 				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				MARKETING_VERSION = 0.14.0;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
@@ -1533,6 +1541,7 @@
 			buildSettings = {
 				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
+				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1545,6 +1554,7 @@
 			buildSettings = {
 				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
+				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1567,6 +1577,7 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
+				MACOSX_DEPLOYMENT_TARGET = 10.13;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SDKROOT = macosx;
@@ -1591,6 +1602,7 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
+				MACOSX_DEPLOYMENT_TARGET = 10.13;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SDKROOT = macosx;
@@ -1608,6 +1620,7 @@
 				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
+				MACOSX_DEPLOYMENT_TARGET = 10.13;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = macosx;
@@ -1623,6 +1636,7 @@
 				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
+				MACOSX_DEPLOYMENT_TARGET = 10.13;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = macosx;
diff --git a/Tests/SPM/Package.swift b/Tests/SPM/Package.swift
index 3e329552..51f176f4 100644
--- a/Tests/SPM/Package.swift
+++ b/Tests/SPM/Package.swift
@@ -6,10 +6,10 @@ import PackageDescription
 let package = Package(
     name: "test",
     platforms: [
-        .iOS(.v9),
-        .macOS(.v10_10),
-        .watchOS(.v3),
-        .tvOS(.v9)
+        .iOS(.v11),
+        .macOS(.v10_13),
+        .watchOS(.v4),
+        .tvOS(.v11)
     ],
     dependencies: [
         // for testing from same repository
diff --git a/run-tests.sh b/run-tests.sh
index 49330c12..c54300ee 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -8,9 +8,9 @@ if [ -n "$BUILD_SCHEME" ]; then
     fi
 elif [ -n "$VALIDATOR_SUBSPEC" ]; then
     if [ "$VALIDATOR_SUBSPEC" == "none" ]; then
-      pod lib lint --no-subspecs --fail-fast
+      pod lib lint --no-subspecs --fail-fast --platforms=ios,osx,tvos
     else
-      pod lib lint --subspec="${VALIDATOR_SUBSPEC}" --fail-fast
+      pod lib lint --subspec="${VALIDATOR_SUBSPEC}" --fail-fast --platforms=ios,osx,tvos
     fi
 elif [ -n "$CARTHAGE_PLATFORM" ]; then
     cd Tests/Carthage && make test CARTHAGE_PLATFORM="$CARTHAGE_PLATFORM"

From a2897d5512f897e566247808bf7d87b2f033b5e7 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 21 May 2023 12:45:26 +0200
Subject: [PATCH 595/685] Run on macos-13

---
 .github/workflows/build.yml | 4 ++--
 .gitignore                  | 1 +
 Package.swift               | 2 +-
 Tests/SPM/Package.swift     | 7 ++-----
 4 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index beec5ca2..ae806ecc 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -2,10 +2,10 @@ name: Build and test
 on: [push, pull_request]
 env:
   IOS_SIMULATOR: iPhone 12
-  IOS_VERSION: "16.0"
+  IOS_VERSION: "16.4"
 jobs:
   build:
-    runs-on: macos-12
+    runs-on: macos-13
     steps:
     - uses: actions/checkout@v2
     - name: Install
diff --git a/.gitignore b/.gitignore
index 5882e0cb..b7d43ec9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,3 +25,4 @@ DerivedData
 # Swift Package Manager
 .build
 Packages/
+.swiftpm/
diff --git a/Package.swift b/Package.swift
index de40367a..70bde7ef 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,4 +1,4 @@
-// swift-tools-version:5.3
+// swift-tools-version:5.7
 import PackageDescription
 
 let package = Package(
diff --git a/Tests/SPM/Package.swift b/Tests/SPM/Package.swift
index 51f176f4..3c446ae6 100644
--- a/Tests/SPM/Package.swift
+++ b/Tests/SPM/Package.swift
@@ -1,4 +1,4 @@
-// swift-tools-version:5.3
+// swift-tools-version:5.7
 // The swift-tools-version declares the minimum version of Swift required to build this package.
 
 import PackageDescription
@@ -18,9 +18,6 @@ let package = Package(
         // .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.1")
     ],
     targets: [
-        .target(
-            name: "test",
-            dependencies: [.product(name: "SQLite", package: "SQLite.swift")]
-	)
+        .executableTarget(name: "test", dependencies: [.product(name: "SQLite", package: "SQLite.swift")])
     ]
 )

From 85f1d443e9b758aaeea3fc5c9b3abef67675931b Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 21 May 2023 15:09:30 +0200
Subject: [PATCH 596/685] Automatically download swiftlint / xcbeautifier, lint
 fixes

---
 .gitignore                                    |  3 +
 .swiftlint.yml                                |  5 +-
 Makefile                                      | 81 +++++++++++++------
 Sources/SQLite/Core/Backup.swift              |  2 +-
 Sources/SQLite/Helpers.swift                  |  1 +
 Sources/SQLite/Schema/SchemaReader.swift      |  2 +-
 Sources/SQLite/Typed/Query.swift              |  2 +-
 Tests/.swiftlint.yml                          |  4 +-
 Tests/SQLiteTests/Schema/SchemaTests.swift    |  2 +
 .../Typed/CustomFunctionsTests.swift          | 16 ++--
 10 files changed, 80 insertions(+), 38 deletions(-)

diff --git a/.gitignore b/.gitignore
index b7d43ec9..e7b2ad4d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,6 +22,9 @@ DerivedData
 # Carthage
 /Carthage/
 
+# Makefile
+bin/
+
 # Swift Package Manager
 .build
 Packages/
diff --git a/.swiftlint.yml b/.swiftlint.yml
index d40be28e..e728e191 100644
--- a/.swiftlint.yml
+++ b/.swiftlint.yml
@@ -4,6 +4,7 @@ disabled_rules: # rule identifiers to exclude from running
   - large_tuple
   - closure_parameter_position
   - inclusive_language  # sqlite_master etc.
+  - blanket_disable_command
 included: # paths to include during linting. `--path` is ignored if present. takes precendence over `excluded`.
   - Sources
   - Tests
@@ -26,8 +27,8 @@ identifier_name:
     - SQLITE_TRANSIENT
 
 type_body_length:
-  warning: 260
-  error: 260
+  warning: 350
+  error: 350
 
 function_body_length:
   warning: 60
diff --git a/Makefile b/Makefile
index 74bf5d18..73b33f97 100644
--- a/Makefile
+++ b/Makefile
@@ -1,41 +1,76 @@
-BUILD_TOOL = xcodebuild
+XCODEBUILD = xcodebuild
 BUILD_SCHEME = SQLite Mac
-IOS_SIMULATOR = iPhone 12
-IOS_VERSION = 15.0
+IOS_SIMULATOR = iPhone 14
+IOS_VERSION = 16.4
+
+# tool settings
+SWIFTLINT_VERSION=0.52.2
+SWIFTLINT=bin/swiftlint-$(SWIFTLINT_VERSION)
+SWIFTLINT_URL=https://github.com/realm/SwiftLint/releases/download/$(SWIFTLINT_VERSION)/portable_swiftlint.zip
+XCBEAUTIFY_VERSION=0.20.0
+XCBEAUTIFY=bin/xcbeautify-$(XCBEAUTIFY_VERSION)
+ifeq ($(shell uname), Linux)
+	XCBEAUTIFY_PLATFORM=x86_64-unknown-linux-gnu.tar.xz
+else
+	XCBEAUTIFY_PLATFORM=universal-apple-macosx.zip
+endif
+XCBEAUTIFY_URL=https://github.com/tuist/xcbeautify/releases/download/$(XCBEAUTIFY_VERSION)/xcbeautify-$(XCBEAUTIFY_VERSION)-$(XCBEAUTIFY_PLATFORM)
+CURL_OPTS=--fail --silent -L --retry 3
+
 ifeq ($(BUILD_SCHEME),SQLite iOS)
 	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -destination "platform=iOS Simulator,name=$(IOS_SIMULATOR),OS=$(IOS_VERSION)"
 else
 	BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)"
 endif
 
-XCPRETTY := $(shell command -v xcpretty)
-TEST_ACTIONS := clean build build-for-testing test-without-building
+test: $(XCBEAUTIFY)
+	set -o pipefail; \
+	$(XCODEBUILD) $(BUILD_ARGUMENTS) test | $(XCBEAUTIFY)
 
-default: test
+build: $(XCBEAUTIFY)
+	set -o pipefail; \
+	$(XCODEBUILD) $(BUILD_ARGUMENTS) | $(XCBEAUTIFY)
 
-build:
-	$(BUILD_TOOL) $(BUILD_ARGUMENTS)
+lint: $(SWIFTLINT)
+	$< --strict
 
-lint:
-	swiftlint --strict
-lint-fix:
-	swiftlint lint fix
-
-test:
-ifdef XCPRETTY
-	@set -o pipefail && $(BUILD_TOOL) $(BUILD_ARGUMENTS) $(TEST_ACTIONS) | $(XCPRETTY) -c
-else
-	$(BUILD_TOOL) $(BUILD_ARGUMENTS) $(TEST_ACTIONS)
-endif
+lint-fix: $(SWIFTLINT)
+	$< lint fix
 
 clean:
-	$(BUILD_TOOL) $(BUILD_ARGUMENTS) clean
+	$(XCODEBUILD) $(BUILD_ARGUMENTS) clean
 
 repl:
-	@$(BUILD_TOOL) $(BUILD_ARGUMENTS) -derivedDataPath $(TMPDIR)/SQLite.swift > /dev/null && \
-		swift -F '$(TMPDIR)/SQLite.swift/Build/Products/Debug'
+	@$(XCODEBUILD) $(BUILD_ARGUMENTS) -derivedDataPath $(TMPDIR)/SQLite.swift > /dev/null && \
+		swift repl -F '$(TMPDIR)/SQLite.swift/Build/Products/Debug'
 
 sloc:
-	@zsh -c "grep -vE '^ *//|^$$' Sources/**/*.{swift,h,m} | wc -l"
+	@zsh -c "grep -vE '^ *//|^$$' Sources/**/*.{swift,h} | wc -l"
+
+$(SWIFTLINT):
+	set -e ; \
+	curl $(CURL_OPTS) $(SWIFTLINT_URL) -o swiftlint.zip; \
+	unzip -o swiftlint.zip swiftlint; \
+	mkdir -p bin; \
+	mv swiftlint $@ && rm -f swiftlint.zip
+
+$(XCBEAUTIFY):
+	set -e; \
+	FILE=$(XCBEAUTIFY_PLATFORM); \
+	curl $(CURL_OPTS) $(XCBEAUTIFY_URL) -o $$FILE; \
+	case "$${FILE#*.}" in \
+	  "zip") \
+		unzip -o $$FILE xcbeautify; \
+		;; \
+	  "tar.xz") \
+	  	tar -xvf $$FILE xcbeautify; \
+		;; \
+	  *) \
+		echo "unknown extension $${FILE#*.}!"; \
+		exit 1; \
+		;; \
+	esac; \
+	mkdir -p bin; \
+	mv xcbeautify $@ && rm -f $$FILE;
 
 .PHONY: test clean repl sloc
diff --git a/Sources/SQLite/Core/Backup.swift b/Sources/SQLite/Core/Backup.swift
index 84ebf1e0..0eebbdd5 100644
--- a/Sources/SQLite/Core/Backup.swift
+++ b/Sources/SQLite/Core/Backup.swift
@@ -140,7 +140,7 @@ public final class Backup {
     /// - Parameter pagesToCopy: The maximal number of pages to copy in one step
     ///
     /// - Throws: `Result.Error` if step fails.
-    //
+    ///
     /// See: <https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupstep>
     public func step(pagesToCopy pages: Pages = .all) throws {
         let status = sqlite3_backup_step(handle, pages.number)
diff --git a/Sources/SQLite/Helpers.swift b/Sources/SQLite/Helpers.swift
index e3d37e11..79d057d6 100644
--- a/Sources/SQLite/Helpers.swift
+++ b/Sources/SQLite/Helpers.swift
@@ -38,6 +38,7 @@ public func *(_: Expression<Binding>?, _: Expression<Binding>?) -> Expression<Vo
     Expression(literal: "*")
 }
 
+// swiftlint:disable:next type_name
 public protocol _OptionalType {
 
     associatedtype WrappedType
diff --git a/Sources/SQLite/Schema/SchemaReader.swift b/Sources/SQLite/Schema/SchemaReader.swift
index 1c26fdd6..0c02ba9f 100644
--- a/Sources/SQLite/Schema/SchemaReader.swift
+++ b/Sources/SQLite/Schema/SchemaReader.swift
@@ -13,7 +13,7 @@ public class SchemaReader {
     // column name, data type, whether or not the column can be NULL, and the default value for the column. The
     // "pk" column in the result set is zero for columns that are not part of the primary key, and is the
     // index of the column in the primary key for columns that are part of the primary key.
-    public func columnDefinitions(table: String) throws  -> [ColumnDefinition] {
+    public func columnDefinitions(table: String) throws -> [ColumnDefinition] {
         func parsePrimaryKey(column: String) throws -> ColumnDefinition.PrimaryKey? {
             try createTableSQL(name: table).flatMap { .init(sql: $0) }
         }
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index feff2f69..c59b728f 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -1105,7 +1105,7 @@ extension Connection {
         return value(try scalar(expression.template, expression.bindings))
     }
 
-    public func scalar<V: Value>(_ query: Select<V?>) throws ->  V.ValueType? {
+    public func scalar<V: Value>(_ query: Select<V?>) throws -> V.ValueType? {
         let expression = query.expression
         guard let value = try scalar(expression.template, expression.bindings) as? V.Datatype else { return nil }
         return V.fromDatatypeValue(value)
diff --git a/Tests/.swiftlint.yml b/Tests/.swiftlint.yml
index 3537085c..81d6c314 100644
--- a/Tests/.swiftlint.yml
+++ b/Tests/.swiftlint.yml
@@ -6,8 +6,8 @@ disabled_rules:
   - identifier_name
 
 type_body_length:
-  warning: 800
-  error: 800
+  warning: 1000
+  error: 1000
 
 function_body_length:
   warning: 200
diff --git a/Tests/SQLiteTests/Schema/SchemaTests.swift b/Tests/SQLiteTests/Schema/SchemaTests.swift
index a7de8bcf..4f4a49d1 100644
--- a/Tests/SQLiteTests/Schema/SchemaTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaTests.swift
@@ -72,6 +72,7 @@ class SchemaTests: XCTestCase {
     }
 
     // thoroughness test for ambiguity
+    // swiftlint:disable:next function_body_length
     func test_column_compilesColumnDefinitionExpression() {
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"int64\" INTEGER NOT NULL)",
@@ -390,6 +391,7 @@ class SchemaTests: XCTestCase {
         )
     }
 
+    // swiftlint:disable:next function_body_length
     func test_column_withStringExpression_compilesCollatedColumnDefinitionExpression() {
         XCTAssertEqual(
             "CREATE TABLE \"table\" (\"string\" TEXT NOT NULL COLLATE RTRIM)",
diff --git a/Tests/SQLiteTests/Typed/CustomFunctionsTests.swift b/Tests/SQLiteTests/Typed/CustomFunctionsTests.swift
index c4eb51e6..0f46b380 100644
--- a/Tests/SQLiteTests/Typed/CustomFunctionsTests.swift
+++ b/Tests/SQLiteTests/Typed/CustomFunctionsTests.swift
@@ -5,8 +5,8 @@ import SQLite
 #if !os(Linux)
 
 class CustomFunctionNoArgsTests: SQLiteTestCase {
-    typealias FunctionNoOptional              = ()  -> Expression<String>
-    typealias FunctionResultOptional          = ()  -> Expression<String?>
+    typealias FunctionNoOptional              = () -> Expression<String>
+    typealias FunctionResultOptional          = () -> Expression<String?>
 
     func testFunctionNoOptional() throws {
         let _: FunctionNoOptional = try db.createFunction("test", deterministic: true) {
@@ -26,9 +26,9 @@ class CustomFunctionNoArgsTests: SQLiteTestCase {
 }
 
 class CustomFunctionWithOneArgTests: SQLiteTestCase {
-    typealias FunctionNoOptional              = (Expression<String>)  -> Expression<String>
+    typealias FunctionNoOptional              = (Expression<String>) -> Expression<String>
     typealias FunctionLeftOptional            = (Expression<String?>) -> Expression<String>
-    typealias FunctionResultOptional          = (Expression<String>)  -> Expression<String?>
+    typealias FunctionResultOptional          = (Expression<String>) -> Expression<String?>
     typealias FunctionLeftResultOptional      = (Expression<String?>) -> Expression<String?>
 
     func testFunctionNoOptional() throws {
@@ -65,12 +65,12 @@ class CustomFunctionWithOneArgTests: SQLiteTestCase {
 }
 
 class CustomFunctionWithTwoArgsTests: SQLiteTestCase {
-    typealias FunctionNoOptional              = (Expression<String>, Expression<String>)  -> Expression<String>
-    typealias FunctionLeftOptional            = (Expression<String?>, Expression<String>)  -> Expression<String>
+    typealias FunctionNoOptional              = (Expression<String>, Expression<String>) -> Expression<String>
+    typealias FunctionLeftOptional            = (Expression<String?>, Expression<String>) -> Expression<String>
     typealias FunctionRightOptional           = (Expression<String>, Expression<String?>) -> Expression<String>
-    typealias FunctionResultOptional          = (Expression<String>, Expression<String>)  -> Expression<String?>
+    typealias FunctionResultOptional          = (Expression<String>, Expression<String>) -> Expression<String?>
     typealias FunctionLeftRightOptional       = (Expression<String?>, Expression<String?>) -> Expression<String>
-    typealias FunctionLeftResultOptional      = (Expression<String?>, Expression<String>)  -> Expression<String?>
+    typealias FunctionLeftResultOptional      = (Expression<String?>, Expression<String>) -> Expression<String?>
     typealias FunctionRightResultOptional     = (Expression<String>, Expression<String?>) -> Expression<String?>
     typealias FunctionLeftRightResultOptional = (Expression<String?>, Expression<String?>) -> Expression<String?>
 

From 4a0ab2a7445712e71ff803e020b74f9557ae64a8 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 21 May 2023 15:14:36 +0200
Subject: [PATCH 597/685] Fix simulator version

---
 .github/workflows/build.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index ae806ecc..ac705e4e 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,7 +1,7 @@
 name: Build and test
 on: [push, pull_request]
 env:
-  IOS_SIMULATOR: iPhone 12
+  IOS_SIMULATOR: "iPhone 14"
   IOS_VERSION: "16.4"
 jobs:
   build:

From e4f4ddff5f124652421d7cd99512181bed86b0e7 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 21 May 2023 15:22:26 +0200
Subject: [PATCH 598/685] Use newer Xcode

---
 .github/workflows/build.yml | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index ac705e4e..fbe4ec49 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -8,13 +8,11 @@ jobs:
     runs-on: macos-13
     steps:
     - uses: actions/checkout@v2
-    - name: Install
+    - name: "Select Xcode"
       run: |
-        gem update bundler
-        gem install xcpretty --no-document
-        brew update
-        brew outdated carthage || brew upgrade carthage
-        brew outdated swiftlint || brew upgrade swiftlint
+        xcode-select -p
+        xcode-select -s /Applications/Xcode-14.3.app/Contents/Developer
+        xcode-select -p
     - name: "Lint"
       run: make lint
     - name: "Run tests (PACKAGE_MANAGER_COMMAND: test)"

From 1bc58a5477cc47856d1e6a31b834f1cc0f66c00b Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 21 May 2023 15:28:43 +0200
Subject: [PATCH 599/685] Fix path

---
 .github/workflows/build.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index fbe4ec49..8c893c77 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -11,7 +11,7 @@ jobs:
     - name: "Select Xcode"
       run: |
         xcode-select -p
-        xcode-select -s /Applications/Xcode-14.3.app/Contents/Developer
+        xcode-select -s /Applications/Xcode_14.3.app/Contents/Developer
         xcode-select -p
     - name: "Lint"
       run: make lint

From 79bab4610b74cc7a8dee118a6b9ebce769aaec61 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 21 May 2023 15:33:04 +0200
Subject: [PATCH 600/685] sudo

---
 .github/workflows/build.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 8c893c77..15f325ed 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -11,7 +11,7 @@ jobs:
     - name: "Select Xcode"
       run: |
         xcode-select -p
-        xcode-select -s /Applications/Xcode_14.3.app/Contents/Developer
+        sudo xcode-select -s /Applications/Xcode_14.3.app/Contents/Developer
         xcode-select -p
     - name: "Lint"
       run: make lint

From b028fcdda1489a3bb0c738f8809154f9c4be7f5b Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 21 May 2023 17:48:05 +0200
Subject: [PATCH 601/685] Try Xcode 14.2

---
 .github/workflows/build.yml | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 15f325ed..242a9021 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -2,7 +2,7 @@ name: Build and test
 on: [push, pull_request]
 env:
   IOS_SIMULATOR: "iPhone 14"
-  IOS_VERSION: "16.4"
+  IOS_VERSION: "16.2"
 jobs:
   build:
     runs-on: macos-13
@@ -11,8 +11,7 @@ jobs:
     - name: "Select Xcode"
       run: |
         xcode-select -p
-        sudo xcode-select -s /Applications/Xcode_14.3.app/Contents/Developer
-        xcode-select -p
+        sudo xcode-select -s /Applications/Xcode_14.2.app/Contents/Developer
     - name: "Lint"
       run: make lint
     - name: "Run tests (PACKAGE_MANAGER_COMMAND: test)"

From 101109848902bb2c7061286c86f15a638d6d5a17 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 21 May 2023 22:28:40 +0200
Subject: [PATCH 602/685] Update docs

---
 .github/workflows/build.yml |  2 ++
 CHANGELOG.md                |  5 +++++
 Documentation/Index.md      | 31 ++++++++++++++-----------------
 README.md                   |  5 +----
 4 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 242a9021..9cc2f56e 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -9,6 +9,8 @@ jobs:
     steps:
     - uses: actions/checkout@v2
     - name: "Select Xcode"
+      # Currently only works with Xcode 14.2:
+      # https://github.com/CocoaPods/CocoaPods/issues/11839
       run: |
         xcode-select -p
         sudo xcode-select -s /Applications/Xcode_14.2.app/Contents/Developer
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fc759118..970b4ca1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+0.15.0 (unreleased)
+========================================
+
+* New minimum deployment targets: iOS/tvOS 11.0, watchOS 4.0
+
 0.14.1 (01-11-2022), [diff][diff-0.14.1]
 ========================================
 
diff --git a/Documentation/Index.md b/Documentation/Index.md
index 583d5def..5d72aa4b 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -77,9 +77,6 @@
 
 ## Installation
 
-> _Note:_ SQLite.swift requires Swift 5 (and
-> [Xcode 10.2](https://developer.apple.com/xcode/downloads/)) or greater.
-
 ### Swift Package Manager
 
 The [Swift Package Manager][] is a tool for managing the distribution of
@@ -1142,11 +1139,11 @@ let query = managers
 chain.with(chain, recursive: true, as: query)
 // WITH RECURSIVE
 //   "chain" AS (
-//     SELECT * FROM "managers" WHERE "id" = 8 
-//     UNION 
-//     SELECT * from "chain" 
+//     SELECT * FROM "managers" WHERE "id" = 8
+//     UNION
+//     SELECT * from "chain"
 //     JOIN "managers" ON "chain"."manager_id" = "managers"."id"
-//   ) 
+//   )
 // SELECT * FROM "chain"
 ```
 
@@ -1156,7 +1153,7 @@ Column names and a materialization hint can optionally be provided.
 // Add a "level" column to the query representing manager's position in the chain
 let level = Expression<Int64>("level")
 
-let queryWithLevel = 
+let queryWithLevel =
     managers
         .select(id, managerId, 0)
         .where(id == 8)
@@ -1166,18 +1163,18 @@ let queryWithLevel =
                 .join(managers, on: chain[managerId] == managers[id])
         )
 
-chain.with(chain, 
-           columns: [id, managerId, level], 
+chain.with(chain,
+           columns: [id, managerId, level],
            recursive: true,
            hint: .materialize,
            as: queryWithLevel)
 // WITH RECURSIVE
 //   "chain" ("id", "manager_id", "level") AS MATERIALIZED (
-//     SELECT ("id", "manager_id", 0) FROM "managers" WHERE "id" = 8 
-//     UNION 
-//     SELECT ("manager"."id", "manager"."manager_id", "level" + 1) FROM "chain" 
+//     SELECT ("id", "manager_id", 0) FROM "managers" WHERE "id" = 8
+//     UNION
+//     SELECT ("manager"."id", "manager"."manager_id", "level" + 1) FROM "chain"
 //     JOIN "managers" ON "chain"."manager_id" = "managers"."id"
-//   ) 
+//   )
 // SELECT * FROM "chain"
 ```
 
@@ -1266,7 +1263,7 @@ let count = try db.scalar(users.filter(name != nil).count)
 We can upsert rows into a table by calling a [query’s](#queries) `upsert`
 function with a list of [setters](#setters)—typically [typed column
 expressions](#expressions) and values (which can also be expressions)—each
-joined by the `<-` operator. Upserting is like inserting, except if there is a 
+joined by the `<-` operator. Upserting is like inserting, except if there is a
 conflict on the specified column value, SQLite will perform an update on the row instead.
 
 ```swift
@@ -1957,7 +1954,7 @@ for row in stmt.bind(kUTTypeImage) { /* ... */ }
 ```
 
 > _Note:_ Prepared queries can be reused, and long lived prepared queries should be `reset()` after each use. Otherwise, the transaction (either [implicit or explicit](https://www.sqlite.org/lang_transaction.html#implicit_versus_explicit_transactions)) will be held open until the query is reset or finalized. This can affect performance. Statements are reset automatically during `deinit`.
-> 
+>
 > ```swift
 > someObj.statement = try db.prepare("SELECT * FROM attachments WHERE typeConformsTo(UTI, ?)")
 > for row in someObj.statement.bind(kUTTypeImage) { /* ... */ }
@@ -2134,7 +2131,7 @@ using the following functions.
         }
     }
     ```
-    
+
   - `run` prepares a single `Statement` object from a SQL string, optionally
     binds values to it (using the statement’s `bind` function), executes,
     and returns the statement.
diff --git a/README.md b/README.md
index 90333b16..e6e5a894 100644
--- a/README.md
+++ b/README.md
@@ -90,7 +90,7 @@ API.
 // Wrap everything in a do...catch to handle errors
 do {
     // ...
-    
+
     let stmt = try db.prepare("INSERT INTO users (email) VALUES (?)")
     for email in ["betty@icloud.com", "cathy@icloud.com"] {
         try stmt.run(email)
@@ -119,9 +119,6 @@ interactively, from the Xcode project’s playground.
 
 ## Installation
 
-> _Note:_ Version 0.11.6 and later requires Swift 5 (and [Xcode](https://developer.apple.com/xcode/downloads/) 10.2) or greater.
-> Version 0.11.5 requires Swift 4.2 (and [Xcode](https://developer.apple.com/xcode/downloads/) 10.1) or greater.
-
 ### Swift Package Manager
 
 The [Swift Package Manager][] is a tool for managing the distribution of

From ab3c598db29a7a2db3e06e9642736cb18e670a0e Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sun, 21 May 2023 23:59:35 +0200
Subject: [PATCH 603/685] Use shorthand optional binding

---
 .swiftlint.yml                                |  2 ++
 Sources/SQLite/Core/Connection+Attach.swift   |  2 +-
 Sources/SQLite/Core/Connection.swift          | 18 +++++------
 Sources/SQLite/Core/Result.swift              |  4 +--
 Sources/SQLite/Extensions/FTS4.swift          | 16 +++++-----
 Sources/SQLite/Extensions/FTS5.swift          |  6 ++--
 Sources/SQLite/Helpers.swift                  |  2 +-
 Sources/SQLite/Schema/SchemaDefinitions.swift |  2 +-
 Sources/SQLite/Schema/SchemaReader.swift      |  4 +--
 Sources/SQLite/Typed/Coding.swift             | 12 ++++----
 Sources/SQLite/Typed/CoreFunctions.swift      | 30 +++++++++----------
 Sources/SQLite/Typed/Operators.swift          | 16 +++++-----
 12 files changed, 58 insertions(+), 56 deletions(-)

diff --git a/.swiftlint.yml b/.swiftlint.yml
index e728e191..1bb21cd5 100644
--- a/.swiftlint.yml
+++ b/.swiftlint.yml
@@ -1,3 +1,5 @@
+opt_in_rules:
+  - shorthand_optional_binding
 disabled_rules: # rule identifiers to exclude from running
   - todo
   - operator_whitespace
diff --git a/Sources/SQLite/Core/Connection+Attach.swift b/Sources/SQLite/Core/Connection+Attach.swift
index 47e6af5e..8a25e51d 100644
--- a/Sources/SQLite/Core/Connection+Attach.swift
+++ b/Sources/SQLite/Core/Connection+Attach.swift
@@ -13,7 +13,7 @@ extension Connection {
     #if SQLITE_SWIFT_SQLCIPHER
     /// See https://www.zetetic.net/sqlcipher/sqlcipher-api/#attach
     public func attach(_ location: Location, as schemaName: String, key: String? = nil) throws {
-        if let key = key {
+        if let key {
             try run("ATTACH DATABASE ? AS ? KEY ?", location.description, schemaName, key)
         } else {
             try run("ATTACH DATABASE ? AS ?", location.description, schemaName)
diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 26cadea4..f2c3b781 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -414,7 +414,7 @@ public final class Connection {
     ///   times it’s been called for this lock. If it returns `true`, it will
     ///   try again. If it returns `false`, no further attempts will be made.
     public func busyHandler(_ callback: ((_ tries: Int) -> Bool)?) {
-        guard let callback = callback else {
+        guard let callback else {
             sqlite3_busy_handler(handle, nil, nil)
             busyHandler = nil
             return
@@ -449,7 +449,7 @@ public final class Connection {
     @available(watchOS, deprecated: 3.0)
     @available(tvOS, deprecated: 10.0)
     fileprivate func trace_v1(_ callback: ((String) -> Void)?) {
-        guard let callback = callback else {
+        guard let callback else {
             sqlite3_trace(handle, nil /* xCallback */, nil /* pCtx */)
             trace = nil
             return
@@ -458,7 +458,7 @@ public final class Connection {
             callback(String(cString: pointer.assumingMemoryBound(to: UInt8.self)))
         }
         sqlite3_trace(handle, { (context: UnsafeMutableRawPointer?, SQL: UnsafePointer<Int8>?) in
-                    if let context = context, let SQL = SQL {
+                    if let context, let SQL {
                         unsafeBitCast(context, to: Trace.self)(SQL)
                     }
             },
@@ -469,7 +469,7 @@ public final class Connection {
 
     @available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *)
     fileprivate func trace_v2(_ callback: ((String) -> Void)?) {
-        guard let callback = callback else {
+        guard let callback else {
             // If the X callback is NULL or if the M mask is zero, then tracing is disabled.
             sqlite3_trace_v2(handle, 0 /* mask */, nil /* xCallback */, nil /* pCtx */)
             trace = nil
@@ -485,7 +485,7 @@ public final class Connection {
                  // callback was invoked. The C argument is a copy of the context pointer.
                  // The P and X arguments are pointers whose meanings depend on T.
                  (_: UInt32, context: UnsafeMutableRawPointer?, pointer: UnsafeMutableRawPointer?, _: UnsafeMutableRawPointer?) in
-                 if let pointer = pointer,
+                 if let pointer,
                     let expandedSQL = sqlite3_expanded_sql(OpaquePointer(pointer)) {
                      unsafeBitCast(context, to: Trace.self)(expandedSQL)
                      sqlite3_free(expandedSQL)
@@ -507,7 +507,7 @@ public final class Connection {
     ///   `.Insert`, `.Update`, or `.Delete`), database name, table name, and
     ///   rowid.
     public func updateHook(_ callback: ((_ operation: Operation, _ db: String, _ table: String, _ rowid: Int64) -> Void)?) {
-        guard let callback = callback else {
+        guard let callback else {
             sqlite3_update_hook(handle, nil, nil)
             updateHook = nil
             return
@@ -535,7 +535,7 @@ public final class Connection {
     ///   committed. If this callback throws, the transaction will be rolled
     ///   back.
     public func commitHook(_ callback: (() throws -> Void)?) {
-        guard let callback = callback else {
+        guard let callback else {
             sqlite3_commit_hook(handle, nil, nil)
             commitHook = nil
             return
@@ -562,7 +562,7 @@ public final class Connection {
     /// - Parameter callback: A callback invoked when a transaction is rolled
     ///   back.
     public func rollbackHook(_ callback: (() -> Void)?) {
-        guard let callback = callback else {
+        guard let callback else {
             sqlite3_rollback_hook(handle, nil, nil)
             rollbackHook = nil
             return
@@ -650,7 +650,7 @@ public final class Connection {
         try check(sqlite3_create_collation_v2(handle, collation, SQLITE_UTF8,
             unsafeBitCast(box, to: UnsafeMutableRawPointer.self), { (callback: UnsafeMutableRawPointer?, _,
                                                                      lhs: UnsafeRawPointer?, _, rhs: UnsafeRawPointer?) in /* xCompare */
-            if let lhs = lhs, let rhs = rhs {
+            if let lhs, let rhs {
                 return unsafeBitCast(callback, to: Collation.self)(lhs, rhs)
             } else {
                 fatalError("sqlite3_create_collation_v2 callback called with NULL pointer")
diff --git a/Sources/SQLite/Core/Result.swift b/Sources/SQLite/Core/Result.swift
index 9fe47ada..ee59e5d1 100644
--- a/Sources/SQLite/Core/Result.swift
+++ b/Sources/SQLite/Core/Result.swift
@@ -51,13 +51,13 @@ extension Result: CustomStringConvertible {
     public var description: String {
         switch self {
         case let .error(message, errorCode, statement):
-            if let statement = statement {
+            if let statement {
                 return "\(message) (\(statement)) (code: \(errorCode))"
             } else {
                 return "\(message) (code: \(errorCode))"
             }
         case let .extendedError(message, extendedCode, statement):
-            if let statement = statement {
+            if let statement {
                 return "\(message) (\(statement)) (extended code: \(extendedCode))"
             } else {
                 return "\(message) (extended code: \(extendedCode))"
diff --git a/Sources/SQLite/Extensions/FTS4.swift b/Sources/SQLite/Extensions/FTS4.swift
index 8e91e453..c02cfdc1 100644
--- a/Sources/SQLite/Extensions/FTS4.swift
+++ b/Sources/SQLite/Extensions/FTS4.swift
@@ -98,7 +98,7 @@ public struct Tokenizer {
                                  separators: Set<Character> = []) -> Tokenizer {
         var arguments = [String]()
 
-        if let removeDiacritics = removeDiacritics {
+        if let removeDiacritics {
             arguments.append("remove_diacritics=\(removeDiacritics ? 1 : 0)".quote())
         }
 
@@ -208,13 +208,13 @@ open class FTSConfig {
     func options() -> Options {
         var options = Options()
         options.append(formatColumnDefinitions())
-        if let tokenizer = tokenizer {
+        if let tokenizer {
             options.append("tokenize", value: Expression<Void>(literal: tokenizer.description))
         }
         options.appendCommaSeparated("prefix", values: prefixes.sorted().map { String($0) })
         if isContentless {
             options.append("content", value: "")
-        } else if let externalContentSchema = externalContentSchema {
+        } else if let externalContentSchema {
             options.append("content", value: externalContentSchema.tableName())
         }
         return options
@@ -306,19 +306,19 @@ open class FTS4Config: FTSConfig {
         for (column, _) in (columnDefinitions.filter { $0.options.contains(.unindexed) }) {
             options.append("notindexed", value: column)
         }
-        if let languageId = languageId {
+        if let languageId {
             options.append("languageid", value: languageId)
         }
-        if let compressFunction = compressFunction {
+        if let compressFunction {
             options.append("compress", value: compressFunction)
         }
-        if let uncompressFunction = uncompressFunction {
+        if let uncompressFunction {
             options.append("uncompress", value: uncompressFunction)
         }
-        if let matchInfo = matchInfo {
+        if let matchInfo {
             options.append("matchinfo", value: matchInfo.rawValue)
         }
-        if let order = order {
+        if let order {
             options.append("order", value: order.rawValue)
         }
         return options
diff --git a/Sources/SQLite/Extensions/FTS5.swift b/Sources/SQLite/Extensions/FTS5.swift
index 2e4f65fb..3e84e171 100644
--- a/Sources/SQLite/Extensions/FTS5.swift
+++ b/Sources/SQLite/Extensions/FTS5.swift
@@ -69,13 +69,13 @@ open class FTS5Config: FTSConfig {
 
     override func options() -> Options {
         var options = super.options()
-        if let contentRowId = contentRowId {
+        if let contentRowId {
             options.append("content_rowid", value: contentRowId)
         }
-        if let columnSize = columnSize {
+        if let columnSize {
             options.append("columnsize", value: Expression<Int>(value: columnSize))
         }
-        if let detail = detail {
+        if let detail {
             options.append("detail", value: detail.rawValue)
         }
         return options
diff --git a/Sources/SQLite/Helpers.swift b/Sources/SQLite/Helpers.swift
index 79d057d6..adfadc8a 100644
--- a/Sources/SQLite/Helpers.swift
+++ b/Sources/SQLite/Helpers.swift
@@ -109,7 +109,7 @@ extension String {
 }
 
 func transcode(_ literal: Binding?) -> String {
-    guard let literal = literal else { return "NULL" }
+    guard let literal else { return "NULL" }
 
     switch literal {
     case let blob as Blob:
diff --git a/Sources/SQLite/Schema/SchemaDefinitions.swift b/Sources/SQLite/Schema/SchemaDefinitions.swift
index b314e5c0..2d38e1fb 100644
--- a/Sources/SQLite/Schema/SchemaDefinitions.swift
+++ b/Sources/SQLite/Schema/SchemaDefinitions.swift
@@ -170,7 +170,7 @@ public enum LiteralValue: Equatable, CustomStringConvertible {
     // swiftlint:enable identifier_name
 
     init(_ string: String?) {
-        guard let string = string else {
+        guard let string else {
             self = .NULL
             return
         }
diff --git a/Sources/SQLite/Schema/SchemaReader.swift b/Sources/SQLite/Schema/SchemaReader.swift
index 0c02ba9f..58a9b1bd 100644
--- a/Sources/SQLite/Schema/SchemaReader.swift
+++ b/Sources/SQLite/Schema/SchemaReader.swift
@@ -39,10 +39,10 @@ public class SchemaReader {
                                   type: ObjectDefinition.ObjectType? = nil,
                                   temp: Bool = false) throws -> [ObjectDefinition] {
         var query: QueryType = SchemaTable.get(for: connection, temp: temp)
-        if let name = name {
+        if let name {
             query = query.where(SchemaTable.nameColumn == name)
         }
-        if let type = type {
+        if let type {
             query = query.where(SchemaTable.typeColumn == type.rawValue)
         }
         return try connection.prepare(query).map { row -> ObjectDefinition in
diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index b96bc64e..e7db03fb 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -215,7 +215,7 @@ private class SQLiteEncoder: Encoder {
         }
 
         func encodeIfPresent(_ value: Int?, forKey key: SQLiteEncoder.SQLiteKeyedEncodingContainer<Key>.Key) throws {
-            if let value = value {
+            if let value {
                 try encode(value, forKey: key)
             } else if forcingNilValueSetters {
                 encoder.setters.append(Expression<Int?>(key.stringValue) <- nil)
@@ -223,7 +223,7 @@ private class SQLiteEncoder: Encoder {
         }
 
         func encodeIfPresent(_ value: Bool?, forKey key: Key) throws {
-            if let value = value {
+            if let value {
                 try encode(value, forKey: key)
             } else if forcingNilValueSetters {
                 encoder.setters.append(Expression<Bool?>(key.stringValue) <- nil)
@@ -231,7 +231,7 @@ private class SQLiteEncoder: Encoder {
         }
 
         func encodeIfPresent(_ value: Float?, forKey key: Key) throws {
-            if let value = value {
+            if let value {
                 try encode(value, forKey: key)
             } else if forcingNilValueSetters {
                 encoder.setters.append(Expression<Double?>(key.stringValue) <- nil)
@@ -239,7 +239,7 @@ private class SQLiteEncoder: Encoder {
         }
 
         func encodeIfPresent(_ value: Double?, forKey key: Key) throws {
-            if let value = value {
+            if let value {
                 try encode(value, forKey: key)
             } else if forcingNilValueSetters {
                 encoder.setters.append(Expression<Double?>(key.stringValue) <- nil)
@@ -247,7 +247,7 @@ private class SQLiteEncoder: Encoder {
         }
 
         func encodeIfPresent(_ value: String?, forKey key: MyKey) throws {
-            if let value = value {
+            if let value {
                 try encode(value, forKey: key)
             } else if forcingNilValueSetters {
                 encoder.setters.append(Expression<String?>(key.stringValue) <- nil)
@@ -270,7 +270,7 @@ private class SQLiteEncoder: Encoder {
         }
 
         func encodeIfPresent<T>(_ value: T?, forKey key: Key) throws where T: Swift.Encodable {
-            guard let value = value else {
+            guard let value else {
                 guard forcingNilValueSetters else {
                     return
                 }
diff --git a/Sources/SQLite/Typed/CoreFunctions.swift b/Sources/SQLite/Typed/CoreFunctions.swift
index dc6a1044..4429bb5f 100644
--- a/Sources/SQLite/Typed/CoreFunctions.swift
+++ b/Sources/SQLite/Typed/CoreFunctions.swift
@@ -100,7 +100,7 @@ extension ExpressionType where UnderlyingType == Double {
     ///
     /// - Returns: A copy of the expression wrapped with the `round` function.
     public func round(_ precision: Int? = nil) -> Expression<UnderlyingType> {
-        guard let precision = precision else {
+        guard let precision else {
             return Function.round.wrap([self])
         }
         return Function.round.wrap([self, Int(precision)])
@@ -120,7 +120,7 @@ extension ExpressionType where UnderlyingType == Double? {
     ///
     /// - Returns: A copy of the expression wrapped with the `round` function.
     public func round(_ precision: Int? = nil) -> Expression<UnderlyingType> {
-        guard let precision = precision else {
+        guard let precision else {
             return Function.round.wrap(self)
         }
         return Function.round.wrap([self, Int(precision)])
@@ -250,7 +250,7 @@ extension ExpressionType where UnderlyingType == String {
     /// - Returns: A copy of the expression appended with a `LIKE` query against
     ///   the given pattern.
     public func like(_ pattern: String, escape character: Character? = nil) -> Expression<Bool> {
-        guard let character = character else {
+        guard let character else {
             return "LIKE".infix(self, pattern)
         }
         return Expression("(\(template) LIKE ? ESCAPE ?)", bindings + [pattern, String(character)])
@@ -274,7 +274,7 @@ extension ExpressionType where UnderlyingType == String {
     /// - Returns: A copy of the expression appended with a `LIKE` query against
     ///   the given pattern.
     public func like(_ pattern: Expression<String>, escape character: Character? = nil) -> Expression<Bool> {
-        guard let character = character else {
+        guard let character else {
             return Function.like.infix(self, pattern)
         }
         let like: Expression<Bool> =  Function.like.infix(self, pattern, wrap: false)
@@ -349,7 +349,7 @@ extension ExpressionType where UnderlyingType == String {
     ///
     /// - Returns: A copy of the expression wrapped with the `ltrim` function.
     public func ltrim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
-        guard let characters = characters else {
+        guard let characters else {
             return Function.ltrim.wrap(self)
         }
         return Function.ltrim.wrap([self, String(characters)])
@@ -367,7 +367,7 @@ extension ExpressionType where UnderlyingType == String {
     ///
     /// - Returns: A copy of the expression wrapped with the `rtrim` function.
     public func rtrim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
-        guard let characters = characters else {
+        guard let characters else {
             return Function.rtrim.wrap(self)
         }
         return Function.rtrim.wrap([self, String(characters)])
@@ -385,7 +385,7 @@ extension ExpressionType where UnderlyingType == String {
     ///
     /// - Returns: A copy of the expression wrapped with the `trim` function.
     public func trim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
-        guard let characters = characters else {
+        guard let characters else {
             return Function.trim.wrap([self])
         }
         return Function.trim.wrap([self, String(characters)])
@@ -409,7 +409,7 @@ extension ExpressionType where UnderlyingType == String {
     }
 
     public func substring(_ location: Int, length: Int? = nil) -> Expression<UnderlyingType> {
-        guard let length = length else {
+        guard let length else {
             return Function.substr.wrap([self, location])
         }
         return Function.substr.wrap([self, location, length])
@@ -475,7 +475,7 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression appended with a `LIKE` query against
     ///   the given pattern.
     public func like(_ pattern: String, escape character: Character? = nil) -> Expression<Bool?> {
-        guard let character = character else {
+        guard let character else {
             return Function.like.infix(self, pattern)
         }
         return Expression("(\(template) LIKE ? ESCAPE ?)", bindings + [pattern, String(character)])
@@ -499,7 +499,7 @@ extension ExpressionType where UnderlyingType == String? {
     /// - Returns: A copy of the expression appended with a `LIKE` query against
     ///   the given pattern.
     public func like(_ pattern: Expression<String>, escape character: Character? = nil) -> Expression<Bool?> {
-        guard let character = character else {
+        guard let character else {
             return Function.like.infix(self, pattern)
         }
         let like: Expression<Bool> = Function.like.infix(self, pattern, wrap: false)
@@ -574,7 +574,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression wrapped with the `ltrim` function.
     public func ltrim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
-        guard let characters = characters else {
+        guard let characters else {
             return Function.ltrim.wrap(self)
         }
         return Function.ltrim.wrap([self, String(characters)])
@@ -592,7 +592,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression wrapped with the `rtrim` function.
     public func rtrim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
-        guard let characters = characters else {
+        guard let characters else {
             return Function.rtrim.wrap(self)
         }
         return Function.rtrim.wrap([self, String(characters)])
@@ -610,7 +610,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression wrapped with the `trim` function.
     public func trim(_ characters: Set<Character>? = nil) -> Expression<UnderlyingType> {
-        guard let characters = characters else {
+        guard let characters else {
             return Function.trim.wrap(self)
         }
         return Function.trim.wrap([self, String(characters)])
@@ -649,7 +649,7 @@ extension ExpressionType where UnderlyingType == String? {
     ///
     /// - Returns: A copy of the expression wrapped with the `substr` function.
     public func substring(_ location: Int, length: Int? = nil) -> Expression<UnderlyingType> {
-        guard let length = length else {
+        guard let length else {
             return Function.substr.wrap([self, location])
         }
         return Function.substr.wrap([self, location, length])
@@ -726,7 +726,7 @@ extension String {
     /// - Returns: A copy of the expression appended with a `LIKE` query against
     ///   the given pattern.
     public func like(_ pattern: Expression<String>, escape character: Character? = nil) -> Expression<Bool> {
-        guard let character = character else {
+        guard let character else {
             return Function.like.infix(self, pattern)
         }
         let like: Expression<Bool> = Function.like.infix(self, pattern, wrap: false)
diff --git a/Sources/SQLite/Typed/Operators.swift b/Sources/SQLite/Typed/Operators.swift
index 5ffbbceb..1c611cbc 100644
--- a/Sources/SQLite/Typed/Operators.swift
+++ b/Sources/SQLite/Typed/Operators.swift
@@ -367,14 +367,14 @@ public func ==<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V
     Operator.eq.infix(lhs, rhs)
 }
 public func ==<V: Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype: Equatable {
-    guard let rhs = rhs else { return "IS".infix(lhs, Expression<V?>(value: nil)) }
+    guard let rhs else { return "IS".infix(lhs, Expression<V?>(value: nil)) }
     return Operator.eq.infix(lhs, rhs)
 }
 public func ==<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Equatable {
     Operator.eq.infix(lhs, rhs)
 }
 public func ==<V: Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
-    guard let lhs = lhs else { return "IS".infix(Expression<V?>(value: nil), rhs) }
+    guard let lhs else { return "IS".infix(Expression<V?>(value: nil), rhs) }
     return Operator.eq.infix(lhs, rhs)
 }
 
@@ -394,14 +394,14 @@ public func ===<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where
     "IS".infix(lhs, rhs)
 }
 public func ===<V: Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype: Equatable {
-    guard let rhs = rhs else { return "IS".infix(lhs, Expression<V?>(value: nil)) }
+    guard let rhs else { return "IS".infix(lhs, Expression<V?>(value: nil)) }
     return "IS".infix(lhs, rhs)
 }
 public func ===<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Equatable {
     "IS".infix(lhs, rhs)
 }
 public func ===<V: Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
-    guard let lhs = lhs else { return "IS".infix(Expression<V?>(value: nil), rhs) }
+    guard let lhs else { return "IS".infix(Expression<V?>(value: nil), rhs) }
     return "IS".infix(lhs, rhs)
 }
 
@@ -421,14 +421,14 @@ public func !=<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where V
     Operator.neq.infix(lhs, rhs)
 }
 public func !=<V: Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype: Equatable {
-    guard let rhs = rhs else { return "IS NOT".infix(lhs, Expression<V?>(value: nil)) }
+    guard let rhs else { return "IS NOT".infix(lhs, Expression<V?>(value: nil)) }
     return Operator.neq.infix(lhs, rhs)
 }
 public func !=<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Equatable {
     Operator.neq.infix(lhs, rhs)
 }
 public func !=<V: Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
-    guard let lhs = lhs else { return "IS NOT".infix(Expression<V?>(value: nil), rhs) }
+    guard let lhs else { return "IS NOT".infix(Expression<V?>(value: nil), rhs) }
     return Operator.neq.infix(lhs, rhs)
 }
 
@@ -448,14 +448,14 @@ public func !==<V: Value>(lhs: Expression<V>, rhs: V) -> Expression<Bool> where
     "IS NOT".infix(lhs, rhs)
 }
 public func !==<V: Value>(lhs: Expression<V?>, rhs: V?) -> Expression<Bool?> where V.Datatype: Equatable {
-    guard let rhs = rhs else { return "IS NOT".infix(lhs, Expression<V?>(value: nil)) }
+    guard let rhs else { return "IS NOT".infix(lhs, Expression<V?>(value: nil)) }
     return "IS NOT".infix(lhs, rhs)
 }
 public func !==<V: Value>(lhs: V, rhs: Expression<V>) -> Expression<Bool> where V.Datatype: Equatable {
     "IS NOT".infix(lhs, rhs)
 }
 public func !==<V: Value>(lhs: V?, rhs: Expression<V?>) -> Expression<Bool?> where V.Datatype: Equatable {
-    guard let lhs = lhs else { return "IS NOT".infix(Expression<V?>(value: nil), rhs) }
+    guard let lhs else { return "IS NOT".infix(Expression<V?>(value: nil), rhs) }
     return "IS NOT".infix(lhs, rhs)
 }
 

From 6aab9fcdc27c97f04b4153589908ec871b17ba55 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Mon, 22 May 2023 00:56:52 +0200
Subject: [PATCH 604/685] Re-enable watch tests

---
 run-tests.sh | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/run-tests.sh b/run-tests.sh
index c54300ee..49330c12 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -8,9 +8,9 @@ if [ -n "$BUILD_SCHEME" ]; then
     fi
 elif [ -n "$VALIDATOR_SUBSPEC" ]; then
     if [ "$VALIDATOR_SUBSPEC" == "none" ]; then
-      pod lib lint --no-subspecs --fail-fast --platforms=ios,osx,tvos
+      pod lib lint --no-subspecs --fail-fast
     else
-      pod lib lint --subspec="${VALIDATOR_SUBSPEC}" --fail-fast --platforms=ios,osx,tvos
+      pod lib lint --subspec="${VALIDATOR_SUBSPEC}" --fail-fast
     fi
 elif [ -n "$CARTHAGE_PLATFORM" ]; then
     cd Tests/Carthage && make test CARTHAGE_PLATFORM="$CARTHAGE_PLATFORM"

From ff93ebc831c01daa0117be6c19e0960347e001a6 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Sat, 27 May 2023 23:09:08 +0200
Subject: [PATCH 605/685] Handle FK definitions w/o key references

Closes #1199
---
 SQLite.xcodeproj/project.pbxproj              |  8 ++++
 Sources/SQLite/Schema/SchemaDefinitions.swift |  4 +-
 Sources/SQLite/Schema/SchemaReader.swift      |  2 +-
 .../Schema/SchemaReaderTests.swift            | 38 +++++++++++++++++++
 4 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index def32855..e6bb4fc9 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -211,6 +211,9 @@
 		DB7C5DA728D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
 		DB7C5DA828D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
 		DB7C5DA928D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
+		DBB93D5A2A22A373009BB96E /* SchemaReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB93D592A22A373009BB96E /* SchemaReaderTests.swift */; };
+		DBB93D5B2A22A373009BB96E /* SchemaReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB93D592A22A373009BB96E /* SchemaReaderTests.swift */; };
+		DBB93D5C2A22A373009BB96E /* SchemaReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB93D592A22A373009BB96E /* SchemaReaderTests.swift */; };
 		EE247AD71C3F04ED00AE3E12 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		EE247ADE1C3F04ED00AE3E12 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE247AD31C3F04ED00AE3E12 /* SQLite.framework */; };
 		EE247B031C3F06E900AE3E12 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
@@ -340,6 +343,7 @@
 		DB58B21028FB864300F8EEA4 /* SchemaReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaReader.swift; sourceTree = "<group>"; };
 		DB58B21528FC7C4600F8EEA4 /* SQLiteFeature.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SQLiteFeature.swift; sourceTree = "<group>"; };
 		DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SQLiteVersion.swift; sourceTree = "<group>"; };
+		DBB93D592A22A373009BB96E /* SchemaReaderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaReaderTests.swift; sourceTree = "<group>"; };
 		EE247AD31C3F04ED00AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AD61C3F04ED00AE3E12 /* SQLite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLite.h; sourceTree = "<group>"; };
 		EE247AD81C3F04ED00AE3E12 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -483,6 +487,7 @@
 		19A17B56FBA20E7245BC8AC0 /* Schema */ = {
 			isa = PBXGroup;
 			children = (
+				DBB93D592A22A373009BB96E /* SchemaReaderTests.swift */,
 				19A176174862D0F0139B3987 /* SchemaDefinitionsTests.swift */,
 				19A17FDB0B0CFB8987906FD0 /* SchemaChangerTests.swift */,
 				19A17CA1DF7D0F7C9A94C51C /* Connection+SchemaTests.swift */,
@@ -998,6 +1003,7 @@
 				19A17FACE8E4D54A50BA934E /* FTS5Tests.swift in Sources */,
 				19A177909023B7B940C5805E /* FTSIntegrationTests.swift in Sources */,
 				19A17E1DD976D5CE80018749 /* FTS4Tests.swift in Sources */,
+				DBB93D5C2A22A373009BB96E /* SchemaReaderTests.swift in Sources */,
 				19A17411403D60640467209E /* ExpressionTests.swift in Sources */,
 				19A17CA4D7B63D845428A9C5 /* StatementTests.swift in Sources */,
 				19A17885B646CB0201BE4BD5 /* QueryTests.swift in Sources */,
@@ -1119,6 +1125,7 @@
 				19A178DA2BB5970778CCAF13 /* FTS5Tests.swift in Sources */,
 				19A1755C49154C87304C9146 /* FTSIntegrationTests.swift in Sources */,
 				19A17444861E1443143DEB44 /* FTS4Tests.swift in Sources */,
+				DBB93D5A2A22A373009BB96E /* SchemaReaderTests.swift in Sources */,
 				19A17DD33C2E43DD6EE05A60 /* ExpressionTests.swift in Sources */,
 				19A17D6EC40BC35A5DC81BA8 /* StatementTests.swift in Sources */,
 				19A17E3F47DA087E2B76D087 /* QueryTests.swift in Sources */,
@@ -1199,6 +1206,7 @@
 				19A1776BD5127DFDF847FF1F /* FTS5Tests.swift in Sources */,
 				19A173088B85A7E18E8582A7 /* FTSIntegrationTests.swift in Sources */,
 				19A178767223229E61C5066F /* FTS4Tests.swift in Sources */,
+				DBB93D5B2A22A373009BB96E /* SchemaReaderTests.swift in Sources */,
 				19A1781CBA8968ABD3E00877 /* ExpressionTests.swift in Sources */,
 				19A17923494236793893BF72 /* StatementTests.swift in Sources */,
 				19A17A52BF29D27C9AA229E7 /* QueryTests.swift in Sources */,
diff --git a/Sources/SQLite/Schema/SchemaDefinitions.swift b/Sources/SQLite/Schema/SchemaDefinitions.swift
index 2d38e1fb..9f4c126f 100644
--- a/Sources/SQLite/Schema/SchemaDefinitions.swift
+++ b/Sources/SQLite/Schema/SchemaDefinitions.swift
@@ -107,7 +107,7 @@ public struct ColumnDefinition: Equatable {
     public struct ForeignKey: Equatable {
         let table: String
         let column: String
-        let primaryKey: String
+        let primaryKey: String?
         let onUpdate: String?
         let onDelete: String?
     }
@@ -365,7 +365,7 @@ extension ColumnDefinition.ForeignKey {
         ([
             "REFERENCES",
             table.quote(),
-            "(\(primaryKey.quote()))",
+            primaryKey.map { "(\($0.quote()))" },
             onUpdate.map { "ON UPDATE \($0)" },
             onDelete.map { "ON DELETE \($0)" }
         ] as [String?]).compactMap { $0 }
diff --git a/Sources/SQLite/Schema/SchemaReader.swift b/Sources/SQLite/Schema/SchemaReader.swift
index 58a9b1bd..eb31888b 100644
--- a/Sources/SQLite/Schema/SchemaReader.swift
+++ b/Sources/SQLite/Schema/SchemaReader.swift
@@ -187,7 +187,7 @@ private enum ForeignKeyListTable {
     static let seqColumn = Expression<Int64>("seq")
     static let tableColumn = Expression<String>("table")
     static let fromColumn = Expression<String>("from")
-    static let toColumn = Expression<String>("to")
+    static let toColumn = Expression<String?>("to") // when null, use primary key
     static let onUpdateColumn = Expression<String>("on_update")
     static let onDeleteColumn = Expression<String>("on_delete")
     static let matchColumn = Expression<String>("match")
diff --git a/Tests/SQLiteTests/Schema/SchemaReaderTests.swift b/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
index dd5ae103..e90578e7 100644
--- a/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
@@ -135,6 +135,44 @@ class SchemaReaderTests: SQLiteTestCase {
         ])
     }
 
+    func test_foreignKeys_references_column() throws {
+        let sql = """
+          CREATE TABLE artist(
+            artistid    INTEGER PRIMARY KEY,
+            artistname  TEXT
+          );
+          CREATE TABLE track(
+            trackid     INTEGER,
+            trackname   TEXT,
+            trackartist INTEGER REFERENCES artist(artistid)
+          );
+          """
+        try db.execute(sql)
+        let trackColumns = try db.schema.foreignKeys(table: "track")
+        XCTAssertEqual(trackColumns.map { $0.toSQL() }.joined(separator: "\n"), """
+            REFERENCES "artist" ("artistid")
+            """)
+    }
+
+    func test_foreignKeys_references_null_column() throws {
+        let sql = """
+          CREATE TABLE artist(
+            artistid    INTEGER PRIMARY KEY,
+            artistname  TEXT
+          );
+          CREATE TABLE track(
+            trackid     INTEGER,
+            trackname   TEXT,
+            trackartist INTEGER REFERENCES artist
+          );
+          """
+        try db.execute(sql)
+        let trackColumns = try db.schema.foreignKeys(table: "track")
+        XCTAssertEqual(trackColumns.map { $0.toSQL() }.joined(separator: "\n"), """
+            REFERENCES "artist"
+            """)
+    }
+
     func test_tableDefinitions() throws {
         let tables = try schemaReader.tableDefinitions()
         XCTAssertEqual(tables.count, 1)

From 7997c85cbf6c0a1f8caf300b483f04028548e40e Mon Sep 17 00:00:00 2001
From: Stefan Saasen <stefan@ohoj-software.com>
Date: Wed, 7 Jun 2023 15:45:35 +0200
Subject: [PATCH 606/685] SchemaReader: return the correct column definition
 for a composite primary key

The `PRAGMA` `table_info` that is used to return the column definitions,
returns one row for each defined column. The `pk` column contains:

> ... either zero for columns that are not part of the primary key, or the 1-based index of the column within the primary key).

See https://www.sqlite.org/pragma.html#pragma_table_info

Checking whether the `pk` column equals 1 only detects a single primary
key and ignores other columns that are part of a composite primary key.
---
 Sources/SQLite/Schema/SchemaReader.swift      |  2 +-
 .../Schema/SchemaReaderTests.swift            | 37 +++++++++++++++++++
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/Sources/SQLite/Schema/SchemaReader.swift b/Sources/SQLite/Schema/SchemaReader.swift
index 58a9b1bd..2be15f29 100644
--- a/Sources/SQLite/Schema/SchemaReader.swift
+++ b/Sources/SQLite/Schema/SchemaReader.swift
@@ -25,7 +25,7 @@ public class SchemaReader {
             .map { (row: Row) -> ColumnDefinition in
                 ColumnDefinition(
                     name: row[TableInfoTable.nameColumn],
-                    primaryKey: row[TableInfoTable.primaryKeyColumn] == 1 ?
+                    primaryKey: (row[TableInfoTable.primaryKeyColumn] ?? 0) > 0 ?
                         try parsePrimaryKey(column: row[TableInfoTable.nameColumn]) : nil,
                     type: ColumnDefinition.Affinity(row[TableInfoTable.typeColumn]),
                     nullable: row[TableInfoTable.notNullColumn] == 0,
diff --git a/Tests/SQLiteTests/Schema/SchemaReaderTests.swift b/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
index dd5ae103..49871c10 100644
--- a/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
@@ -90,6 +90,43 @@ class SchemaReaderTests: SQLiteTestCase {
         )
     }
 
+    func test_columnDefinitions_composite_primary_keys() throws {
+        try db.run("""
+        CREATE TABLE t (
+          col1 INTEGER,
+          col2 INTEGER,
+          col3 INTEGER,
+          PRIMARY KEY (col1, col2)
+        );
+        """)
+
+        XCTAssertEqual(
+            try schemaReader.columnDefinitions(table: "t"), [
+            ColumnDefinition(
+                    name: "col1",
+                    primaryKey: .init(autoIncrement: false),
+                    type: .INTEGER,
+                    nullable: true,
+                    defaultValue: .NULL,
+                    references: nil),
+            ColumnDefinition(
+                    name: "col2",
+                    primaryKey: .init(autoIncrement: false),
+                    type: .INTEGER,
+                    nullable: true,
+                    defaultValue: .NULL,
+                    references: nil),
+            ColumnDefinition(
+                    name: "col3",
+                    primaryKey: nil,
+                    type: .INTEGER,
+                    nullable: true,
+                    defaultValue: .NULL,
+                    references: nil)
+            ]
+        )
+    }
+
     func test_indexDefinitions_no_index() throws {
         let indexes = try schemaReader.indexDefinitions(table: "users")
         XCTAssertTrue(indexes.isEmpty)

From 656ca871e357df8ef45b7344c777102cdbf7dfc6 Mon Sep 17 00:00:00 2001
From: Stefan Saasen <stefan@ohoj-software.com>
Date: Tue, 30 May 2023 16:20:29 +0200
Subject: [PATCH 607/685] Fix column affinity parsing to match how SQLite
 determines affinity

See https://www.sqlite.org/datatype3.html#determination_of_column_affinity
for how SQLite determines column affinity.
---
 Sources/SQLite/Schema/SchemaDefinitions.swift | 14 +++-
 .../Schema/SchemaDefinitionsTests.swift       | 64 ++++++++++++++++++-
 .../Schema/SchemaReaderTests.swift            |  4 +-
 3 files changed, 77 insertions(+), 5 deletions(-)

diff --git a/Sources/SQLite/Schema/SchemaDefinitions.swift b/Sources/SQLite/Schema/SchemaDefinitions.swift
index 2d38e1fb..3c6b0523 100644
--- a/Sources/SQLite/Schema/SchemaDefinitions.swift
+++ b/Sources/SQLite/Schema/SchemaDefinitions.swift
@@ -57,7 +57,19 @@ public struct ColumnDefinition: Equatable {
         }
 
         init(_ string: String) {
-            self = Affinity.allCases.first { $0.rawValue.lowercased() == string.lowercased() } ?? .TEXT
+            let test = string.uppercased()
+            // https://sqlite.org/datatype3.html#determination_of_column_affinity
+            if test.contains("INT") { // Rule 1
+                self = .INTEGER
+            } else if ["CHAR", "CLOB", "TEXT"].first(where: {test.contains($0)}) != nil { // Rule 2
+                self = .TEXT
+            } else if string.contains("BLOB") { // Rule 3
+                self = .BLOB
+            } else if ["REAL", "FLOA", "DOUB"].first(where: {test.contains($0)}) != nil { // Rule 4
+                self = .REAL
+            } else { // Rule 5
+                self = .NUMERIC
+            }
         }
     }
 
diff --git a/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift b/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
index ef97b981..8b7e27e3 100644
--- a/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
@@ -71,8 +71,68 @@ class AffinityTests: XCTestCase {
         XCTAssertEqual(ColumnDefinition.Affinity("NUMERIC"), .NUMERIC)
     }
 
-    func test_returns_TEXT_for_unknown_type() {
-        XCTAssertEqual(ColumnDefinition.Affinity("baz"), .TEXT)
+    // [Determination Of Column Affinity](https://sqlite.org/datatype3.html#determination_of_column_affinity)
+    // Rule 1
+    func testIntegerAffinity() {
+        let declared = [
+            "INT",
+            "INTEGER",
+            "TINYINT",
+            "SMALLINT",
+            "MEDIUMINT",
+            "BIGINT",
+            "UNSIGNED BIG INT",
+            "INT2",
+            "INT8"
+        ]
+        XCTAssertTrue(declared.allSatisfy({ColumnDefinition.Affinity($0) == .INTEGER}))
+    }
+
+    // Rule 2
+    func testTextAffinity() {
+        let declared = [
+            "CHARACTER(20)",
+            "VARCHAR(255)",
+            "VARYING CHARACTER(255)",
+            "NCHAR(55)",
+            "NATIVE CHARACTER(70)",
+            "NVARCHAR(100)",
+            "TEXT",
+            "CLOB"
+        ]
+        XCTAssertTrue(declared.allSatisfy({ColumnDefinition.Affinity($0) == .TEXT}))
+    }
+
+    // Rule 3
+    func testBlobAffinity() {
+        XCTAssertEqual(ColumnDefinition.Affinity("BLOB"), .BLOB)
+    }
+
+    // Rule 4
+    func testRealAffinity() {
+        let declared = [
+            "REAL",
+            "DOUBLE",
+            "DOUBLE PRECISION",
+            "FLOAT"
+        ]
+        XCTAssertTrue(declared.allSatisfy({ColumnDefinition.Affinity($0) == .REAL}))
+    }
+
+    // Rule 5
+    func testNumericAffinity() {
+        let declared = [
+            "NUMERIC",
+            "DECIMAL(10,5)",
+            "BOOLEAN",
+            "DATE",
+            "DATETIME"
+        ]
+        XCTAssertTrue(declared.allSatisfy({ColumnDefinition.Affinity($0) == .NUMERIC}))
+    }
+
+    func test_returns_NUMERIC_for_unknown_type() {
+        XCTAssertEqual(ColumnDefinition.Affinity("baz"), .NUMERIC)
     }
 }
 
diff --git a/Tests/SQLiteTests/Schema/SchemaReaderTests.swift b/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
index dd5ae103..b03045de 100644
--- a/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
@@ -40,7 +40,7 @@ class SchemaReaderTests: SQLiteTestCase {
                              references: nil),
             ColumnDefinition(name: "admin",
                              primaryKey: nil,
-                             type: .TEXT,
+                             type: .NUMERIC,
                              nullable: false,
                              defaultValue: .numericLiteral("0"),
                              references: nil),
@@ -51,7 +51,7 @@ class SchemaReaderTests: SQLiteTestCase {
                              references: .init(table: "users", column: "manager_id", primaryKey: "id", onUpdate: nil, onDelete: nil)),
             ColumnDefinition(name: "created_at",
                              primaryKey: nil,
-                             type: .TEXT,
+                             type: .NUMERIC,
                              nullable: true,
                              defaultValue: .NULL,
                              references: nil)

From 3023a1f63336f70c1470bdef59ac2dfded258206 Mon Sep 17 00:00:00 2001
From: Jacob Hearst <jacob.hearst@jamf.com>
Date: Mon, 16 Oct 2023 07:33:54 -0500
Subject: [PATCH 608/685] Add optional support for decoding

---
 Sources/SQLite/Typed/Coding.swift | 48 +++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index e7db03fb..8c7755c3 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -471,6 +471,54 @@ private class SQLiteDecoder: Decoder {
             }
         }
 
+        func decodeIfPresent(_ type: Bool.Type, forKey key: Key) throws -> Bool? {
+            try? row.get(Expression(key.stringValue))
+        }
+
+        func decodeIfPresent(_ type: Int.Type, forKey key: Key) throws -> Int? {
+            try? row.get(Expression(key.stringValue))
+        }
+
+        func decodeIfPresent(_ type: Int64.Type, forKey key: Key) throws -> Int64? {
+            try? row.get(Expression(key.stringValue))
+        }
+
+        func decodeIfPresent(_ type: Float.Type, forKey key: Key) throws -> Float? {
+            try? Float(row.get(Expression<Double>(key.stringValue)))
+        }
+
+        func decodeIfPresent(_ type: Double.Type, forKey key: Key) throws -> Double? {
+            try? row.get(Expression(key.stringValue))
+        }
+
+        func decodeIfPresent(_ type: String.Type, forKey key: Key) throws -> String? {
+            try? row.get(Expression(key.stringValue))
+        }
+
+        func decode<T>(_ type: T.Type, forKey key: Key) throws -> T? where T: Swift.Decodable {
+            switch type {
+            case is Data.Type:
+                let data = try row.get(Expression<Data>(key.stringValue))
+                return data as? T
+            case is Date.Type:
+                let date = try row.get(Expression<Date>(key.stringValue))
+                return date as? T
+            case is UUID.Type:
+                let uuid = try row.get(Expression<UUID>(key.stringValue))
+                return uuid as? T
+            default:
+                guard let JSONString = try row.get(Expression<String?>(key.stringValue)) else {
+                    throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
+                                                                                 debugDescription: "an unsupported type was found"))
+                }
+                guard let data = JSONString.data(using: .utf8) else {
+                    throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,
+                                                                            debugDescription: "invalid utf8 data found"))
+                }
+                return try JSONDecoder().decode(type, from: data)
+            }
+        }
+
         func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws
         -> KeyedDecodingContainer<NestedKey> where NestedKey: CodingKey {
             throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,

From e7c259226373e9469d9166b842e5395dae302b6e Mon Sep 17 00:00:00 2001
From: Jacob Hearst <jacob.hearst@jamf.com>
Date: Thu, 19 Oct 2023 07:13:41 -0500
Subject: [PATCH 609/685] Fix copypasta

---
 Sources/SQLite/Typed/Coding.swift | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index 8c7755c3..f62f5b6b 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -495,19 +495,22 @@ private class SQLiteDecoder: Decoder {
             try? row.get(Expression(key.stringValue))
         }
 
-        func decode<T>(_ type: T.Type, forKey key: Key) throws -> T? where T: Swift.Decodable {
+        func decodeIfPresent<T>(_ type: T.Type, forKey key: Key) throws -> T? where T: Swift.Decodable {
             switch type {
             case is Data.Type:
-                let data = try row.get(Expression<Data>(key.stringValue))
-                return data as? T
+                if let data = try? row.get(Expression<Data>(key.stringValue)) {
+                    return data as? T
+                }
             case is Date.Type:
-                let date = try row.get(Expression<Date>(key.stringValue))
-                return date as? T
+                if let date = try? row.get(Expression<Date>(key.stringValue)) {
+                    return date as? T
+                }
             case is UUID.Type:
-                let uuid = try row.get(Expression<UUID>(key.stringValue))
-                return uuid as? T
+                if let uuid = try? row.get(Expression<UUID>(key.stringValue)) {
+                    return uuid as? T
+                }
             default:
-                guard let JSONString = try row.get(Expression<String?>(key.stringValue)) else {
+                guard let JSONString = try? row.get(Expression<String?>(key.stringValue)) else {
                     throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
                                                                                  debugDescription: "an unsupported type was found"))
                 }

From 128246f30a396ef864318e3a7ca851e90b3e84a1 Mon Sep 17 00:00:00 2001
From: Jacob Hearst <jacob.hearst@jamf.com>
Date: Thu, 19 Oct 2023 11:04:58 -0500
Subject: [PATCH 610/685] Fix missing return

---
 Sources/SQLite/Typed/Coding.swift | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index f62f5b6b..52612063 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -520,6 +520,8 @@ private class SQLiteDecoder: Decoder {
                 }
                 return try JSONDecoder().decode(type, from: data)
             }
+
+            return nil
         }
 
         func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws

From 1c6bf76948de5b6ab1ef7a45629788e3c5c70d0a Mon Sep 17 00:00:00 2001
From: Jacob Hearst <jacob.hearst@jamf.com>
Date: Fri, 20 Oct 2023 07:20:58 -0500
Subject: [PATCH 611/685] Fix smoothbrain

---
 Sources/SQLite/Typed/Coding.swift | 14 +++-----------
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index 52612063..bfddc5ee 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -498,17 +498,11 @@ private class SQLiteDecoder: Decoder {
         func decodeIfPresent<T>(_ type: T.Type, forKey key: Key) throws -> T? where T: Swift.Decodable {
             switch type {
             case is Data.Type:
-                if let data = try? row.get(Expression<Data>(key.stringValue)) {
-                    return data as? T
-                }
+                return try? row.get(Expression<Data>(key.stringValue)) as? T
             case is Date.Type:
-                if let date = try? row.get(Expression<Date>(key.stringValue)) {
-                    return date as? T
-                }
+                return try? row.get(Expression<Date>(key.stringValue)) as? T
             case is UUID.Type:
-                if let uuid = try? row.get(Expression<UUID>(key.stringValue)) {
-                    return uuid as? T
-                }
+                return try? row.get(Expression<UUID>(key.stringValue)) as? T
             default:
                 guard let JSONString = try? row.get(Expression<String?>(key.stringValue)) else {
                     throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
@@ -520,8 +514,6 @@ private class SQLiteDecoder: Decoder {
                 }
                 return try JSONDecoder().decode(type, from: data)
             }
-
-            return nil
         }
 
         func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws

From fc96d30b72db986b7f930d951eca14c16e32b9b5 Mon Sep 17 00:00:00 2001
From: Geoff MacDonald <geoffmacd@gmail.com>
Date: Sat, 18 Nov 2023 18:30:28 -0800
Subject: [PATCH 612/685] Implements built-in window functions

---
 SQLite.xcodeproj/project.pbxproj              |  18 +++
 Sources/SQLite/Typed/AggregateFunctions.swift |   6 +-
 Sources/SQLite/Typed/WindowFunctions.swift    | 145 ++++++++++++++++++
 .../Typed/QueryIntegrationTests.swift         |  95 ++++++++++++
 .../Typed/WindowFunctionsTests.swift          |  58 +++++++
 5 files changed, 319 insertions(+), 3 deletions(-)
 create mode 100644 Sources/SQLite/Typed/WindowFunctions.swift
 create mode 100644 Tests/SQLiteTests/Typed/WindowFunctionsTests.swift

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index def32855..95ed6806 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -195,6 +195,13 @@
 		49EB68C51F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
 		49EB68C61F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
 		49EB68C71F7B3CB400D89D40 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
+		64A8EE432B095FBB00F583F7 /* WindowFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64A8EE422B095FBB00F583F7 /* WindowFunctions.swift */; };
+		64A8EE442B095FBB00F583F7 /* WindowFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64A8EE422B095FBB00F583F7 /* WindowFunctions.swift */; };
+		64A8EE452B095FBB00F583F7 /* WindowFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64A8EE422B095FBB00F583F7 /* WindowFunctions.swift */; };
+		64A8EE462B095FBB00F583F7 /* WindowFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64A8EE422B095FBB00F583F7 /* WindowFunctions.swift */; };
+		64B8E1702B09748000545AFB /* WindowFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64B8E16F2B09748000545AFB /* WindowFunctionsTests.swift */; };
+		64B8E1712B09748000545AFB /* WindowFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64B8E16F2B09748000545AFB /* WindowFunctionsTests.swift */; };
+		64B8E1722B09748000545AFB /* WindowFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64B8E16F2B09748000545AFB /* WindowFunctionsTests.swift */; };
 		997DF2AE287FC06D00F8DF95 /* Query+with.swift in Sources */ = {isa = PBXBuildFile; fileRef = 997DF2AD287FC06D00F8DF95 /* Query+with.swift */; };
 		997DF2AF287FC06D00F8DF95 /* Query+with.swift in Sources */ = {isa = PBXBuildFile; fileRef = 997DF2AD287FC06D00F8DF95 /* Query+with.swift */; };
 		997DF2B0287FC06D00F8DF95 /* Query+with.swift in Sources */ = {isa = PBXBuildFile; fileRef = 997DF2AD287FC06D00F8DF95 /* Query+with.swift */; };
@@ -335,6 +342,8 @@
 		3DF7B79B2884C901005DD8CA /* Planning.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Planning.md; sourceTree = "<group>"; };
 		3DFC0B862886C239001C8FC9 /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = "<group>"; };
 		49EB68C31F7B3CB400D89D40 /* Coding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coding.swift; sourceTree = "<group>"; };
+		64A8EE422B095FBB00F583F7 /* WindowFunctions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowFunctions.swift; sourceTree = "<group>"; };
+		64B8E16F2B09748000545AFB /* WindowFunctionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowFunctionsTests.swift; sourceTree = "<group>"; };
 		997DF2AD287FC06D00F8DF95 /* Query+with.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Query+with.swift"; sourceTree = "<group>"; };
 		A121AC451CA35C79005A31D1 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		DB58B21028FB864300F8EEA4 /* SchemaReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaReader.swift; sourceTree = "<group>"; };
@@ -476,6 +485,7 @@
 				19A177EF5E2D91BA86DA4480 /* CustomAggregationTests.swift */,
 				19A1709D5BDD2691BA160012 /* SetterTests.swift */,
 				19A174FE5B47A97937A27276 /* RowTests.swift */,
+				64B8E16F2B09748000545AFB /* WindowFunctionsTests.swift */,
 			);
 			path = Typed;
 			sourceTree = "<group>";
@@ -607,6 +617,7 @@
 			isa = PBXGroup;
 			children = (
 				EE247AFA1C3F06E900AE3E12 /* AggregateFunctions.swift */,
+				64A8EE422B095FBB00F583F7 /* WindowFunctions.swift */,
 				EE247AFB1C3F06E900AE3E12 /* Collation.swift */,
 				EE247AFC1C3F06E900AE3E12 /* CoreFunctions.swift */,
 				EE247AFD1C3F06E900AE3E12 /* CustomFunctions.swift */,
@@ -960,6 +971,7 @@
 				3DF7B78A28842972005DD8CA /* Connection+Attach.swift in Sources */,
 				03A65E811C6BB2FB0062603F /* CustomFunctions.swift in Sources */,
 				03A65E7A1C6BB2F70062603F /* Statement.swift in Sources */,
+				64A8EE452B095FBB00F583F7 /* WindowFunctions.swift in Sources */,
 				03A65E741C6BB2DA0062603F /* Helpers.swift in Sources */,
 				03A65E831C6BB2FB0062603F /* Operators.swift in Sources */,
 				03A65E851C6BB2FB0062603F /* Schema.swift in Sources */,
@@ -1014,6 +1026,7 @@
 				19A17746150A815944A6820B /* SelectTests.swift in Sources */,
 				19A1766135CE9786B1878603 /* ValueTests.swift in Sources */,
 				19A177D5C6542E2D572162E5 /* QueryIntegrationTests.swift in Sources */,
+				64B8E1722B09748000545AFB /* WindowFunctionsTests.swift in Sources */,
 				19A178DF5A96CFEFF1E271F6 /* AggregateFunctionsTests.swift in Sources */,
 				19A17437659BD7FD787D94A6 /* CustomAggregationTests.swift in Sources */,
 				19A17F907258E524B3CA2FAE /* SetterTests.swift in Sources */,
@@ -1057,6 +1070,7 @@
 				19A17DC282E36C4F41AA440B /* Errors.swift in Sources */,
 				19A173668D948AD4DF1F5352 /* DateAndTimeFunctions.swift in Sources */,
 				19A17DF8D4F13A20F5D2269E /* Result.swift in Sources */,
+				64A8EE462B095FBB00F583F7 /* WindowFunctions.swift in Sources */,
 				19A17DFE05ED8B1F7C45F7EE /* SchemaChanger.swift in Sources */,
 				19A17D1BEABA610ABF003D67 /* SchemaDefinitions.swift in Sources */,
 				19A17A33EA026C2E2CEBAF36 /* Connection+Schema.swift in Sources */,
@@ -1081,6 +1095,7 @@
 				EE247B151C3F06E900AE3E12 /* Setter.swift in Sources */,
 				3DF7B78828842972005DD8CA /* Connection+Attach.swift in Sources */,
 				EE247B101C3F06E900AE3E12 /* CustomFunctions.swift in Sources */,
+				64A8EE432B095FBB00F583F7 /* WindowFunctions.swift in Sources */,
 				EE247B091C3F06E900AE3E12 /* FTS4.swift in Sources */,
 				EE247B081C3F06E900AE3E12 /* Value.swift in Sources */,
 				EE247B121C3F06E900AE3E12 /* Operators.swift in Sources */,
@@ -1135,6 +1150,7 @@
 				19A17F7977364EC8CD33C3C3 /* SelectTests.swift in Sources */,
 				19A17FD22EF43DF428DD93BA /* ValueTests.swift in Sources */,
 				19A177AA5922527BBDC77CF9 /* QueryIntegrationTests.swift in Sources */,
+				64B8E1702B09748000545AFB /* WindowFunctionsTests.swift in Sources */,
 				19A179786A6826D58A70F8BC /* AggregateFunctionsTests.swift in Sources */,
 				19A1793972BDDDB027C113BB /* CustomAggregationTests.swift in Sources */,
 				19A1773155AC2BF2CA86A473 /* SetterTests.swift in Sources */,
@@ -1161,6 +1177,7 @@
 				3DF7B78928842972005DD8CA /* Connection+Attach.swift in Sources */,
 				EE247B701C3F3FEC00AE3E12 /* CustomFunctions.swift in Sources */,
 				EE247B691C3F3FEC00AE3E12 /* Statement.swift in Sources */,
+				64A8EE442B095FBB00F583F7 /* WindowFunctions.swift in Sources */,
 				EE247B641C3F3FDB00AE3E12 /* Helpers.swift in Sources */,
 				EE247B721C3F3FEC00AE3E12 /* Operators.swift in Sources */,
 				EE247B741C3F3FEC00AE3E12 /* Schema.swift in Sources */,
@@ -1215,6 +1232,7 @@
 				19A17DE1FCDB5695702AD24D /* SelectTests.swift in Sources */,
 				19A1726002D24C14F876C8FE /* ValueTests.swift in Sources */,
 				19A173389E53CB24DFA8CEDD /* QueryIntegrationTests.swift in Sources */,
+				64B8E1712B09748000545AFB /* WindowFunctionsTests.swift in Sources */,
 				19A170C56745F9D722A73D77 /* AggregateFunctionsTests.swift in Sources */,
 				19A1772EBE65173EDFB1AFCA /* CustomAggregationTests.swift in Sources */,
 				19A17E0ABA6C415F014CD51C /* SetterTests.swift in Sources */,
diff --git a/Sources/SQLite/Typed/AggregateFunctions.swift b/Sources/SQLite/Typed/AggregateFunctions.swift
index bf4fb8fc..17fc4a20 100644
--- a/Sources/SQLite/Typed/AggregateFunctions.swift
+++ b/Sources/SQLite/Typed/AggregateFunctions.swift
@@ -166,7 +166,7 @@ extension ExpressionType where UnderlyingType: Value, UnderlyingType.Datatype: N
     ///     salary.average
     ///     // avg("salary")
     ///
-    /// - Returns: A copy of the expression wrapped with the `min` aggregate
+    /// - Returns: A copy of the expression wrapped with the `avg` aggregate
     ///   function.
     public var average: Expression<Double?> {
         Function.avg.wrap(self)
@@ -179,7 +179,7 @@ extension ExpressionType where UnderlyingType: Value, UnderlyingType.Datatype: N
     ///     salary.sum
     ///     // sum("salary")
     ///
-    /// - Returns: A copy of the expression wrapped with the `min` aggregate
+    /// - Returns: A copy of the expression wrapped with the `sum` aggregate
     ///   function.
     public var sum: Expression<UnderlyingType?> {
         Function.sum.wrap(self)
@@ -192,7 +192,7 @@ extension ExpressionType where UnderlyingType: Value, UnderlyingType.Datatype: N
     ///     salary.total
     ///     // total("salary")
     ///
-    /// - Returns: A copy of the expression wrapped with the `min` aggregate
+    /// - Returns: A copy of the expression wrapped with the `total` aggregate
     ///   function.
     public var total: Expression<Double> {
         Function.total.wrap(self)
diff --git a/Sources/SQLite/Typed/WindowFunctions.swift b/Sources/SQLite/Typed/WindowFunctions.swift
new file mode 100644
index 00000000..e71e1ada
--- /dev/null
+++ b/Sources/SQLite/Typed/WindowFunctions.swift
@@ -0,0 +1,145 @@
+import Foundation
+
+// see https://www.sqlite.org/windowfunctions.html#builtins
+private enum WindowFunction: String {
+    // swiftlint:disable identifier_name
+    case ntile
+    case row_number
+    case rank
+    case dense_rank
+    case percent_rank
+    case cume_dist
+    case lag
+    case lead
+    case first_value
+    case last_value
+    case nth_value
+    // swiftlint:enable identifier_name
+
+    func wrap<T>(_ value: Int? = nil) -> Expression<T> {
+        if let value {
+            return self.rawValue.wrap(Expression(value: value))
+        }
+        return Expression(literal: "\(rawValue)()")
+    }
+
+    func over<T>(value: Int? = nil, _ orderBy: Expressible) -> Expression<T> {
+        return Expression<T>(" ".join([
+            self.wrap(value),
+            Expression<T>("OVER (ORDER BY \(orderBy.expression.template))", orderBy.expression.bindings)
+        ]).expression)
+    }
+
+    func over<T>(valueExpr: Expressible, _ orderBy: Expressible) -> Expression<T> {
+        return Expression<T>(" ".join([
+            self.rawValue.wrap(valueExpr),
+            Expression<T>("OVER (ORDER BY \(orderBy.expression.template))", orderBy.expression.bindings)
+        ]).expression)
+    }
+}
+
+extension ExpressionType where UnderlyingType: Value {
+    /// Builds a copy of the expression with `lag(self, offset, default) OVER (ORDER BY {orderBy})` window function
+    ///
+    /// - Parameter orderBy: Expression to evaluate window order
+    /// - Returns: An expression returning `lag(self, offset, default) OVER (ORDER BY {orderBy})` window function
+    public func lag(offset: Int = 0, default: Expressible? = nil, _ orderBy: Expressible) -> Expression<UnderlyingType> {
+        if let defaultExpression = `default` {
+            return Expression(
+                "lag(\(template), \(offset), \(defaultExpression.asSQL())) OVER (ORDER BY \(orderBy.expression.template))",
+                bindings + orderBy.expression.bindings
+            )
+
+        }
+        return Expression("lag(\(template), \(offset)) OVER (ORDER BY \(orderBy.expression.template))", bindings + orderBy.expression.bindings)
+    }
+
+    /// Builds a copy of the expression with `lead(self, offset, default) OVER (ORDER BY {orderBy})` window function
+    ///
+    /// - Parameter orderBy: Expression to evaluate window order
+    /// - Returns: An expression returning `lead(self, offset, default) OVER (ORDER BY {orderBy})` window function
+    public func lead(offset: Int = 0, default: Expressible? = nil, _ orderBy: Expressible) -> Expression<UnderlyingType> {
+        if let defaultExpression = `default` {
+            return Expression(
+                "lead(\(template), \(offset), \(defaultExpression.asSQL())) OVER (ORDER BY \(orderBy.expression.template))",
+                bindings + orderBy.expression.bindings)
+
+        }
+        return Expression("lead(\(template), \(offset)) OVER (ORDER BY \(orderBy.expression.template))", bindings + orderBy.expression.bindings)
+    }
+
+    /// Builds a copy of the expression with `first_value(self) OVER (ORDER BY {orderBy})` window function
+    ///
+    /// - Parameter orderBy: Expression to evaluate window order
+    /// - Returns: An expression returning `first_value(self) OVER (ORDER BY {orderBy})` window function
+    public func firstValue(_ orderBy: Expressible) -> Expression<UnderlyingType> {
+        WindowFunction.first_value.over(valueExpr: self, orderBy)
+    }
+
+    /// Builds a copy of the expression with `last_value(self) OVER (ORDER BY {orderBy})` window function
+    ///
+    /// - Parameter orderBy: Expression to evaluate window order
+    /// - Returns: An expression returning `last_value(self) OVER (ORDER BY {orderBy})` window function
+    public func lastValue(_ orderBy: Expressible) -> Expression<UnderlyingType> {
+        WindowFunction.last_value.over(valueExpr: self, orderBy)
+    }
+
+    /// Builds a copy of the expression with `nth_value(self) OVER (ORDER BY {orderBy})` window function
+    ///
+    /// - Parameter index: Row N of the window frame to return
+    /// - Parameter orderBy: Expression to evaluate window order
+    /// - Returns: An expression returning `nth_value(self) OVER (ORDER BY {orderBy})` window function
+    public func value(_ index: Int, _ orderBy: Expressible) -> Expression<UnderlyingType> {
+        Expression("nth_value(\(template), \(index)) OVER (ORDER BY \(orderBy.expression.template))", bindings + orderBy.expression.bindings)
+    }
+}
+
+/// Builds an expression representing `ntile(size) OVER (ORDER BY {orderBy})`
+///
+/// - Parameter orderBy: Expression to evaluate window order
+/// - Returns: An expression returning  `ntile(size) OVER (ORDER BY {orderBy})`
+public func ntile(_ size: Int, _ orderBy: Expressible) -> Expression<Int> {
+//    Expression.ntile(size, orderBy)
+
+        WindowFunction.ntile.over(value: size, orderBy)
+}
+
+/// Builds an expression representing `row_count() OVER (ORDER BY {orderBy})`
+///
+/// - Parameter orderBy: Expression to evaluate window order
+/// - Returns: An expression returning `row_count() OVER (ORDER BY {orderBy})`
+public func rowNumber(_ orderBy: Expressible) -> Expression<Int> {
+    WindowFunction.row_number.over(orderBy)
+}
+
+/// Builds an expression representing `rank() OVER (ORDER BY {orderBy})`
+///
+/// - Parameter orderBy: Expression to evaluate window order
+/// - Returns: An expression returning `rank() OVER (ORDER BY {orderBy})`
+public func rank(_ orderBy: Expressible) -> Expression<Int> {
+    WindowFunction.rank.over(orderBy)
+}
+
+/// Builds an expression representing `dense_rank() OVER (ORDER BY {orderBy})`
+///
+/// - Parameter orderBy: Expression to evaluate window order
+/// - Returns: An expression returning `dense_rank() OVER ('over')`
+public func denseRank(_ orderBy: Expressible) -> Expression<Int> {
+    WindowFunction.dense_rank.over(orderBy)
+}
+
+/// Builds an expression representing `percent_rank() OVER (ORDER BY {orderBy})`
+///
+/// - Parameter orderBy: Expression to evaluate window order
+/// - Returns: An expression returning `percent_rank() OVER (ORDER BY {orderBy})`
+public func percentRank(_ orderBy: Expressible) -> Expression<Double> {
+    WindowFunction.percent_rank.over(orderBy)
+}
+
+/// Builds an expression representing `cume_dist() OVER (ORDER BY {orderBy})`
+///
+/// - Parameter orderBy: Expression to evaluate window order
+/// - Returns: An expression returning `cume_dist() OVER (ORDER BY {orderBy})`
+public func cumeDist(_ orderBy: Expressible) -> Expression<Double> {
+    WindowFunction.cume_dist.over(orderBy)
+}
diff --git a/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift b/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
index d8d31a79..aa45cafe 100644
--- a/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
+++ b/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
@@ -322,6 +322,101 @@ class QueryIntegrationTests: SQLiteTestCase {
         XCTAssertNotNil(row[name])
         XCTAssertNotNil(row[email])
     }
+
+    func test_select_ntile_function() throws {
+        let users = Table("users")
+
+        try insertUser("Joey")
+        try insertUser("Timmy")
+        try insertUser("Jimmy")
+        try insertUser("Billy")
+
+        let bucket = ntile(1, id.asc)
+        try db.prepare(users.select(id, bucket)).forEach {
+            XCTAssertEqual($0[bucket], 1) // only 1 window
+        }
+    }
+
+    func test_select_cume_dist_function() throws {
+        let users = Table("users")
+
+        try insertUser("Joey")
+        try insertUser("Timmy")
+        try insertUser("Jimmy")
+        try insertUser("Billy")
+
+        let cumeDist = cumeDist(email)
+        let results = try db.prepare(users.select(id, cumeDist)).map {
+            $0[cumeDist]
+        }
+        XCTAssertEqual([0.25, 0.5, 0.75, 1], results)
+    }
+
+    func test_select_window_row_number() throws {
+        let users = Table("users")
+
+        try insertUser("Billy")
+        try insertUser("Jimmy")
+        try insertUser("Joey")
+        try insertUser("Timmy")
+
+        let rowNumber = rowNumber(email.asc)
+        var expectedRowNum = 1
+        try db.prepare(users.select(id, rowNumber)).forEach {
+            // should retrieve row numbers in order of INSERT above
+            XCTAssertEqual($0[rowNumber], expectedRowNum)
+            expectedRowNum += 1
+        }
+    }
+
+    func test_select_window_ranking() throws {
+        let users = Table("users")
+
+        try insertUser("Billy")
+        try insertUser("Jimmy")
+        try insertUser("Joey")
+        try insertUser("Timmy")
+
+        let percentRank = percentRank(email)
+        let actualPercentRank: [Int] = try db.prepare(users.select(id, percentRank)).map {
+            Int($0[percentRank] * 100)
+        }
+        XCTAssertEqual([0, 33, 66, 100], actualPercentRank)
+
+        let rank = rank(email)
+        let actualRank: [Int] = try db.prepare(users.select(id, rank)).map {
+            $0[rank]
+        }
+        XCTAssertEqual([1, 2, 3, 4], actualRank)
+
+        let denseRank = denseRank(email)
+        let actualDenseRank: [Int] = try db.prepare(users.select(id, denseRank)).map {
+            $0[denseRank]
+        }
+        XCTAssertEqual([1, 2, 3, 4], actualDenseRank)
+    }
+
+    func test_select_window_values() throws {
+        let users = Table("users")
+
+        try insertUser("Billy")
+        try insertUser("Jimmy")
+        try insertUser("Joey")
+        try insertUser("Timmy")
+
+        let firstValue = email.firstValue(email.desc)
+        try db.prepare(users.select(id, firstValue)).forEach {
+            XCTAssertEqual($0[firstValue], "Timmy@example.com") // should grab last email alphabetically
+        }
+
+        let lastValue = email.lastValue(email.asc)
+        var row = try db.pluck(users.select(id, lastValue))!
+        XCTAssertEqual(row[lastValue], "Billy@example.com")
+
+        let nthValue = email.value(1, email.asc)
+        row = try db.pluck(users.select(id, nthValue))!
+        XCTAssertEqual(row[nthValue], "Billy@example.com")
+    }
 }
 
 extension Connection {
diff --git a/Tests/SQLiteTests/Typed/WindowFunctionsTests.swift b/Tests/SQLiteTests/Typed/WindowFunctionsTests.swift
new file mode 100644
index 00000000..6ded152b
--- /dev/null
+++ b/Tests/SQLiteTests/Typed/WindowFunctionsTests.swift
@@ -0,0 +1,58 @@
+import XCTest
+import SQLite
+
+class WindowFunctionsTests: XCTestCase {
+
+    func test_ntile_wrapsExpressionWithOverClause() {
+        assertSQL("ntile(1) OVER (ORDER BY \"int\" DESC)", ntile(1, int.desc))
+        assertSQL("ntile(20) OVER (ORDER BY \"intOptional\" ASC)", ntile(20, intOptional.asc))
+        assertSQL("ntile(20) OVER (ORDER BY \"double\" ASC)", ntile(20, double.asc))
+        assertSQL("ntile(1) OVER (ORDER BY \"doubleOptional\" ASC)", ntile(1, doubleOptional.asc))
+        assertSQL("ntile(1) OVER (ORDER BY \"int\" DESC)", ntile(1, int.desc))
+    }
+
+    func test_row_number_wrapsExpressionWithOverClause() {
+        assertSQL("row_number() OVER (ORDER BY \"int\" DESC)", rowNumber(int.desc))
+    }
+
+    func test_rank_wrapsExpressionWithOverClause() {
+        assertSQL("rank() OVER (ORDER BY \"int\" DESC)", rank(int.desc))
+    }
+
+    func test_dense_rank_wrapsExpressionWithOverClause() {
+        assertSQL("dense_rank() OVER (ORDER BY \"int\" DESC)", denseRank(int.desc))
+    }
+
+    func test_percent_rank_wrapsExpressionWithOverClause() {
+        assertSQL("percent_rank() OVER (ORDER BY \"int\" DESC)", percentRank(int.desc))
+    }
+
+    func test_cume_dist_wrapsExpressionWithOverClause() {
+        assertSQL("cume_dist() OVER (ORDER BY \"int\" DESC)", cumeDist(int.desc))
+    }
+
+    func test_lag_wrapsExpressionWithOverClause() {
+        assertSQL("lag(\"int\", 0) OVER (ORDER BY \"int\" DESC)", int.lag(int.desc))
+        assertSQL("lag(\"int\", 7) OVER (ORDER BY \"int\" DESC)", int.lag(offset: 7, int.desc))
+        assertSQL("lag(\"int\", 1, 3) OVER (ORDER BY \"int\" DESC)", int.lag(offset: 1, default: Expression<Int>(value: 3), int.desc))
+    }
+
+    func test_lead_wrapsExpressionWithOverClause() {
+        assertSQL("lead(\"int\", 0) OVER (ORDER BY \"int\" DESC)", int.lead(int.desc))
+        assertSQL("lead(\"int\", 7) OVER (ORDER BY \"int\" DESC)", int.lead(offset: 7, int.desc))
+        assertSQL("lead(\"int\", 1, 3) OVER (ORDER BY \"int\" DESC)", int.lead(offset: 1, default: Expression<Int>(value: 3), int.desc))
+    }
+
+    func test_firstValue_wrapsExpressionWithOverClause() {
+        assertSQL("first_value(\"int\") OVER (ORDER BY \"int\" DESC)", int.firstValue(int.desc))
+        assertSQL("first_value(\"double\") OVER (ORDER BY \"int\" DESC)", double.firstValue(int.desc))
+    }
+
+    func test_lastValue_wrapsExpressionWithOverClause() {
+        assertSQL("last_value(\"int\") OVER (ORDER BY \"int\" DESC)", int.lastValue(int.desc))
+    }
+
+    func test_nth_value_wrapsExpressionWithOverClause() {
+        assertSQL("nth_value(\"int\", 3) OVER (ORDER BY \"int\" DESC)", int.value(3, int.desc))
+    }
+}

From 2fc62a96f03112f77604285cd0ad24b60558c22a Mon Sep 17 00:00:00 2001
From: Geoff MacDonald <geoffmacd@gmail.com>
Date: Sat, 18 Nov 2023 18:42:41 -0800
Subject: [PATCH 613/685] update docs

---
 Documentation/Index.md | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index 5d72aa4b..a03c26a3 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -64,6 +64,7 @@
   - [Other Operators](#other-operators)
   - [Core SQLite Functions](#core-sqlite-functions)
   - [Aggregate SQLite Functions](#aggregate-sqlite-functions)
+  - [Window SQLite Functions](#window-sqlite-functions)
   - [Date and Time Functions](#date-and-time-functions)
   - [Custom SQL Functions](#custom-sql-functions)
   - [Custom Collations](#custom-collations)
@@ -1871,6 +1872,11 @@ Most of SQLite’s
 [aggregate functions](https://www.sqlite.org/lang_aggfunc.html) have been
 surfaced in and type-audited for SQLite.swift.
 
+## Window SQLite Functions
+
+Most of SQLite's [window functions](https://www.sqlite.org/windowfunctions.html) have been
+surfaced in and type-audited for SQLite.swift. Currently only `OVER (ORDER BY ...)` windowing is possible. 
+
 ## Date and Time functions
 
 SQLite's [date and time](https://www.sqlite.org/lang_datefunc.html)

From dedef242d9253e5d6169dfe91d9e67ba4597291b Mon Sep 17 00:00:00 2001
From: ivan <ivanlares1@gmail.com>
Date: Thu, 4 Jan 2024 11:22:10 -0800
Subject: [PATCH 614/685] Add privacy manifest

---
 SQLite.xcodeproj/project.pbxproj     | 16 ++++++++++++++++
 Sources/SQLite/PrivacyInfo.xcprivacy | 14 ++++++++++++++
 2 files changed, 30 insertions(+)
 create mode 100644 Sources/SQLite/PrivacyInfo.xcprivacy

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index def32855..8eb1df66 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -211,6 +211,13 @@
 		DB7C5DA728D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
 		DB7C5DA828D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
 		DB7C5DA928D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
+		EAE1E1542B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EAE1E1532B473B0C0048B157 /* PrivacyInfo.xcprivacy */; };
+		EAE1E1552B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EAE1E1532B473B0C0048B157 /* PrivacyInfo.xcprivacy */; };
+		EAE1E1562B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EAE1E1532B473B0C0048B157 /* PrivacyInfo.xcprivacy */; };
+		EAE1E1572B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EAE1E1532B473B0C0048B157 /* PrivacyInfo.xcprivacy */; };
+		EAE1E1582B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EAE1E1532B473B0C0048B157 /* PrivacyInfo.xcprivacy */; };
+		EAE1E1592B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EAE1E1532B473B0C0048B157 /* PrivacyInfo.xcprivacy */; };
+		EAE1E15A2B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EAE1E1532B473B0C0048B157 /* PrivacyInfo.xcprivacy */; };
 		EE247AD71C3F04ED00AE3E12 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		EE247ADE1C3F04ED00AE3E12 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE247AD31C3F04ED00AE3E12 /* SQLite.framework */; };
 		EE247B031C3F06E900AE3E12 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
@@ -340,6 +347,7 @@
 		DB58B21028FB864300F8EEA4 /* SchemaReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaReader.swift; sourceTree = "<group>"; };
 		DB58B21528FC7C4600F8EEA4 /* SQLiteFeature.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SQLiteFeature.swift; sourceTree = "<group>"; };
 		DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SQLiteVersion.swift; sourceTree = "<group>"; };
+		EAE1E1532B473B0C0048B157 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
 		EE247AD31C3F04ED00AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AD61C3F04ED00AE3E12 /* SQLite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLite.h; sourceTree = "<group>"; };
 		EE247AD81C3F04ED00AE3E12 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -546,6 +554,7 @@
 				EE247AF71C3F06E900AE3E12 /* Foundation.swift */,
 				EE247AF81C3F06E900AE3E12 /* Helpers.swift */,
 				EE247AD81C3F04ED00AE3E12 /* Info.plist */,
+				EAE1E1532B473B0C0048B157 /* PrivacyInfo.xcprivacy */,
 				EE247AED1C3F06E900AE3E12 /* Core */,
 				EE247AF41C3F06E900AE3E12 /* Extensions */,
 				EE247AF91C3F06E900AE3E12 /* Typed */,
@@ -892,6 +901,7 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				EAE1E1582B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -899,6 +909,7 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				EAE1E1592B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */,
 				3DF7B79828846FED005DD8CA /* Resources in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -907,6 +918,7 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				EAE1E15A2B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -914,6 +926,7 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				EAE1E1542B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -921,6 +934,7 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				EAE1E1552B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */,
 				3DF7B79628846FCC005DD8CA /* Resources in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -929,6 +943,7 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				EAE1E1562B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -936,6 +951,7 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				EAE1E1572B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */,
 				3DF7B79928847055005DD8CA /* Resources in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
diff --git a/Sources/SQLite/PrivacyInfo.xcprivacy b/Sources/SQLite/PrivacyInfo.xcprivacy
new file mode 100644
index 00000000..987771fa
--- /dev/null
+++ b/Sources/SQLite/PrivacyInfo.xcprivacy
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>NSPrivacyTrackingDomains</key>
+	<array/>
+	<key>NSPrivacyCollectedDataTypes</key>
+	<array/>
+	<key>NSPrivacyAccessedAPITypes</key>
+	<array/>
+	<key>NSPrivacyTracking</key>
+	<false/>
+</dict>
+</plist>

From e7c4212a213f8dec5d68ec6e7acadeed8f4fb912 Mon Sep 17 00:00:00 2001
From: Anthony Miller <anthonymdev@gmail.com>
Date: Wed, 24 Jan 2024 15:18:34 -0800
Subject: [PATCH 615/685] Add visionOS support to Package.swift

---
 Package.swift | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/Package.swift b/Package.swift
index 70bde7ef..238661ae 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,4 +1,4 @@
-// swift-tools-version:5.7
+// swift-tools-version:5.9
 import PackageDescription
 
 let package = Package(
@@ -7,7 +7,8 @@ let package = Package(
         .iOS(.v11),
         .macOS(.v10_13),
         .watchOS(.v4),
-        .tvOS(.v11)
+        .tvOS(.v11),
+        .visionOS(.v1)
     ],
     products: [
         .library(

From 240f0802792cce82ebd0c27300cd1748b322e200 Mon Sep 17 00:00:00 2001
From: Anthony Miller <anthonymdev@gmail.com>
Date: Wed, 24 Jan 2024 15:18:43 -0800
Subject: [PATCH 616/685] Create visionOS target and test plan

---
 SQLite.xcodeproj/project.pbxproj              | 344 +++++++++++++++++-
 .../xcschemes/SQLite visionOS.xcscheme        |  71 ++++
 Tests/SQLite visionOS.xctestplan              |  24 ++
 3 files changed, 435 insertions(+), 4 deletions(-)
 create mode 100644 SQLite.xcodeproj/xcshareddata/xcschemes/SQLite visionOS.xcscheme
 create mode 100644 Tests/SQLite visionOS.xctestplan

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index def32855..857c6fd9 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -211,6 +211,76 @@
 		DB7C5DA728D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
 		DB7C5DA828D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
 		DB7C5DA928D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
+		DEB306BA2B61CEF500F9D46B /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		DEB306BC2B61CEF500F9D46B /* CoreFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFC1C3F06E900AE3E12 /* CoreFunctions.swift */; };
+		DEB306BD2B61CEF500F9D46B /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
+		DEB306BE2B61CEF500F9D46B /* RTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF61C3F06E900AE3E12 /* RTree.swift */; };
+		DEB306BF2B61CEF500F9D46B /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
+		DEB306C02B61CEF500F9D46B /* URIQueryParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B790288449BA005DD8CA /* URIQueryParameter.swift */; };
+		DEB306C12B61CEF500F9D46B /* Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF71C3F06E900AE3E12 /* Foundation.swift */; };
+		DEB306C22B61CEF500F9D46B /* Connection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEF1C3F06E900AE3E12 /* Connection.swift */; };
+		DEB306C32B61CEF500F9D46B /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFE1C3F06E900AE3E12 /* Expression.swift */; };
+		DEB306C42B61CEF500F9D46B /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF81C3F06E900AE3E12 /* Helpers.swift */; };
+		DEB306C52B61CEF500F9D46B /* Collation.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFB1C3F06E900AE3E12 /* Collation.swift */; };
+		DEB306C62B61CEF500F9D46B /* Setter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B021C3F06E900AE3E12 /* Setter.swift */; };
+		DEB306C72B61CEF500F9D46B /* Connection+Attach.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF7B78728842972005DD8CA /* Connection+Attach.swift */; };
+		DEB306C82B61CEF500F9D46B /* CustomFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFD1C3F06E900AE3E12 /* CustomFunctions.swift */; };
+		DEB306C92B61CEF500F9D46B /* FTS4.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF51C3F06E900AE3E12 /* FTS4.swift */; };
+		DEB306CA2B61CEF500F9D46B /* Value.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF31C3F06E900AE3E12 /* Value.swift */; };
+		DEB306CB2B61CEF500F9D46B /* Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFF1C3F06E900AE3E12 /* Operators.swift */; };
+		DEB306CC2B61CEF500F9D46B /* Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B011C3F06E900AE3E12 /* Schema.swift */; };
+		DEB306CD2B61CEF500F9D46B /* Query.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B001C3F06E900AE3E12 /* Query.swift */; };
+		DEB306CE2B61CEF500F9D46B /* Statement.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AF21C3F06E900AE3E12 /* Statement.swift */; };
+		DEB306CF2B61CEF500F9D46B /* AggregateFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFA1C3F06E900AE3E12 /* AggregateFunctions.swift */; };
+		DEB306D02B61CEF500F9D46B /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
+		DEB306D12B61CEF500F9D46B /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
+		DEB306D22B61CEF500F9D46B /* Backup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A43A9722738CF100FEC494 /* Backup.swift */; };
+		DEB306D32B61CEF500F9D46B /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
+		DEB306D42B61CEF500F9D46B /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
+		DEB306D52B61CEF500F9D46B /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
+		DEB306D62B61CEF500F9D46B /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17E723300E5ED3771DCB5 /* Result.swift */; };
+		DEB306D72B61CEF500F9D46B /* Query+with.swift in Sources */ = {isa = PBXBuildFile; fileRef = 997DF2AD287FC06D00F8DF95 /* Query+with.swift */; };
+		DEB306D82B61CEF500F9D46B /* Connection+Aggregation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */; };
+		DEB306D92B61CEF500F9D46B /* SQLiteFeature.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB58B21528FC7C4600F8EEA4 /* SQLiteFeature.swift */; };
+		DEB306DA2B61CEF500F9D46B /* SchemaChanger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171B262DDE8718513CFDA /* SchemaChanger.swift */; };
+		DEB306DB2B61CEF500F9D46B /* SchemaDefinitions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17268AE67B746B96AC125 /* SchemaDefinitions.swift */; };
+		DEB306DC2B61CEF500F9D46B /* Connection+Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A170A97B51DC5EE365F3C5 /* Connection+Schema.swift */; };
+		DEB306DD2B61CEF500F9D46B /* Connection+Pragmas.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17F285B767BFACD96714B /* Connection+Pragmas.swift */; };
+		DEB306DE2B61CEF500F9D46B /* SchemaReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB58B21028FB864300F8EEA4 /* SchemaReader.swift */; };
+		DEB306E02B61CEF500F9D46B /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = EE9180931C46EA210038162A /* libsqlite3.tbd */; };
+		DEB306EB2B61CF9500F9D46B /* TestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247B161C3F127200AE3E12 /* TestHelpers.swift */; };
+		DEB306EC2B61CF9500F9D46B /* FoundationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1794CC4D7827E997E32A7 /* FoundationTests.swift */; };
+		DEB306ED2B61CF9500F9D46B /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; };
+		DEB306EE2B61CF9500F9D46B /* SchemaDefinitionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A176174862D0F0139B3987 /* SchemaDefinitionsTests.swift */; };
+		DEB306EF2B61CF9500F9D46B /* SchemaChangerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17FDB0B0CFB8987906FD0 /* SchemaChangerTests.swift */; };
+		DEB306F02B61CF9500F9D46B /* Connection+SchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17CA1DF7D0F7C9A94C51C /* Connection+SchemaTests.swift */; };
+		DEB306F12B61CF9500F9D46B /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B96EBD42C878E609CDC /* FTS5Tests.swift */; };
+		DEB306F22B61CF9500F9D46B /* FTSIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BE1CC4AD4036BAB8EE0 /* FTSIntegrationTests.swift */; };
+		DEB306F32B61CF9500F9D46B /* FTS4Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1715904F7B6851FCB5EF6 /* FTS4Tests.swift */; };
+		DEB306F42B61CF9500F9D46B /* ExpressionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A170F141BF21946D159083 /* ExpressionTests.swift */; };
+		DEB306F52B61CF9500F9D46B /* StatementTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1756EB81E9F7F45B12A78 /* StatementTests.swift */; };
+		DEB306F62B61CF9500F9D46B /* QueryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171ED017645C8B04DF9F2 /* QueryTests.swift */; };
+		DEB306F72B61CF9500F9D46B /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1787E16C8562C09C076F5 /* CipherTests.swift */; };
+		DEB306F82B61CF9500F9D46B /* BlobTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171A2ED4E2640F197F48C /* BlobTests.swift */; };
+		DEB306F92B61CF9500F9D46B /* ConnectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17855BD524FF888265B3C /* ConnectionTests.swift */; };
+		DEB306FA2B61CF9500F9D46B /* CoreFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B55F2409B7031443495 /* CoreFunctionsTests.swift */; };
+		DEB306FB2B61CF9500F9D46B /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178AEF32ABC8BF2993FB5 /* DateAndTimeFunctionTests.swift */; };
+		DEB306FC2B61CF9500F9D46B /* CustomFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17F2B5959B212A33C383F /* CustomFunctionsTests.swift */; };
+		DEB306FD2B61CF9500F9D46B /* OperatorsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17475DCA068453F787613 /* OperatorsTests.swift */; };
+		DEB306FE2B61CF9500F9D46B /* ResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1745BE8623D8C6808DB3C /* ResultTests.swift */; };
+		DEB306FF2B61CF9500F9D46B /* RTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17162C9861E5C4900455D /* RTreeTests.swift */; };
+		DEB307002B61CF9500F9D46B /* SchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A171A7714C6524093255C5 /* SchemaTests.swift */; };
+		DEB307012B61CF9500F9D46B /* SelectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17EC0C43015063945D32E /* SelectTests.swift */; };
+		DEB307022B61CF9500F9D46B /* ValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17AE284BB1DF31D1B753E /* ValueTests.swift */; };
+		DEB307032B61CF9500F9D46B /* QueryIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17CAE60446607E99C22A6 /* QueryIntegrationTests.swift */; };
+		DEB307042B61CF9500F9D46B /* AggregateFunctionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17613F00A3F4D4A257A04 /* AggregateFunctionsTests.swift */; };
+		DEB307052B61CF9500F9D46B /* CustomAggregationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A177EF5E2D91BA86DA4480 /* CustomAggregationTests.swift */; };
+		DEB307062B61CF9500F9D46B /* SetterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1709D5BDD2691BA160012 /* SetterTests.swift */; };
+		DEB307072B61CF9500F9D46B /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A174FE5B47A97937A27276 /* RowTests.swift */; };
+		DEB307082B61CF9500F9D46B /* Connection+PragmaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17C60D3464461057E4D63 /* Connection+PragmaTests.swift */; };
+		DEB307092B61CF9500F9D46B /* Connection+AttachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A170C08525D3D27CB5F83C /* Connection+AttachTests.swift */; };
+		DEB3070B2B61CF9500F9D46B /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03A65E5A1C6BB0F50062603F /* SQLite.framework */; };
+		DEB3070D2B61CF9500F9D46B /* Resources in Resources */ = {isa = PBXBuildFile; fileRef = 3DF7B79528846FCC005DD8CA /* Resources */; };
 		EE247AD71C3F04ED00AE3E12 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		EE247ADE1C3F04ED00AE3E12 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE247AD31C3F04ED00AE3E12 /* SQLite.framework */; };
 		EE247B031C3F06E900AE3E12 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
@@ -263,6 +333,13 @@
 			remoteGlobalIDString = 03A65E591C6BB0F50062603F;
 			remoteInfo = "SQLite tvOS";
 		};
+		DEB307142B61D07F00F9D46B /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = EE247ACA1C3F04ED00AE3E12 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = DEB306B82B61CEF500F9D46B;
+			remoteInfo = "SQLite visionOS";
+		};
 		EE247ADF1C3F04ED00AE3E12 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = EE247ACA1C3F04ED00AE3E12 /* Project object */;
@@ -340,6 +417,9 @@
 		DB58B21028FB864300F8EEA4 /* SchemaReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaReader.swift; sourceTree = "<group>"; };
 		DB58B21528FC7C4600F8EEA4 /* SQLiteFeature.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SQLiteFeature.swift; sourceTree = "<group>"; };
 		DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SQLiteVersion.swift; sourceTree = "<group>"; };
+		DEB306E52B61CEF500F9D46B /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		DEB307112B61CF9500F9D46B /* SQLiteTests visionOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SQLiteTests visionOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
+		DEB307132B61D04500F9D46B /* SQLite visionOS.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; name = "SQLite visionOS.xctestplan"; path = "Tests/SQLite visionOS.xctestplan"; sourceTree = "<group>"; };
 		EE247AD31C3F04ED00AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AD61C3F04ED00AE3E12 /* SQLite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLite.h; sourceTree = "<group>"; };
 		EE247AD81C3F04ED00AE3E12 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -401,6 +481,22 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		DEB306DF2B61CEF500F9D46B /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				DEB306E02B61CEF500F9D46B /* libsqlite3.tbd in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		DEB3070A2B61CF9500F9D46B /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				DEB3070B2B61CF9500F9D46B /* SQLite.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		EE247ACF1C3F04ED00AE3E12 /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
@@ -517,6 +613,7 @@
 				3D3C3CCB26E5568800759140 /* SQLite.playground */,
 				EE247AD51C3F04ED00AE3E12 /* SQLite */,
 				EE247AE11C3F04ED00AE3E12 /* SQLiteTests */,
+				DEB307132B61D04500F9D46B /* SQLite visionOS.xctestplan */,
 				EE247B8A1C3F81D000AE3E12 /* Metadata */,
 				EE247AD41C3F04ED00AE3E12 /* Products */,
 				3D67B3E41DB2469200A4F4C6 /* Frameworks */,
@@ -535,6 +632,8 @@
 				03A65E5A1C6BB0F50062603F /* SQLite.framework */,
 				03A65E631C6BB0F60062603F /* SQLiteTests tvOS.xctest */,
 				A121AC451CA35C79005A31D1 /* SQLite.framework */,
+				DEB306E52B61CEF500F9D46B /* SQLite.framework */,
+				DEB307112B61CF9500F9D46B /* SQLiteTests visionOS.xctest */,
 			);
 			name = Products;
 			sourceTree = "<group>";
@@ -679,6 +778,14 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		DEB306B92B61CEF500F9D46B /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				DEB306BA2B61CEF500F9D46B /* SQLite.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		EE247AD01C3F04ED00AE3E12 /* Headers */ = {
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
@@ -752,6 +859,42 @@
 			productReference = A121AC451CA35C79005A31D1 /* SQLite.framework */;
 			productType = "com.apple.product-type.framework";
 		};
+		DEB306B82B61CEF500F9D46B /* SQLite visionOS */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = DEB306E22B61CEF500F9D46B /* Build configuration list for PBXNativeTarget "SQLite visionOS" */;
+			buildPhases = (
+				DEB306B92B61CEF500F9D46B /* Headers */,
+				DEB306BB2B61CEF500F9D46B /* Sources */,
+				DEB306DF2B61CEF500F9D46B /* Frameworks */,
+				DEB306E12B61CEF500F9D46B /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "SQLite visionOS";
+			productName = SQLite;
+			productReference = DEB306E52B61CEF500F9D46B /* SQLite.framework */;
+			productType = "com.apple.product-type.framework";
+		};
+		DEB306E72B61CF9500F9D46B /* SQLiteTests visionOS */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = DEB3070E2B61CF9500F9D46B /* Build configuration list for PBXNativeTarget "SQLiteTests visionOS" */;
+			buildPhases = (
+				DEB306EA2B61CF9500F9D46B /* Sources */,
+				DEB3070A2B61CF9500F9D46B /* Frameworks */,
+				DEB3070C2B61CF9500F9D46B /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				DEB307152B61D07F00F9D46B /* PBXTargetDependency */,
+			);
+			name = "SQLiteTests visionOS";
+			productName = "SQLite tvOSTests";
+			productReference = DEB307112B61CF9500F9D46B /* SQLiteTests visionOS.xctest */;
+			productType = "com.apple.product-type.bundle.unit-test";
+		};
 		EE247AD21C3F04ED00AE3E12 /* SQLite iOS */ = {
 			isa = PBXNativeTarget;
 			buildConfigurationList = EE247AE71C3F04ED00AE3E12 /* Build configuration list for PBXNativeTarget "SQLite iOS" */;
@@ -883,6 +1026,8 @@
 				03A65E591C6BB0F50062603F /* SQLite tvOS */,
 				03A65E621C6BB0F60062603F /* SQLiteTests tvOS */,
 				A121AC441CA35C79005A31D1 /* SQLite watchOS */,
+				DEB306B82B61CEF500F9D46B /* SQLite visionOS */,
+				DEB306E72B61CF9500F9D46B /* SQLiteTests visionOS */,
 			);
 		};
 /* End PBXProject section */
@@ -910,6 +1055,21 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		DEB306E12B61CEF500F9D46B /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		DEB3070C2B61CF9500F9D46B /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				DEB3070D2B61CF9500F9D46B /* Resources in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		EE247AD11C3F04ED00AE3E12 /* Resources */ = {
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
@@ -1064,6 +1224,86 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		DEB306BB2B61CEF500F9D46B /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				DEB306BC2B61CEF500F9D46B /* CoreFunctions.swift in Sources */,
+				DEB306BD2B61CEF500F9D46B /* Coding.swift in Sources */,
+				DEB306BE2B61CEF500F9D46B /* RTree.swift in Sources */,
+				DEB306BF2B61CEF500F9D46B /* Blob.swift in Sources */,
+				DEB306C02B61CEF500F9D46B /* URIQueryParameter.swift in Sources */,
+				DEB306C12B61CEF500F9D46B /* Foundation.swift in Sources */,
+				DEB306C22B61CEF500F9D46B /* Connection.swift in Sources */,
+				DEB306C32B61CEF500F9D46B /* Expression.swift in Sources */,
+				DEB306C42B61CEF500F9D46B /* Helpers.swift in Sources */,
+				DEB306C52B61CEF500F9D46B /* Collation.swift in Sources */,
+				DEB306C62B61CEF500F9D46B /* Setter.swift in Sources */,
+				DEB306C72B61CEF500F9D46B /* Connection+Attach.swift in Sources */,
+				DEB306C82B61CEF500F9D46B /* CustomFunctions.swift in Sources */,
+				DEB306C92B61CEF500F9D46B /* FTS4.swift in Sources */,
+				DEB306CA2B61CEF500F9D46B /* Value.swift in Sources */,
+				DEB306CB2B61CEF500F9D46B /* Operators.swift in Sources */,
+				DEB306CC2B61CEF500F9D46B /* Schema.swift in Sources */,
+				DEB306CD2B61CEF500F9D46B /* Query.swift in Sources */,
+				DEB306CE2B61CEF500F9D46B /* Statement.swift in Sources */,
+				DEB306CF2B61CEF500F9D46B /* AggregateFunctions.swift in Sources */,
+				DEB306D02B61CEF500F9D46B /* FTS5.swift in Sources */,
+				DEB306D12B61CEF500F9D46B /* Cipher.swift in Sources */,
+				DEB306D22B61CEF500F9D46B /* Backup.swift in Sources */,
+				DEB306D32B61CEF500F9D46B /* Errors.swift in Sources */,
+				DEB306D42B61CEF500F9D46B /* DateAndTimeFunctions.swift in Sources */,
+				DEB306D52B61CEF500F9D46B /* SQLiteVersion.swift in Sources */,
+				DEB306D62B61CEF500F9D46B /* Result.swift in Sources */,
+				DEB306D72B61CEF500F9D46B /* Query+with.swift in Sources */,
+				DEB306D82B61CEF500F9D46B /* Connection+Aggregation.swift in Sources */,
+				DEB306D92B61CEF500F9D46B /* SQLiteFeature.swift in Sources */,
+				DEB306DA2B61CEF500F9D46B /* SchemaChanger.swift in Sources */,
+				DEB306DB2B61CEF500F9D46B /* SchemaDefinitions.swift in Sources */,
+				DEB306DC2B61CEF500F9D46B /* Connection+Schema.swift in Sources */,
+				DEB306DD2B61CEF500F9D46B /* Connection+Pragmas.swift in Sources */,
+				DEB306DE2B61CEF500F9D46B /* SchemaReader.swift in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		DEB306EA2B61CF9500F9D46B /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				DEB306EB2B61CF9500F9D46B /* TestHelpers.swift in Sources */,
+				DEB306EC2B61CF9500F9D46B /* FoundationTests.swift in Sources */,
+				DEB306ED2B61CF9500F9D46B /* Fixtures.swift in Sources */,
+				DEB306EE2B61CF9500F9D46B /* SchemaDefinitionsTests.swift in Sources */,
+				DEB306EF2B61CF9500F9D46B /* SchemaChangerTests.swift in Sources */,
+				DEB306F02B61CF9500F9D46B /* Connection+SchemaTests.swift in Sources */,
+				DEB306F12B61CF9500F9D46B /* FTS5Tests.swift in Sources */,
+				DEB306F22B61CF9500F9D46B /* FTSIntegrationTests.swift in Sources */,
+				DEB306F32B61CF9500F9D46B /* FTS4Tests.swift in Sources */,
+				DEB306F42B61CF9500F9D46B /* ExpressionTests.swift in Sources */,
+				DEB306F52B61CF9500F9D46B /* StatementTests.swift in Sources */,
+				DEB306F62B61CF9500F9D46B /* QueryTests.swift in Sources */,
+				DEB306F72B61CF9500F9D46B /* CipherTests.swift in Sources */,
+				DEB306F82B61CF9500F9D46B /* BlobTests.swift in Sources */,
+				DEB306F92B61CF9500F9D46B /* ConnectionTests.swift in Sources */,
+				DEB306FA2B61CF9500F9D46B /* CoreFunctionsTests.swift in Sources */,
+				DEB306FB2B61CF9500F9D46B /* DateAndTimeFunctionTests.swift in Sources */,
+				DEB306FC2B61CF9500F9D46B /* CustomFunctionsTests.swift in Sources */,
+				DEB306FD2B61CF9500F9D46B /* OperatorsTests.swift in Sources */,
+				DEB306FE2B61CF9500F9D46B /* ResultTests.swift in Sources */,
+				DEB306FF2B61CF9500F9D46B /* RTreeTests.swift in Sources */,
+				DEB307002B61CF9500F9D46B /* SchemaTests.swift in Sources */,
+				DEB307012B61CF9500F9D46B /* SelectTests.swift in Sources */,
+				DEB307022B61CF9500F9D46B /* ValueTests.swift in Sources */,
+				DEB307032B61CF9500F9D46B /* QueryIntegrationTests.swift in Sources */,
+				DEB307042B61CF9500F9D46B /* AggregateFunctionsTests.swift in Sources */,
+				DEB307052B61CF9500F9D46B /* CustomAggregationTests.swift in Sources */,
+				DEB307062B61CF9500F9D46B /* SetterTests.swift in Sources */,
+				DEB307072B61CF9500F9D46B /* RowTests.swift in Sources */,
+				DEB307082B61CF9500F9D46B /* Connection+PragmaTests.swift in Sources */,
+				DEB307092B61CF9500F9D46B /* Connection+AttachTests.swift in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		EE247ACE1C3F04ED00AE3E12 /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
@@ -1232,6 +1472,11 @@
 			target = 03A65E591C6BB0F50062603F /* SQLite tvOS */;
 			targetProxy = 03A65E651C6BB0F60062603F /* PBXContainerItemProxy */;
 		};
+		DEB307152B61D07F00F9D46B /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = DEB306B82B61CEF500F9D46B /* SQLite visionOS */;
+			targetProxy = DEB307142B61D07F00F9D46B /* PBXContainerItemProxy */;
+		};
 		EE247AE01C3F04ED00AE3E12 /* PBXTargetDependency */ = {
 			isa = PBXTargetDependency;
 			target = EE247AD21C3F04ED00AE3E12 /* SQLite iOS */;
@@ -1365,6 +1610,83 @@
 			};
 			name = Release;
 		};
+		DEB306E32B61CEF500F9D46B /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				APPLICATION_EXTENSION_API_ONLY = YES;
+				CLANG_ENABLE_MODULES = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
+				DEFINES_MODULE = YES;
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				DYLIB_INSTALL_NAME_BASE = "@rpath";
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
+				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				MARKETING_VERSION = 0.14.0;
+				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
+				PRODUCT_NAME = SQLite;
+				SDKROOT = xros;
+				SKIP_INSTALL = YES;
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
+				TARGETED_DEVICE_FAMILY = 7;
+			};
+			name = Debug;
+		};
+		DEB306E42B61CEF500F9D46B /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				APPLICATION_EXTENSION_API_ONLY = YES;
+				CLANG_ENABLE_MODULES = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
+				DEFINES_MODULE = YES;
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				DYLIB_INSTALL_NAME_BASE = "@rpath";
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
+				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				MARKETING_VERSION = 0.14.0;
+				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
+				PRODUCT_NAME = SQLite;
+				SDKROOT = xros;
+				SKIP_INSTALL = YES;
+				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
+				TARGETED_DEVICE_FAMILY = 7;
+			};
+			name = Release;
+		};
+		DEB3070F2B61CF9500F9D46B /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
+				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SDKROOT = xros;
+				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
+				TARGETED_DEVICE_FAMILY = 7;
+			};
+			name = Debug;
+		};
+		DEB307102B61CF9500F9D46B /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
+				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SDKROOT = xros;
+				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
+				TARGETED_DEVICE_FAMILY = 7;
+			};
+			name = Release;
+		};
 		EE247AE51C3F04ED00AE3E12 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
@@ -1502,7 +1824,6 @@
 				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
-				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				MARKETING_VERSION = 0.14.0;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
@@ -1526,7 +1847,6 @@
 				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
-				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				MARKETING_VERSION = 0.14.0;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
@@ -1541,7 +1861,6 @@
 			buildSettings = {
 				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
-				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1554,7 +1873,6 @@
 			buildSettings = {
 				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
-				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1674,6 +1992,24 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
+		DEB306E22B61CEF500F9D46B /* Build configuration list for PBXNativeTarget "SQLite visionOS" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				DEB306E32B61CEF500F9D46B /* Debug */,
+				DEB306E42B61CEF500F9D46B /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		DEB3070E2B61CF9500F9D46B /* Build configuration list for PBXNativeTarget "SQLiteTests visionOS" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				DEB3070F2B61CF9500F9D46B /* Debug */,
+				DEB307102B61CF9500F9D46B /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
 		EE247ACD1C3F04ED00AE3E12 /* Build configuration list for PBXProject "SQLite" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite visionOS.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite visionOS.xcscheme
new file mode 100644
index 00000000..58783573
--- /dev/null
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite visionOS.xcscheme	
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1520"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "DEB306B82B61CEF500F9D46B"
+               BuildableName = "SQLite visionOS.framework"
+               BlueprintName = "SQLite visionOS"
+               ReferencedContainer = "container:SQLite.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <TestPlans>
+         <TestPlanReference
+            reference = "container:Tests/SQLite visionOS.xctestplan"
+            default = "YES">
+         </TestPlanReference>
+      </TestPlans>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "DEB306B82B61CEF500F9D46B"
+            BuildableName = "SQLite visionOS.framework"
+            BlueprintName = "SQLite visionOS"
+            ReferencedContainer = "container:SQLite.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/Tests/SQLite visionOS.xctestplan b/Tests/SQLite visionOS.xctestplan
new file mode 100644
index 00000000..9b4e90ed
--- /dev/null
+++ b/Tests/SQLite visionOS.xctestplan	
@@ -0,0 +1,24 @@
+{
+  "configurations" : [
+    {
+      "id" : "72B91FD4-441C-4C06-9E92-CAEDCB7325AB",
+      "name" : "Configuration 1",
+      "options" : {
+
+      }
+    }
+  ],
+  "defaultOptions" : {
+
+  },
+  "testTargets" : [
+    {
+      "target" : {
+        "containerPath" : "container:SQLite.xcodeproj",
+        "identifier" : "DEB306E72B61CF9500F9D46B",
+        "name" : "SQLiteTests visionOS"
+      }
+    }
+  ],
+  "version" : 1
+}

From 9043277c83fcddf18d325192616ec5214c3a50df Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Tue, 6 Feb 2024 18:54:57 +0100
Subject: [PATCH 617/685] Using macOS 14 to build

---
 .github/workflows/build.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 9cc2f56e..d4fc87d8 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -5,7 +5,7 @@ env:
   IOS_VERSION: "16.2"
 jobs:
   build:
-    runs-on: macos-13
+    runs-on: macos-14
     steps:
     - uses: actions/checkout@v2
     - name: "Select Xcode"

From 623ac53da9a23e6e8d53acdcc07291b8496580c5 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Tue, 6 Feb 2024 18:56:12 +0100
Subject: [PATCH 618/685] Xcode 15?

---
 .github/workflows/build.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index d4fc87d8..ec25e7bf 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -13,7 +13,7 @@ jobs:
       # https://github.com/CocoaPods/CocoaPods/issues/11839
       run: |
         xcode-select -p
-        sudo xcode-select -s /Applications/Xcode_14.2.app/Contents/Developer
+        sudo xcode-select -s /Applications/Xcode_15.0.1.app/Contents/Developer
     - name: "Lint"
       run: make lint
     - name: "Run tests (PACKAGE_MANAGER_COMMAND: test)"

From 0c68b99da0e8378a0d43c7ad6911b98e437dd8c1 Mon Sep 17 00:00:00 2001
From: Nathan Fallet <contact@nathanfallet.me>
Date: Tue, 6 Feb 2024 19:00:02 +0100
Subject: [PATCH 619/685] Testing using iOS 17

---
 .github/workflows/build.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index ec25e7bf..7be89270 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,8 +1,8 @@
 name: Build and test
 on: [push, pull_request]
 env:
-  IOS_SIMULATOR: "iPhone 14"
-  IOS_VERSION: "16.2"
+  IOS_SIMULATOR: "iPhone 15"
+  IOS_VERSION: "17.2"
 jobs:
   build:
     runs-on: macos-14

From 03724bf3d28a16ac0197027d47956b8039c42e69 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Elfred=20Pag=C3=A1n?= <elfred@elfredpagan.com>
Date: Tue, 20 Feb 2024 20:06:37 -0600
Subject: [PATCH 620/685] make fromDatatypeValue throw

When using custom types, sometimes decoding can fail, say due to
changes in the type structure. In this case decoding would fail
and the only way to handle it is forcing a crash.

This change allows you to use `try row.get()` instead. Givng you
the chance to handle the mismatch.
---
 Sources/SQLite/Core/Value.swift        |  2 +-
 Sources/SQLite/Helpers.swift           |  4 ++--
 Sources/SQLite/Typed/Query.swift       | 12 +++++------
 Tests/SQLiteTests/Typed/RowTests.swift | 30 ++++++++++++++++++++++++++
 4 files changed, 39 insertions(+), 9 deletions(-)

diff --git a/Sources/SQLite/Core/Value.swift b/Sources/SQLite/Core/Value.swift
index 9c463f0c..249a7728 100644
--- a/Sources/SQLite/Core/Value.swift
+++ b/Sources/SQLite/Core/Value.swift
@@ -39,7 +39,7 @@ public protocol Value: Expressible { // extensions cannot have inheritance claus
 
     static var declaredDatatype: String { get }
 
-    static func fromDatatypeValue(_ datatypeValue: Datatype) -> ValueType
+    static func fromDatatypeValue(_ datatypeValue: Datatype) throws -> ValueType
 
     var datatypeValue: Datatype { get }
 
diff --git a/Sources/SQLite/Helpers.swift b/Sources/SQLite/Helpers.swift
index adfadc8a..c27ccf05 100644
--- a/Sources/SQLite/Helpers.swift
+++ b/Sources/SQLite/Helpers.swift
@@ -121,9 +121,9 @@ func transcode(_ literal: Binding?) -> String {
     }
 }
 
-// swiftlint:disable force_cast
+// swiftlint:disable force_cast force_try
 func value<A: Value>(_ binding: Binding) -> A {
-    A.fromDatatypeValue(binding as! A.Datatype) as! A
+    try! A.fromDatatypeValue(binding as! A.Datatype) as! A
 }
 
 func value<A: Value>(_ binding: Binding?) -> A {
diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index c59b728f..2a83665c 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -1097,7 +1097,7 @@ extension Connection {
     public func scalar<V: Value>(_ query: ScalarQuery<V?>) throws -> V.ValueType? {
         let expression = query.expression
         guard let value = try scalar(expression.template, expression.bindings) as? V.Datatype else { return nil }
-        return V.fromDatatypeValue(value)
+        return try V.fromDatatypeValue(value)
     }
 
     public func scalar<V: Value>(_ query: Select<V>) throws -> V {
@@ -1108,7 +1108,7 @@ extension Connection {
     public func scalar<V: Value>(_ query: Select<V?>) throws -> V.ValueType? {
         let expression = query.expression
         guard let value = try scalar(expression.template, expression.bindings) as? V.Datatype else { return nil }
-        return V.fromDatatypeValue(value)
+        return try V.fromDatatypeValue(value)
     }
 
     public func pluck(_ query: QueryType) throws -> Row? {
@@ -1200,9 +1200,9 @@ public struct Row {
     }
 
     public func get<V: Value>(_ column: Expression<V?>) throws -> V? {
-        func valueAtIndex(_ idx: Int) -> V? {
+        func valueAtIndex(_ idx: Int) throws -> V? {
             guard let value = values[idx] as? V.Datatype else { return nil }
-            return V.fromDatatypeValue(value) as? V
+            return try V.fromDatatypeValue(value) as? V
         }
 
         guard let idx = columnNames[column.template] else {
@@ -1224,10 +1224,10 @@ public struct Row {
                     similar: columnNames.keys.filter(similar).sorted()
                 )
             }
-            return valueAtIndex(columnNames[firstIndex].value)
+            return try valueAtIndex(columnNames[firstIndex].value)
         }
 
-        return valueAtIndex(idx)
+        return try valueAtIndex(idx)
     }
 
     public subscript<T: Value>(column: Expression<T>) -> T {
diff --git a/Tests/SQLiteTests/Typed/RowTests.swift b/Tests/SQLiteTests/Typed/RowTests.swift
index 506f6b10..14fa373b 100644
--- a/Tests/SQLiteTests/Typed/RowTests.swift
+++ b/Tests/SQLiteTests/Typed/RowTests.swift
@@ -85,4 +85,34 @@ class RowTests: XCTestCase {
             }
         }
     }
+
+    public func test_get_datatype_throws() {
+        // swiftlint:disable nesting
+        struct MyType: Value {
+            enum MyError: Error {
+                case failed
+            }
+
+            public static var declaredDatatype: String {
+                Blob.declaredDatatype
+            }
+
+            public static func fromDatatypeValue(_ dataValue: Blob) throws -> Data {
+                throw MyError.failed
+            }
+
+            public var datatypeValue: Blob {
+                return Blob(bytes: [])
+            }
+        }
+
+        let row = Row(["\"foo\"": 0], [Blob(bytes: [])])
+        XCTAssertThrowsError(try row.get(Expression<MyType>("foo"))) { error in
+            if case MyType.MyError.failed = error {
+                XCTAssertTrue(true)
+            } else {
+                XCTFail("unexpected error: \(error)")
+            }
+        }
+    }
 }

From 5bfaddf455a152a276e534b24c98ff08c67d3f63 Mon Sep 17 00:00:00 2001
From: NathanFallet <contact@nathanfallet.me>
Date: Fri, 23 Feb 2024 13:50:42 +0100
Subject: [PATCH 621/685] fix: json tests (due to a swift upgrade)

---
 Tests/SQLiteTests/TestHelpers.swift      | 10 ++++++++++
 Tests/SQLiteTests/Typed/QueryTests.swift | 15 ++++++++++++---
 2 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index 65cff8bb..e2da5927 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -105,6 +105,16 @@ func assertSQL(_ expression1: @autoclosure () -> String, _ expression2: @autoclo
     XCTAssertEqual(expression1(), expression2().asSQL(), file: file, line: line)
 }
 
+func extractAndReplace(_ value: String, regex: String, with replacement: String) -> (String, String) {
+    // We cannot use `Regex` because it is not available before iOS 16 :(
+    let regex = try! NSRegularExpression(pattern: regex)
+    let valueRange = NSRange(location: 0, length: value.utf16.count)
+    let match = regex.firstMatch(in: value, options: [], range: valueRange)!.range
+    let range = Range(match, in: value)!
+    let extractedValue = String(value[range])
+    return (value.replacingCharacters(in: range, with: replacement), extractedValue)
+}
+
 let table = Table("table")
 let qualifiedTable = Table("table", database: "main")
 let virtualTable = VirtualTable("virtual_table")
diff --git a/Tests/SQLiteTests/Typed/QueryTests.swift b/Tests/SQLiteTests/Typed/QueryTests.swift
index 82a33808..f698c621 100644
--- a/Tests/SQLiteTests/Typed/QueryTests.swift
+++ b/Tests/SQLiteTests/Typed/QueryTests.swift
@@ -364,13 +364,22 @@ class QueryTests: XCTestCase {
         let insert = try emails.insert(value)
         let encodedJSON = try JSONEncoder().encode(value1)
         let encodedJSONString = String(data: encodedJSON, encoding: .utf8)!
-        assertSQL(
+
+        let expectedSQL =
             """
             INSERT INTO \"emails\" (\"int\", \"string\", \"bool\", \"float\", \"double\", \"date\", \"uuid\", \"optional\",
              \"sub\") VALUES (1, '2', 1, 3.0, 4.0, '1970-01-01T00:00:00.000', 'E621E1F8-C36C-495A-93FC-0C247A3E6E5F',
              'optional', '\(encodedJSONString)')
-            """.replacingOccurrences(of: "\n", with: ""),
-            insert
+            """.replacingOccurrences(of: "\n", with: "")
+
+        // As JSON serialization gives a different result each time, we extract JSON and compare it by deserializing it
+        // and keep comparing the query but with the json replaced by the `JSON` string
+        let (expectedQuery, expectedJSON) = extractAndReplace(expectedSQL, regex: "\\{.*\\}", with: "JSON")
+        let (actualQuery, actualJSON) = extractAndReplace(insert.asSQL(), regex: "\\{.*\\}", with: "JSON")
+        XCTAssertEqual(expectedQuery, actualQuery)
+        XCTAssertEqual(
+            try JSONDecoder().decode(TestCodable.self, from: expectedJSON.data(using: .utf8)!),
+            try JSONDecoder().decode(TestCodable.self, from: actualJSON.data(using: .utf8)!)
         )
     }
     #endif

From 485b677b8991287bf9b91de2b7d18f3eff21c38e Mon Sep 17 00:00:00 2001
From: Nathan Fallet <nathan.fallet@gmail.com>
Date: Fri, 23 Feb 2024 14:26:22 +0100
Subject: [PATCH 622/685] Revert "Add privacy manifest"

---
 SQLite.xcodeproj/project.pbxproj     | 16 ----------------
 Sources/SQLite/PrivacyInfo.xcprivacy | 14 --------------
 2 files changed, 30 deletions(-)
 delete mode 100644 Sources/SQLite/PrivacyInfo.xcprivacy

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 8eb1df66..def32855 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -211,13 +211,6 @@
 		DB7C5DA728D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
 		DB7C5DA828D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
 		DB7C5DA928D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
-		EAE1E1542B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EAE1E1532B473B0C0048B157 /* PrivacyInfo.xcprivacy */; };
-		EAE1E1552B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EAE1E1532B473B0C0048B157 /* PrivacyInfo.xcprivacy */; };
-		EAE1E1562B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EAE1E1532B473B0C0048B157 /* PrivacyInfo.xcprivacy */; };
-		EAE1E1572B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EAE1E1532B473B0C0048B157 /* PrivacyInfo.xcprivacy */; };
-		EAE1E1582B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EAE1E1532B473B0C0048B157 /* PrivacyInfo.xcprivacy */; };
-		EAE1E1592B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EAE1E1532B473B0C0048B157 /* PrivacyInfo.xcprivacy */; };
-		EAE1E15A2B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EAE1E1532B473B0C0048B157 /* PrivacyInfo.xcprivacy */; };
 		EE247AD71C3F04ED00AE3E12 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		EE247ADE1C3F04ED00AE3E12 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE247AD31C3F04ED00AE3E12 /* SQLite.framework */; };
 		EE247B031C3F06E900AE3E12 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
@@ -347,7 +340,6 @@
 		DB58B21028FB864300F8EEA4 /* SchemaReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaReader.swift; sourceTree = "<group>"; };
 		DB58B21528FC7C4600F8EEA4 /* SQLiteFeature.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SQLiteFeature.swift; sourceTree = "<group>"; };
 		DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SQLiteVersion.swift; sourceTree = "<group>"; };
-		EAE1E1532B473B0C0048B157 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
 		EE247AD31C3F04ED00AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AD61C3F04ED00AE3E12 /* SQLite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLite.h; sourceTree = "<group>"; };
 		EE247AD81C3F04ED00AE3E12 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -554,7 +546,6 @@
 				EE247AF71C3F06E900AE3E12 /* Foundation.swift */,
 				EE247AF81C3F06E900AE3E12 /* Helpers.swift */,
 				EE247AD81C3F04ED00AE3E12 /* Info.plist */,
-				EAE1E1532B473B0C0048B157 /* PrivacyInfo.xcprivacy */,
 				EE247AED1C3F06E900AE3E12 /* Core */,
 				EE247AF41C3F06E900AE3E12 /* Extensions */,
 				EE247AF91C3F06E900AE3E12 /* Typed */,
@@ -901,7 +892,6 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				EAE1E1582B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -909,7 +899,6 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				EAE1E1592B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */,
 				3DF7B79828846FED005DD8CA /* Resources in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -918,7 +907,6 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				EAE1E15A2B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -926,7 +914,6 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				EAE1E1542B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -934,7 +921,6 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				EAE1E1552B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */,
 				3DF7B79628846FCC005DD8CA /* Resources in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -943,7 +929,6 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				EAE1E1562B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -951,7 +936,6 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				EAE1E1572B473B0C0048B157 /* PrivacyInfo.xcprivacy in Resources */,
 				3DF7B79928847055005DD8CA /* Resources in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
diff --git a/Sources/SQLite/PrivacyInfo.xcprivacy b/Sources/SQLite/PrivacyInfo.xcprivacy
deleted file mode 100644
index 987771fa..00000000
--- a/Sources/SQLite/PrivacyInfo.xcprivacy
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>NSPrivacyTrackingDomains</key>
-	<array/>
-	<key>NSPrivacyCollectedDataTypes</key>
-	<array/>
-	<key>NSPrivacyAccessedAPITypes</key>
-	<array/>
-	<key>NSPrivacyTracking</key>
-	<false/>
-</dict>
-</plist>

From fec58b90b7a340377d16dfcce89027a6b6f81e26 Mon Sep 17 00:00:00 2001
From: NathanFallet <contact@nathanfallet.me>
Date: Fri, 23 Feb 2024 14:47:00 +0100
Subject: [PATCH 623/685] fix: ios deployment target

---
 SQLite.swift.podspec                                          | 2 +-
 SQLite.xcodeproj/project.pbxproj                              | 4 ++--
 .../xcshareddata/xcschemes/SQLite visionOS.xcscheme           | 4 ++--
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 4edddd67..b8aaaa8f 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -18,7 +18,7 @@ Pod::Spec.new do |s|
   s.default_subspec  = 'standard'
   s.swift_versions = ['5']
 
-  ios_deployment_target = '11.0'
+  ios_deployment_target = '17.0'
   tvos_deployment_target = '11.0'
   osx_deployment_target = '10.13'
   watchos_deployment_target = '4.0'
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 857c6fd9..d23b6d64 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1736,7 +1736,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 17.0;
 				MACOSX_DEPLOYMENT_TARGET = 10.13;
 				MTL_ENABLE_DEBUG_INFO = YES;
 				ONLY_ACTIVE_ARCH = YES;
@@ -1795,7 +1795,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 17.0;
 				MACOSX_DEPLOYMENT_TARGET = 10.13;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				PRODUCT_NAME = "";
diff --git a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite visionOS.xcscheme b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite visionOS.xcscheme
index 58783573..c1536b66 100644
--- a/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite visionOS.xcscheme	
+++ b/SQLite.xcodeproj/xcshareddata/xcschemes/SQLite visionOS.xcscheme	
@@ -15,7 +15,7 @@
             <BuildableReference
                BuildableIdentifier = "primary"
                BlueprintIdentifier = "DEB306B82B61CEF500F9D46B"
-               BuildableName = "SQLite visionOS.framework"
+               BuildableName = "SQLite.framework"
                BlueprintName = "SQLite visionOS"
                ReferencedContainer = "container:SQLite.xcodeproj">
             </BuildableReference>
@@ -55,7 +55,7 @@
          <BuildableReference
             BuildableIdentifier = "primary"
             BlueprintIdentifier = "DEB306B82B61CEF500F9D46B"
-            BuildableName = "SQLite visionOS.framework"
+            BuildableName = "SQLite.framework"
             BlueprintName = "SQLite visionOS"
             ReferencedContainer = "container:SQLite.xcodeproj">
          </BuildableReference>

From ce125ce64c03e9fcd142f18aca254637c223be8c Mon Sep 17 00:00:00 2001
From: NathanFallet <contact@nathanfallet.me>
Date: Fri, 23 Feb 2024 15:37:04 +0100
Subject: [PATCH 624/685] fix: deployment targets?

---
 SQLite.swift.podspec | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index b8aaaa8f..2a75f169 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -19,9 +19,9 @@ Pod::Spec.new do |s|
   s.swift_versions = ['5']
 
   ios_deployment_target = '17.0'
-  tvos_deployment_target = '11.0'
-  osx_deployment_target = '10.13'
-  watchos_deployment_target = '4.0'
+  tvos_deployment_target = '17.0'
+  osx_deployment_target = '14.0'
+  watchos_deployment_target = '10.0'
 
   s.ios.deployment_target = ios_deployment_target
   s.tvos.deployment_target = tvos_deployment_target
@@ -32,6 +32,11 @@ Pod::Spec.new do |s|
     ss.source_files = 'Sources/SQLite/**/*.{c,h,m,swift}'
     ss.exclude_files = 'Sources/**/Cipher.swift'
     ss.library = 'sqlite3'
+    
+    ss.ios.deployment_target = ios_deployment_target
+    ss.tvos.deployment_target = tvos_deployment_target
+    ss.osx.deployment_target = osx_deployment_target
+    ss.watchos.deployment_target = watchos_deployment_target
 
     ss.test_spec 'tests' do |test_spec|
       test_spec.resources = 'Tests/SQLiteTests/Resources/*'
@@ -51,6 +56,11 @@ Pod::Spec.new do |s|
       'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SQLITE_SWIFT_STANDALONE=1'
     }
     ss.dependency 'sqlite3'
+    
+    ss.ios.deployment_target = ios_deployment_target
+    ss.tvos.deployment_target = tvos_deployment_target
+    ss.osx.deployment_target = osx_deployment_target
+    ss.watchos.deployment_target = watchos_deployment_target
 
     ss.test_spec 'tests' do |test_spec|
       test_spec.resources = 'Tests/SQLiteTests/Resources/*'
@@ -68,6 +78,11 @@ Pod::Spec.new do |s|
       'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SQLITE_HAS_CODEC=1 SQLITE_SWIFT_SQLCIPHER=1'
     }
     ss.dependency 'SQLCipher', '>= 4.0.0'
+    
+    ss.ios.deployment_target = ios_deployment_target
+    ss.tvos.deployment_target = tvos_deployment_target
+    ss.osx.deployment_target = osx_deployment_target
+    ss.watchos.deployment_target = watchos_deployment_target
 
     ss.test_spec 'tests' do |test_spec|
       test_spec.resources = 'Tests/SQLiteTests/Resources/*'

From e7813517c80c5bd79d4e7029ec8a89121f5afe60 Mon Sep 17 00:00:00 2001
From: ivan <ivanlares1@gmail.com>
Date: Fri, 23 Feb 2024 12:51:28 -0800
Subject: [PATCH 625/685] Add privacy manifest

- fixes build issue https://github.com/stephencelis/SQLite.swift/actions/runs/8019552944/job/21907598856
---
 SQLite.xcodeproj/project.pbxproj     | 10 ++++++++++
 Sources/SQLite/PrivacyInfo.xcprivacy | 14 ++++++++++++++
 2 files changed, 24 insertions(+)
 create mode 100644 Sources/SQLite/PrivacyInfo.xcprivacy

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 37c8a802..0b246a00 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -221,6 +221,10 @@
 		DBB93D5A2A22A373009BB96E /* SchemaReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB93D592A22A373009BB96E /* SchemaReaderTests.swift */; };
 		DBB93D5B2A22A373009BB96E /* SchemaReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB93D592A22A373009BB96E /* SchemaReaderTests.swift */; };
 		DBB93D5C2A22A373009BB96E /* SchemaReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB93D592A22A373009BB96E /* SchemaReaderTests.swift */; };
+		EAE5A0372B893C43007C7EA4 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EAE5A0362B893C43007C7EA4 /* PrivacyInfo.xcprivacy */; };
+		EAE5A0382B893C43007C7EA4 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EAE5A0362B893C43007C7EA4 /* PrivacyInfo.xcprivacy */; };
+		EAE5A0392B893C43007C7EA4 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EAE5A0362B893C43007C7EA4 /* PrivacyInfo.xcprivacy */; };
+		EAE5A03A2B893C43007C7EA4 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EAE5A0362B893C43007C7EA4 /* PrivacyInfo.xcprivacy */; };
 		EE247AD71C3F04ED00AE3E12 /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		EE247ADE1C3F04ED00AE3E12 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE247AD31C3F04ED00AE3E12 /* SQLite.framework */; };
 		EE247B031C3F06E900AE3E12 /* Blob.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AEE1C3F06E900AE3E12 /* Blob.swift */; };
@@ -353,6 +357,7 @@
 		DB58B21528FC7C4600F8EEA4 /* SQLiteFeature.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SQLiteFeature.swift; sourceTree = "<group>"; };
 		DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SQLiteVersion.swift; sourceTree = "<group>"; };
 		DBB93D592A22A373009BB96E /* SchemaReaderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaReaderTests.swift; sourceTree = "<group>"; };
+		EAE5A0362B893C43007C7EA4 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
 		EE247AD31C3F04ED00AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AD61C3F04ED00AE3E12 /* SQLite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLite.h; sourceTree = "<group>"; };
 		EE247AD81C3F04ED00AE3E12 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -560,6 +565,7 @@
 				EE247AD61C3F04ED00AE3E12 /* SQLite.h */,
 				EE247AF71C3F06E900AE3E12 /* Foundation.swift */,
 				EE247AF81C3F06E900AE3E12 /* Helpers.swift */,
+				EAE5A0362B893C43007C7EA4 /* PrivacyInfo.xcprivacy */,
 				EE247AD81C3F04ED00AE3E12 /* Info.plist */,
 				EE247AED1C3F06E900AE3E12 /* Core */,
 				EE247AF41C3F06E900AE3E12 /* Extensions */,
@@ -908,6 +914,7 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				EAE5A0392B893C43007C7EA4 /* PrivacyInfo.xcprivacy in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -923,6 +930,7 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				EAE5A03A2B893C43007C7EA4 /* PrivacyInfo.xcprivacy in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -930,6 +938,7 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				EAE5A0372B893C43007C7EA4 /* PrivacyInfo.xcprivacy in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -945,6 +954,7 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				EAE5A0382B893C43007C7EA4 /* PrivacyInfo.xcprivacy in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/Sources/SQLite/PrivacyInfo.xcprivacy b/Sources/SQLite/PrivacyInfo.xcprivacy
new file mode 100644
index 00000000..987771fa
--- /dev/null
+++ b/Sources/SQLite/PrivacyInfo.xcprivacy
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>NSPrivacyTrackingDomains</key>
+	<array/>
+	<key>NSPrivacyCollectedDataTypes</key>
+	<array/>
+	<key>NSPrivacyAccessedAPITypes</key>
+	<array/>
+	<key>NSPrivacyTracking</key>
+	<false/>
+</dict>
+</plist>

From e78ae0220e17525a15ac68c697a155eb7a672a8e Mon Sep 17 00:00:00 2001
From: NathanFallet <contact@nathanfallet.me>
Date: Sat, 24 Feb 2024 11:51:41 +0100
Subject: [PATCH 626/685] changelogs

---
 CHANGELOG.md            | 33 ++++++++++++++++++++++++++++++--
 Documentation/Index.md  | 42 ++++++++++++++++++++++++++++++-----------
 README.md               |  4 ++--
 SQLite.swift.podspec    |  2 +-
 Tests/SPM/Package.swift |  2 +-
 5 files changed, 66 insertions(+), 17 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 970b4ca1..4c5c1fba 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,20 @@
-0.15.0 (unreleased)
+0.15.0 (24-02-2024), [diff][diff-0.15.0]
 ========================================
 
+* Fix incorrect behavior when preparing `SELECT *` preceded by a `WITH` ([#1179][])
+* Adds support for returning extended error codes ([#1178][])
+* Fix typos ([#1182][])
+* fix Xcode build error ([#1192][])
+* Make the IndexDefinition properties public ([#1196][])
+* Fix GitHub Actions build badge ([#1200][])
+* Run CI on macOS 13 ([#1206][])
+* SchemaReader: return the correct column definition for a composite primary key ([#1217][])
+* Add optional support for decoding ([#1224][])
+* make fromDatatypeValue throw ([#1242][])
+* Implements built-in window functions ([#1228][])
+* Fix column affinity parsing to match how SQLite determines affinity ([#1218][])
+* Handle FK definitions w/o key references ([#1210][])
+* Add privacy manifest ([#1245][])
 * New minimum deployment targets: iOS/tvOS 11.0, watchOS 4.0
 
 0.14.1 (01-11-2022), [diff][diff-0.14.1]
@@ -14,7 +28,7 @@ For breaking changes, see [Upgrading.md](Documentation/Upgrading.md).
 
 * Support more complex schema changes and queries ([#1073][], [#1146][] [#1148][])
 * Support `ATTACH`/`DETACH` ([#30][], [#1142][])
-* Expose connection flags (via `URIQueryParameter`) to open db ([#1074][]))
+* Expose connection flags (via `URIQueryParameter`) to open db ([#1074][])
 * Support `WITH` clause ([#1139][])
 * Add `Value` conformance for `NSURL` ([#1110][], [#1141][])
 * Add decoding for `UUID` ([#1137][])
@@ -140,6 +154,7 @@ For breaking changes, see [Upgrading.md](Documentation/Upgrading.md).
 [diff-0.13.3]: https://github.com/stephencelis/SQLite.swift/compare/0.13.2...0.13.3
 [diff-0.14.0]: https://github.com/stephencelis/SQLite.swift/compare/0.13.3...0.14.0
 [diff-0.14.1]: https://github.com/stephencelis/SQLite.swift/compare/0.14.0...0.14.1
+[diff-0.15.0]: https://github.com/stephencelis/SQLite.swift/compare/0.14.0...0.15.0
 
 [#30]: https://github.com/stephencelis/SQLite.swift/issues/30
 [#142]: https://github.com/stephencelis/SQLite.swift/issues/142
@@ -206,3 +221,17 @@ For breaking changes, see [Upgrading.md](Documentation/Upgrading.md).
 [#1146]: https://github.com/stephencelis/SQLite.swift/pull/1146
 [#1148]: https://github.com/stephencelis/SQLite.swift/pull/1148
 [#1167]: https://github.com/stephencelis/SQLite.swift/pull/1167
+[#1179]: https://github.com/stephencelis/SQLite.swift/pull/1179
+[#1178]: https://github.com/stephencelis/SQLite.swift/pull/1178
+[#1182]: https://github.com/stephencelis/SQLite.swift/pull/1182
+[#1192]: https://github.com/stephencelis/SQLite.swift/pull/1192
+[#1196]: https://github.com/stephencelis/SQLite.swift/pull/1196
+[#1200]: https://github.com/stephencelis/SQLite.swift/pull/1200
+[#1206]: https://github.com/stephencelis/SQLite.swift/pull/1206
+[#1217]: https://github.com/stephencelis/SQLite.swift/pull/1217
+[#1224]: https://github.com/stephencelis/SQLite.swift/pull/1224
+[#1242]: https://github.com/stephencelis/SQLite.swift/pull/1242
+[#1228]: https://github.com/stephencelis/SQLite.swift/pull/1228
+[#1218]: https://github.com/stephencelis/SQLite.swift/pull/1218
+[#1210]: https://github.com/stephencelis/SQLite.swift/pull/1210
+[#1245]: https://github.com/stephencelis/SQLite.swift/pull/1245
diff --git a/Documentation/Index.md b/Documentation/Index.md
index a03c26a3..7f900bc5 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1,21 +1,24 @@
 # SQLite.swift Documentation
 
+- [SQLite.swift Documentation](#sqliteswift-documentation)
   - [Installation](#installation)
     - [Swift Package Manager](#swift-package-manager)
     - [Carthage](#carthage)
     - [CocoaPods](#cocoapods)
+      - [Requiring a specific version of SQLite](#requiring-a-specific-version-of-sqlite)
+      - [Using SQLite.swift with SQLCipher](#using-sqliteswift-with-sqlcipher)
     - [Manual](#manual)
   - [Getting Started](#getting-started)
     - [Connecting to a Database](#connecting-to-a-database)
       - [Read-Write Databases](#read-write-databases)
       - [Read-Only Databases](#read-only-databases)
-      - [In a Shared Group Container](#in-a-shared-group-container)
+      - [In a shared group container](#in-a-shared-group-container)
       - [In-Memory Databases](#in-memory-databases)
       - [URI parameters](#uri-parameters)
       - [Thread-Safety](#thread-safety)
   - [Building Type-Safe SQL](#building-type-safe-sql)
     - [Expressions](#expressions)
-      - [Compound Expressions](#compound-expressions)
+    - [Compound Expressions](#compound-expressions)
     - [Queries](#queries)
   - [Creating a Table](#creating-a-table)
     - [Create Table Options](#create-table-options)
@@ -24,8 +27,11 @@
   - [Inserting Rows](#inserting-rows)
     - [Handling SQLite errors](#handling-sqlite-errors)
     - [Setters](#setters)
+          - [Infix Setters](#infix-setters)
+          - [Postfix Setters](#postfix-setters)
   - [Selecting Rows](#selecting-rows)
     - [Iterating and Accessing Values](#iterating-and-accessing-values)
+      - [Failable iteration](#failable-iteration)
     - [Plucking Rows](#plucking-rows)
     - [Building Complex Queries](#building-complex-queries)
       - [Selecting Columns](#selecting-columns)
@@ -34,6 +40,9 @@
         - [Table Aliasing](#table-aliasing)
       - [Filtering Rows](#filtering-rows)
         - [Filter Operators and Functions](#filter-operators-and-functions)
+          - [Infix Filter Operators](#infix-filter-operators)
+          - [Prefix Filter Operators](#prefix-filter-operators)
+          - [Filtering Functions](#filtering-functions)
       - [Sorting Rows](#sorting-rows)
       - [Limiting and Paging Results](#limiting-and-paging-results)
       - [Recursive and Hierarchical Queries](#recursive-and-hierarchical-queries)
@@ -43,13 +52,14 @@
   - [Deleting Rows](#deleting-rows)
   - [Transactions and Savepoints](#transactions-and-savepoints)
   - [Querying the Schema](#querying-the-schema)
+    - [Indexes and Columns](#indexes-and-columns)
   - [Altering the Schema](#altering-the-schema)
     - [Renaming Tables](#renaming-tables)
     - [Dropping Tables](#dropping-tables)
     - [Adding Columns](#adding-columns)
       - [Added Column Constraints](#added-column-constraints)
-    - [Schema Changer](#schemachanger)
-      - [Adding Columns](#adding-columns)
+    - [SchemaChanger](#schemachanger)
+      - [Adding Columns](#adding-columns-1)
       - [Renaming Columns](#renaming-columns)
       - [Dropping Columns](#dropping-columns)
       - [Renaming/Dropping Tables](#renamingdropping-tables)
@@ -61,17 +71,27 @@
     - [Date-Time Values](#date-time-values)
     - [Binary Data](#binary-data)
   - [Codable Types](#codable-types)
+    - [Inserting Codable Types](#inserting-codable-types)
+    - [Updating Codable Types](#updating-codable-types)
+    - [Retrieving Codable Types](#retrieving-codable-types)
+    - [Restrictions](#restrictions)
   - [Other Operators](#other-operators)
+          - [Other Infix Operators](#other-infix-operators)
+          - [Other Prefix Operators](#other-prefix-operators)
   - [Core SQLite Functions](#core-sqlite-functions)
   - [Aggregate SQLite Functions](#aggregate-sqlite-functions)
   - [Window SQLite Functions](#window-sqlite-functions)
-  - [Date and Time Functions](#date-and-time-functions)
+  - [Date and Time functions](#date-and-time-functions)
   - [Custom SQL Functions](#custom-sql-functions)
+  - [Custom Aggregations](#custom-aggregations)
   - [Custom Collations](#custom-collations)
   - [Full-text Search](#full-text-search)
+    - [FTS5](#fts5)
   - [Executing Arbitrary SQL](#executing-arbitrary-sql)
+  - [Online Database Backup](#online-database-backup)
   - [Attaching and detaching databases](#attaching-and-detaching-databases)
   - [Logging](#logging)
+  - [Vacuum](#vacuum)
 
 [↩]: #sqliteswift-documentation
 
@@ -88,7 +108,7 @@ process of downloading, compiling, and linking dependencies.
 
   ```swift
   dependencies: [
-    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.1")
+    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.0")
   ]
   ```
 
@@ -109,7 +129,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.14.1
+    github "stephencelis/SQLite.swift" ~> 0.15.0
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -139,7 +159,7 @@ install SQLite.swift with Carthage:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.14.1'
+        pod 'SQLite.swift', '~> 0.15.0'
     end
     ```
 
@@ -153,7 +173,7 @@ with the OS you can require the `standalone` subspec:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.14.1'
+  pod 'SQLite.swift/standalone', '~> 0.15.0'
 end
 ```
 
@@ -163,7 +183,7 @@ dependency to sqlite3 or one of its subspecs:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.14.1'
+  pod 'SQLite.swift/standalone', '~> 0.15.0'
   pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
 end
 ```
@@ -179,7 +199,7 @@ If you want to use [SQLCipher][] with SQLite.swift you can require the
 target 'YourAppTargetName' do
   # Make sure you only require the subspec, otherwise you app might link against
   # the system SQLite, which means the SQLCipher-specific methods won't work.
-  pod 'SQLite.swift/SQLCipher', '~> 0.14.1'
+  pod 'SQLite.swift/SQLCipher', '~> 0.15.0'
 end
 ```
 
diff --git a/README.md b/README.md
index e6e5a894..117edb5a 100644
--- a/README.md
+++ b/README.md
@@ -128,7 +128,7 @@ Swift code.
 
   ```swift
   dependencies: [
-      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.1")
+      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.0")
   ]
   ```
 
@@ -152,7 +152,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.14.1
+    github "stephencelis/SQLite.swift" ~> 0.15.0
     ```
 
  3. Run `carthage update` and
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 4edddd67..b691aeab 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.14.1"
+  s.version          = "0.15.0"
   s.summary          = "A type-safe, Swift-language layer over SQLite3."
 
   s.description      = <<-DESC
diff --git a/Tests/SPM/Package.swift b/Tests/SPM/Package.swift
index 3c446ae6..c82b3b9e 100644
--- a/Tests/SPM/Package.swift
+++ b/Tests/SPM/Package.swift
@@ -15,7 +15,7 @@ let package = Package(
         // for testing from same repository
         .package(path: "../..")
         // normally this would be:
-        // .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.1")
+        // .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.0")
     ],
     targets: [
         .executableTarget(name: "test", dependencies: [.product(name: "SQLite", package: "SQLite.swift")])

From 20ebe9b334ff557c1166e26ca6c89e94a77a7f2d Mon Sep 17 00:00:00 2001
From: Chris Stockbridge <chris.stockbridge@vantaca.com>
Date: Mon, 4 Mar 2024 20:07:22 -0500
Subject: [PATCH 627/685] Adding failing test that includes an optional struct

This test passes with release 0.14.1, but fails starting with 0.15
---
 .../Typed/QueryIntegrationTests.swift         | 27 +++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift b/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
index aa45cafe..7ac72d0c 100644
--- a/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
+++ b/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
@@ -152,6 +152,33 @@ class QueryIntegrationTests: SQLiteTestCase {
          XCTAssertEqual(values.count, 2)
     }
 
+    func test_insert_custom_encodable_type() throws {
+        struct TestTypeWithOptionalArray: Codable {
+            var myInt: Int
+            var myString: String
+            var myOptionalArray: [Int]?
+        }
+
+        let table = Table("custom_codable")
+        try db.run(table.create { builder in
+            builder.column(Expression<Int?>("myInt"))
+            builder.column(Expression<String?>("myString"))
+            builder.column(Expression<String?>("myOptionalArray"))
+        })
+
+        let customType = TestTypeWithOptionalArray(myInt: 13, myString: "foo", myOptionalArray: [1, 2, 3])
+        try db.run(table.insert(customType))
+        let rows = try db.prepare(table)
+        let values: [TestTypeWithOptionalArray] = try rows.map({ try $0.decode() })
+        XCTAssertEqual(values.count, 1, "return one optional custom type")
+
+        let customTypeWithNil = TestTypeWithOptionalArray(myInt: 123, myString: "String", myOptionalArray: nil)
+        try db.run(table.insert(customTypeWithNil))
+        let rowsNil = try db.prepare(table)
+        let valuesNil: [TestTypeWithOptionalArray] = try rowsNil.map({ try $0.decode() })
+        XCTAssertEqual(valuesNil.count, 2, "return two custom objects, including one that contains a nil optional")
+    }
+
     func test_upsert() throws {
         try XCTSkipUnless(db.satisfiesMinimumVersion(minor: 24))
         let fetchAge = { () throws -> Int? in

From bad16cb5d1a09e93bbdb40f50df5f222920a10e3 Mon Sep 17 00:00:00 2001
From: Chris Stockbridge <chris.stockbridge@vantaca.com>
Date: Tue, 5 Mar 2024 11:11:50 -0500
Subject: [PATCH 628/685] Bugfix: returning nil when decoding an optional
 should not throw an error

---
 Sources/SQLite/Typed/Coding.swift | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/Sources/SQLite/Typed/Coding.swift b/Sources/SQLite/Typed/Coding.swift
index bfddc5ee..d0061851 100644
--- a/Sources/SQLite/Typed/Coding.swift
+++ b/Sources/SQLite/Typed/Coding.swift
@@ -504,9 +504,8 @@ private class SQLiteDecoder: Decoder {
             case is UUID.Type:
                 return try? row.get(Expression<UUID>(key.stringValue)) as? T
             default:
-                guard let JSONString = try? row.get(Expression<String?>(key.stringValue)) else {
-                    throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath,
-                                                                                 debugDescription: "an unsupported type was found"))
+                guard let JSONString = try row.get(Expression<String?>(key.stringValue)) else {
+                    return nil
                 }
                 guard let data = JSONString.data(using: .utf8) else {
                     throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath,

From cda8a1274a5c426c043bea6d381fddab630dad95 Mon Sep 17 00:00:00 2001
From: Steven <tongwanglin@gmail.com>
Date: Sun, 17 Mar 2024 01:10:17 +0800
Subject: [PATCH 629/685] Update CoreFunctions.swift fix typo

fix lower to upper
---
 Sources/SQLite/Typed/CoreFunctions.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Sources/SQLite/Typed/CoreFunctions.swift b/Sources/SQLite/Typed/CoreFunctions.swift
index 4429bb5f..c4359d8b 100644
--- a/Sources/SQLite/Typed/CoreFunctions.swift
+++ b/Sources/SQLite/Typed/CoreFunctions.swift
@@ -224,7 +224,7 @@ extension ExpressionType where UnderlyingType == String {
     ///
     ///     let name = Expression<String>("name")
     ///     name.uppercaseString
-    ///     // lower("name")
+    ///     // upper("name")
     ///
     /// - Returns: A copy of the expression wrapped with the `upper` function.
     public var uppercaseString: Expression<UnderlyingType> {

From 6d821f83499500cb7bb7f258655fe83ac6f890ed Mon Sep 17 00:00:00 2001
From: Sagar Dagdu <shags032@gmail.com>
Date: Sat, 13 Apr 2024 08:23:49 +0530
Subject: [PATCH 630/685] Add dependency on custom cocoapods fork

---
 Gemfile      |   1 +
 Gemfile.lock | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 117 insertions(+)
 create mode 100644 Gemfile
 create mode 100644 Gemfile.lock

diff --git a/Gemfile b/Gemfile
new file mode 100644
index 00000000..2f97c391
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1 @@
+gem 'cocoapods', :git => 'https://github.com/SagarSDagdu/CocoaPods.git', tag: '1.15.2.1-sagard'
diff --git a/Gemfile.lock b/Gemfile.lock
new file mode 100644
index 00000000..75374a30
--- /dev/null
+++ b/Gemfile.lock
@@ -0,0 +1,116 @@
+GIT
+  remote: https://github.com/SagarSDagdu/CocoaPods.git
+  revision: d96f491f79abd2804d1359c5228cce404dd365b7
+  tag: 1.15.2.1-sagard
+  specs:
+    cocoapods (1.15.2.1.pre.sagard)
+      addressable (~> 2.8)
+      claide (>= 1.0.2, < 2.0)
+      cocoapods-core (= 1.15.2)
+      cocoapods-deintegrate (>= 1.0.3, < 2.0)
+      cocoapods-downloader (>= 2.1, < 3.0)
+      cocoapods-plugins (>= 1.0.0, < 2.0)
+      cocoapods-search (>= 1.0.0, < 2.0)
+      cocoapods-trunk (>= 1.6.0, < 2.0)
+      cocoapods-try (>= 1.1.0, < 2.0)
+      colored2 (~> 3.1)
+      escape (~> 0.0.4)
+      fourflusher (>= 2.3.0, < 3.0)
+      gh_inspector (~> 1.0)
+      molinillo (~> 0.8.0)
+      nap (~> 1.0)
+      ruby-macho (>= 2.3.0, < 3.0)
+      xcodeproj (>= 1.23.0, < 2.0)
+
+GEM
+  specs:
+    CFPropertyList (3.0.7)
+      base64
+      nkf
+      rexml
+    activesupport (7.1.3.2)
+      base64
+      bigdecimal
+      concurrent-ruby (~> 1.0, >= 1.0.2)
+      connection_pool (>= 2.2.5)
+      drb
+      i18n (>= 1.6, < 2)
+      minitest (>= 5.1)
+      mutex_m
+      tzinfo (~> 2.0)
+    addressable (2.8.6)
+      public_suffix (>= 2.0.2, < 6.0)
+    algoliasearch (1.27.5)
+      httpclient (~> 2.8, >= 2.8.3)
+      json (>= 1.5.1)
+    atomos (0.1.3)
+    base64 (0.2.0)
+    bigdecimal (3.1.5)
+    claide (1.1.0)
+    cocoapods-core (1.15.2)
+      activesupport (>= 5.0, < 8)
+      addressable (~> 2.8)
+      algoliasearch (~> 1.0)
+      concurrent-ruby (~> 1.1)
+      fuzzy_match (~> 2.0.4)
+      nap (~> 1.0)
+      netrc (~> 0.11)
+      public_suffix (~> 4.0)
+      typhoeus (~> 1.0)
+    cocoapods-deintegrate (1.0.5)
+    cocoapods-downloader (2.1)
+    cocoapods-plugins (1.0.0)
+      nap
+    cocoapods-search (1.0.1)
+    cocoapods-trunk (1.6.0)
+      nap (>= 0.8, < 2.0)
+      netrc (~> 0.11)
+    cocoapods-try (1.2.0)
+    colored2 (3.1.2)
+    concurrent-ruby (1.2.3)
+    connection_pool (2.4.1)
+    drb (2.2.0)
+      ruby2_keywords
+    escape (0.0.4)
+    ethon (0.16.0)
+      ffi (>= 1.15.0)
+    ffi (1.16.3)
+    fourflusher (2.3.1)
+    fuzzy_match (2.0.4)
+    gh_inspector (1.1.3)
+    httpclient (2.8.3)
+    i18n (1.14.4)
+      concurrent-ruby (~> 1.0)
+    json (2.7.1)
+    minitest (5.22.0)
+    molinillo (0.8.0)
+    mutex_m (0.2.0)
+    nanaimo (0.3.0)
+    nap (1.1.0)
+    netrc (0.11.0)
+    nkf (0.1.3)
+    public_suffix (4.0.7)
+    rexml (3.2.6)
+    ruby-macho (2.5.1)
+    ruby2_keywords (0.0.5)
+    typhoeus (1.4.1)
+      ethon (>= 0.9.0)
+    tzinfo (2.0.6)
+      concurrent-ruby (~> 1.0)
+    xcodeproj (1.24.0)
+      CFPropertyList (>= 2.3.3, < 4.0)
+      atomos (~> 0.1.3)
+      claide (>= 1.0.2, < 2.0)
+      colored2 (~> 3.1)
+      nanaimo (~> 0.3.0)
+      rexml (~> 3.2.4)
+
+PLATFORMS
+  arm64-darwin-23
+  ruby
+
+DEPENDENCIES
+  cocoapods!
+
+BUNDLED WITH
+   2.5.4

From 6491e381d7f827ced234e6aa7edca0a92f25eff6 Mon Sep 17 00:00:00 2001
From: Sagar Dagdu <shags032@gmail.com>
Date: Sat, 13 Apr 2024 08:24:03 +0530
Subject: [PATCH 631/685] Update deployment targets for Xcode 15

---
 SQLite.swift.podspec             |  4 ++--
 SQLite.xcodeproj/project.pbxproj | 24 ++++++++++++------------
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index b691aeab..4a7a390c 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -18,8 +18,8 @@ Pod::Spec.new do |s|
   s.default_subspec  = 'standard'
   s.swift_versions = ['5']
 
-  ios_deployment_target = '11.0'
-  tvos_deployment_target = '11.0'
+  ios_deployment_target = '12.0'
+  tvos_deployment_target = '12.0'
   osx_deployment_target = '10.13'
   watchos_deployment_target = '4.0'
 
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 0b246a00..c5215807 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1299,7 +1299,7 @@
 				SDKROOT = appletvos;
 				SKIP_INSTALL = YES;
 				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
-				TVOS_DEPLOYMENT_TARGET = 11.0;
+				TVOS_DEPLOYMENT_TARGET = 12.0;
 			};
 			name = Debug;
 		};
@@ -1321,7 +1321,7 @@
 				SDKROOT = appletvos;
 				SKIP_INSTALL = YES;
 				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
-				TVOS_DEPLOYMENT_TARGET = 11.0;
+				TVOS_DEPLOYMENT_TARGET = 12.0;
 			};
 			name = Release;
 		};
@@ -1335,7 +1335,7 @@
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = appletvos;
 				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
-				TVOS_DEPLOYMENT_TARGET = 11.0;
+				TVOS_DEPLOYMENT_TARGET = 12.0;
 			};
 			name = Debug;
 		};
@@ -1349,7 +1349,7 @@
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = appletvos;
 				SWIFT_TREAT_WARNINGS_AS_ERRORS = YES;
-				TVOS_DEPLOYMENT_TARGET = 11.0;
+				TVOS_DEPLOYMENT_TARGET = 12.0;
 			};
 			name = Release;
 		};
@@ -1450,7 +1450,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
 				MACOSX_DEPLOYMENT_TARGET = 10.13;
 				MTL_ENABLE_DEBUG_INFO = YES;
 				ONLY_ACTIVE_ARCH = YES;
@@ -1459,7 +1459,7 @@
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
 				SWIFT_VERSION = 5.0;
 				TARGETED_DEVICE_FAMILY = "1,2,3";
-				TVOS_DEPLOYMENT_TARGET = 11.0;
+				TVOS_DEPLOYMENT_TARGET = 12.0;
 				VERSIONING_SYSTEM = "apple-generic";
 				VERSION_INFO_PREFIX = "";
 				WATCHOS_DEPLOYMENT_TARGET = 4.0;
@@ -1509,7 +1509,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
 				MACOSX_DEPLOYMENT_TARGET = 10.13;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				PRODUCT_NAME = "";
@@ -1517,7 +1517,7 @@
 				SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
 				SWIFT_VERSION = 5.0;
 				TARGETED_DEVICE_FAMILY = "1,2,3";
-				TVOS_DEPLOYMENT_TARGET = 11.0;
+				TVOS_DEPLOYMENT_TARGET = 12.0;
 				VALIDATE_PRODUCT = YES;
 				VERSIONING_SYSTEM = "apple-generic";
 				VERSION_INFO_PREFIX = "";
@@ -1538,7 +1538,7 @@
 				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
-				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				MARKETING_VERSION = 0.14.0;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
@@ -1562,7 +1562,7 @@
 				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
-				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				MARKETING_VERSION = 0.14.0;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
@@ -1577,7 +1577,7 @@
 			buildSettings = {
 				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
-				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1590,7 +1590,7 @@
 			buildSettings = {
 				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				INFOPLIST_FILE = Tests/SQLiteTests/Info.plist;
-				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLiteTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";

From c4ec236be4b089984c8239869309bd4c637642b6 Mon Sep 17 00:00:00 2001
From: NathanFallet <contact@nathanfallet.me>
Date: Sat, 13 Apr 2024 15:17:15 +0200
Subject: [PATCH 632/685] using temp cocoapods (fix xcode 15 build, to be
 reverted later)

---
 run-tests.sh | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/run-tests.sh b/run-tests.sh
index 49330c12..1bf8de96 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -7,10 +7,11 @@ if [ -n "$BUILD_SCHEME" ]; then
         make test BUILD_SCHEME="$BUILD_SCHEME"
     fi
 elif [ -n "$VALIDATOR_SUBSPEC" ]; then
+    bundle install
     if [ "$VALIDATOR_SUBSPEC" == "none" ]; then
-      pod lib lint --no-subspecs --fail-fast
+      bundle exec pod lib lint --no-subspecs --fail-fast
     else
-      pod lib lint --subspec="${VALIDATOR_SUBSPEC}" --fail-fast
+      bundle exec pod lib lint --subspec="${VALIDATOR_SUBSPEC}" --fail-fast
     fi
 elif [ -n "$CARTHAGE_PLATFORM" ]; then
     cd Tests/Carthage && make test CARTHAGE_PLATFORM="$CARTHAGE_PLATFORM"

From a6e7697bac187dd6ee5ee8026e7fca91235e5b73 Mon Sep 17 00:00:00 2001
From: NathanFallet <contact@nathanfallet.me>
Date: Sat, 13 Apr 2024 15:31:08 +0200
Subject: [PATCH 633/685] fixing bundle versions?

---
 Gemfile.lock | 2 +-
 run-tests.sh | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Gemfile.lock b/Gemfile.lock
index 75374a30..159cbf9c 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -82,7 +82,7 @@ GEM
     i18n (1.14.4)
       concurrent-ruby (~> 1.0)
     json (2.7.1)
-    minitest (5.22.0)
+    minitest (5.22.3)
     molinillo (0.8.0)
     mutex_m (0.2.0)
     nanaimo (0.3.0)
diff --git a/run-tests.sh b/run-tests.sh
index 1bf8de96..13975f0e 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -7,7 +7,7 @@ if [ -n "$BUILD_SCHEME" ]; then
         make test BUILD_SCHEME="$BUILD_SCHEME"
     fi
 elif [ -n "$VALIDATOR_SUBSPEC" ]; then
-    bundle install
+    bundle install --deployment
     if [ "$VALIDATOR_SUBSPEC" == "none" ]; then
       bundle exec pod lib lint --no-subspecs --fail-fast
     else

From 9bed2450cbd38352a5a3316b2817bec8baf4f5d3 Mon Sep 17 00:00:00 2001
From: NathanFallet <contact@nathanfallet.me>
Date: Sat, 13 Apr 2024 15:38:17 +0200
Subject: [PATCH 634/685] adding source for gems as otherwise it does not
 resolve correctly in CI

---
 Gemfile      |  2 ++
 Gemfile.lock | 11 +++++------
 run-tests.sh |  2 +-
 3 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/Gemfile b/Gemfile
index 2f97c391..eb6036cd 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1 +1,3 @@
+source "https://rubygems.org"
+
 gem 'cocoapods', :git => 'https://github.com/SagarSDagdu/CocoaPods.git', tag: '1.15.2.1-sagard'
diff --git a/Gemfile.lock b/Gemfile.lock
index 159cbf9c..a58783ea 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -23,6 +23,7 @@ GIT
       xcodeproj (>= 1.23.0, < 2.0)
 
 GEM
+  remote: https://rubygems.org/
   specs:
     CFPropertyList (3.0.7)
       base64
@@ -45,7 +46,7 @@ GEM
       json (>= 1.5.1)
     atomos (0.1.3)
     base64 (0.2.0)
-    bigdecimal (3.1.5)
+    bigdecimal (3.1.7)
     claide (1.1.0)
     cocoapods-core (1.15.2)
       activesupport (>= 5.0, < 8)
@@ -69,8 +70,7 @@ GEM
     colored2 (3.1.2)
     concurrent-ruby (1.2.3)
     connection_pool (2.4.1)
-    drb (2.2.0)
-      ruby2_keywords
+    drb (2.2.1)
     escape (0.0.4)
     ethon (0.16.0)
       ffi (>= 1.15.0)
@@ -81,18 +81,17 @@ GEM
     httpclient (2.8.3)
     i18n (1.14.4)
       concurrent-ruby (~> 1.0)
-    json (2.7.1)
+    json (2.7.2)
     minitest (5.22.3)
     molinillo (0.8.0)
     mutex_m (0.2.0)
     nanaimo (0.3.0)
     nap (1.1.0)
     netrc (0.11.0)
-    nkf (0.1.3)
+    nkf (0.2.0)
     public_suffix (4.0.7)
     rexml (3.2.6)
     ruby-macho (2.5.1)
-    ruby2_keywords (0.0.5)
     typhoeus (1.4.1)
       ethon (>= 0.9.0)
     tzinfo (2.0.6)
diff --git a/run-tests.sh b/run-tests.sh
index 13975f0e..1bf8de96 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -7,7 +7,7 @@ if [ -n "$BUILD_SCHEME" ]; then
         make test BUILD_SCHEME="$BUILD_SCHEME"
     fi
 elif [ -n "$VALIDATOR_SUBSPEC" ]; then
-    bundle install --deployment
+    bundle install
     if [ "$VALIDATOR_SUBSPEC" == "none" ]; then
       bundle exec pod lib lint --no-subspecs --fail-fast
     else

From 6be8ca943138e3b3d77bb14b74c1b498d75b0cf4 Mon Sep 17 00:00:00 2001
From: NathanFallet <contact@nathanfallet.me>
Date: Sat, 13 Apr 2024 16:30:09 +0200
Subject: [PATCH 635/685] fix carthage location?

---
 Tests/Carthage/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Tests/Carthage/Makefile b/Tests/Carthage/Makefile
index b44d85b9..fe708ab0 100644
--- a/Tests/Carthage/Makefile
+++ b/Tests/Carthage/Makefile
@@ -1,4 +1,4 @@
-CARTHAGE := /usr/local/bin/carthage
+CARTHAGE := $(shell which carthage)
 CARTHAGE_PLATFORM := iOS
 CARTHAGE_CONFIGURATION := Release
 CARTHAGE_DIR := Carthage

From a2a550e6266e80ebe4d896d1360cff4ef9ad202a Mon Sep 17 00:00:00 2001
From: NathanFallet <contact@nathanfallet.me>
Date: Sat, 13 Apr 2024 17:18:49 +0200
Subject: [PATCH 636/685] bump xcode version + carthage visionOS tests

---
 .github/workflows/build.yml | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 7be89270..9fbba1c5 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -13,7 +13,7 @@ jobs:
       # https://github.com/CocoaPods/CocoaPods/issues/11839
       run: |
         xcode-select -p
-        sudo xcode-select -s /Applications/Xcode_15.0.1.app/Contents/Developer
+        sudo xcode-select -s /Applications/Xcode_15.3.app/Contents/Developer
     - name: "Lint"
       run: make lint
     - name: "Run tests (PACKAGE_MANAGER_COMMAND: test)"
@@ -64,6 +64,10 @@ jobs:
       env:
         CARTHAGE_PLATFORM: tvOS
       run: ./run-tests.sh
+    - name: "Run tests (CARTHAGE_PLATFORM: visionOS)"
+      env:
+        CARTHAGE_PLATFORM: visionOS
+      run: ./run-tests.sh
   build-linux:
     runs-on: ubuntu-latest
     steps:

From f0af5e0a2b6917ae38e3019e3456fd0fa9365864 Mon Sep 17 00:00:00 2001
From: NathanFallet <contact@nathanfallet.me>
Date: Sat, 13 Apr 2024 18:55:58 +0200
Subject: [PATCH 637/685] Changelogs v0.15.1

---
 CHANGELOG.md            | 13 +++++++++++++
 Documentation/Index.md  | 12 ++++++------
 README.md               |  4 ++--
 SQLite.swift.podspec    |  2 +-
 Tests/SPM/Package.swift |  2 +-
 5 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4c5c1fba..79085ce3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,11 @@
+0.15.1 (14-04-2024), [diff][diff-0.15.1]
+========================================
+
+* Update CoreFunctions.swift fix typo ([#1249][])
+* Fix #1247 support nil case when decoding optionals ([#1248][])
+* Change deployment targets for Xcode 15 and add dependency on custom Cocoapods fork ([#1255][])
+* Add VisionOS support ([#1237][])
+
 0.15.0 (24-02-2024), [diff][diff-0.15.0]
 ========================================
 
@@ -155,6 +163,7 @@ For breaking changes, see [Upgrading.md](Documentation/Upgrading.md).
 [diff-0.14.0]: https://github.com/stephencelis/SQLite.swift/compare/0.13.3...0.14.0
 [diff-0.14.1]: https://github.com/stephencelis/SQLite.swift/compare/0.14.0...0.14.1
 [diff-0.15.0]: https://github.com/stephencelis/SQLite.swift/compare/0.14.0...0.15.0
+[diff-0.15.1]: https://github.com/stephencelis/SQLite.swift/compare/0.15.0...0.15.1
 
 [#30]: https://github.com/stephencelis/SQLite.swift/issues/30
 [#142]: https://github.com/stephencelis/SQLite.swift/issues/142
@@ -235,3 +244,7 @@ For breaking changes, see [Upgrading.md](Documentation/Upgrading.md).
 [#1218]: https://github.com/stephencelis/SQLite.swift/pull/1218
 [#1210]: https://github.com/stephencelis/SQLite.swift/pull/1210
 [#1245]: https://github.com/stephencelis/SQLite.swift/pull/1245
+[#1249]: https://github.com/stephencelis/SQLite.swift/pull/1249
+[#1248]: https://github.com/stephencelis/SQLite.swift/pull/1248
+[#1255]: https://github.com/stephencelis/SQLite.swift/pull/1255
+[#1237]: https://github.com/stephencelis/SQLite.swift/pull/1237
diff --git a/Documentation/Index.md b/Documentation/Index.md
index 7f900bc5..edb9dab3 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -108,7 +108,7 @@ process of downloading, compiling, and linking dependencies.
 
   ```swift
   dependencies: [
-    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.0")
+    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.1")
   ]
   ```
 
@@ -129,7 +129,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.15.0
+    github "stephencelis/SQLite.swift" ~> 0.15.1
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -159,7 +159,7 @@ install SQLite.swift with Carthage:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.15.0'
+        pod 'SQLite.swift', '~> 0.15.1'
     end
     ```
 
@@ -173,7 +173,7 @@ with the OS you can require the `standalone` subspec:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.15.0'
+  pod 'SQLite.swift/standalone', '~> 0.15.1'
 end
 ```
 
@@ -183,7 +183,7 @@ dependency to sqlite3 or one of its subspecs:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.15.0'
+  pod 'SQLite.swift/standalone', '~> 0.15.1'
   pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
 end
 ```
@@ -199,7 +199,7 @@ If you want to use [SQLCipher][] with SQLite.swift you can require the
 target 'YourAppTargetName' do
   # Make sure you only require the subspec, otherwise you app might link against
   # the system SQLite, which means the SQLCipher-specific methods won't work.
-  pod 'SQLite.swift/SQLCipher', '~> 0.15.0'
+  pod 'SQLite.swift/SQLCipher', '~> 0.15.1'
 end
 ```
 
diff --git a/README.md b/README.md
index 117edb5a..51090e5d 100644
--- a/README.md
+++ b/README.md
@@ -128,7 +128,7 @@ Swift code.
 
   ```swift
   dependencies: [
-      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.0")
+      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.1")
   ]
   ```
 
@@ -152,7 +152,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.15.0
+    github "stephencelis/SQLite.swift" ~> 0.15.1
     ```
 
  3. Run `carthage update` and
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 860fe3d4..035fffb0 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.15.0"
+  s.version          = "0.15.1"
   s.summary          = "A type-safe, Swift-language layer over SQLite3."
 
   s.description      = <<-DESC
diff --git a/Tests/SPM/Package.swift b/Tests/SPM/Package.swift
index c82b3b9e..5a96daff 100644
--- a/Tests/SPM/Package.swift
+++ b/Tests/SPM/Package.swift
@@ -15,7 +15,7 @@ let package = Package(
         // for testing from same repository
         .package(path: "../..")
         // normally this would be:
-        // .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.0")
+        // .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.1")
     ],
     targets: [
         .executableTarget(name: "test", dependencies: [.product(name: "SQLite", package: "SQLite.swift")])

From fc236997c8e1b21be4ecaaa547496857483dcf6b Mon Sep 17 00:00:00 2001
From: NathanFallet <contact@nathanfallet.me>
Date: Tue, 16 Apr 2024 05:40:47 +0200
Subject: [PATCH 638/685] fix: visionos to cocoapods

---
 CHANGELOG.md            |  6 ++++++
 Documentation/Index.md  | 12 ++++++------
 README.md               |  4 ++--
 SQLite.swift.podspec    |  7 ++++++-
 Tests/SPM/Package.swift |  2 +-
 5 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 79085ce3..376c19d8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+0.15.2 (16-04-2024), [diff][diff-0.15.2]
+========================================
+* fix: visionos to cocoapods ([#1260][])
+
 0.15.1 (14-04-2024), [diff][diff-0.15.1]
 ========================================
 
@@ -164,6 +168,7 @@ For breaking changes, see [Upgrading.md](Documentation/Upgrading.md).
 [diff-0.14.1]: https://github.com/stephencelis/SQLite.swift/compare/0.14.0...0.14.1
 [diff-0.15.0]: https://github.com/stephencelis/SQLite.swift/compare/0.14.0...0.15.0
 [diff-0.15.1]: https://github.com/stephencelis/SQLite.swift/compare/0.15.0...0.15.1
+[diff-0.15.2]: https://github.com/stephencelis/SQLite.swift/compare/0.15.1...0.15.2
 
 [#30]: https://github.com/stephencelis/SQLite.swift/issues/30
 [#142]: https://github.com/stephencelis/SQLite.swift/issues/142
@@ -248,3 +253,4 @@ For breaking changes, see [Upgrading.md](Documentation/Upgrading.md).
 [#1248]: https://github.com/stephencelis/SQLite.swift/pull/1248
 [#1255]: https://github.com/stephencelis/SQLite.swift/pull/1255
 [#1237]: https://github.com/stephencelis/SQLite.swift/pull/1237
+[#1260]: https://github.com/stephencelis/SQLite.swift/pull/1260
diff --git a/Documentation/Index.md b/Documentation/Index.md
index edb9dab3..adbbff8b 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -108,7 +108,7 @@ process of downloading, compiling, and linking dependencies.
 
   ```swift
   dependencies: [
-    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.1")
+    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.2")
   ]
   ```
 
@@ -129,7 +129,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.15.1
+    github "stephencelis/SQLite.swift" ~> 0.15.2
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -159,7 +159,7 @@ install SQLite.swift with Carthage:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.15.1'
+        pod 'SQLite.swift', '~> 0.15.2'
     end
     ```
 
@@ -173,7 +173,7 @@ with the OS you can require the `standalone` subspec:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.15.1'
+  pod 'SQLite.swift/standalone', '~> 0.15.2'
 end
 ```
 
@@ -183,7 +183,7 @@ dependency to sqlite3 or one of its subspecs:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.15.1'
+  pod 'SQLite.swift/standalone', '~> 0.15.2'
   pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
 end
 ```
@@ -199,7 +199,7 @@ If you want to use [SQLCipher][] with SQLite.swift you can require the
 target 'YourAppTargetName' do
   # Make sure you only require the subspec, otherwise you app might link against
   # the system SQLite, which means the SQLCipher-specific methods won't work.
-  pod 'SQLite.swift/SQLCipher', '~> 0.15.1'
+  pod 'SQLite.swift/SQLCipher', '~> 0.15.2'
 end
 ```
 
diff --git a/README.md b/README.md
index 51090e5d..a87ab937 100644
--- a/README.md
+++ b/README.md
@@ -128,7 +128,7 @@ Swift code.
 
   ```swift
   dependencies: [
-      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.1")
+      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.2")
   ]
   ```
 
@@ -152,7 +152,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.15.1
+    github "stephencelis/SQLite.swift" ~> 0.15.2
     ```
 
  3. Run `carthage update` and
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 035fffb0..efed67c1 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.15.1"
+  s.version          = "0.15.2"
   s.summary          = "A type-safe, Swift-language layer over SQLite3."
 
   s.description      = <<-DESC
@@ -22,11 +22,13 @@ Pod::Spec.new do |s|
   tvos_deployment_target = '12.0'
   osx_deployment_target = '10.13'
   watchos_deployment_target = '4.0'
+  visionos_deployment_target = '1.0'
 
   s.ios.deployment_target = ios_deployment_target
   s.tvos.deployment_target = tvos_deployment_target
   s.osx.deployment_target = osx_deployment_target
   s.watchos.deployment_target = watchos_deployment_target
+  s.visionos.deployment_target = visionos_deployment_target
 
   s.subspec 'standard' do |ss|
     ss.source_files = 'Sources/SQLite/**/*.{c,h,m,swift}'
@@ -37,6 +39,7 @@ Pod::Spec.new do |s|
     ss.tvos.deployment_target = tvos_deployment_target
     ss.osx.deployment_target = osx_deployment_target
     ss.watchos.deployment_target = watchos_deployment_target
+    ss.visionos.deployment_target = visionos_deployment_target
 
     ss.test_spec 'tests' do |test_spec|
       test_spec.resources = 'Tests/SQLiteTests/Resources/*'
@@ -61,6 +64,7 @@ Pod::Spec.new do |s|
     ss.tvos.deployment_target = tvos_deployment_target
     ss.osx.deployment_target = osx_deployment_target
     ss.watchos.deployment_target = watchos_deployment_target
+    ss.visionos.deployment_target = visionos_deployment_target
 
     ss.test_spec 'tests' do |test_spec|
       test_spec.resources = 'Tests/SQLiteTests/Resources/*'
@@ -83,6 +87,7 @@ Pod::Spec.new do |s|
     ss.tvos.deployment_target = tvos_deployment_target
     ss.osx.deployment_target = osx_deployment_target
     ss.watchos.deployment_target = watchos_deployment_target
+    ss.visionos.deployment_target = visionos_deployment_target
 
     ss.test_spec 'tests' do |test_spec|
       test_spec.resources = 'Tests/SQLiteTests/Resources/*'
diff --git a/Tests/SPM/Package.swift b/Tests/SPM/Package.swift
index 5a96daff..b73ecd83 100644
--- a/Tests/SPM/Package.swift
+++ b/Tests/SPM/Package.swift
@@ -15,7 +15,7 @@ let package = Package(
         // for testing from same repository
         .package(path: "../..")
         // normally this would be:
-        // .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.1")
+        // .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.2")
     ],
     targets: [
         .executableTarget(name: "test", dependencies: [.product(name: "SQLite", package: "SQLite.swift")])

From 8f75f4609221c55901cf60b1438b7a8441af145e Mon Sep 17 00:00:00 2001
From: NathanFallet <contact@nathanfallet.me>
Date: Tue, 16 Apr 2024 06:06:25 +0200
Subject: [PATCH 639/685] gonna fix that later

---
 SQLite.swift.podspec | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index efed67c1..88713c9e 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -87,7 +87,7 @@ Pod::Spec.new do |s|
     ss.tvos.deployment_target = tvos_deployment_target
     ss.osx.deployment_target = osx_deployment_target
     ss.watchos.deployment_target = watchos_deployment_target
-    ss.visionos.deployment_target = visionos_deployment_target
+    #ss.visionos.deployment_target = visionos_deployment_target # Not supported by SQLCipher for now
 
     ss.test_spec 'tests' do |test_spec|
       test_spec.resources = 'Tests/SQLiteTests/Resources/*'

From 15fe07e3d5d0555a7f03966114ce5a9390823af7 Mon Sep 17 00:00:00 2001
From: Sagar Dagdu <shags032@gmail.com>
Date: Thu, 18 Apr 2024 18:57:43 +0530
Subject: [PATCH 640/685] Update the marketing version to the version we will
 be releasing next

For recent releases, the `Info.plist` shipped inside the `xcframeworks` do not match the release version. Fixing that to reflect the marketing version we will be releasing next.
---
 SQLite.xcodeproj/project.pbxproj | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index 79de22e7..a2d7edbe 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -218,6 +218,9 @@
 		DB7C5DA728D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
 		DB7C5DA828D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
 		DB7C5DA928D7C9B6006395CF /* SQLiteVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */; };
+		DBB93D5A2A22A373009BB96E /* SchemaReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB93D592A22A373009BB96E /* SchemaReaderTests.swift */; };
+		DBB93D5B2A22A373009BB96E /* SchemaReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB93D592A22A373009BB96E /* SchemaReaderTests.swift */; };
+		DBB93D5C2A22A373009BB96E /* SchemaReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB93D592A22A373009BB96E /* SchemaReaderTests.swift */; };
 		DEB306BA2B61CEF500F9D46B /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = EE247AD61C3F04ED00AE3E12 /* SQLite.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		DEB306BC2B61CEF500F9D46B /* CoreFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE247AFC1C3F06E900AE3E12 /* CoreFunctions.swift */; };
 		DEB306BD2B61CEF500F9D46B /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EB68C31F7B3CB400D89D40 /* Coding.swift */; };
@@ -288,9 +291,6 @@
 		DEB307092B61CF9500F9D46B /* Connection+AttachTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A170C08525D3D27CB5F83C /* Connection+AttachTests.swift */; };
 		DEB3070B2B61CF9500F9D46B /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03A65E5A1C6BB0F50062603F /* SQLite.framework */; };
 		DEB3070D2B61CF9500F9D46B /* Resources in Resources */ = {isa = PBXBuildFile; fileRef = 3DF7B79528846FCC005DD8CA /* Resources */; };
-		DBB93D5A2A22A373009BB96E /* SchemaReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB93D592A22A373009BB96E /* SchemaReaderTests.swift */; };
-		DBB93D5B2A22A373009BB96E /* SchemaReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB93D592A22A373009BB96E /* SchemaReaderTests.swift */; };
-		DBB93D5C2A22A373009BB96E /* SchemaReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB93D592A22A373009BB96E /* SchemaReaderTests.swift */; };
 		EAE5A0372B893C43007C7EA4 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EAE5A0362B893C43007C7EA4 /* PrivacyInfo.xcprivacy */; };
 		EAE5A0382B893C43007C7EA4 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EAE5A0362B893C43007C7EA4 /* PrivacyInfo.xcprivacy */; };
 		EAE5A0392B893C43007C7EA4 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EAE5A0362B893C43007C7EA4 /* PrivacyInfo.xcprivacy */; };
@@ -433,10 +433,10 @@
 		DB58B21028FB864300F8EEA4 /* SchemaReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaReader.swift; sourceTree = "<group>"; };
 		DB58B21528FC7C4600F8EEA4 /* SQLiteFeature.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SQLiteFeature.swift; sourceTree = "<group>"; };
 		DB7C5DA528D7C9B6006395CF /* SQLiteVersion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SQLiteVersion.swift; sourceTree = "<group>"; };
+		DBB93D592A22A373009BB96E /* SchemaReaderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaReaderTests.swift; sourceTree = "<group>"; };
 		DEB306E52B61CEF500F9D46B /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		DEB307112B61CF9500F9D46B /* SQLiteTests visionOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SQLiteTests visionOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
 		DEB307132B61D04500F9D46B /* SQLite visionOS.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; name = "SQLite visionOS.xctestplan"; path = "Tests/SQLite visionOS.xctestplan"; sourceTree = "<group>"; };
-		DBB93D592A22A373009BB96E /* SchemaReaderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaReaderTests.swift; sourceTree = "<group>"; };
 		EAE5A0362B893C43007C7EA4 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
 		EE247AD31C3F04ED00AE3E12 /* SQLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		EE247AD61C3F04ED00AE3E12 /* SQLite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLite.h; sourceTree = "<group>"; };
@@ -1539,6 +1539,7 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				MARKETING_VERSION = 0.15.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SDKROOT = appletvos;
@@ -1561,6 +1562,7 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				MARKETING_VERSION = 0.15.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SDKROOT = appletvos;
@@ -1612,6 +1614,7 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				MARKETING_VERSION = 0.15.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SDKROOT = watchos;
@@ -1636,6 +1639,7 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				MARKETING_VERSION = 0.15.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SDKROOT = watchos;
@@ -1660,7 +1664,7 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
-				MARKETING_VERSION = 0.14.0;
+				MARKETING_VERSION = 0.15.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SDKROOT = xros;
@@ -1685,7 +1689,7 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
-				MARKETING_VERSION = 0.14.0;
+				MARKETING_VERSION = 0.15.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SDKROOT = xros;
@@ -1862,7 +1866,7 @@
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
-				MARKETING_VERSION = 0.14.0;
+				MARKETING_VERSION = 0.15.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
@@ -1886,7 +1890,7 @@
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
-				MARKETING_VERSION = 0.14.0;
+				MARKETING_VERSION = 0.15.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
@@ -1936,6 +1940,7 @@
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
 				MACOSX_DEPLOYMENT_TARGET = 10.13;
+				MARKETING_VERSION = 0.15.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SDKROOT = macosx;
@@ -1961,6 +1966,7 @@
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
 				MACOSX_DEPLOYMENT_TARGET = 10.13;
+				MARKETING_VERSION = 0.15.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SDKROOT = macosx;

From 5d3db22d9b1e979a3436d199f10bc7dddd4d3a39 Mon Sep 17 00:00:00 2001
From: Sagar Dagdu <shags032@gmail.com>
Date: Thu, 18 Apr 2024 21:26:22 +0530
Subject: [PATCH 641/685] Update `podspec` to include privacy manifest

Update `podspec` to include privacy manifest
---
 SQLite.swift.podspec | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 88713c9e..e6aa2c6a 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -34,6 +34,7 @@ Pod::Spec.new do |s|
     ss.source_files = 'Sources/SQLite/**/*.{c,h,m,swift}'
     ss.exclude_files = 'Sources/**/Cipher.swift'
     ss.library = 'sqlite3'
+    ss.resource_bundle = { 'SQLite.swift' => 'Sources/SQLite/PrivacyInfo.xcprivacy' }
     
     ss.ios.deployment_target = ios_deployment_target
     ss.tvos.deployment_target = tvos_deployment_target
@@ -53,6 +54,7 @@ Pod::Spec.new do |s|
   s.subspec 'standalone' do |ss|
     ss.source_files = 'Sources/SQLite/**/*.{c,h,m,swift}'
     ss.exclude_files = 'Sources/**/Cipher.swift'
+    ss.resource_bundle = { 'SQLite.swift' => 'Sources/SQLite/PrivacyInfo.xcprivacy' }
 
     ss.xcconfig = {
       'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_SWIFT_STANDALONE',
@@ -77,6 +79,8 @@ Pod::Spec.new do |s|
 
   s.subspec 'SQLCipher' do |ss|
     ss.source_files = 'Sources/SQLite/**/*.{c,h,m,swift}'
+    ss.resource_bundle = { 'SQLite.swift' => 'Sources/SQLite/PrivacyInfo.xcprivacy' }
+
     ss.xcconfig = {
       'OTHER_SWIFT_FLAGS' => '$(inherited) -DSQLITE_SWIFT_SQLCIPHER',
       'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SQLITE_HAS_CODEC=1 SQLITE_SWIFT_SQLCIPHER=1'

From a95fc6df17d108bd99210db5e8a9bac90fe984b8 Mon Sep 17 00:00:00 2001
From: NathanFallet <contact@nathanfallet.me>
Date: Fri, 19 Apr 2024 02:50:43 +0200
Subject: [PATCH 642/685] v0.15.3 (oups)

---
 CHANGELOG.md            |  5 +++++
 Documentation/Index.md  | 12 ++++++------
 README.md               |  4 ++--
 SQLite.swift.podspec    |  2 +-
 Tests/SPM/Package.swift |  2 +-
 5 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 376c19d8..c96724fd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+0.15.3 (19-04-2024), [diff][diff-0.15.3]
+========================================
+* Update `podspec` to include privacy manifest ([#1265][])
+
 0.15.2 (16-04-2024), [diff][diff-0.15.2]
 ========================================
 * fix: visionos to cocoapods ([#1260][])
@@ -254,3 +258,4 @@ For breaking changes, see [Upgrading.md](Documentation/Upgrading.md).
 [#1255]: https://github.com/stephencelis/SQLite.swift/pull/1255
 [#1237]: https://github.com/stephencelis/SQLite.swift/pull/1237
 [#1260]: https://github.com/stephencelis/SQLite.swift/pull/1260
+[#1265]: https://github.com/stephencelis/SQLite.swift/pull/1265
diff --git a/Documentation/Index.md b/Documentation/Index.md
index adbbff8b..fcd2d642 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -108,7 +108,7 @@ process of downloading, compiling, and linking dependencies.
 
   ```swift
   dependencies: [
-    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.2")
+    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.3")
   ]
   ```
 
@@ -129,7 +129,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.15.2
+    github "stephencelis/SQLite.swift" ~> 0.15.3
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -159,7 +159,7 @@ install SQLite.swift with Carthage:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.15.2'
+        pod 'SQLite.swift', '~> 0.15.3'
     end
     ```
 
@@ -173,7 +173,7 @@ with the OS you can require the `standalone` subspec:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.15.2'
+  pod 'SQLite.swift/standalone', '~> 0.15.3'
 end
 ```
 
@@ -183,7 +183,7 @@ dependency to sqlite3 or one of its subspecs:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.15.2'
+  pod 'SQLite.swift/standalone', '~> 0.15.3'
   pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
 end
 ```
@@ -199,7 +199,7 @@ If you want to use [SQLCipher][] with SQLite.swift you can require the
 target 'YourAppTargetName' do
   # Make sure you only require the subspec, otherwise you app might link against
   # the system SQLite, which means the SQLCipher-specific methods won't work.
-  pod 'SQLite.swift/SQLCipher', '~> 0.15.2'
+  pod 'SQLite.swift/SQLCipher', '~> 0.15.3'
 end
 ```
 
diff --git a/README.md b/README.md
index a87ab937..a4d713b6 100644
--- a/README.md
+++ b/README.md
@@ -128,7 +128,7 @@ Swift code.
 
   ```swift
   dependencies: [
-      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.2")
+      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.3")
   ]
   ```
 
@@ -152,7 +152,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.15.2
+    github "stephencelis/SQLite.swift" ~> 0.15.3
     ```
 
  3. Run `carthage update` and
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index e6aa2c6a..184ce23e 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.15.2"
+  s.version          = "0.15.3"
   s.summary          = "A type-safe, Swift-language layer over SQLite3."
 
   s.description      = <<-DESC
diff --git a/Tests/SPM/Package.swift b/Tests/SPM/Package.swift
index b73ecd83..6521211a 100644
--- a/Tests/SPM/Package.swift
+++ b/Tests/SPM/Package.swift
@@ -15,7 +15,7 @@ let package = Package(
         // for testing from same repository
         .package(path: "../..")
         // normally this would be:
-        // .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.2")
+        // .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.3")
     ],
     targets: [
         .executableTarget(name: "test", dependencies: [.product(name: "SQLite", package: "SQLite.swift")])

From 363141ac6c070799239593cf6dcad63fe33edd17 Mon Sep 17 00:00:00 2001
From: YiKai Deng <dyikai@gmail.com>
Date: Thu, 26 Sep 2024 17:33:15 +0800
Subject: [PATCH 643/685] Add `CustomStringConvertible` for Setter

---
 Documentation/Upgrading.md                    |  4 +-
 Sources/SQLite/Typed/Setter.swift             |  6 ++
 .../Core/Connection+AttachTests.swift         |  4 +-
 .../SQLiteTests/Core/CoreFunctionsTests.swift | 16 ++---
 Tests/SQLiteTests/Core/StatementTests.swift   |  4 +-
 Tests/SQLiteTests/Extensions/FTS4Tests.swift  |  6 +-
 .../Extensions/FTSIntegrationTests.swift      |  2 +-
 .../Schema/SchemaChangerTests.swift           |  2 +-
 .../Schema/SchemaReaderTests.swift            |  4 +-
 Tests/SQLiteTests/TestHelpers.swift           | 32 ++++-----
 .../Typed/CustomFunctionsTests.swift          | 28 ++++----
 Tests/SQLiteTests/Typed/ExpressionTests.swift | 10 +--
 Tests/SQLiteTests/Typed/OperatorsTests.swift  |  2 +-
 .../Typed/QueryIntegrationTests.swift         | 70 +++++++++----------
 Tests/SQLiteTests/Typed/QueryTests.swift      | 22 +++---
 Tests/SQLiteTests/Typed/RowTests.swift        | 22 +++---
 Tests/SQLiteTests/Typed/SelectTests.swift     |  8 +--
 Tests/SQLiteTests/Typed/SetterTests.swift     |  3 +
 .../Typed/WindowFunctionsTests.swift          |  4 +-
 19 files changed, 130 insertions(+), 119 deletions(-)

diff --git a/Documentation/Upgrading.md b/Documentation/Upgrading.md
index f2cc2ecb..0e12aacf 100644
--- a/Documentation/Upgrading.md
+++ b/Documentation/Upgrading.md
@@ -4,6 +4,8 @@
 
 - `Expression.asSQL()` is no longer available. Expressions now implement `CustomStringConvertible`,
   where `description` returns the SQL.
-- `Statement.prepareRowIterator()` is now longer available. Instead, use the methods
+- `Statement.prepareRowIterator()` is no longer available. Instead, use the methods
   of the same name on `Connection`.
 - `Connection.registerTokenizer` is no longer available to register custom FTS4 tokenizers.
+- `Setter.asSQL()` is no longer available. Instead, Setter now implement `CustomStringConvertible`,
+  where `description` returns the SQL.
diff --git a/Sources/SQLite/Typed/Setter.swift b/Sources/SQLite/Typed/Setter.swift
index 7910cab8..8dc8a0e0 100644
--- a/Sources/SQLite/Typed/Setter.swift
+++ b/Sources/SQLite/Typed/Setter.swift
@@ -75,6 +75,12 @@ extension Setter: Expressible {
 
 }
 
+extension Setter: CustomStringConvertible {
+    public var description: String {
+        asSQL()
+    }
+}
+
 public func <-<V: Value>(column: Expression<V>, value: Expression<V>) -> Setter {
     Setter(column: column, value: value)
 }
diff --git a/Tests/SQLiteTests/Core/Connection+AttachTests.swift b/Tests/SQLiteTests/Core/Connection+AttachTests.swift
index 940a30ca..f37300ca 100644
--- a/Tests/SQLiteTests/Core/Connection+AttachTests.swift
+++ b/Tests/SQLiteTests/Core/Connection+AttachTests.swift
@@ -19,7 +19,7 @@ class ConnectionAttachTests: SQLiteTestCase {
         try db.attach(.inMemory, as: schemaName)
 
         let table = Table("attached_users", database: schemaName)
-        let name = Expression<String>("string")
+        let name = SQLite.Expression<String>("string")
 
         // create a table, insert some data
         try db.run(table.create { builder in
@@ -41,7 +41,7 @@ class ConnectionAttachTests: SQLiteTestCase {
         try db.attach(.uri(testDb, parameters: [.mode(.readOnly)]), as: schemaName)
 
         let table = Table("tests", database: schemaName)
-        let email = Expression<String>("email")
+        let email = SQLite.Expression<String>("email")
 
         let rows = try db.prepare(table.select(email)).map { $0[email] }
         XCTAssertEqual(["foo@bar.com"], rows)
diff --git a/Tests/SQLiteTests/Core/CoreFunctionsTests.swift b/Tests/SQLiteTests/Core/CoreFunctionsTests.swift
index e03e3769..b866c4e9 100644
--- a/Tests/SQLiteTests/Core/CoreFunctionsTests.swift
+++ b/Tests/SQLiteTests/Core/CoreFunctionsTests.swift
@@ -12,8 +12,8 @@ class CoreFunctionsTests: XCTestCase {
     }
 
     func test_random_generatesExpressionWithRandomFunction() {
-        assertSQL("random()", Expression<Int64>.random())
-        assertSQL("random()", Expression<Int>.random())
+        assertSQL("random()", SQLite.Expression<Int64>.random())
+        assertSQL("random()", SQLite.Expression<Int>.random())
     }
 
     func test_length_wrapsStringExpressionWithLengthFunction() {
@@ -38,14 +38,14 @@ class CoreFunctionsTests: XCTestCase {
         assertSQL("(\"string\" LIKE '%\\%' ESCAPE '\\')", string.like("%\\%", escape: "\\"))
         assertSQL("(\"stringOptional\" LIKE '_\\_' ESCAPE '\\')", stringOptional.like("_\\_", escape: "\\"))
 
-        assertSQL("(\"string\" LIKE \"a\")", string.like(Expression<String>("a")))
-        assertSQL("(\"stringOptional\" LIKE \"a\")", stringOptional.like(Expression<String>("a")))
+        assertSQL("(\"string\" LIKE \"a\")", string.like(SQLite.Expression<String>("a")))
+        assertSQL("(\"stringOptional\" LIKE \"a\")", stringOptional.like(SQLite.Expression<String>("a")))
 
-        assertSQL("(\"string\" LIKE \"a\" ESCAPE '\\')", string.like(Expression<String>("a"), escape: "\\"))
-        assertSQL("(\"stringOptional\" LIKE \"a\" ESCAPE '\\')", stringOptional.like(Expression<String>("a"), escape: "\\"))
+        assertSQL("(\"string\" LIKE \"a\" ESCAPE '\\')", string.like(SQLite.Expression<String>("a"), escape: "\\"))
+        assertSQL("(\"stringOptional\" LIKE \"a\" ESCAPE '\\')", stringOptional.like(SQLite.Expression<String>("a"), escape: "\\"))
 
-        assertSQL("('string' LIKE \"a\")", "string".like(Expression<String>("a")))
-        assertSQL("('string' LIKE \"a\" ESCAPE '\\')", "string".like(Expression<String>("a"), escape: "\\"))
+        assertSQL("('string' LIKE \"a\")", "string".like(SQLite.Expression<String>("a")))
+        assertSQL("('string' LIKE \"a\" ESCAPE '\\')", "string".like(SQLite.Expression<String>("a"), escape: "\\"))
     }
 
     func test_glob_buildsExpressionWithGlobOperator() {
diff --git a/Tests/SQLiteTests/Core/StatementTests.swift b/Tests/SQLiteTests/Core/StatementTests.swift
index 5f212505..dbf99d7c 100644
--- a/Tests/SQLiteTests/Core/StatementTests.swift
+++ b/Tests/SQLiteTests/Core/StatementTests.swift
@@ -27,7 +27,7 @@ class StatementTests: SQLiteTestCase {
 
     func test_zero_sized_blob_returns_null() throws {
         let blobs = Table("blobs")
-        let blobColumn = Expression<Blob>("blob_column")
+        let blobColumn = SQLite.Expression<Blob>("blob_column")
         try db.run(blobs.create { $0.column(blobColumn) })
         try db.run(blobs.insert(blobColumn <- Blob(bytes: [])))
         let blobValue = try db.scalar(blobs.select(blobColumn).limit(1, offset: 0))
@@ -38,7 +38,7 @@ class StatementTests: SQLiteTestCase {
         let names = ["a", "b", "c"]
         try insertUsers(names)
 
-        let emailColumn = Expression<String>("email")
+        let emailColumn = SQLite.Expression<String>("email")
         let statement = try db.prepare("SELECT email FROM users")
         let emails = try statement.prepareRowIterator().map { $0[emailColumn] }
 
diff --git a/Tests/SQLiteTests/Extensions/FTS4Tests.swift b/Tests/SQLiteTests/Extensions/FTS4Tests.swift
index 5e595007..f7258fb5 100644
--- a/Tests/SQLiteTests/Extensions/FTS4Tests.swift
+++ b/Tests/SQLiteTests/Extensions/FTS4Tests.swift
@@ -35,9 +35,9 @@ class FTS4Tests: XCTestCase {
     }
 
     func test_match_onVirtualTableAsExpression_compilesMatchExpression() {
-        assertSQL("(\"virtual_table\" MATCH 'string')", virtualTable.match("string") as Expression<Bool>)
-        assertSQL("(\"virtual_table\" MATCH \"string\")", virtualTable.match(string) as Expression<Bool>)
-        assertSQL("(\"virtual_table\" MATCH \"stringOptional\")", virtualTable.match(stringOptional) as Expression<Bool?>)
+        assertSQL("(\"virtual_table\" MATCH 'string')", virtualTable.match("string") as SQLite.Expression<Bool>)
+        assertSQL("(\"virtual_table\" MATCH \"string\")", virtualTable.match(string) as SQLite.Expression<Bool>)
+        assertSQL("(\"virtual_table\" MATCH \"stringOptional\")", virtualTable.match(stringOptional) as SQLite.Expression<Bool?>)
     }
 
     func test_match_onVirtualTableAsQueryType_compilesMatchExpression() {
diff --git a/Tests/SQLiteTests/Extensions/FTSIntegrationTests.swift b/Tests/SQLiteTests/Extensions/FTSIntegrationTests.swift
index da9ba8dc..1129ae08 100644
--- a/Tests/SQLiteTests/Extensions/FTSIntegrationTests.swift
+++ b/Tests/SQLiteTests/Extensions/FTSIntegrationTests.swift
@@ -11,7 +11,7 @@ import SQLite3
 @testable import SQLite
 
 class FTSIntegrationTests: SQLiteTestCase {
-    let email = Expression<String>("email")
+    let email = SQLite.Expression<String>("email")
     let index = VirtualTable("index")
 
     private func createIndex() throws {
diff --git a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
index 9f8e21f4..2bec6a06 100644
--- a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
@@ -92,7 +92,7 @@ class SchemaChangerTests: SQLiteTestCase {
     }
 
     func test_add_column() throws {
-        let column = Expression<String>("new_column")
+        let column = SQLite.Expression<String>("new_column")
         let newColumn = ColumnDefinition(name: "new_column",
                                          type: .TEXT,
                                          nullable: true,
diff --git a/Tests/SQLiteTests/Schema/SchemaReaderTests.swift b/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
index d57ebff7..8c033e41 100644
--- a/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
@@ -163,7 +163,7 @@ class SchemaReaderTests: SQLiteTestCase {
 
         try db.run(linkTable.create(block: { definition in
             definition.column(idColumn, primaryKey: .autoincrement)
-            definition.column(testIdColumn, unique: false, check: nil, references: users, Expression<Int64>("id"))
+            definition.column(testIdColumn, unique: false, check: nil, references: users, SQLite.Expression<Int64>("id"))
         }))
 
         let foreignKeys = try schemaReader.foreignKeys(table: "test_links")
@@ -238,7 +238,7 @@ class SchemaReaderTests: SQLiteTestCase {
     }
 
     func test_objectDefinitions_indexes() throws {
-        let emailIndex = users.createIndex(Expression<String>("email"), unique: false, ifNotExists: true)
+        let emailIndex = users.createIndex(SQLite.Expression<String>("email"), unique: false, ifNotExists: true)
         try db.run(emailIndex)
 
         let indexes = try schemaReader.objectDefinitions(type: .index)
diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index e2da5927..56415a59 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -74,29 +74,29 @@ class SQLiteTestCase: XCTestCase {
 
 }
 
-let bool = Expression<Bool>("bool")
-let boolOptional = Expression<Bool?>("boolOptional")
+let bool = SQLite.Expression<Bool>("bool")
+let boolOptional = SQLite.Expression<Bool?>("boolOptional")
 
-let data = Expression<Blob>("blob")
-let dataOptional = Expression<Blob?>("blobOptional")
+let data = SQLite.Expression<Blob>("blob")
+let dataOptional = SQLite.Expression<Blob?>("blobOptional")
 
-let date = Expression<Date>("date")
-let dateOptional = Expression<Date?>("dateOptional")
+let date = SQLite.Expression<Date>("date")
+let dateOptional = SQLite.Expression<Date?>("dateOptional")
 
-let double = Expression<Double>("double")
-let doubleOptional = Expression<Double?>("doubleOptional")
+let double = SQLite.Expression<Double>("double")
+let doubleOptional = SQLite.Expression<Double?>("doubleOptional")
 
-let int = Expression<Int>("int")
-let intOptional = Expression<Int?>("intOptional")
+let int = SQLite.Expression<Int>("int")
+let intOptional = SQLite.Expression<Int?>("intOptional")
 
-let int64 = Expression<Int64>("int64")
-let int64Optional = Expression<Int64?>("int64Optional")
+let int64 = SQLite.Expression<Int64>("int64")
+let int64Optional = SQLite.Expression<Int64?>("int64Optional")
 
-let string = Expression<String>("string")
-let stringOptional = Expression<String?>("stringOptional")
+let string = SQLite.Expression<String>("string")
+let stringOptional = SQLite.Expression<String?>("stringOptional")
 
-let uuid = Expression<UUID>("uuid")
-let uuidOptional = Expression<UUID?>("uuidOptional")
+let uuid = SQLite.Expression<UUID>("uuid")
+let uuidOptional = SQLite.Expression<UUID?>("uuidOptional")
 
 let testUUIDValue = UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!
 
diff --git a/Tests/SQLiteTests/Typed/CustomFunctionsTests.swift b/Tests/SQLiteTests/Typed/CustomFunctionsTests.swift
index 0f46b380..8598b6fb 100644
--- a/Tests/SQLiteTests/Typed/CustomFunctionsTests.swift
+++ b/Tests/SQLiteTests/Typed/CustomFunctionsTests.swift
@@ -5,8 +5,8 @@ import SQLite
 #if !os(Linux)
 
 class CustomFunctionNoArgsTests: SQLiteTestCase {
-    typealias FunctionNoOptional              = () -> Expression<String>
-    typealias FunctionResultOptional          = () -> Expression<String?>
+    typealias FunctionNoOptional              = () -> SQLite.Expression<String>
+    typealias FunctionResultOptional          = () -> SQLite.Expression<String?>
 
     func testFunctionNoOptional() throws {
         let _: FunctionNoOptional = try db.createFunction("test", deterministic: true) {
@@ -26,10 +26,10 @@ class CustomFunctionNoArgsTests: SQLiteTestCase {
 }
 
 class CustomFunctionWithOneArgTests: SQLiteTestCase {
-    typealias FunctionNoOptional              = (Expression<String>) -> Expression<String>
-    typealias FunctionLeftOptional            = (Expression<String?>) -> Expression<String>
-    typealias FunctionResultOptional          = (Expression<String>) -> Expression<String?>
-    typealias FunctionLeftResultOptional      = (Expression<String?>) -> Expression<String?>
+    typealias FunctionNoOptional              = (SQLite.Expression<String>) -> SQLite.Expression<String>
+    typealias FunctionLeftOptional            = (SQLite.Expression<String?>) -> SQLite.Expression<String>
+    typealias FunctionResultOptional          = (SQLite.Expression<String>) -> SQLite.Expression<String?>
+    typealias FunctionLeftResultOptional      = (SQLite.Expression<String?>) -> SQLite.Expression<String?>
 
     func testFunctionNoOptional() throws {
         let _: FunctionNoOptional = try db.createFunction("test", deterministic: true) { a in
@@ -65,14 +65,14 @@ class CustomFunctionWithOneArgTests: SQLiteTestCase {
 }
 
 class CustomFunctionWithTwoArgsTests: SQLiteTestCase {
-    typealias FunctionNoOptional              = (Expression<String>, Expression<String>) -> Expression<String>
-    typealias FunctionLeftOptional            = (Expression<String?>, Expression<String>) -> Expression<String>
-    typealias FunctionRightOptional           = (Expression<String>, Expression<String?>) -> Expression<String>
-    typealias FunctionResultOptional          = (Expression<String>, Expression<String>) -> Expression<String?>
-    typealias FunctionLeftRightOptional       = (Expression<String?>, Expression<String?>) -> Expression<String>
-    typealias FunctionLeftResultOptional      = (Expression<String?>, Expression<String>) -> Expression<String?>
-    typealias FunctionRightResultOptional     = (Expression<String>, Expression<String?>) -> Expression<String?>
-    typealias FunctionLeftRightResultOptional = (Expression<String?>, Expression<String?>) -> Expression<String?>
+    typealias FunctionNoOptional              = (SQLite.Expression<String>, SQLite.Expression<String>) -> SQLite.Expression<String>
+    typealias FunctionLeftOptional            = (SQLite.Expression<String?>, SQLite.Expression<String>) -> SQLite.Expression<String>
+    typealias FunctionRightOptional           = (SQLite.Expression<String>, SQLite.Expression<String?>) -> SQLite.Expression<String>
+    typealias FunctionResultOptional          = (SQLite.Expression<String>, SQLite.Expression<String>) -> SQLite.Expression<String?>
+    typealias FunctionLeftRightOptional       = (SQLite.Expression<String?>, SQLite.Expression<String?>) -> SQLite.Expression<String>
+    typealias FunctionLeftResultOptional      = (SQLite.Expression<String?>, SQLite.Expression<String>) -> SQLite.Expression<String?>
+    typealias FunctionRightResultOptional     = (SQLite.Expression<String>, SQLite.Expression<String?>) -> SQLite.Expression<String?>
+    typealias FunctionLeftRightResultOptional = (SQLite.Expression<String?>, SQLite.Expression<String?>) -> SQLite.Expression<String?>
 
     func testNoOptional() throws {
         let _: FunctionNoOptional = try db.createFunction("test", deterministic: true) { a, b in
diff --git a/Tests/SQLiteTests/Typed/ExpressionTests.swift b/Tests/SQLiteTests/Typed/ExpressionTests.swift
index 147d62e9..1b97fe94 100644
--- a/Tests/SQLiteTests/Typed/ExpressionTests.swift
+++ b/Tests/SQLiteTests/Typed/ExpressionTests.swift
@@ -4,17 +4,17 @@ import XCTest
 class ExpressionTests: XCTestCase {
 
     func test_asSQL_expression_bindings() {
-        let expression = Expression<String>("foo ? bar", ["baz"])
+        let expression = SQLite.Expression<String>("foo ? bar", ["baz"])
         XCTAssertEqual(expression.asSQL(), "foo 'baz' bar")
     }
 
     func test_asSQL_expression_bindings_quoting() {
-        let expression = Expression<String>("foo ? bar", ["'baz'"])
+        let expression = SQLite.Expression<String>("foo ? bar", ["'baz'"])
         XCTAssertEqual(expression.asSQL(), "foo '''baz''' bar")
     }
 
     func test_expression_custom_string_convertible() {
-        let expression = Expression<String>("foo ? bar", ["baz"])
+        let expression = SQLite.Expression<String>("foo ? bar", ["baz"])
         XCTAssertEqual(expression.asSQL(), expression.description)
     }
 
@@ -24,12 +24,12 @@ class ExpressionTests: XCTestCase {
     }
 
     func test_init_literal() {
-        let expression = Expression<String>(literal: "literal")
+        let expression = SQLite.Expression<String>(literal: "literal")
         XCTAssertEqual(expression.template, "literal")
     }
 
     func test_init_identifier() {
-        let expression = Expression<String>("identifier")
+        let expression = SQLite.Expression<String>("identifier")
         XCTAssertEqual(expression.template, "\"identifier\"")
     }
 }
diff --git a/Tests/SQLiteTests/Typed/OperatorsTests.swift b/Tests/SQLiteTests/Typed/OperatorsTests.swift
index 370b910b..7a5d83da 100644
--- a/Tests/SQLiteTests/Typed/OperatorsTests.swift
+++ b/Tests/SQLiteTests/Typed/OperatorsTests.swift
@@ -356,7 +356,7 @@ class OperatorsTests: XCTestCase {
     }
 
     func test_precedencePreserved() {
-        let n = Expression<Int>(value: 1)
+        let n = SQLite.Expression<Int>(value: 1)
         assertSQL("(((1 = 1) AND (1 = 1)) OR (1 = 1))", (n == n && n == n) || n == n)
         assertSQL("((1 = 1) AND ((1 = 1) OR (1 = 1)))", n == n && (n == n || n == n))
     }
diff --git a/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift b/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
index 7ac72d0c..6be98ca0 100644
--- a/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
+++ b/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
@@ -12,9 +12,9 @@ import SQLite3
 
 class QueryIntegrationTests: SQLiteTestCase {
 
-    let id = Expression<Int64>("id")
-    let email = Expression<String>("email")
-    let age = Expression<Int>("age")
+    let id = SQLite.Expression<Int64>("id")
+    let email = SQLite.Expression<String>("email")
+    let age = SQLite.Expression<Int>("age")
 
     override func setUpWithError() throws {
         try super.setUpWithError()
@@ -24,7 +24,7 @@ class QueryIntegrationTests: SQLiteTestCase {
     // MARK: -
 
     func test_select() throws {
-        let managerId = Expression<Int64>("manager_id")
+        let managerId = SQLite.Expression<Int64>("manager_id")
         let managers = users.alias("managers")
 
         let alice = try db.run(users.insert(email <- "alice@example.com"))
@@ -39,7 +39,7 @@ class QueryIntegrationTests: SQLiteTestCase {
         let names = ["a", "b", "c"]
         try insertUsers(names)
 
-        let emailColumn = Expression<String>("email")
+        let emailColumn = SQLite.Expression<String>("email")
         let emails = try db.prepareRowIterator(users).map { $0[emailColumn] }
 
         XCTAssertEqual(names.map({ "\($0)@example.com" }), emails.sorted())
@@ -55,7 +55,7 @@ class QueryIntegrationTests: SQLiteTestCase {
     }
 
     func test_select_optional() throws {
-        let managerId = Expression<Int64?>("manager_id")
+        let managerId = SQLite.Expression<Int64?>("manager_id")
         let managers = users.alias("managers")
 
         let alice = try db.run(users.insert(email <- "alice@example.com"))
@@ -69,15 +69,15 @@ class QueryIntegrationTests: SQLiteTestCase {
     func test_select_codable() throws {
         let table = Table("codable")
         try db.run(table.create { builder in
-            builder.column(Expression<Int>("int"))
-            builder.column(Expression<String>("string"))
-            builder.column(Expression<Bool>("bool"))
-            builder.column(Expression<Double>("float"))
-            builder.column(Expression<Double>("double"))
-            builder.column(Expression<Date>("date"))
-            builder.column(Expression<UUID>("uuid"))
-            builder.column(Expression<String?>("optional"))
-            builder.column(Expression<Data>("sub"))
+            builder.column(SQLite.Expression<Int>("int"))
+            builder.column(SQLite.Expression<String>("string"))
+            builder.column(SQLite.Expression<Bool>("bool"))
+            builder.column(SQLite.Expression<Double>("float"))
+            builder.column(SQLite.Expression<Double>("double"))
+            builder.column(SQLite.Expression<Date>("date"))
+            builder.column(SQLite.Expression<UUID>("uuid"))
+            builder.column(SQLite.Expression<String?>("optional"))
+            builder.column(SQLite.Expression<Data>("sub"))
         })
 
         let value1 = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
@@ -133,13 +133,13 @@ class QueryIntegrationTests: SQLiteTestCase {
     func test_insert_many_encodables() throws {
         let table = Table("codable")
         try db.run(table.create { builder in
-            builder.column(Expression<Int?>("int"))
-            builder.column(Expression<String?>("string"))
-            builder.column(Expression<Bool?>("bool"))
-            builder.column(Expression<Double?>("float"))
-            builder.column(Expression<Double?>("double"))
-            builder.column(Expression<Date?>("date"))
-            builder.column(Expression<UUID?>("uuid"))
+            builder.column(SQLite.Expression<Int?>("int"))
+            builder.column(SQLite.Expression<String?>("string"))
+            builder.column(SQLite.Expression<Bool?>("bool"))
+            builder.column(SQLite.Expression<Double?>("float"))
+            builder.column(SQLite.Expression<Double?>("double"))
+            builder.column(SQLite.Expression<Date?>("date"))
+            builder.column(SQLite.Expression<UUID?>("uuid"))
         })
 
         let value1 = TestOptionalCodable(int: 5, string: "6", bool: true, float: 7, double: 8,
@@ -161,9 +161,9 @@ class QueryIntegrationTests: SQLiteTestCase {
 
         let table = Table("custom_codable")
         try db.run(table.create { builder in
-            builder.column(Expression<Int?>("myInt"))
-            builder.column(Expression<String?>("myString"))
-            builder.column(Expression<String?>("myOptionalArray"))
+            builder.column(SQLite.Expression<Int?>("myInt"))
+            builder.column(SQLite.Expression<String?>("myString"))
+            builder.column(SQLite.Expression<String?>("myOptionalArray"))
         })
 
         let customType = TestTypeWithOptionalArray(myInt: 13, myString: "foo", myOptionalArray: [1, 2, 3])
@@ -216,22 +216,22 @@ class QueryIntegrationTests: SQLiteTestCase {
         let actualIDs = try db.prepare(query1.union(query2)).map { $0[id] }
         XCTAssertEqual(expectedIDs, actualIDs)
 
-        let query3 = users.select(users[*], Expression<Int>(literal: "1 AS weight")).filter(email == "sally@example.com")
-        let query4 = users.select(users[*], Expression<Int>(literal: "2 AS weight")).filter(email == "alice@example.com")
+        let query3 = users.select(users[*], SQLite.Expression<Int>(literal: "1 AS weight")).filter(email == "sally@example.com")
+        let query4 = users.select(users[*], SQLite.Expression<Int>(literal: "2 AS weight")).filter(email == "alice@example.com")
 
-        let sql = query3.union(query4).order(Expression<Int>(literal: "weight")).asSQL()
+        let sql = query3.union(query4).order(SQLite.Expression<Int>(literal: "weight")).asSQL()
         XCTAssertEqual(sql,
         """
         SELECT "users".*, 1 AS weight FROM "users" WHERE ("email" = 'sally@example.com') UNION \
         SELECT "users".*, 2 AS weight FROM "users" WHERE ("email" = 'alice@example.com') ORDER BY weight
         """)
 
-        let orderedIDs = try db.prepare(query3.union(query4).order(Expression<Int>(literal: "weight"), email)).map { $0[id] }
+        let orderedIDs = try db.prepare(query3.union(query4).order(SQLite.Expression<Int>(literal: "weight"), email)).map { $0[id] }
         XCTAssertEqual(Array(expectedIDs.reversed()), orderedIDs)
     }
 
     func test_no_such_column() throws {
-        let doesNotExist = Expression<String>("doesNotExist")
+        let doesNotExist = SQLite.Expression<String>("doesNotExist")
         try insertUser("alice")
         let row = try db.pluck(users.filter(email == "alice@example.com"))!
 
@@ -272,15 +272,15 @@ class QueryIntegrationTests: SQLiteTestCase {
     // https://github.com/stephencelis/SQLite.swift/issues/285
     func test_order_by_random() throws {
         try insertUsers(["a", "b", "c'"])
-        let result = Array(try db.prepare(users.select(email).order(Expression<Int>.random()).limit(1)))
+        let result = Array(try db.prepare(users.select(email).order(SQLite.Expression<Int>.random()).limit(1)))
         XCTAssertEqual(1, result.count)
     }
 
     func test_with_recursive() throws {
         let nodes = Table("nodes")
-        let id = Expression<Int64>("id")
-        let parent = Expression<Int64?>("parent")
-        let value = Expression<Int64>("value")
+        let id = SQLite.Expression<Int64>("id")
+        let parent = SQLite.Expression<Int64?>("parent")
+        let value = SQLite.Expression<Int64>("value")
 
         try db.run(nodes.create { builder in
             builder.column(id)
@@ -320,7 +320,7 @@ class QueryIntegrationTests: SQLiteTestCase {
     /// Verify that `*` is properly expanded in a SELECT statement following a WITH clause.
     func test_with_glob_expansion() throws {
         let names = Table("names")
-        let name = Expression<String>("name")
+        let name = SQLite.Expression<String>("name")
         try db.run(names.create { builder in
             builder.column(email)
             builder.column(name)
diff --git a/Tests/SQLiteTests/Typed/QueryTests.swift b/Tests/SQLiteTests/Typed/QueryTests.swift
index f698c621..f018f097 100644
--- a/Tests/SQLiteTests/Typed/QueryTests.swift
+++ b/Tests/SQLiteTests/Typed/QueryTests.swift
@@ -13,19 +13,19 @@ import SQLite3
 class QueryTests: XCTestCase {
 
     let users = Table("users")
-    let id = Expression<Int64>("id")
-    let email = Expression<String>("email")
-    let age = Expression<Int?>("age")
-    let admin = Expression<Bool>("admin")
-    let optionalAdmin = Expression<Bool?>("admin")
+    let id = SQLite.Expression<Int64>("id")
+    let email = SQLite.Expression<String>("email")
+    let age = SQLite.Expression<Int?>("age")
+    let admin = SQLite.Expression<Bool>("admin")
+    let optionalAdmin = SQLite.Expression<Bool?>("admin")
 
     let posts = Table("posts")
-    let userId = Expression<Int64>("user_id")
-    let categoryId = Expression<Int64>("category_id")
-    let published = Expression<Bool>("published")
+    let userId = SQLite.Expression<Int64>("user_id")
+    let categoryId = SQLite.Expression<Int64>("category_id")
+    let published = SQLite.Expression<Bool>("published")
 
     let categories = Table("categories")
-    let tag = Expression<String>("tag")
+    let tag = SQLite.Expression<String>("tag")
 
     func test_select_withExpression_compilesSelectClause() {
         assertSQL("SELECT \"email\" FROM \"users\"", users.select(email))
@@ -217,7 +217,7 @@ class QueryTests: XCTestCase {
     }
 
     func test_alias_aliasesTable() {
-        let managerId = Expression<Int64>("manager_id")
+        let managerId = SQLite.Expression<Int64>("manager_id")
 
         let managers = users.alias("managers")
 
@@ -422,7 +422,7 @@ class QueryTests: XCTestCase {
 
     func test_upsert_encodable() throws {
         let emails = Table("emails")
-        let string = Expression<String>("string")
+        let string = SQLite.Expression<String>("string")
         let value = TestCodable(int: 1, string: "2", bool: true, float: 3, double: 4,
                                 date: Date(timeIntervalSince1970: 0), uuid: testUUIDValue, optional: nil, sub: nil)
         let insert = try emails.upsert(value, onConflictOf: string)
diff --git a/Tests/SQLiteTests/Typed/RowTests.swift b/Tests/SQLiteTests/Typed/RowTests.swift
index 14fa373b..1aed00a7 100644
--- a/Tests/SQLiteTests/Typed/RowTests.swift
+++ b/Tests/SQLiteTests/Typed/RowTests.swift
@@ -5,49 +5,49 @@ class RowTests: XCTestCase {
 
     public func test_get_value() throws {
         let row = Row(["\"foo\"": 0], ["value"])
-        let result = try row.get(Expression<String>("foo"))
+        let result = try row.get(SQLite.Expression<String>("foo"))
 
         XCTAssertEqual("value", result)
     }
 
     public func test_get_value_subscript() {
         let row = Row(["\"foo\"": 0], ["value"])
-        let result = row[Expression<String>("foo")]
+        let result = row[SQLite.Expression<String>("foo")]
 
         XCTAssertEqual("value", result)
     }
 
     public func test_get_value_optional() throws {
         let row = Row(["\"foo\"": 0], ["value"])
-        let result = try row.get(Expression<String?>("foo"))
+        let result = try row.get(SQLite.Expression<String?>("foo"))
 
         XCTAssertEqual("value", result)
     }
 
     public func test_get_value_optional_subscript() {
         let row = Row(["\"foo\"": 0], ["value"])
-        let result = row[Expression<String?>("foo")]
+        let result = row[SQLite.Expression<String?>("foo")]
 
         XCTAssertEqual("value", result)
     }
 
     public func test_get_value_optional_nil() throws {
         let row = Row(["\"foo\"": 0], [nil])
-        let result = try row.get(Expression<String?>("foo"))
+        let result = try row.get(SQLite.Expression<String?>("foo"))
 
         XCTAssertNil(result)
     }
 
     public func test_get_value_optional_nil_subscript() {
         let row = Row(["\"foo\"": 0], [nil])
-        let result = row[Expression<String?>("foo")]
+        let result = row[SQLite.Expression<String?>("foo")]
 
         XCTAssertNil(result)
     }
 
     public func test_get_type_mismatch_throws_unexpected_null_value() {
         let row = Row(["\"foo\"": 0], ["value"])
-        XCTAssertThrowsError(try row.get(Expression<Int>("foo"))) { error in
+        XCTAssertThrowsError(try row.get(SQLite.Expression<Int>("foo"))) { error in
             if case QueryError.unexpectedNullValue(let name) = error {
                 XCTAssertEqual("\"foo\"", name)
             } else {
@@ -58,13 +58,13 @@ class RowTests: XCTestCase {
 
     public func test_get_type_mismatch_optional_returns_nil() throws {
         let row = Row(["\"foo\"": 0], ["value"])
-        let result = try row.get(Expression<Int?>("foo"))
+        let result = try row.get(SQLite.Expression<Int?>("foo"))
         XCTAssertNil(result)
     }
 
     public func test_get_non_existent_column_throws_no_such_column() {
         let row = Row(["\"foo\"": 0], ["value"])
-        XCTAssertThrowsError(try row.get(Expression<Int>("bar"))) { error in
+        XCTAssertThrowsError(try row.get(SQLite.Expression<Int>("bar"))) { error in
             if case QueryError.noSuchColumn(let name, let columns) = error {
                 XCTAssertEqual("\"bar\"", name)
                 XCTAssertEqual(["\"foo\""], columns)
@@ -76,7 +76,7 @@ class RowTests: XCTestCase {
 
     public func test_get_ambiguous_column_throws() {
         let row = Row(["table1.\"foo\"": 0, "table2.\"foo\"": 1], ["value"])
-        XCTAssertThrowsError(try row.get(Expression<Int>("foo"))) { error in
+        XCTAssertThrowsError(try row.get(SQLite.Expression<Int>("foo"))) { error in
             if case QueryError.ambiguousColumn(let name, let columns) = error {
                 XCTAssertEqual("\"foo\"", name)
                 XCTAssertEqual(["table1.\"foo\"", "table2.\"foo\""], columns.sorted())
@@ -107,7 +107,7 @@ class RowTests: XCTestCase {
         }
 
         let row = Row(["\"foo\"": 0], [Blob(bytes: [])])
-        XCTAssertThrowsError(try row.get(Expression<MyType>("foo"))) { error in
+        XCTAssertThrowsError(try row.get(SQLite.Expression<MyType>("foo"))) { error in
             if case MyType.MyError.failed = error {
                 XCTAssertTrue(true)
             } else {
diff --git a/Tests/SQLiteTests/Typed/SelectTests.swift b/Tests/SQLiteTests/Typed/SelectTests.swift
index 52d5bb6b..5fa3cd30 100644
--- a/Tests/SQLiteTests/Typed/SelectTests.swift
+++ b/Tests/SQLiteTests/Typed/SelectTests.swift
@@ -24,10 +24,10 @@ class SelectTests: SQLiteTestCase {
         let usersData = Table("users_name")
         let users = Table("users")
 
-        let name = Expression<String>("name")
-        let id = Expression<Int64>("id")
-        let userID = Expression<Int64>("user_id")
-        let email = Expression<String>("email")
+        let name = SQLite.Expression<String>("name")
+        let id = SQLite.Expression<Int64>("id")
+        let userID = SQLite.Expression<Int64>("user_id")
+        let email = SQLite.Expression<String>("email")
 
         try insertUser("Joey")
         try db.run(usersData.insert(
diff --git a/Tests/SQLiteTests/Typed/SetterTests.swift b/Tests/SQLiteTests/Typed/SetterTests.swift
index 938dd013..05da57a4 100644
--- a/Tests/SQLiteTests/Typed/SetterTests.swift
+++ b/Tests/SQLiteTests/Typed/SetterTests.swift
@@ -134,4 +134,7 @@ class SetterTests: XCTestCase {
         assertSQL("\"intOptional\" = (\"intOptional\" - 1)", intOptional--)
     }
 
+    func test_setter_custom_string_convertible() {
+        XCTAssertEqual("\"int\" = \"int\"", (int <- int).description)
+    }
 }
diff --git a/Tests/SQLiteTests/Typed/WindowFunctionsTests.swift b/Tests/SQLiteTests/Typed/WindowFunctionsTests.swift
index 6ded152b..01e88297 100644
--- a/Tests/SQLiteTests/Typed/WindowFunctionsTests.swift
+++ b/Tests/SQLiteTests/Typed/WindowFunctionsTests.swift
@@ -34,13 +34,13 @@ class WindowFunctionsTests: XCTestCase {
     func test_lag_wrapsExpressionWithOverClause() {
         assertSQL("lag(\"int\", 0) OVER (ORDER BY \"int\" DESC)", int.lag(int.desc))
         assertSQL("lag(\"int\", 7) OVER (ORDER BY \"int\" DESC)", int.lag(offset: 7, int.desc))
-        assertSQL("lag(\"int\", 1, 3) OVER (ORDER BY \"int\" DESC)", int.lag(offset: 1, default: Expression<Int>(value: 3), int.desc))
+        assertSQL("lag(\"int\", 1, 3) OVER (ORDER BY \"int\" DESC)", int.lag(offset: 1, default: SQLite.Expression<Int>(value: 3), int.desc))
     }
 
     func test_lead_wrapsExpressionWithOverClause() {
         assertSQL("lead(\"int\", 0) OVER (ORDER BY \"int\" DESC)", int.lead(int.desc))
         assertSQL("lead(\"int\", 7) OVER (ORDER BY \"int\" DESC)", int.lead(offset: 7, int.desc))
-        assertSQL("lead(\"int\", 1, 3) OVER (ORDER BY \"int\" DESC)", int.lead(offset: 1, default: Expression<Int>(value: 3), int.desc))
+        assertSQL("lead(\"int\", 1, 3) OVER (ORDER BY \"int\" DESC)", int.lead(offset: 1, default: SQLite.Expression<Int>(value: 3), int.desc))
     }
 
     func test_firstValue_wrapsExpressionWithOverClause() {

From 4a5eda39a5aa63b4151b54e13ac9cd6ff3390a7e Mon Sep 17 00:00:00 2001
From: Cary Clark <clarkcb@gmail.com>
Date: Fri, 4 Oct 2024 15:54:10 -0700
Subject: [PATCH 644/685] Update oldest supported platform versions

---
 Package.swift | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Package.swift b/Package.swift
index 238661ae..12a2f11c 100644
--- a/Package.swift
+++ b/Package.swift
@@ -4,10 +4,10 @@ import PackageDescription
 let package = Package(
     name: "SQLite.swift",
     platforms: [
-        .iOS(.v11),
+        .iOS(.v12),
         .macOS(.v10_13),
         .watchOS(.v4),
-        .tvOS(.v11),
+        .tvOS(.v12),
         .visionOS(.v1)
     ],
     products: [

From 748dcba3312485151fa91b551a4564238f2b69b9 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 20 May 2025 18:35:08 +0200
Subject: [PATCH 645/685] Support creating tables in schema changer

---
 Makefile                                      |  2 +-
 Sources/SQLite/Schema/SchemaChanger.swift     | 49 +++++++++++++++++++
 Sources/SQLite/Schema/SchemaDefinitions.swift |  5 +-
 .../Schema/SchemaChangerTests.swift           | 46 +++++++++++++++++
 4 files changed, 100 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile
index 73b33f97..52a25a12 100644
--- a/Makefile
+++ b/Makefile
@@ -35,7 +35,7 @@ lint: $(SWIFTLINT)
 	$< --strict
 
 lint-fix: $(SWIFTLINT)
-	$< lint fix
+	$< --fix
 
 clean:
 	$(XCODEBUILD) $(BUILD_ARGUMENTS) clean
diff --git a/Sources/SQLite/Schema/SchemaChanger.swift b/Sources/SQLite/Schema/SchemaChanger.swift
index af7b5e27..b6ed7312 100644
--- a/Sources/SQLite/Schema/SchemaChanger.swift
+++ b/Sources/SQLite/Schema/SchemaChanger.swift
@@ -43,19 +43,31 @@ public class SchemaChanger: CustomStringConvertible {
 
     public enum Operation {
         case addColumn(ColumnDefinition)
+        case addIndex(IndexDefinition)
         case dropColumn(String)
         case renameColumn(String, String)
         case renameTable(String)
+        case createTable(columns: [ColumnDefinition])
 
         /// Returns non-nil if the operation can be executed with a simple SQL statement
         func toSQL(_ table: String, version: SQLiteVersion) -> String? {
             switch self {
             case .addColumn(let definition):
                 return "ALTER TABLE \(table.quote()) ADD COLUMN \(definition.toSQL())"
+            case .addIndex(let definition):
+                let unique = definition.unique ? "UNIQUE" : ""
+                let columns = definition.columns.joined(separator: ", ")
+                let `where` = definition.where.map { " WHERE " + $0 } ?? ""
+
+                return "CREATE \(unique) INDEX \(definition.name) ON \(definition.table) (\(columns)) \(`where`)"
             case .renameColumn(let from, let to) where SQLiteFeature.renameColumn.isSupported(by: version):
                 return "ALTER TABLE \(table.quote()) RENAME COLUMN \(from.quote()) TO \(to.quote())"
             case .dropColumn(let column) where SQLiteFeature.dropColumn.isSupported(by: version):
                 return "ALTER TABLE \(table.quote()) DROP COLUMN \(column.quote())"
+            case .createTable(let columns):
+                return "CREATE TABLE \(table.quote()) (" +
+                    columns.map { $0.toSQL() }.joined(separator: ", ") +
+                ")"
             default: return nil
             }
         }
@@ -108,12 +120,39 @@ public class SchemaChanger: CustomStringConvertible {
         }
     }
 
+    public class CreateTableDefinition {
+        fileprivate var columnDefinitions: [ColumnDefinition] = []
+        fileprivate var indexDefinitions: [IndexDefinition] = []
+
+        let name: String
+
+        init(name: String) {
+            self.name = name
+        }
+
+        public func add(column: ColumnDefinition) {
+            columnDefinitions.append(column)
+        }
+
+        public func add(index: IndexDefinition) {
+            indexDefinitions.append(index)
+        }
+
+        var operations: [Operation] {
+            precondition(!columnDefinitions.isEmpty)
+            return [
+                .createTable(columns: columnDefinitions)
+            ] + indexDefinitions.map { .addIndex($0) }
+        }
+    }
+
     private let connection: Connection
     private let schemaReader: SchemaReader
     private let version: SQLiteVersion
     static let tempPrefix = "tmp_"
     typealias Block = () throws -> Void
     public typealias AlterTableDefinitionBlock = (AlterTableDefinition) -> Void
+    public typealias CreateTableDefinitionBlock = (CreateTableDefinition) -> Void
 
     struct Options: OptionSet {
         let rawValue: Int
@@ -141,6 +180,15 @@ public class SchemaChanger: CustomStringConvertible {
         }
     }
 
+    public func create(table: String, ifNotExists: Bool = false, block: CreateTableDefinitionBlock) throws {
+        let createTableDefinition = CreateTableDefinition(name: table)
+        block(createTableDefinition)
+
+        for operation in createTableDefinition.operations {
+            try run(table: table, operation: operation)
+        }
+    }
+
     public func drop(table: String, ifExists: Bool = true) throws {
         try dropTable(table, ifExists: ifExists)
     }
@@ -263,6 +311,7 @@ extension TableDefinition {
     func apply(_ operation: SchemaChanger.Operation?) -> TableDefinition {
         switch operation {
         case .none: return self
+        case .createTable, .addIndex: fatalError()
         case .addColumn: fatalError("Use 'ALTER TABLE ADD COLUMN (...)'")
         case .dropColumn(let column):
             return TableDefinition(name: name,
diff --git a/Sources/SQLite/Schema/SchemaDefinitions.swift b/Sources/SQLite/Schema/SchemaDefinitions.swift
index 80f9e199..60837244 100644
--- a/Sources/SQLite/Schema/SchemaDefinitions.swift
+++ b/Sources/SQLite/Schema/SchemaDefinitions.swift
@@ -270,12 +270,15 @@ public struct IndexDefinition: Equatable {
                         return memo2
             }
         }
+
+        let orders = indexSQL.flatMap(orders)
+
         self.init(table: table,
                   name: name,
                   unique: unique,
                   columns: columns,
                   where: indexSQL.flatMap(wherePart),
-                  orders: indexSQL.flatMap(orders))
+                  orders: (orders?.isEmpty ?? false) ? nil : orders)
     }
 
     public let table: String
diff --git a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
index 2bec6a06..125ef09e 100644
--- a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
@@ -154,4 +154,50 @@ class SchemaChangerTests: SQLiteTestCase {
         let users_new = Table("users_new")
         XCTAssertEqual((try db.scalar(users_new.count)) as Int, 1)
     }
+
+    func test_create_table() throws {
+        try schemaChanger.create(table: "foo") { table in
+            table.add(column: .init(name: "id", primaryKey: .init(autoIncrement: true), type: .INTEGER))
+            table.add(column: .init(name: "name", type: .TEXT, nullable: false))
+            table.add(column: .init(name: "age", type: .INTEGER))
+
+            table.add(index: .init(table: table.name,
+                                   name: "nameIndex",
+                                   unique: true,
+                                   columns: ["name"],
+                                   where: nil,
+                                   orders: nil))
+        }
+
+        // make sure new table can be queried
+        let foo = Table("foo")
+        XCTAssertEqual((try db.scalar(foo.count)) as Int, 0)
+
+        let columns = try schema.columnDefinitions(table: "foo")
+        XCTAssertEqual(columns, [
+            ColumnDefinition(name: "id",
+                             primaryKey: .init(autoIncrement: true, onConflict: nil),
+                             type: .INTEGER,
+                             nullable: true,
+                             defaultValue: .NULL,
+                             references: nil),
+            ColumnDefinition(name: "name",
+                             primaryKey: nil,
+                             type: .TEXT,
+                             nullable: false,
+                             defaultValue: .NULL,
+                             references: nil),
+            ColumnDefinition(name: "age",
+                             primaryKey: nil,
+                             type: .INTEGER,
+                             nullable: true,
+                             defaultValue: .NULL,
+                             references: nil)
+        ])
+
+        let indexes = try schema.indexDefinitions(table: "foo")
+        XCTAssertEqual(indexes, [
+            IndexDefinition(table: "foo", name: "nameIndex", unique: true, columns: ["name"], where: nil, orders: nil)
+        ])
+    }
 }

From 261f98ae268f986ec6e54822d45d9bda263bdd50 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 20 May 2025 22:17:45 +0200
Subject: [PATCH 646/685] Update docs

---
 Documentation/Index.md | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index fcd2d642..bc62c791 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -63,6 +63,7 @@
       - [Renaming Columns](#renaming-columns)
       - [Dropping Columns](#dropping-columns)
       - [Renaming/Dropping Tables](#renamingdropping-tables)
+      - [Creating Tables](#creating-tables)      
     - [Indexes](#indexes)
       - [Creating Indexes](#creating-indexes)
       - [Dropping Indexes](#dropping-indexes)
@@ -1583,6 +1584,16 @@ try schemaChanger.rename(table: "users", to: "users_new")
 try schemaChanger.drop(table: "emails", ifExists: false)
 ```
 
+#### Creating Tables
+
+```swift
+let schemaChanger = SchemaChanger(connection: db)
+
+try schemaChanger.create(table: "users") { table in 
+    table.add(column: .init(name: "id", primaryKey: .init(autoIncrement: true), type: .INTEGER))
+    table.add(column: .init(name: "name", type: .TEXT, nullable: false))            
+} 
+
 ### Indexes
 
 

From e21fde28f0f96cc452151aaa17413b198f3718a9 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 20 May 2025 22:18:37 +0200
Subject: [PATCH 647/685] Revert to standard cocoapods

---
 Gemfile      |  2 +-
 Gemfile.lock | 93 ++++++++++++++++++++++++++--------------------------
 2 files changed, 48 insertions(+), 47 deletions(-)

diff --git a/Gemfile b/Gemfile
index eb6036cd..1f2ebb87 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,3 +1,3 @@
 source "https://rubygems.org"
 
-gem 'cocoapods', :git => 'https://github.com/SagarSDagdu/CocoaPods.git', tag: '1.15.2.1-sagard'
+gem 'cocoapods' 
diff --git a/Gemfile.lock b/Gemfile.lock
index a58783ea..464ef06b 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,27 +1,3 @@
-GIT
-  remote: https://github.com/SagarSDagdu/CocoaPods.git
-  revision: d96f491f79abd2804d1359c5228cce404dd365b7
-  tag: 1.15.2.1-sagard
-  specs:
-    cocoapods (1.15.2.1.pre.sagard)
-      addressable (~> 2.8)
-      claide (>= 1.0.2, < 2.0)
-      cocoapods-core (= 1.15.2)
-      cocoapods-deintegrate (>= 1.0.3, < 2.0)
-      cocoapods-downloader (>= 2.1, < 3.0)
-      cocoapods-plugins (>= 1.0.0, < 2.0)
-      cocoapods-search (>= 1.0.0, < 2.0)
-      cocoapods-trunk (>= 1.6.0, < 2.0)
-      cocoapods-try (>= 1.1.0, < 2.0)
-      colored2 (~> 3.1)
-      escape (~> 0.0.4)
-      fourflusher (>= 2.3.0, < 3.0)
-      gh_inspector (~> 1.0)
-      molinillo (~> 0.8.0)
-      nap (~> 1.0)
-      ruby-macho (>= 2.3.0, < 3.0)
-      xcodeproj (>= 1.23.0, < 2.0)
-
 GEM
   remote: https://rubygems.org/
   specs:
@@ -29,26 +5,47 @@ GEM
       base64
       nkf
       rexml
-    activesupport (7.1.3.2)
+    activesupport (7.2.2.1)
       base64
+      benchmark (>= 0.3)
       bigdecimal
-      concurrent-ruby (~> 1.0, >= 1.0.2)
+      concurrent-ruby (~> 1.0, >= 1.3.1)
       connection_pool (>= 2.2.5)
       drb
       i18n (>= 1.6, < 2)
+      logger (>= 1.4.2)
       minitest (>= 5.1)
-      mutex_m
-      tzinfo (~> 2.0)
-    addressable (2.8.6)
-      public_suffix (>= 2.0.2, < 6.0)
+      securerandom (>= 0.3)
+      tzinfo (~> 2.0, >= 2.0.5)
+    addressable (2.8.7)
+      public_suffix (>= 2.0.2, < 7.0)
     algoliasearch (1.27.5)
       httpclient (~> 2.8, >= 2.8.3)
       json (>= 1.5.1)
     atomos (0.1.3)
     base64 (0.2.0)
-    bigdecimal (3.1.7)
+    benchmark (0.4.0)
+    bigdecimal (3.1.9)
     claide (1.1.0)
-    cocoapods-core (1.15.2)
+    cocoapods (1.16.2)
+      addressable (~> 2.8)
+      claide (>= 1.0.2, < 2.0)
+      cocoapods-core (= 1.16.2)
+      cocoapods-deintegrate (>= 1.0.3, < 2.0)
+      cocoapods-downloader (>= 2.1, < 3.0)
+      cocoapods-plugins (>= 1.0.0, < 2.0)
+      cocoapods-search (>= 1.0.0, < 2.0)
+      cocoapods-trunk (>= 1.6.0, < 2.0)
+      cocoapods-try (>= 1.1.0, < 2.0)
+      colored2 (~> 3.1)
+      escape (~> 0.0.4)
+      fourflusher (>= 2.3.0, < 3.0)
+      gh_inspector (~> 1.0)
+      molinillo (~> 0.8.0)
+      nap (~> 1.0)
+      ruby-macho (>= 2.3.0, < 3.0)
+      xcodeproj (>= 1.27.0, < 2.0)
+    cocoapods-core (1.16.2)
       activesupport (>= 5.0, < 8)
       addressable (~> 2.8)
       algoliasearch (~> 1.0)
@@ -68,48 +65,52 @@ GEM
       netrc (~> 0.11)
     cocoapods-try (1.2.0)
     colored2 (3.1.2)
-    concurrent-ruby (1.2.3)
-    connection_pool (2.4.1)
+    concurrent-ruby (1.3.5)
+    connection_pool (2.5.3)
     drb (2.2.1)
     escape (0.0.4)
     ethon (0.16.0)
       ffi (>= 1.15.0)
-    ffi (1.16.3)
+    ffi (1.17.2)
+    ffi (1.17.2-arm64-darwin)
     fourflusher (2.3.1)
     fuzzy_match (2.0.4)
     gh_inspector (1.1.3)
-    httpclient (2.8.3)
-    i18n (1.14.4)
+    httpclient (2.9.0)
+      mutex_m
+    i18n (1.14.7)
       concurrent-ruby (~> 1.0)
-    json (2.7.2)
-    minitest (5.22.3)
+    json (2.12.0)
+    logger (1.7.0)
+    minitest (5.25.5)
     molinillo (0.8.0)
-    mutex_m (0.2.0)
-    nanaimo (0.3.0)
+    mutex_m (0.3.0)
+    nanaimo (0.4.0)
     nap (1.1.0)
     netrc (0.11.0)
     nkf (0.2.0)
     public_suffix (4.0.7)
-    rexml (3.2.6)
+    rexml (3.4.1)
     ruby-macho (2.5.1)
+    securerandom (0.4.1)
     typhoeus (1.4.1)
       ethon (>= 0.9.0)
     tzinfo (2.0.6)
       concurrent-ruby (~> 1.0)
-    xcodeproj (1.24.0)
+    xcodeproj (1.27.0)
       CFPropertyList (>= 2.3.3, < 4.0)
       atomos (~> 0.1.3)
       claide (>= 1.0.2, < 2.0)
       colored2 (~> 3.1)
-      nanaimo (~> 0.3.0)
-      rexml (~> 3.2.4)
+      nanaimo (~> 0.4.0)
+      rexml (>= 3.3.6, < 4.0)
 
 PLATFORMS
   arm64-darwin-23
   ruby
 
 DEPENDENCIES
-  cocoapods!
+  cocoapods
 
 BUNDLED WITH
    2.5.4

From 5ef20d1887e4b8763df890c4f1ffc256b3f79b99 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 20 May 2025 22:39:15 +0200
Subject: [PATCH 648/685] Don't lint against visionOS

---
 run-tests.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/run-tests.sh b/run-tests.sh
index 1bf8de96..cb68a022 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -11,7 +11,7 @@ elif [ -n "$VALIDATOR_SUBSPEC" ]; then
     if [ "$VALIDATOR_SUBSPEC" == "none" ]; then
       bundle exec pod lib lint --no-subspecs --fail-fast
     else
-      bundle exec pod lib lint --subspec="${VALIDATOR_SUBSPEC}" --fail-fast
+      bundle exec pod lib lint --subspec="${VALIDATOR_SUBSPEC}" --fail-fast --platforms=macos,ios,tvos,watchos
     fi
 elif [ -n "$CARTHAGE_PLATFORM" ]; then
     cd Tests/Carthage && make test CARTHAGE_PLATFORM="$CARTHAGE_PLATFORM"

From 017929080c146c2085b21adcce95ff67b9e82d2e Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 20 May 2025 23:14:13 +0200
Subject: [PATCH 649/685] Disable visionos just for standalone

---
 run-tests.sh | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/run-tests.sh b/run-tests.sh
index cb68a022..94f643e4 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -8,15 +8,21 @@ if [ -n "$BUILD_SCHEME" ]; then
     fi
 elif [ -n "$VALIDATOR_SUBSPEC" ]; then
     bundle install
-    if [ "$VALIDATOR_SUBSPEC" == "none" ]; then
-      bundle exec pod lib lint --no-subspecs --fail-fast
-    else
-      bundle exec pod lib lint --subspec="${VALIDATOR_SUBSPEC}" --fail-fast --platforms=macos,ios,tvos,watchos
-    fi
+    case "$VALIDATOR_SUBSPEC" in
+      none)
+        bundle exec pod lib lint --no-subspecs --fail-fast
+        ;;
+      standalone)
+        bundle exec pod lib lint --subspec="${VALIDATOR_SUBSPEC}" --fail-fast --platforms=macos,ios,tvos,watchos
+        ;;
+      *)
+        bundle exec pod lib lint --subspec="${VALIDATOR_SUBSPEC}" --fail-fast
+        ;;
+      esac
 elif [ -n "$CARTHAGE_PLATFORM" ]; then
     cd Tests/Carthage && make test CARTHAGE_PLATFORM="$CARTHAGE_PLATFORM"
 elif [ -n "$SPM" ]; then
-    cd Tests/SPM && swift ${SPM}
+    cd Tests/SPM && swift "${SPM}"
 elif [ -n "${PACKAGE_MANAGER_COMMAND}" ]; then
-    swift ${PACKAGE_MANAGER_COMMAND}
+    swift "${PACKAGE_MANAGER_COMMAND}"
 fi

From 023c5039780b1c086f1d4bbea1c6d5a683e3041f Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 20 May 2025 23:18:21 +0200
Subject: [PATCH 650/685] Enable word splitting

---
 run-tests.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/run-tests.sh b/run-tests.sh
index 94f643e4..7d5c26d2 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -24,5 +24,5 @@ elif [ -n "$CARTHAGE_PLATFORM" ]; then
 elif [ -n "$SPM" ]; then
     cd Tests/SPM && swift "${SPM}"
 elif [ -n "${PACKAGE_MANAGER_COMMAND}" ]; then
-    swift "${PACKAGE_MANAGER_COMMAND}"
+    swift ${PACKAGE_MANAGER_COMMAND}
 fi

From 673367b772b04a8df0be64e757b2979da8798939 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Tue, 20 May 2025 23:36:41 +0200
Subject: [PATCH 651/685] Public init

---
 Sources/SQLite/Schema/SchemaDefinitions.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Sources/SQLite/Schema/SchemaDefinitions.swift b/Sources/SQLite/Schema/SchemaDefinitions.swift
index 60837244..897f8557 100644
--- a/Sources/SQLite/Schema/SchemaDefinitions.swift
+++ b/Sources/SQLite/Schema/SchemaDefinitions.swift
@@ -93,7 +93,7 @@ public struct ColumnDefinition: Equatable {
         // swiftlint:disable:next force_try
         static let pattern = try! NSRegularExpression(pattern: "PRIMARY KEY\\s*(?:ASC|DESC)?\\s*(?:ON CONFLICT (\\w+)?)?\\s*(AUTOINCREMENT)?")
 
-        init(autoIncrement: Bool = true, onConflict: OnConflict? = nil) {
+        public init(autoIncrement: Bool = true, onConflict: OnConflict? = nil) {
             self.autoIncrement = autoIncrement
             self.onConflict = onConflict
         }

From 5de1420d58a87e082bb3659da9b59a19687cb867 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 21 May 2025 14:23:31 +0200
Subject: [PATCH 652/685] Support ifNotExists

---
 Sources/SQLite/Schema/SchemaChanger.swift     | 14 +++++++-----
 .../Schema/SchemaChangerTests.swift           | 22 +++++++++++++++++++
 2 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/Sources/SQLite/Schema/SchemaChanger.swift b/Sources/SQLite/Schema/SchemaChanger.swift
index b6ed7312..e2e3d5fa 100644
--- a/Sources/SQLite/Schema/SchemaChanger.swift
+++ b/Sources/SQLite/Schema/SchemaChanger.swift
@@ -47,7 +47,7 @@ public class SchemaChanger: CustomStringConvertible {
         case dropColumn(String)
         case renameColumn(String, String)
         case renameTable(String)
-        case createTable(columns: [ColumnDefinition])
+        case createTable(columns: [ColumnDefinition], ifNotExists: Bool)
 
         /// Returns non-nil if the operation can be executed with a simple SQL statement
         func toSQL(_ table: String, version: SQLiteVersion) -> String? {
@@ -64,8 +64,8 @@ public class SchemaChanger: CustomStringConvertible {
                 return "ALTER TABLE \(table.quote()) RENAME COLUMN \(from.quote()) TO \(to.quote())"
             case .dropColumn(let column) where SQLiteFeature.dropColumn.isSupported(by: version):
                 return "ALTER TABLE \(table.quote()) DROP COLUMN \(column.quote())"
-            case .createTable(let columns):
-                return "CREATE TABLE \(table.quote()) (" +
+            case .createTable(let columns, let ifNotExists):
+                return "CREATE TABLE \(ifNotExists ? " IF NOT EXISTS " : "") \(table.quote()) (" +
                     columns.map { $0.toSQL() }.joined(separator: ", ") +
                 ")"
             default: return nil
@@ -125,9 +125,11 @@ public class SchemaChanger: CustomStringConvertible {
         fileprivate var indexDefinitions: [IndexDefinition] = []
 
         let name: String
+        let ifNotExists: Bool
 
-        init(name: String) {
+        init(name: String, ifNotExists: Bool) {
             self.name = name
+            self.ifNotExists = ifNotExists
         }
 
         public func add(column: ColumnDefinition) {
@@ -141,7 +143,7 @@ public class SchemaChanger: CustomStringConvertible {
         var operations: [Operation] {
             precondition(!columnDefinitions.isEmpty)
             return [
-                .createTable(columns: columnDefinitions)
+                .createTable(columns: columnDefinitions, ifNotExists: ifNotExists)
             ] + indexDefinitions.map { .addIndex($0) }
         }
     }
@@ -181,7 +183,7 @@ public class SchemaChanger: CustomStringConvertible {
     }
 
     public func create(table: String, ifNotExists: Bool = false, block: CreateTableDefinitionBlock) throws {
-        let createTableDefinition = CreateTableDefinition(name: table)
+        let createTableDefinition = CreateTableDefinition(name: table, ifNotExists: ifNotExists)
         block(createTableDefinition)
 
         for operation in createTableDefinition.operations {
diff --git a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
index 125ef09e..bba16e08 100644
--- a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
@@ -200,4 +200,26 @@ class SchemaChangerTests: SQLiteTestCase {
             IndexDefinition(table: "foo", name: "nameIndex", unique: true, columns: ["name"], where: nil, orders: nil)
         ])
     }
+
+    func test_create_table_if_not_exists() throws {
+        try schemaChanger.create(table: "foo") { table in
+            table.add(column: .init(name: "id", primaryKey: .init(autoIncrement: true), type: .INTEGER))
+        }
+
+        try schemaChanger.create(table: "foo", ifNotExists: true) { table in
+            table.add(column: .init(name: "id", primaryKey: .init(autoIncrement: true), type: .INTEGER))
+        }
+
+        XCTAssertThrowsError(
+            try schemaChanger.create(table: "foo", ifNotExists: false) { table in
+                table.add(column: .init(name: "id", primaryKey: .init(autoIncrement: true), type: .INTEGER))
+            }
+        ) { error in
+            if case Result.error(_, let code, _) = error {
+                XCTAssertEqual(code, 1)
+            } else {
+                XCTFail("unexpected error: \(error)")
+            }
+        }
+    }
 }

From f2a86841f527f756610797d56b6c49a46c947f41 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 21 May 2025 17:24:57 +0200
Subject: [PATCH 653/685] Add columns via Expressions

---
 Sources/SQLite/Schema/SchemaChanger.swift     | 25 ++++++++++++++++
 .../Schema/SchemaChangerTests.swift           | 30 +++++++++++++++++++
 2 files changed, 55 insertions(+)

diff --git a/Sources/SQLite/Schema/SchemaChanger.swift b/Sources/SQLite/Schema/SchemaChanger.swift
index e2e3d5fa..d3342032 100644
--- a/Sources/SQLite/Schema/SchemaChanger.swift
+++ b/Sources/SQLite/Schema/SchemaChanger.swift
@@ -136,6 +136,14 @@ public class SchemaChanger: CustomStringConvertible {
             columnDefinitions.append(column)
         }
 
+        public func add<T>(expression: Expression<T>) where T: Value {
+            add(column: .init(name: columnName(for: expression), type: .init(expression: expression), nullable: false))
+        }
+
+        public func add<T>(expression: Expression<T?>) where T: Value {
+            add(column: .init(name: columnName(for: expression), type: .init(expression: expression), nullable: true))
+        }
+
         public func add(index: IndexDefinition) {
             indexDefinitions.append(index)
         }
@@ -146,6 +154,13 @@ public class SchemaChanger: CustomStringConvertible {
                 .createTable(columns: columnDefinitions, ifNotExists: ifNotExists)
             ] + indexDefinitions.map { .addIndex($0) }
         }
+
+        private func columnName<T>(for expression: Expression<T>) -> String {
+            switch LiteralValue(expression.template) {
+            case .stringLiteral(let string): return string
+            default: fatalError("expression is not a literal string value")
+            }
+        }
     }
 
     private let connection: Connection
@@ -331,3 +346,13 @@ extension TableDefinition {
         }
     }
 }
+
+extension ColumnDefinition.Affinity {
+    init<T>(expression: Expression<T>) where T: Value {
+        self.init(T.declaredDatatype)
+    }
+
+    init<T>(expression: Expression<T?>) where T: Value {
+        self.init(T.declaredDatatype)
+    }
+}
diff --git a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
index bba16e08..6b53c9ce 100644
--- a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
@@ -201,6 +201,36 @@ class SchemaChangerTests: SQLiteTestCase {
         ])
     }
 
+    func test_create_table_add_column_expression() throws {
+        try schemaChanger.create(table: "foo") { table in
+            table.add(expression: Expression<String>("name"))
+            table.add(expression: Expression<Int>("age"))
+            table.add(expression: Expression<Double?>("salary"))
+        }
+
+        let columns = try schema.columnDefinitions(table: "foo")
+        XCTAssertEqual(columns, [
+            ColumnDefinition(name: "name",
+                             primaryKey: nil,
+                             type: .TEXT,
+                             nullable: false,
+                             defaultValue: .NULL,
+                             references: nil),
+            ColumnDefinition(name: "age",
+                             primaryKey: nil,
+                             type: .INTEGER,
+                             nullable: false,
+                             defaultValue: .NULL,
+                             references: nil),
+            ColumnDefinition(name: "salary",
+                             primaryKey: nil,
+                             type: .REAL,
+                             nullable: true,
+                             defaultValue: .NULL,
+                             references: nil)
+            ])
+    }
+
     func test_create_table_if_not_exists() throws {
         try schemaChanger.create(table: "foo") { table in
             table.add(column: .init(name: "id", primaryKey: .init(autoIncrement: true), type: .INTEGER))

From cdaade15b93a43a5db8038da05da1c30c997ea3d Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 21 May 2025 18:45:26 +0200
Subject: [PATCH 654/685] Respect ifNotExists for index

---
 Sources/SQLite/Schema/SchemaChanger.swift         | 12 ++++--------
 Tests/SQLiteTests/Schema/SchemaChangerTests.swift | 14 ++++++++++++++
 2 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/Sources/SQLite/Schema/SchemaChanger.swift b/Sources/SQLite/Schema/SchemaChanger.swift
index d3342032..13222dab 100644
--- a/Sources/SQLite/Schema/SchemaChanger.swift
+++ b/Sources/SQLite/Schema/SchemaChanger.swift
@@ -43,7 +43,7 @@ public class SchemaChanger: CustomStringConvertible {
 
     public enum Operation {
         case addColumn(ColumnDefinition)
-        case addIndex(IndexDefinition)
+        case addIndex(IndexDefinition, ifNotExists: Bool)
         case dropColumn(String)
         case renameColumn(String, String)
         case renameTable(String)
@@ -54,12 +54,8 @@ public class SchemaChanger: CustomStringConvertible {
             switch self {
             case .addColumn(let definition):
                 return "ALTER TABLE \(table.quote()) ADD COLUMN \(definition.toSQL())"
-            case .addIndex(let definition):
-                let unique = definition.unique ? "UNIQUE" : ""
-                let columns = definition.columns.joined(separator: ", ")
-                let `where` = definition.where.map { " WHERE " + $0 } ?? ""
-
-                return "CREATE \(unique) INDEX \(definition.name) ON \(definition.table) (\(columns)) \(`where`)"
+            case .addIndex(let definition, let ifNotExists):
+                return definition.toSQL(ifNotExists: ifNotExists)
             case .renameColumn(let from, let to) where SQLiteFeature.renameColumn.isSupported(by: version):
                 return "ALTER TABLE \(table.quote()) RENAME COLUMN \(from.quote()) TO \(to.quote())"
             case .dropColumn(let column) where SQLiteFeature.dropColumn.isSupported(by: version):
@@ -152,7 +148,7 @@ public class SchemaChanger: CustomStringConvertible {
             precondition(!columnDefinitions.isEmpty)
             return [
                 .createTable(columns: columnDefinitions, ifNotExists: ifNotExists)
-            ] + indexDefinitions.map { .addIndex($0) }
+            ] + indexDefinitions.map { .addIndex($0, ifNotExists: ifNotExists) }
         }
 
         private func columnName<T>(for expression: Expression<T>) -> String {
diff --git a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
index 6b53c9ce..02a82267 100644
--- a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
@@ -252,4 +252,18 @@ class SchemaChangerTests: SQLiteTestCase {
             }
         }
     }
+
+    func test_create_table_if_not_exists_with_index() throws {
+        try schemaChanger.create(table: "foo") { table in
+            table.add(column: .init(name: "id", primaryKey: .init(autoIncrement: true), type: .INTEGER))
+            table.add(column: .init(name: "name", type: .TEXT))
+            table.add(index: .init(table: "foo", name: "name_index", unique: true, columns: ["name"], indexSQL: nil))
+        }
+
+        // ifNotExists needs to apply to index creation as well
+        try schemaChanger.create(table: "foo", ifNotExists: true) { table in
+            table.add(column: .init(name: "id", primaryKey: .init(autoIncrement: true), type: .INTEGER))
+            table.add(index: .init(table: "foo", name: "name_index", unique: true, columns: ["name"], indexSQL: nil))
+        }
+    }
 }

From a0136544e9627b941008d7c59836b61feaf1f142 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 21 May 2025 22:17:39 +0200
Subject: [PATCH 655/685] New visionOS0-compatible pod has been release

---
 run-tests.sh | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/run-tests.sh b/run-tests.sh
index 7d5c26d2..3ffba810 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -12,9 +12,6 @@ elif [ -n "$VALIDATOR_SUBSPEC" ]; then
       none)
         bundle exec pod lib lint --no-subspecs --fail-fast
         ;;
-      standalone)
-        bundle exec pod lib lint --subspec="${VALIDATOR_SUBSPEC}" --fail-fast --platforms=macos,ios,tvos,watchos
-        ;;
       *)
         bundle exec pod lib lint --subspec="${VALIDATOR_SUBSPEC}" --fail-fast
         ;;

From 77b493e661cff1498892dbaa48aa2205b673ce46 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 21 May 2025 22:42:20 +0200
Subject: [PATCH 656/685] Use inheritance

---
 SQLite.swift.podspec | 43 +++++--------------------------------------
 1 file changed, 5 insertions(+), 38 deletions(-)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 184ce23e..4cbd91bb 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -18,17 +18,11 @@ Pod::Spec.new do |s|
   s.default_subspec  = 'standard'
   s.swift_versions = ['5']
 
-  ios_deployment_target = '12.0'
-  tvos_deployment_target = '12.0'
-  osx_deployment_target = '10.13'
-  watchos_deployment_target = '4.0'
-  visionos_deployment_target = '1.0'
-
-  s.ios.deployment_target = ios_deployment_target
-  s.tvos.deployment_target = tvos_deployment_target
-  s.osx.deployment_target = osx_deployment_target
-  s.watchos.deployment_target = watchos_deployment_target
-  s.visionos.deployment_target = visionos_deployment_target
+  s.ios.deployment_target = '12.0'
+  s.tvos.deployment_target = '12.0'
+  s.osx.deployment_target = '10.13'
+  s.watchos.deployment_target = '4.0'
+  s.visionos.deployment_target = '1.0'
 
   s.subspec 'standard' do |ss|
     ss.source_files = 'Sources/SQLite/**/*.{c,h,m,swift}'
@@ -36,18 +30,9 @@ Pod::Spec.new do |s|
     ss.library = 'sqlite3'
     ss.resource_bundle = { 'SQLite.swift' => 'Sources/SQLite/PrivacyInfo.xcprivacy' }
     
-    ss.ios.deployment_target = ios_deployment_target
-    ss.tvos.deployment_target = tvos_deployment_target
-    ss.osx.deployment_target = osx_deployment_target
-    ss.watchos.deployment_target = watchos_deployment_target
-    ss.visionos.deployment_target = visionos_deployment_target
-
     ss.test_spec 'tests' do |test_spec|
       test_spec.resources = 'Tests/SQLiteTests/Resources/*'
       test_spec.source_files = 'Tests/SQLiteTests/*.swift'
-      test_spec.ios.deployment_target = ios_deployment_target
-      test_spec.tvos.deployment_target = tvos_deployment_target
-      test_spec.osx.deployment_target = osx_deployment_target
     end
   end
 
@@ -62,18 +47,9 @@ Pod::Spec.new do |s|
     }
     ss.dependency 'sqlite3'
     
-    ss.ios.deployment_target = ios_deployment_target
-    ss.tvos.deployment_target = tvos_deployment_target
-    ss.osx.deployment_target = osx_deployment_target
-    ss.watchos.deployment_target = watchos_deployment_target
-    ss.visionos.deployment_target = visionos_deployment_target
-
     ss.test_spec 'tests' do |test_spec|
       test_spec.resources = 'Tests/SQLiteTests/Resources/*'
       test_spec.source_files = 'Tests/SQLiteTests/*.swift'
-      test_spec.ios.deployment_target = ios_deployment_target
-      test_spec.tvos.deployment_target = tvos_deployment_target
-      test_spec.osx.deployment_target = osx_deployment_target
     end
   end
 
@@ -87,18 +63,9 @@ Pod::Spec.new do |s|
     }
     ss.dependency 'SQLCipher', '>= 4.0.0'
     
-    ss.ios.deployment_target = ios_deployment_target
-    ss.tvos.deployment_target = tvos_deployment_target
-    ss.osx.deployment_target = osx_deployment_target
-    ss.watchos.deployment_target = watchos_deployment_target
-    #ss.visionos.deployment_target = visionos_deployment_target # Not supported by SQLCipher for now
-
     ss.test_spec 'tests' do |test_spec|
       test_spec.resources = 'Tests/SQLiteTests/Resources/*'
       test_spec.source_files = 'Tests/SQLiteTests/*.swift'
-      test_spec.ios.deployment_target = ios_deployment_target
-      test_spec.tvos.deployment_target = tvos_deployment_target
-      test_spec.osx.deployment_target = osx_deployment_target
     end
   end
 end

From 7309b4337a0649d53d8ebd703f582117c1dc9e91 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 21 May 2025 23:04:30 +0200
Subject: [PATCH 657/685] Use newer Xcode

---
 .github/workflows/build.yml | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 9fbba1c5..5b6b74a6 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -5,15 +5,9 @@ env:
   IOS_VERSION: "17.2"
 jobs:
   build:
-    runs-on: macos-14
+    runs-on: macos-15
     steps:
     - uses: actions/checkout@v2
-    - name: "Select Xcode"
-      # Currently only works with Xcode 14.2:
-      # https://github.com/CocoaPods/CocoaPods/issues/11839
-      run: |
-        xcode-select -p
-        sudo xcode-select -s /Applications/Xcode_15.3.app/Contents/Developer
     - name: "Lint"
       run: make lint
     - name: "Run tests (PACKAGE_MANAGER_COMMAND: test)"

From 4166f86e844f5d1e87e25264eb9a5194dbaf3b08 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 21 May 2025 23:10:36 +0200
Subject: [PATCH 658/685] iOS 17.5

---
 .github/workflows/build.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 5b6b74a6..a0274321 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -2,7 +2,7 @@ name: Build and test
 on: [push, pull_request]
 env:
   IOS_SIMULATOR: "iPhone 15"
-  IOS_VERSION: "17.2"
+  IOS_VERSION: "17.5"
 jobs:
   build:
     runs-on: macos-15

From f312ab4d12b344f7e541df5cb0363070a0f964ba Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Wed, 21 May 2025 23:29:27 +0200
Subject: [PATCH 659/685] Update bundler

---
 Gemfile.lock | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Gemfile.lock b/Gemfile.lock
index 464ef06b..9f71603b 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -67,7 +67,7 @@ GEM
     colored2 (3.1.2)
     concurrent-ruby (1.3.5)
     connection_pool (2.5.3)
-    drb (2.2.1)
+    drb (2.2.3)
     escape (0.0.4)
     ethon (0.16.0)
       ffi (>= 1.15.0)
@@ -113,4 +113,4 @@ DEPENDENCIES
   cocoapods
 
 BUNDLED WITH
-   2.5.4
+   2.6.9

From 9dc478c9f1f6eaae43f1aa4286e3bf574bb5976d Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 22 May 2025 10:02:48 +0200
Subject: [PATCH 660/685] SchemaReader: parse and create unique constraints

---
 Sources/SQLite/Schema/SchemaDefinitions.swift | 27 ++++++++--
 Sources/SQLite/Schema/SchemaReader.swift      | 52 ++++++++++++++-----
 .../Schema/SchemaChangerTests.swift           |  9 ++--
 .../Schema/SchemaReaderTests.swift            | 32 ++++++++++--
 4 files changed, 98 insertions(+), 22 deletions(-)

diff --git a/Sources/SQLite/Schema/SchemaDefinitions.swift b/Sources/SQLite/Schema/SchemaDefinitions.swift
index 897f8557..bb4ce82b 100644
--- a/Sources/SQLite/Schema/SchemaDefinitions.swift
+++ b/Sources/SQLite/Schema/SchemaDefinitions.swift
@@ -128,6 +128,7 @@ public struct ColumnDefinition: Equatable {
     public let primaryKey: PrimaryKey?
     public let type: Affinity
     public let nullable: Bool
+    public let unique: Bool
     public let defaultValue: LiteralValue
     public let references: ForeignKey?
 
@@ -135,12 +136,14 @@ public struct ColumnDefinition: Equatable {
                 primaryKey: PrimaryKey? = nil,
                 type: Affinity,
                 nullable: Bool = true,
+                unique: Bool = false,
                 defaultValue: LiteralValue = .NULL,
                 references: ForeignKey? = nil) {
         self.name = name
         self.primaryKey = primaryKey
         self.type = type
         self.nullable = nullable
+        self.unique = unique
         self.defaultValue = defaultValue
         self.references = references
     }
@@ -244,16 +247,18 @@ public struct IndexDefinition: Equatable {
 
     public enum Order: String { case ASC, DESC }
 
-    public init(table: String, name: String, unique: Bool = false, columns: [String], `where`: String? = nil, orders: [String: Order]? = nil) {
+    public init(table: String, name: String, unique: Bool = false, columns: [String], `where`: String? = nil,
+                orders: [String: Order]? = nil, origin: Origin? = nil) {
         self.table = table
         self.name = name
         self.unique = unique
         self.columns = columns
         self.where = `where`
         self.orders = orders
+        self.origin = origin
     }
 
-    init (table: String, name: String, unique: Bool, columns: [String], indexSQL: String?) {
+    init (table: String, name: String, unique: Bool, columns: [String], indexSQL: String?, origin: Origin? = nil) {
         func wherePart(sql: String) -> String? {
             IndexDefinition.whereRe.firstMatch(in: sql, options: [], range: NSRange(location: 0, length: sql.count)).map {
                 (sql as NSString).substring(with: $0.range(at: 1))
@@ -278,7 +283,8 @@ public struct IndexDefinition: Equatable {
                   unique: unique,
                   columns: columns,
                   where: indexSQL.flatMap(wherePart),
-                  orders: (orders?.isEmpty ?? false) ? nil : orders)
+                  orders: (orders?.isEmpty ?? false) ? nil : orders,
+                  origin: origin)
     }
 
     public let table: String
@@ -287,6 +293,13 @@ public struct IndexDefinition: Equatable {
     public let columns: [String]
     public let `where`: String?
     public let orders: [String: Order]?
+    public let origin: Origin?
+
+    public enum Origin: String {
+        case uniqueConstraint = "u" // index created from a "CREATE TABLE (... UNIQUE)" column constraint
+        case createIndex = "c"      // index created explicitly via "CREATE INDEX ..."
+        case primaryKey = "pk"      // index created from a "CREATE TABLE PRIMARY KEY" column constraint
+    }
 
     enum IndexError: LocalizedError {
         case tooLong(String, String)
@@ -300,6 +313,13 @@ public struct IndexDefinition: Equatable {
         }
     }
 
+    // Indices with names of the form "sqlite_autoindex_TABLE_N" that are used to implement UNIQUE and PRIMARY KEY
+    // constraints on ordinary tables.
+    // https://sqlite.org/fileformat2.html#intschema
+    var isInternal: Bool {
+        name.starts(with: "sqlite_autoindex_")
+    }
+
     func validate() throws {
         if name.count > IndexDefinition.maxIndexLength {
             throw IndexError.tooLong(name, table)
@@ -348,6 +368,7 @@ extension ColumnDefinition {
             defaultValue.map { "DEFAULT \($0)" },
             primaryKey.map { $0.toSQL() },
             nullable ? nil : "NOT NULL",
+            unique ? "UNIQUE" : nil,
             references.map { $0.toSQL() }
         ].compactMap { $0 }
          .joined(separator: " ")
diff --git a/Sources/SQLite/Schema/SchemaReader.swift b/Sources/SQLite/Schema/SchemaReader.swift
index 1989ad6f..a67fb94f 100644
--- a/Sources/SQLite/Schema/SchemaReader.swift
+++ b/Sources/SQLite/Schema/SchemaReader.swift
@@ -21,7 +21,7 @@ public class SchemaReader {
         let foreignKeys: [String: [ColumnDefinition.ForeignKey]] =
             Dictionary(grouping: try foreignKeys(table: table), by: { $0.column })
 
-        return try connection.prepareRowIterator("PRAGMA table_info(\(table.quote()))")
+        let columnDefinitions = try connection.prepareRowIterator("PRAGMA table_info(\(table.quote()))")
             .map { (row: Row) -> ColumnDefinition in
                 ColumnDefinition(
                     name: row[TableInfoTable.nameColumn],
@@ -29,10 +29,27 @@ public class SchemaReader {
                         try parsePrimaryKey(column: row[TableInfoTable.nameColumn]) : nil,
                     type: ColumnDefinition.Affinity(row[TableInfoTable.typeColumn]),
                     nullable: row[TableInfoTable.notNullColumn] == 0,
+                    unique: false,
                     defaultValue: LiteralValue(row[TableInfoTable.defaultValueColumn]),
                     references: foreignKeys[row[TableInfoTable.nameColumn]]?.first
                 )
             }
+
+        let internalIndexes = try indexDefinitions(table: table).filter { $0.isInternal }
+        return columnDefinitions.map { definition in
+            if let index = internalIndexes.first(where: { $0.columns.contains(definition.name) }), index.origin == .uniqueConstraint {
+
+                ColumnDefinition(name: definition.name,
+                                 primaryKey: definition.primaryKey,
+                                 type: definition.type,
+                                 nullable: definition.nullable,
+                                 unique: true,
+                                 defaultValue: definition.defaultValue,
+                                 references: definition.references)
+            } else {
+                definition
+            }
+        }
     }
 
     public func objectDefinitions(name: String? = nil,
@@ -66,27 +83,26 @@ public class SchemaReader {
                 .first
         }
 
-        func columns(name: String) throws -> [String] {
+        func indexInfos(name: String) throws -> [IndexInfo] {
             try connection.prepareRowIterator("PRAGMA index_info(\(name.quote()))")
                 .compactMap { row in
-                    row[IndexInfoTable.nameColumn]
+                    IndexInfo(name: row[IndexInfoTable.nameColumn],
+                              columnRank: row[IndexInfoTable.seqnoColumn],
+                              columnRankWithinTable: row[IndexInfoTable.cidColumn])
+
                 }
         }
 
         return try connection.prepareRowIterator("PRAGMA index_list(\(table.quote()))")
             .compactMap { row -> IndexDefinition? in
                 let name = row[IndexListTable.nameColumn]
-                guard !name.starts(with: "sqlite_") else {
-                    // Indexes SQLite creates implicitly for internal use start with "sqlite_".
-                    // See https://www.sqlite.org/fileformat2.html#intschema
-                    return nil
-                }
                 return IndexDefinition(
                     table: table,
                     name: name,
                     unique: row[IndexListTable.uniqueColumn] == 1,
-                    columns: try columns(name: name),
-                    indexSQL: try indexSQL(name: name)
+                    columns: try indexInfos(name: name).compactMap { $0.name },
+                    indexSQL: try indexSQL(name: name),
+                    origin: IndexDefinition.Origin(rawValue: row[IndexListTable.originColumn])
                 )
             }
     }
@@ -123,6 +139,15 @@ public class SchemaReader {
             objectDefinitions(name: name, type: .table, temp: true)
         ).compactMap(\.sql).first
     }
+
+    struct IndexInfo {
+        let name: String?
+        // The rank of the column within the index. (0 means left-most.)
+        let columnRank: Int
+        // The rank of the column within the table being indexed.
+        // A value of -1 means rowid and a value of -2 means that an expression is being used
+        let columnRankWithinTable: Int
+    }
 }
 
 private enum SchemaTable {
@@ -159,11 +184,12 @@ private enum TableInfoTable {
 
 private enum IndexInfoTable {
     // The rank of the column within the index. (0 means left-most.)
-    static let seqnoColumn = Expression<Int64>("seqno")
+    static let seqnoColumn = Expression<Int>("seqno")
     // The rank of the column within the table being indexed.
     // A value of -1 means rowid and a value of -2 means that an expression is being used.
-    static let cidColumn = Expression<Int64>("cid")
-    // The name of the column being indexed. This columns is NULL if the column is the rowid or an expression.
+    static let cidColumn = Expression<Int>("cid")
+    // The name of the column being indexed.
+    // This columns is NULL if the column is the rowid or an expression.
     static let nameColumn = Expression<String?>("name")
 }
 
diff --git a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
index 02a82267..724c2d0c 100644
--- a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
@@ -158,7 +158,7 @@ class SchemaChangerTests: SQLiteTestCase {
     func test_create_table() throws {
         try schemaChanger.create(table: "foo") { table in
             table.add(column: .init(name: "id", primaryKey: .init(autoIncrement: true), type: .INTEGER))
-            table.add(column: .init(name: "name", type: .TEXT, nullable: false))
+            table.add(column: .init(name: "name", type: .TEXT, nullable: false, unique: true))
             table.add(column: .init(name: "age", type: .INTEGER))
 
             table.add(index: .init(table: table.name,
@@ -179,25 +179,28 @@ class SchemaChangerTests: SQLiteTestCase {
                              primaryKey: .init(autoIncrement: true, onConflict: nil),
                              type: .INTEGER,
                              nullable: true,
+                             unique: false,
                              defaultValue: .NULL,
                              references: nil),
             ColumnDefinition(name: "name",
                              primaryKey: nil,
                              type: .TEXT,
                              nullable: false,
+                             unique: true,
                              defaultValue: .NULL,
                              references: nil),
             ColumnDefinition(name: "age",
                              primaryKey: nil,
                              type: .INTEGER,
                              nullable: true,
+                             unique: false,
                              defaultValue: .NULL,
                              references: nil)
         ])
 
-        let indexes = try schema.indexDefinitions(table: "foo")
+        let indexes = try schema.indexDefinitions(table: "foo").filter { !$0.isInternal }
         XCTAssertEqual(indexes, [
-            IndexDefinition(table: "foo", name: "nameIndex", unique: true, columns: ["name"], where: nil, orders: nil)
+            IndexDefinition(table: "foo", name: "nameIndex", unique: true, columns: ["name"], where: nil, orders: nil, origin: .createIndex)
         ])
     }
 
diff --git a/Tests/SQLiteTests/Schema/SchemaReaderTests.swift b/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
index 8c033e41..01047c9c 100644
--- a/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
@@ -18,41 +18,48 @@ class SchemaReaderTests: SQLiteTestCase {
                              primaryKey: .init(autoIncrement: false, onConflict: nil),
                              type: .INTEGER,
                              nullable: true,
+                             unique: false,
                              defaultValue: .NULL,
                              references: nil),
             ColumnDefinition(name: "email",
                              primaryKey: nil,
                              type: .TEXT,
                              nullable: false,
+                             unique: true,
                              defaultValue: .NULL,
                              references: nil),
             ColumnDefinition(name: "age",
                              primaryKey: nil,
                              type: .INTEGER,
                              nullable: true,
+                             unique: false,
                              defaultValue: .NULL,
                              references: nil),
             ColumnDefinition(name: "salary",
                              primaryKey: nil,
                              type: .REAL,
                              nullable: true,
+                             unique: false,
                              defaultValue: .NULL,
                              references: nil),
             ColumnDefinition(name: "admin",
                              primaryKey: nil,
                              type: .NUMERIC,
                              nullable: false,
+                             unique: false,
                              defaultValue: .numericLiteral("0"),
                              references: nil),
             ColumnDefinition(name: "manager_id",
                              primaryKey: nil, type: .INTEGER,
                              nullable: true,
+                             unique: false,
                              defaultValue: .NULL,
                              references: .init(table: "users", column: "manager_id", primaryKey: "id", onUpdate: nil, onDelete: nil)),
             ColumnDefinition(name: "created_at",
                              primaryKey: nil,
                              type: .NUMERIC,
                              nullable: true,
+                             unique: false,
                              defaultValue: .NULL,
                              references: nil)
         ])
@@ -68,6 +75,24 @@ class SchemaReaderTests: SQLiteTestCase {
                 primaryKey: .init(autoIncrement: true, onConflict: .IGNORE),
                 type: .INTEGER,
                 nullable: true,
+                unique: false,
+                defaultValue: .NULL,
+                references: nil)
+            ]
+        )
+    }
+
+    func test_columnDefinitions_parses_unique() throws {
+        try db.run("CREATE TABLE t (name TEXT UNIQUE)")
+
+        let columns = try schemaReader.columnDefinitions(table: "t")
+        XCTAssertEqual(columns, [
+            ColumnDefinition(
+                name: "name",
+                primaryKey: nil,
+                type: .TEXT,
+                nullable: true,
+                unique: true,
                 defaultValue: .NULL,
                 references: nil)
             ]
@@ -128,13 +153,13 @@ class SchemaReaderTests: SQLiteTestCase {
     }
 
     func test_indexDefinitions_no_index() throws {
-        let indexes = try schemaReader.indexDefinitions(table: "users")
+        let indexes = try schemaReader.indexDefinitions(table: "users").filter { !$0.isInternal }
         XCTAssertTrue(indexes.isEmpty)
     }
 
     func test_indexDefinitions_with_index() throws {
         try db.run("CREATE UNIQUE INDEX index_users ON users (age DESC) WHERE age IS NOT NULL")
-        let indexes = try schemaReader.indexDefinitions(table: "users")
+        let indexes = try schemaReader.indexDefinitions(table: "users").filter { !$0.isInternal }
 
         XCTAssertEqual(indexes, [
             IndexDefinition(
@@ -143,7 +168,8 @@ class SchemaReaderTests: SQLiteTestCase {
                 unique: true,
                 columns: ["age"],
                 where: "age IS NOT NULL",
-                orders: ["age": .DESC]
+                orders: ["age": .DESC],
+                origin: .createIndex
             )
         ])
     }

From 374d99da2107656adf12670feea4f167853321d9 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 22 May 2025 10:53:36 +0200
Subject: [PATCH 661/685] Use cocoapods with watchOS fix

---
 Gemfile      |  2 +-
 Gemfile.lock | 46 ++++++++++++++++++++++++++--------------------
 2 files changed, 27 insertions(+), 21 deletions(-)

diff --git a/Gemfile b/Gemfile
index 1f2ebb87..2bb803ca 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,3 +1,3 @@
 source "https://rubygems.org"
 
-gem 'cocoapods' 
+gem 'cocoapods', :git => 'https://github.com/jberkel/CocoaPods.git', branch: 'watchos-fourflusher'
diff --git a/Gemfile.lock b/Gemfile.lock
index 9f71603b..20ed2aad 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,3 +1,27 @@
+GIT
+  remote: https://github.com/jberkel/CocoaPods.git
+  revision: 899f273f298ea20de2378687ea55331004b39371
+  branch: watchos-fourflusher
+  specs:
+    cocoapods (1.16.2)
+      addressable (~> 2.8)
+      claide (>= 1.0.2, < 2.0)
+      cocoapods-core (= 1.16.2)
+      cocoapods-deintegrate (>= 1.0.3, < 2.0)
+      cocoapods-downloader (>= 2.1, < 3.0)
+      cocoapods-plugins (>= 1.0.0, < 2.0)
+      cocoapods-search (>= 1.0.0, < 2.0)
+      cocoapods-trunk (>= 1.6.0, < 2.0)
+      cocoapods-try (>= 1.1.0, < 2.0)
+      colored2 (~> 3.1)
+      escape (~> 0.0.4)
+      fourflusher (>= 2.3.0, < 3.0)
+      gh_inspector (~> 1.0)
+      molinillo (~> 0.8.0)
+      nap (~> 1.0)
+      ruby-macho (~> 4.1.0)
+      xcodeproj (>= 1.27.0, < 2.0)
+
 GEM
   remote: https://rubygems.org/
   specs:
@@ -27,24 +51,6 @@ GEM
     benchmark (0.4.0)
     bigdecimal (3.1.9)
     claide (1.1.0)
-    cocoapods (1.16.2)
-      addressable (~> 2.8)
-      claide (>= 1.0.2, < 2.0)
-      cocoapods-core (= 1.16.2)
-      cocoapods-deintegrate (>= 1.0.3, < 2.0)
-      cocoapods-downloader (>= 2.1, < 3.0)
-      cocoapods-plugins (>= 1.0.0, < 2.0)
-      cocoapods-search (>= 1.0.0, < 2.0)
-      cocoapods-trunk (>= 1.6.0, < 2.0)
-      cocoapods-try (>= 1.1.0, < 2.0)
-      colored2 (~> 3.1)
-      escape (~> 0.0.4)
-      fourflusher (>= 2.3.0, < 3.0)
-      gh_inspector (~> 1.0)
-      molinillo (~> 0.8.0)
-      nap (~> 1.0)
-      ruby-macho (>= 2.3.0, < 3.0)
-      xcodeproj (>= 1.27.0, < 2.0)
     cocoapods-core (1.16.2)
       activesupport (>= 5.0, < 8)
       addressable (~> 2.8)
@@ -91,7 +97,7 @@ GEM
     nkf (0.2.0)
     public_suffix (4.0.7)
     rexml (3.4.1)
-    ruby-macho (2.5.1)
+    ruby-macho (4.1.0)
     securerandom (0.4.1)
     typhoeus (1.4.1)
       ethon (>= 0.9.0)
@@ -110,7 +116,7 @@ PLATFORMS
   ruby
 
 DEPENDENCIES
-  cocoapods
+  cocoapods!
 
 BUNDLED WITH
    2.6.9

From 108431244de611050f25c20efd02bcfe68687b28 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 22 May 2025 11:52:52 +0200
Subject: [PATCH 662/685] Disable visionOS for SQLCipher

---
 SQLite.swift.podspec | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index 4cbd91bb..d0ccb136 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -54,6 +54,13 @@ Pod::Spec.new do |s|
   end
 
   s.subspec 'SQLCipher' do |ss|
+    # Disable unsupported visionOS
+    # https://github.com/sqlcipher/sqlcipher/issues/483
+    ss.ios.deployment_target = s.deployment_target(:ios)
+    ss.tvos.deployment_target = s.deployment_target(:tvos)
+    ss.osx.deployment_target = s.deployment_target(:osx)
+    ss.watchos.deployment_target = s.deployment_target(:watchos)
+
     ss.source_files = 'Sources/SQLite/**/*.{c,h,m,swift}'
     ss.resource_bundle = { 'SQLite.swift' => 'Sources/SQLite/PrivacyInfo.xcprivacy' }
 

From 718c7988780f803ede87c03ef2cdce58ea762656 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 22 May 2025 12:21:19 +0200
Subject: [PATCH 663/685] Add comment

---
 Gemfile      | 1 +
 Gemfile.lock | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/Gemfile b/Gemfile
index 2bb803ca..2770e85d 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,3 +1,4 @@
 source "https://rubygems.org"
 
+# https://github.com/CocoaPods/CocoaPods/pull/12816
 gem 'cocoapods', :git => 'https://github.com/jberkel/CocoaPods.git', branch: 'watchos-fourflusher'
diff --git a/Gemfile.lock b/Gemfile.lock
index 20ed2aad..7dac2c18 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,6 +1,6 @@
 GIT
   remote: https://github.com/jberkel/CocoaPods.git
-  revision: 899f273f298ea20de2378687ea55331004b39371
+  revision: 32a90c184bc5dc9ec8b7b9b8ad08e98b7253dec2
   branch: watchos-fourflusher
   specs:
     cocoapods (1.16.2)

From c812caf9c432bc196f87648b56551dff2c0017e3 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 22 May 2025 13:30:36 +0200
Subject: [PATCH 664/685] Make ForeignKey public, rename fields for clarity

---
 Sources/SQLite/Schema/SchemaDefinitions.swift | 23 ++++++++++---
 Sources/SQLite/Schema/SchemaReader.swift      |  8 ++---
 .../Schema/SchemaChangerTests.swift           | 34 +++++++++++++++++++
 .../Schema/SchemaDefinitionsTests.swift       |  8 ++---
 .../Schema/SchemaReaderTests.swift            |  4 +--
 5 files changed, 62 insertions(+), 15 deletions(-)

diff --git a/Sources/SQLite/Schema/SchemaDefinitions.swift b/Sources/SQLite/Schema/SchemaDefinitions.swift
index bb4ce82b..d7803999 100644
--- a/Sources/SQLite/Schema/SchemaDefinitions.swift
+++ b/Sources/SQLite/Schema/SchemaDefinitions.swift
@@ -117,11 +117,24 @@ public struct ColumnDefinition: Equatable {
     }
 
     public struct ForeignKey: Equatable {
-        let table: String
-        let column: String
-        let primaryKey: String?
+        let fromColumn: String
+        let toTable: String
+        // when null, use primary key of "toTable"
+        let toColumn: String?
         let onUpdate: String?
         let onDelete: String?
+
+        public init(toTable: String, toColumn: String? = nil, onUpdate: String? = nil, onDelete: String? = nil) {
+            self.init(fromColumn: "", toTable: toTable, toColumn: toColumn, onUpdate: onUpdate, onDelete: onDelete)
+        }
+
+        public init(fromColumn: String, toTable: String, toColumn: String? = nil, onUpdate: String? = nil, onDelete: String? = nil) {
+            self.fromColumn = fromColumn
+            self.toTable = toTable
+            self.toColumn = toColumn
+            self.onUpdate = onUpdate
+            self.onDelete = onDelete
+        }
     }
 
     public let name: String
@@ -400,8 +413,8 @@ extension ColumnDefinition.ForeignKey {
     func toSQL() -> String {
         ([
             "REFERENCES",
-            table.quote(),
-            primaryKey.map { "(\($0.quote()))" },
+            toTable.quote(),
+            toColumn.map { "(\($0.quote()))" },
             onUpdate.map { "ON UPDATE \($0)" },
             onDelete.map { "ON DELETE \($0)" }
         ] as [String?]).compactMap { $0 }
diff --git a/Sources/SQLite/Schema/SchemaReader.swift b/Sources/SQLite/Schema/SchemaReader.swift
index a67fb94f..995cd4d7 100644
--- a/Sources/SQLite/Schema/SchemaReader.swift
+++ b/Sources/SQLite/Schema/SchemaReader.swift
@@ -19,7 +19,7 @@ public class SchemaReader {
         }
 
         let foreignKeys: [String: [ColumnDefinition.ForeignKey]] =
-            Dictionary(grouping: try foreignKeys(table: table), by: { $0.column })
+            Dictionary(grouping: try foreignKeys(table: table), by: { $0.fromColumn })
 
         let columnDefinitions = try connection.prepareRowIterator("PRAGMA table_info(\(table.quote()))")
             .map { (row: Row) -> ColumnDefinition in
@@ -111,9 +111,9 @@ public class SchemaReader {
         try connection.prepareRowIterator("PRAGMA foreign_key_list(\(table.quote()))")
             .map { row in
                 ColumnDefinition.ForeignKey(
-                    table: row[ForeignKeyListTable.tableColumn],
-                    column: row[ForeignKeyListTable.fromColumn],
-                    primaryKey: row[ForeignKeyListTable.toColumn],
+                    fromColumn: row[ForeignKeyListTable.fromColumn],
+                    toTable: row[ForeignKeyListTable.tableColumn],
+                    toColumn: row[ForeignKeyListTable.toColumn],
                     onUpdate: row[ForeignKeyListTable.onUpdateColumn] == TableBuilder.Dependency.noAction.rawValue
                         ? nil : row[ForeignKeyListTable.onUpdateColumn],
                     onDelete: row[ForeignKeyListTable.onDeleteColumn] == TableBuilder.Dependency.noAction.rawValue
diff --git a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
index 724c2d0c..b08344fc 100644
--- a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
@@ -269,4 +269,38 @@ class SchemaChangerTests: SQLiteTestCase {
             table.add(index: .init(table: "foo", name: "name_index", unique: true, columns: ["name"], indexSQL: nil))
         }
     }
+
+    func test_create_table_with_foreign_key_reference() throws {
+        try schemaChanger.create(table: "foo") { table in
+            table.add(column: .init(name: "id", primaryKey: .init(autoIncrement: true), type: .INTEGER))
+        }
+
+        try schemaChanger.create(table: "bars") { table in
+            table.add(column: .init(name: "id", primaryKey: .init(autoIncrement: true), type: .INTEGER))
+            table.add(column: .init(name: "foo_id",
+                                    type: .INTEGER,
+                                    nullable: false,
+                                    references: .init(toTable: "foo", toColumn: "id")))
+        }
+
+        let barColumns = try schema.columnDefinitions(table: "bars")
+
+        XCTAssertEqual([
+            ColumnDefinition(name: "id",
+                             primaryKey: .init(autoIncrement: true, onConflict: nil),
+                             type: .INTEGER,
+                             nullable: true,
+                             unique: false,
+                             defaultValue: .NULL,
+                             references: nil),
+
+            ColumnDefinition(name: "foo_id",
+                             primaryKey: nil,
+                             type: .INTEGER,
+                             nullable: false,
+                             unique: false,
+                             defaultValue: .NULL,
+                             references: .init(fromColumn: "foo_id", toTable: "foo", toColumn: "id", onUpdate: nil, onDelete: nil))
+        ], barColumns)
+    }
 }
diff --git a/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift b/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
index 8b7e27e3..1c648bd8 100644
--- a/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaDefinitionsTests.swift
@@ -11,7 +11,7 @@ class ColumnDefinitionTests: XCTestCase {
 
         ("\"other_id\" INTEGER NOT NULL REFERENCES \"other_table\" (\"some_id\")",
         ColumnDefinition(name: "other_id", primaryKey: nil, type: .INTEGER, nullable: false, defaultValue: .NULL,
-                         references: .init(table: "other_table", column: "", primaryKey: "some_id", onUpdate: nil, onDelete: nil))),
+                         references: .init(fromColumn: "", toTable: "other_table", toColumn: "some_id", onUpdate: nil, onDelete: nil))),
 
         ("\"text\" TEXT",
         ColumnDefinition(name: "text", primaryKey: nil, type: .TEXT, nullable: true, defaultValue: .NULL, references: nil)),
@@ -245,9 +245,9 @@ class ForeignKeyDefinitionTests: XCTestCase {
     func test_toSQL() {
         XCTAssertEqual(
             ColumnDefinition.ForeignKey(
-                table: "foo",
-                column: "bar",
-                primaryKey: "bar_id",
+                fromColumn: "bar",
+                toTable: "foo",
+                toColumn: "bar_id",
                 onUpdate: nil,
                 onDelete: "SET NULL"
             ).toSQL(), """
diff --git a/Tests/SQLiteTests/Schema/SchemaReaderTests.swift b/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
index 01047c9c..8963070f 100644
--- a/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
@@ -54,7 +54,7 @@ class SchemaReaderTests: SQLiteTestCase {
                              nullable: true,
                              unique: false,
                              defaultValue: .NULL,
-                             references: .init(table: "users", column: "manager_id", primaryKey: "id", onUpdate: nil, onDelete: nil)),
+                             references: .init(fromColumn: "manager_id", toTable: "users", toColumn: "id", onUpdate: nil, onDelete: nil)),
             ColumnDefinition(name: "created_at",
                              primaryKey: nil,
                              type: .NUMERIC,
@@ -194,7 +194,7 @@ class SchemaReaderTests: SQLiteTestCase {
 
         let foreignKeys = try schemaReader.foreignKeys(table: "test_links")
         XCTAssertEqual(foreignKeys, [
-            .init(table: "users", column: "test_id", primaryKey: "id", onUpdate: nil, onDelete: nil)
+            .init(fromColumn: "test_id", toTable: "users", toColumn: "id", onUpdate: nil, onDelete: nil)
         ])
     }
 

From 1c440766b22019190a9c78731f0c69b78f5d177b Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 22 May 2025 17:06:41 +0200
Subject: [PATCH 665/685] Add drop(index:)

---
 Sources/SQLite/Schema/SchemaChanger.swift     | 10 ++++-
 .../Schema/SchemaChangerTests.swift           | 38 +++++++++++++++++++
 2 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/Sources/SQLite/Schema/SchemaChanger.swift b/Sources/SQLite/Schema/SchemaChanger.swift
index 13222dab..7ba458c1 100644
--- a/Sources/SQLite/Schema/SchemaChanger.swift
+++ b/Sources/SQLite/Schema/SchemaChanger.swift
@@ -45,6 +45,7 @@ public class SchemaChanger: CustomStringConvertible {
         case addColumn(ColumnDefinition)
         case addIndex(IndexDefinition, ifNotExists: Bool)
         case dropColumn(String)
+        case dropIndex(String, ifExists: Bool)
         case renameColumn(String, String)
         case renameTable(String)
         case createTable(columns: [ColumnDefinition], ifNotExists: Bool)
@@ -60,6 +61,8 @@ public class SchemaChanger: CustomStringConvertible {
                 return "ALTER TABLE \(table.quote()) RENAME COLUMN \(from.quote()) TO \(to.quote())"
             case .dropColumn(let column) where SQLiteFeature.dropColumn.isSupported(by: version):
                 return "ALTER TABLE \(table.quote()) DROP COLUMN \(column.quote())"
+            case .dropIndex(let name, let ifExists):
+                return "DROP INDEX \(ifExists ? " IF EXISTS " : "") \(name.quote())"
             case .createTable(let columns, let ifNotExists):
                 return "CREATE TABLE \(ifNotExists ? " IF NOT EXISTS " : "") \(table.quote()) (" +
                     columns.map { $0.toSQL() }.joined(separator: ", ") +
@@ -111,6 +114,10 @@ public class SchemaChanger: CustomStringConvertible {
             operations.append(.dropColumn(column))
         }
 
+        public func drop(index: String, ifExists: Bool = false) {
+            operations.append(.dropIndex(index, ifExists: ifExists))
+        }
+
         public func rename(column: String, to: String) {
             operations.append(.renameColumn(column, to))
         }
@@ -324,8 +331,9 @@ extension TableDefinition {
     func apply(_ operation: SchemaChanger.Operation?) -> TableDefinition {
         switch operation {
         case .none: return self
-        case .createTable, .addIndex: fatalError()
+        case .createTable, .addIndex, .dropIndex: fatalError()
         case .addColumn: fatalError("Use 'ALTER TABLE ADD COLUMN (...)'")
+
         case .dropColumn(let column):
             return TableDefinition(name: name,
                 columns: columns.filter { $0.name != column },
diff --git a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
index b08344fc..75331a97 100644
--- a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
@@ -124,6 +124,44 @@ class SchemaChangerTests: SQLiteTestCase {
         }
     }
 
+    func test_drop_index() throws {
+        try db.execute("""
+            CREATE INDEX age_index ON users(age)
+        """)
+
+        try schemaChanger.alter(table: "users") { table in
+            table.drop(index: "age_index")
+        }
+        let indexes = try schema.indexDefinitions(table: "users").filter { !$0.isInternal }
+        XCTAssertEqual(0, indexes.count)
+    }
+
+    func test_drop_index_if_exists() throws {
+        try db.execute("""
+            CREATE INDEX age_index ON users(age)
+        """)
+
+        try schemaChanger.alter(table: "users") { table in
+            table.drop(index: "age_index")
+        }
+
+        try schemaChanger.alter(table: "users") { table in
+            table.drop(index: "age_index", ifExists: true)
+        }
+
+        XCTAssertThrowsError(
+            try schemaChanger.alter(table: "users") { table in
+                table.drop(index: "age_index", ifExists: false)
+            }
+        ) { error in
+            if case Result.error(let message, _, _) =  error {
+                XCTAssertEqual(message, "no such index: age_index")
+            } else {
+                XCTFail("unexpected error \(error)")
+            }
+        }
+    }
+
     func test_drop_table() throws {
         try schemaChanger.drop(table: "users")
         XCTAssertThrowsError(try db.scalar(users.count)) { error in

From 08bed022dc12289d64278cc5ad2e9a63868fb12f Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 22 May 2025 17:23:02 +0200
Subject: [PATCH 666/685] Implement add(index:)

---
 Sources/SQLite/Schema/SchemaChanger.swift     |  4 +++
 .../Schema/SchemaChangerTests.swift           | 34 +++++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/Sources/SQLite/Schema/SchemaChanger.swift b/Sources/SQLite/Schema/SchemaChanger.swift
index 7ba458c1..3badb8d8 100644
--- a/Sources/SQLite/Schema/SchemaChanger.swift
+++ b/Sources/SQLite/Schema/SchemaChanger.swift
@@ -110,6 +110,10 @@ public class SchemaChanger: CustomStringConvertible {
             operations.append(.addColumn(column))
         }
 
+        public func add(index: IndexDefinition, ifNotExists: Bool = false) {
+            operations.append(.addIndex(index, ifNotExists: ifNotExists))
+        }
+
         public func drop(column: String) {
             operations.append(.dropColumn(column))
         }
diff --git a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
index 75331a97..dafdea54 100644
--- a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
@@ -124,6 +124,40 @@ class SchemaChangerTests: SQLiteTestCase {
         }
     }
 
+    func test_add_index() throws {
+        try schemaChanger.alter(table: "users") { table in
+            table.add(index: .init(table: table.name, name: "age_index", unique: false, columns: ["age"], indexSQL: nil))
+        }
+
+        let indexes = try schema.indexDefinitions(table: "users").filter { !$0.isInternal }
+        XCTAssertEqual([
+            IndexDefinition(table: "users",
+                            name: "age_index",
+                            unique: false,
+                            columns: ["age"],
+                            where: nil,
+                            orders: nil,
+                            origin: .createIndex)
+        ], indexes)
+    }
+
+    func test_add_index_if_not_exists() throws {
+        let index = IndexDefinition(table: "users", name: "age_index", unique: false, columns: ["age"], indexSQL: nil)
+        try schemaChanger.alter(table: "users") { table in
+            table.add(index: index)
+        }
+
+        try schemaChanger.alter(table: "users") { table in
+            table.add(index: index, ifNotExists: true)
+        }
+
+        XCTAssertThrowsError(
+            try schemaChanger.alter(table: "users") { table in
+                table.add(index: index, ifNotExists: false)
+            }
+        )
+    }
+
     func test_drop_index() throws {
         try db.execute("""
             CREATE INDEX age_index ON users(age)

From 3def7d60f70b109e0f74f6d42bac61d631de56dd Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 22 May 2025 17:45:33 +0200
Subject: [PATCH 667/685] Make name public, expose plain SQL run

---
 Sources/SQLite/Schema/SchemaChanger.swift | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/Sources/SQLite/Schema/SchemaChanger.swift b/Sources/SQLite/Schema/SchemaChanger.swift
index 3badb8d8..3e146df7 100644
--- a/Sources/SQLite/Schema/SchemaChanger.swift
+++ b/Sources/SQLite/Schema/SchemaChanger.swift
@@ -100,7 +100,7 @@ public class SchemaChanger: CustomStringConvertible {
     public class AlterTableDefinition {
         fileprivate var operations: [Operation] = []
 
-        let name: String
+        public let name: String
 
         init(name: String) {
             self.name = name
@@ -223,6 +223,11 @@ public class SchemaChanger: CustomStringConvertible {
         try connection.run("ALTER TABLE \(table.quote()) RENAME TO \(to.quote())")
     }
 
+    // Runs arbitrary SQL. Should only be used if no predefined operations exist.
+    public func run(sql: String) throws {
+        try connection.run(sql)
+    }
+
     private func run(table: String, operation: Operation) throws {
         try operation.validate()
 

From 25bd06392f65d7ca75ffc481471de05905ec1c79 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 22 May 2025 17:53:46 +0200
Subject: [PATCH 668/685] Better API, test

---
 Sources/SQLite/Schema/SchemaChanger.swift         | 5 +++--
 Tests/SQLiteTests/Schema/SchemaChangerTests.swift | 5 +++++
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/Sources/SQLite/Schema/SchemaChanger.swift b/Sources/SQLite/Schema/SchemaChanger.swift
index 3e146df7..6fae532a 100644
--- a/Sources/SQLite/Schema/SchemaChanger.swift
+++ b/Sources/SQLite/Schema/SchemaChanger.swift
@@ -224,8 +224,9 @@ public class SchemaChanger: CustomStringConvertible {
     }
 
     // Runs arbitrary SQL. Should only be used if no predefined operations exist.
-    public func run(sql: String) throws {
-        try connection.run(sql)
+    @discardableResult
+    public func run(_ sql: String, _ bindings: Binding?...) throws -> Statement {
+        return try connection.run(sql, bindings)
     }
 
     private func run(table: String, operation: Operation) throws {
diff --git a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
index dafdea54..d942fba4 100644
--- a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
@@ -375,4 +375,9 @@ class SchemaChangerTests: SQLiteTestCase {
                              references: .init(fromColumn: "foo_id", toTable: "foo", toColumn: "id", onUpdate: nil, onDelete: nil))
         ], barColumns)
     }
+
+    func test_run_arbitrary_sql() throws {
+        try schemaChanger.run("DROP TABLE users")
+        XCTAssertEqual(0, try schema.objectDefinitions(name: "users", type: .table).count)
+    }
 }

From 8938697549dccc21803c5cbef9f2e5fec7ee274a Mon Sep 17 00:00:00 2001
From: ha100 <thastik@gmail.com>
Date: Sun, 8 Jun 2025 05:38:36 +0200
Subject: [PATCH 669/685] change CSQLite dep to SwiftToolchainCSQLite to allow
 swift sdk cross compilation

---
 Package.swift                                 | 69 +++++++++++--------
 Sources/SQLite/Core/Backup.swift              |  2 +-
 .../SQLite/Core/Connection+Aggregation.swift  |  2 +-
 Sources/SQLite/Core/Connection+Attach.swift   |  2 +-
 Sources/SQLite/Core/Connection.swift          |  2 +-
 Sources/SQLite/Core/Result.swift              |  2 +-
 Sources/SQLite/Core/Statement.swift           |  2 +-
 Sources/SQLite/Helpers.swift                  |  2 +-
 .../Core/Connection+AttachTests.swift         |  2 +-
 .../Core/Connection+PragmaTests.swift         |  2 +-
 Tests/SQLiteTests/Core/ConnectionTests.swift  |  2 +-
 Tests/SQLiteTests/Core/ResultTests.swift      |  2 +-
 Tests/SQLiteTests/Core/StatementTests.swift   |  2 +-
 .../Extensions/FTSIntegrationTests.swift      |  2 +-
 .../Typed/CustomAggregationTests.swift        |  2 +-
 .../Typed/QueryIntegrationTests.swift         |  2 +-
 Tests/SQLiteTests/Typed/QueryTests.swift      |  2 +-
 17 files changed, 56 insertions(+), 45 deletions(-)

diff --git a/Package.swift b/Package.swift
index 238661ae..690d41e2 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,6 +1,38 @@
 // swift-tools-version:5.9
 import PackageDescription
 
+let deps: [Package.Dependency] = [
+    .github("swiftlang/swift-toolchain-sqlite", exact: "1.0.4")
+]
+
+let targets: [Target] = [
+    .target(
+        name: "SQLite",
+        dependencies: [
+            .product(name: "SwiftToolchainCSQLite", package: "swift-toolchain-sqlite")
+        ],
+        exclude: [
+            "Info.plist"
+        ]
+    )
+]
+
+let testTargets: [Target] = [
+    .testTarget(
+        name: "SQLiteTests",
+        dependencies: [
+            "SQLite"
+        ],
+        path: "Tests/SQLiteTests",
+        exclude: [
+            "Info.plist"
+        ],
+        resources: [
+            .copy("Resources")
+        ]
+    )
+]
+
 let package = Package(
     name: "SQLite.swift",
     platforms: [
@@ -16,34 +48,13 @@ let package = Package(
             targets: ["SQLite"]
         )
     ],
-    targets: [
-        .target(
-            name: "SQLite",
-            exclude: [
-                "Info.plist"
-            ]
-        ),
-        .testTarget(
-            name: "SQLiteTests",
-            dependencies: [
-                "SQLite"
-            ],
-            path: "Tests/SQLiteTests",
-            exclude: [
-                "Info.plist"
-            ],
-            resources: [
-                .copy("Resources")
-            ]
-        )
-    ]
+    dependencies: deps,
+    targets: targets + testTargets
 )
 
-#if os(Linux)
-package.dependencies = [
-    .package(url: "https://github.com/stephencelis/CSQLite.git", from: "0.0.3")
-]
-package.targets.first?.dependencies += [
-    .product(name: "CSQLite", package: "CSQLite")
-]
-#endif
+extension Package.Dependency {
+
+    static func github(_ repo: String, exact ver: Version) -> Package.Dependency {
+        .package(url: "https://github.com/\(repo)", exact: ver)
+    }
+}
diff --git a/Sources/SQLite/Core/Backup.swift b/Sources/SQLite/Core/Backup.swift
index 0eebbdd5..5e741ecd 100644
--- a/Sources/SQLite/Core/Backup.swift
+++ b/Sources/SQLite/Core/Backup.swift
@@ -29,7 +29,7 @@ import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
 #elseif os(Linux)
-import CSQLite
+import SwiftToolchainCSQLite
 #else
 import SQLite3
 #endif
diff --git a/Sources/SQLite/Core/Connection+Aggregation.swift b/Sources/SQLite/Core/Connection+Aggregation.swift
index 4eea76c3..bfe253a7 100644
--- a/Sources/SQLite/Core/Connection+Aggregation.swift
+++ b/Sources/SQLite/Core/Connection+Aggregation.swift
@@ -4,7 +4,7 @@ import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
 #elseif os(Linux)
-import CSQLite
+import SwiftToolchainCSQLite
 #else
 import SQLite3
 #endif
diff --git a/Sources/SQLite/Core/Connection+Attach.swift b/Sources/SQLite/Core/Connection+Attach.swift
index 8a25e51d..32461468 100644
--- a/Sources/SQLite/Core/Connection+Attach.swift
+++ b/Sources/SQLite/Core/Connection+Attach.swift
@@ -4,7 +4,7 @@ import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
 #elseif os(Linux)
-import CSQLite
+import SwiftToolchainCSQLite
 #else
 import SQLite3
 #endif
diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index f2c3b781..188ff80b 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -29,7 +29,7 @@ import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
 #elseif os(Linux)
-import CSQLite
+import SwiftToolchainCSQLite
 #else
 import SQLite3
 #endif
diff --git a/Sources/SQLite/Core/Result.swift b/Sources/SQLite/Core/Result.swift
index ee59e5d1..2659ad21 100644
--- a/Sources/SQLite/Core/Result.swift
+++ b/Sources/SQLite/Core/Result.swift
@@ -3,7 +3,7 @@ import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
 #elseif os(Linux)
-import CSQLite
+import SwiftToolchainCSQLite
 #else
 import SQLite3
 #endif
diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index 6cb2e5d3..458e3d9c 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -27,7 +27,7 @@ import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
 #elseif os(Linux)
-import CSQLite
+import SwiftToolchainCSQLite
 #else
 import SQLite3
 #endif
diff --git a/Sources/SQLite/Helpers.swift b/Sources/SQLite/Helpers.swift
index c27ccf05..00493f21 100644
--- a/Sources/SQLite/Helpers.swift
+++ b/Sources/SQLite/Helpers.swift
@@ -27,7 +27,7 @@ import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
 #elseif os(Linux)
-import CSQLite
+import SwiftToolchainCSQLite
 #else
 import SQLite3
 #endif
diff --git a/Tests/SQLiteTests/Core/Connection+AttachTests.swift b/Tests/SQLiteTests/Core/Connection+AttachTests.swift
index f37300ca..68618596 100644
--- a/Tests/SQLiteTests/Core/Connection+AttachTests.swift
+++ b/Tests/SQLiteTests/Core/Connection+AttachTests.swift
@@ -7,7 +7,7 @@ import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
 #elseif os(Linux)
-import CSQLite
+import SwiftToolchainCSQLite
 #else
 import SQLite3
 #endif
diff --git a/Tests/SQLiteTests/Core/Connection+PragmaTests.swift b/Tests/SQLiteTests/Core/Connection+PragmaTests.swift
index 2bcdb6af..bd29bd98 100644
--- a/Tests/SQLiteTests/Core/Connection+PragmaTests.swift
+++ b/Tests/SQLiteTests/Core/Connection+PragmaTests.swift
@@ -7,7 +7,7 @@ import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
 #elseif os(Linux)
-import CSQLite
+import SwiftToolchainCSQLite
 #else
 import SQLite3
 #endif
diff --git a/Tests/SQLiteTests/Core/ConnectionTests.swift b/Tests/SQLiteTests/Core/ConnectionTests.swift
index 6a1d94ae..61083453 100644
--- a/Tests/SQLiteTests/Core/ConnectionTests.swift
+++ b/Tests/SQLiteTests/Core/ConnectionTests.swift
@@ -8,7 +8,7 @@ import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
 #elseif os(Linux)
-import CSQLite
+import SwiftToolchainCSQLite
 #else
 import SQLite3
 #endif
diff --git a/Tests/SQLiteTests/Core/ResultTests.swift b/Tests/SQLiteTests/Core/ResultTests.swift
index d3c8bb1f..b6a373f7 100644
--- a/Tests/SQLiteTests/Core/ResultTests.swift
+++ b/Tests/SQLiteTests/Core/ResultTests.swift
@@ -7,7 +7,7 @@ import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
 #elseif os(Linux)
-import CSQLite
+import SwiftToolchainCSQLite
 #else
 import SQLite3
 #endif
diff --git a/Tests/SQLiteTests/Core/StatementTests.swift b/Tests/SQLiteTests/Core/StatementTests.swift
index dbf99d7c..ceaa8813 100644
--- a/Tests/SQLiteTests/Core/StatementTests.swift
+++ b/Tests/SQLiteTests/Core/StatementTests.swift
@@ -6,7 +6,7 @@ import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
 #elseif os(Linux)
-import CSQLite
+import SwiftToolchainCSQLite
 #else
 import SQLite3
 #endif
diff --git a/Tests/SQLiteTests/Extensions/FTSIntegrationTests.swift b/Tests/SQLiteTests/Extensions/FTSIntegrationTests.swift
index 1129ae08..8a34e93b 100644
--- a/Tests/SQLiteTests/Extensions/FTSIntegrationTests.swift
+++ b/Tests/SQLiteTests/Extensions/FTSIntegrationTests.swift
@@ -4,7 +4,7 @@ import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
 #elseif os(Linux)
-import CSQLite
+import SwiftToolchainCSQLite
 #else
 import SQLite3
 #endif
diff --git a/Tests/SQLiteTests/Typed/CustomAggregationTests.swift b/Tests/SQLiteTests/Typed/CustomAggregationTests.swift
index 71cbba9c..8b7ec09a 100644
--- a/Tests/SQLiteTests/Typed/CustomAggregationTests.swift
+++ b/Tests/SQLiteTests/Typed/CustomAggregationTests.swift
@@ -8,7 +8,7 @@ import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
 #elseif os(Linux)
-import CSQLite
+import SwiftToolchainCSQLite
 #else
 import SQLite3
 #endif
diff --git a/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift b/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
index 6be98ca0..899bf354 100644
--- a/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
+++ b/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
@@ -4,7 +4,7 @@ import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
 #elseif os(Linux)
-import CSQLite
+import SwiftToolchainCSQLite
 #else
 import SQLite3
 #endif
diff --git a/Tests/SQLiteTests/Typed/QueryTests.swift b/Tests/SQLiteTests/Typed/QueryTests.swift
index f018f097..7fc3dcf5 100644
--- a/Tests/SQLiteTests/Typed/QueryTests.swift
+++ b/Tests/SQLiteTests/Typed/QueryTests.swift
@@ -4,7 +4,7 @@ import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
 #elseif os(Linux)
-import CSQLite
+import SwiftToolchainCSQLite
 #else
 import SQLite3
 #endif

From fc774a2585965a90f60aa034001e6d69aee42382 Mon Sep 17 00:00:00 2001
From: ha100 <thastik@gmail.com>
Date: Sun, 8 Jun 2025 07:08:47 +0200
Subject: [PATCH 670/685] fix macOS build via platform condition

---
 Package.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Package.swift b/Package.swift
index 690d41e2..48085178 100644
--- a/Package.swift
+++ b/Package.swift
@@ -9,7 +9,7 @@ let targets: [Target] = [
     .target(
         name: "SQLite",
         dependencies: [
-            .product(name: "SwiftToolchainCSQLite", package: "swift-toolchain-sqlite")
+            .product(name: "SwiftToolchainCSQLite", package: "swift-toolchain-sqlite", condition: .when(platforms: [.linux, .windows]))
         ],
         exclude: [
             "Info.plist"

From f3cb9105a80d566575c02bb77ac50e74e5895ccc Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 12 Jun 2025 12:15:34 +0200
Subject: [PATCH 671/685] Fully qualify Expression

---
 Tests/SQLiteTests/Schema/SchemaChangerTests.swift | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
index d942fba4..f5a6de42 100644
--- a/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
+++ b/Tests/SQLiteTests/Schema/SchemaChangerTests.swift
@@ -278,9 +278,9 @@ class SchemaChangerTests: SQLiteTestCase {
 
     func test_create_table_add_column_expression() throws {
         try schemaChanger.create(table: "foo") { table in
-            table.add(expression: Expression<String>("name"))
-            table.add(expression: Expression<Int>("age"))
-            table.add(expression: Expression<Double?>("salary"))
+            table.add(expression: SQLite.Expression<String>("name"))
+            table.add(expression: SQLite.Expression<Int>("age"))
+            table.add(expression: SQLite.Expression<Double?>("salary"))
         }
 
         let columns = try schema.columnDefinitions(table: "foo")

From a7d7e8c0b7529f851fd8927071003095f1e87522 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 12 Jun 2025 12:27:28 +0200
Subject: [PATCH 672/685] 17.5 no longer available

---
 .github/workflows/build.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index a0274321..33c4dba6 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -2,7 +2,7 @@ name: Build and test
 on: [push, pull_request]
 env:
   IOS_SIMULATOR: "iPhone 15"
-  IOS_VERSION: "17.5"
+  IOS_VERSION: "18.0"
 jobs:
   build:
     runs-on: macos-15

From 716394d091618047dfe86b7da5106fb21ede412f Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 12 Jun 2025 12:34:42 +0200
Subject: [PATCH 673/685] iPhone 16

---
 .github/workflows/build.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 33c4dba6..37f75476 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,7 +1,7 @@
 name: Build and test
 on: [push, pull_request]
 env:
-  IOS_SIMULATOR: "iPhone 15"
+  IOS_SIMULATOR: "iPhone 16"
   IOS_VERSION: "18.0"
 jobs:
   build:

From 9831a45edb84d492cd5b68ba6f8d53300808499f Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Thu, 12 Jun 2025 13:17:56 +0200
Subject: [PATCH 674/685] Update Index.md

---
 Documentation/Index.md | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index bc62c791..bd2a7a77 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -1592,7 +1592,8 @@ let schemaChanger = SchemaChanger(connection: db)
 try schemaChanger.create(table: "users") { table in 
     table.add(column: .init(name: "id", primaryKey: .init(autoIncrement: true), type: .INTEGER))
     table.add(column: .init(name: "name", type: .TEXT, nullable: false))            
-} 
+}
+``` 
 
 ### Indexes
 

From e3a916637162ece77b0ffd89b9e758669adc62f0 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 13 Jun 2025 22:49:43 +0200
Subject: [PATCH 675/685] Update CHANGELOG for release

---
 CHANGELOG.md | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c96724fd..b77a8b07 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+0.15.4 (13-06-2025), [diff][diff-0.15.4]
+========================================
+* Fix cross compilation for linux on macOS fails ([#1317][])
+* Support creating tables in schema changer ([#1315][])
+* Update oldest supported platform versions ([#1280][])
+* Add CustomStringConvertible for Setter ([#1279][])
+
 0.15.3 (19-04-2024), [diff][diff-0.15.3]
 ========================================
 * Update `podspec` to include privacy manifest ([#1265][])
@@ -173,6 +180,8 @@ For breaking changes, see [Upgrading.md](Documentation/Upgrading.md).
 [diff-0.15.0]: https://github.com/stephencelis/SQLite.swift/compare/0.14.0...0.15.0
 [diff-0.15.1]: https://github.com/stephencelis/SQLite.swift/compare/0.15.0...0.15.1
 [diff-0.15.2]: https://github.com/stephencelis/SQLite.swift/compare/0.15.1...0.15.2
+[diff-0.15.3]: https://github.com/stephencelis/SQLite.swift/compare/0.15.2...0.15.3
+[diff-0.15.4]: https://github.com/stephencelis/SQLite.swift/compare/0.15.3...0.15.4
 
 [#30]: https://github.com/stephencelis/SQLite.swift/issues/30
 [#142]: https://github.com/stephencelis/SQLite.swift/issues/142
@@ -259,3 +268,7 @@ For breaking changes, see [Upgrading.md](Documentation/Upgrading.md).
 [#1237]: https://github.com/stephencelis/SQLite.swift/pull/1237
 [#1260]: https://github.com/stephencelis/SQLite.swift/pull/1260
 [#1265]: https://github.com/stephencelis/SQLite.swift/pull/1265
+[#1279]: https://github.com/stephencelis/SQLite.swift/pull/1279
+[#1280]: https://github.com/stephencelis/SQLite.swift/pull/1280
+[#1315]: https://github.com/stephencelis/SQLite.swift/pull/1315
+[#1317]: https://github.com/stephencelis/SQLite.swift/pull/1317
\ No newline at end of file

From 02e055c99c4fa19604a95fea4e82fd085391fdf0 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 13 Jun 2025 22:51:53 +0200
Subject: [PATCH 676/685] Update README

---
 README.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index a4d713b6..3e782f86 100644
--- a/README.md
+++ b/README.md
@@ -128,7 +128,7 @@ Swift code.
 
   ```swift
   dependencies: [
-      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.3")
+      .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.4")
   ]
   ```
 
@@ -152,7 +152,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.15.3
+    github "stephencelis/SQLite.swift" ~> 0.15.4
     ```
 
  3. Run `carthage update` and
@@ -183,7 +183,7 @@ SQLite.swift with CocoaPods:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.14.0'
+        pod 'SQLite.swift', '~> 0.15.0'
     end
     ```
 

From bbc5212c2ae9905d17ae581927c06e2cbad61ff7 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 13 Jun 2025 22:53:36 +0200
Subject: [PATCH 677/685] Project looks dead

---
 README.md | 1 -
 1 file changed, 1 deletion(-)

diff --git a/README.md b/README.md
index 3e782f86..db80fd3a 100644
--- a/README.md
+++ b/README.md
@@ -266,7 +266,6 @@ Looking for something else? Try another Swift wrapper (or [FMDB][]):
 
  - [GRDB](https://github.com/groue/GRDB.swift)
  - [SQLiteDB](https://github.com/FahimF/SQLiteDB)
- - [Squeal](https://github.com/nerdyc/Squeal)
 
 [Swift]: https://swift.org/
 [SQLite3]: https://www.sqlite.org

From 4e289bed6f1ed6737ffa963570beae3359a849e8 Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 13 Jun 2025 23:00:44 +0200
Subject: [PATCH 678/685] No longer maintained

---
 README.md | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/README.md b/README.md
index db80fd3a..0e83504f 100644
--- a/README.md
+++ b/README.md
@@ -226,8 +226,6 @@ device:
 
 ## Communication
 
-[See the planning document] for a roadmap and existing feature requests.
-
 [Read the contributing guidelines][]. The _TL;DR_ (but please; _R_):
 
  - Need **help** or have a **general question**? [Ask on Stack
@@ -235,7 +233,6 @@ device:
  - Found a **bug** or have a **feature request**? [Open an issue][].
  - Want to **contribute**? [Submit a pull request][].
 
-[See the planning document]: /Documentation/Planning.md
 [Read the contributing guidelines]: ./CONTRIBUTING.md#contributing
 [Ask on Stack Overflow]: https://stackoverflow.com/questions/tagged/sqlite.swift
 [Open an issue]: https://github.com/stephencelis/SQLite.swift/issues/new

From 0f4f2c85c5beddeb70f02e1db36785b5f6e2dccf Mon Sep 17 00:00:00 2001
From: Jan Berkel <jan@berkel.fr>
Date: Fri, 13 Jun 2025 23:12:38 +0200
Subject: [PATCH 679/685] Bump version to 0.15.4

---
 Documentation/Index.md           | 12 ++++++------
 SQLite.swift.podspec             |  2 +-
 SQLite.xcodeproj/project.pbxproj | 12 ++----------
 Tests/SPM/Package.swift          |  2 +-
 4 files changed, 10 insertions(+), 18 deletions(-)

diff --git a/Documentation/Index.md b/Documentation/Index.md
index bd2a7a77..0e8261f2 100644
--- a/Documentation/Index.md
+++ b/Documentation/Index.md
@@ -109,7 +109,7 @@ process of downloading, compiling, and linking dependencies.
 
   ```swift
   dependencies: [
-    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.3")
+    .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.4")
   ]
   ```
 
@@ -130,7 +130,7 @@ install SQLite.swift with Carthage:
  2. Update your Cartfile to include the following:
 
     ```ruby
-    github "stephencelis/SQLite.swift" ~> 0.15.3
+    github "stephencelis/SQLite.swift" ~> 0.15.4
     ```
 
  3. Run `carthage update` and [add the appropriate framework][Carthage Usage].
@@ -160,7 +160,7 @@ install SQLite.swift with Carthage:
     use_frameworks!
 
     target 'YourAppTargetName' do
-        pod 'SQLite.swift', '~> 0.15.3'
+        pod 'SQLite.swift', '~> 0.15.4'
     end
     ```
 
@@ -174,7 +174,7 @@ with the OS you can require the `standalone` subspec:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.15.3'
+  pod 'SQLite.swift/standalone', '~> 0.15.4'
 end
 ```
 
@@ -184,7 +184,7 @@ dependency to sqlite3 or one of its subspecs:
 
 ```ruby
 target 'YourAppTargetName' do
-  pod 'SQLite.swift/standalone', '~> 0.15.3'
+  pod 'SQLite.swift/standalone', '~> 0.15.4'
   pod 'sqlite3/fts5', '= 3.15.0'  # SQLite 3.15.0 with FTS5 enabled
 end
 ```
@@ -200,7 +200,7 @@ If you want to use [SQLCipher][] with SQLite.swift you can require the
 target 'YourAppTargetName' do
   # Make sure you only require the subspec, otherwise you app might link against
   # the system SQLite, which means the SQLCipher-specific methods won't work.
-  pod 'SQLite.swift/SQLCipher', '~> 0.15.3'
+  pod 'SQLite.swift/SQLCipher', '~> 0.15.4'
 end
 ```
 
diff --git a/SQLite.swift.podspec b/SQLite.swift.podspec
index d0ccb136..73c6f705 100644
--- a/SQLite.swift.podspec
+++ b/SQLite.swift.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = "SQLite.swift"
-  s.version          = "0.15.3"
+  s.version          = "0.15.4"
   s.summary          = "A type-safe, Swift-language layer over SQLite3."
 
   s.description      = <<-DESC
diff --git a/SQLite.xcodeproj/project.pbxproj b/SQLite.xcodeproj/project.pbxproj
index a2d7edbe..ec0423e9 100644
--- a/SQLite.xcodeproj/project.pbxproj
+++ b/SQLite.xcodeproj/project.pbxproj
@@ -1539,7 +1539,6 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
-				MARKETING_VERSION = 0.15.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SDKROOT = appletvos;
@@ -1562,7 +1561,6 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
-				MARKETING_VERSION = 0.15.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SDKROOT = appletvos;
@@ -1614,7 +1612,6 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
-				MARKETING_VERSION = 0.15.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SDKROOT = watchos;
@@ -1639,7 +1636,6 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
-				MARKETING_VERSION = 0.15.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SDKROOT = watchos;
@@ -1664,7 +1660,6 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
-				MARKETING_VERSION = 0.15.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SDKROOT = xros;
@@ -1689,7 +1684,6 @@
 				INFOPLIST_FILE = "$(SRCROOT)/Sources/SQLite/Info.plist";
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
-				MARKETING_VERSION = 0.15.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SDKROOT = xros;
@@ -1778,6 +1772,7 @@
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
 				MACOSX_DEPLOYMENT_TARGET = 10.13;
+				MARKETING_VERSION = 0.15.4;
 				MTL_ENABLE_DEBUG_INFO = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				PRODUCT_NAME = "";
@@ -1837,6 +1832,7 @@
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
 				MACOSX_DEPLOYMENT_TARGET = 10.13;
+				MARKETING_VERSION = 0.15.4;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				PRODUCT_NAME = "";
 				SDKROOT = iphoneos;
@@ -1866,7 +1862,6 @@
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
-				MARKETING_VERSION = 0.15.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
@@ -1890,7 +1885,6 @@
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
-				MARKETING_VERSION = 0.15.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SKIP_INSTALL = YES;
@@ -1940,7 +1934,6 @@
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
 				MACOSX_DEPLOYMENT_TARGET = 10.13;
-				MARKETING_VERSION = 0.15.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SDKROOT = macosx;
@@ -1966,7 +1959,6 @@
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
 				MACOSX_DEPLOYMENT_TARGET = 10.13;
-				MARKETING_VERSION = 0.15.3;
 				PRODUCT_BUNDLE_IDENTIFIER = com.stephencelis.SQLite;
 				PRODUCT_NAME = SQLite;
 				SDKROOT = macosx;
diff --git a/Tests/SPM/Package.swift b/Tests/SPM/Package.swift
index 6521211a..a5a4afc4 100644
--- a/Tests/SPM/Package.swift
+++ b/Tests/SPM/Package.swift
@@ -15,7 +15,7 @@ let package = Package(
         // for testing from same repository
         .package(path: "../..")
         // normally this would be:
-        // .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.3")
+        // .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.15.4")
     ],
     targets: [
         .executableTarget(name: "test", dependencies: [.product(name: "SQLite", package: "SQLite.swift")])

From 496a086e5a4d03fb6b0338f63b600dc153be6fa3 Mon Sep 17 00:00:00 2001
From: Alsey Coleman Miller <alseycmiller@gmail.com>
Date: Mon, 14 Jul 2025 15:14:14 -0400
Subject: [PATCH 680/685] Build `SwiftToolchainCSQLite` for Android

---
 Package.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Package.swift b/Package.swift
index cf3a0b60..56925d18 100644
--- a/Package.swift
+++ b/Package.swift
@@ -9,7 +9,7 @@ let targets: [Target] = [
     .target(
         name: "SQLite",
         dependencies: [
-            .product(name: "SwiftToolchainCSQLite", package: "swift-toolchain-sqlite", condition: .when(platforms: [.linux, .windows]))
+            .product(name: "SwiftToolchainCSQLite", package: "swift-toolchain-sqlite", condition: .when(platforms: [.linux, .windows, .android]))
         ],
         exclude: [
             "Info.plist"

From e8cfef658cbdbdd297ed7f549d197ec481b6b7a9 Mon Sep 17 00:00:00 2001
From: Alsey Coleman Miller <alseycmiller@gmail.com>
Date: Mon, 14 Jul 2025 15:14:34 -0400
Subject: [PATCH 681/685] Fix Android build

---
 Sources/SQLite/Core/Backup.swift                       | 2 +-
 Sources/SQLite/Core/Connection+Aggregation.swift       | 2 +-
 Sources/SQLite/Core/Connection+Attach.swift            | 2 +-
 Sources/SQLite/Core/Connection.swift                   | 2 +-
 Sources/SQLite/Core/Result.swift                       | 2 +-
 Sources/SQLite/Core/Statement.swift                    | 2 +-
 Sources/SQLite/Helpers.swift                           | 2 +-
 Tests/SQLiteTests/Core/Connection+AttachTests.swift    | 2 +-
 Tests/SQLiteTests/Core/Connection+PragmaTests.swift    | 2 +-
 Tests/SQLiteTests/Core/ConnectionTests.swift           | 2 +-
 Tests/SQLiteTests/Core/ResultTests.swift               | 2 +-
 Tests/SQLiteTests/Core/StatementTests.swift            | 2 +-
 Tests/SQLiteTests/Extensions/FTSIntegrationTests.swift | 2 +-
 Tests/SQLiteTests/Typed/CustomAggregationTests.swift   | 2 +-
 Tests/SQLiteTests/Typed/QueryIntegrationTests.swift    | 2 +-
 Tests/SQLiteTests/Typed/QueryTests.swift               | 2 +-
 16 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/Sources/SQLite/Core/Backup.swift b/Sources/SQLite/Core/Backup.swift
index 5e741ecd..023acc08 100644
--- a/Sources/SQLite/Core/Backup.swift
+++ b/Sources/SQLite/Core/Backup.swift
@@ -28,7 +28,7 @@ import Dispatch
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif os(Linux)
+#elseif canImport(SwiftToolchainCSQLite)
 import SwiftToolchainCSQLite
 #else
 import SQLite3
diff --git a/Sources/SQLite/Core/Connection+Aggregation.swift b/Sources/SQLite/Core/Connection+Aggregation.swift
index bfe253a7..a1abb74a 100644
--- a/Sources/SQLite/Core/Connection+Aggregation.swift
+++ b/Sources/SQLite/Core/Connection+Aggregation.swift
@@ -3,7 +3,7 @@ import Foundation
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif os(Linux)
+#elseif canImport(SwiftToolchainCSQLite)
 import SwiftToolchainCSQLite
 #else
 import SQLite3
diff --git a/Sources/SQLite/Core/Connection+Attach.swift b/Sources/SQLite/Core/Connection+Attach.swift
index 32461468..0c674ee6 100644
--- a/Sources/SQLite/Core/Connection+Attach.swift
+++ b/Sources/SQLite/Core/Connection+Attach.swift
@@ -3,7 +3,7 @@ import Foundation
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif os(Linux)
+#elseif canImport(SwiftToolchainCSQLite)
 import SwiftToolchainCSQLite
 #else
 import SQLite3
diff --git a/Sources/SQLite/Core/Connection.swift b/Sources/SQLite/Core/Connection.swift
index 188ff80b..57521f83 100644
--- a/Sources/SQLite/Core/Connection.swift
+++ b/Sources/SQLite/Core/Connection.swift
@@ -28,7 +28,7 @@ import Dispatch
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif os(Linux)
+#elseif canImport(SwiftToolchainCSQLite)
 import SwiftToolchainCSQLite
 #else
 import SQLite3
diff --git a/Sources/SQLite/Core/Result.swift b/Sources/SQLite/Core/Result.swift
index 2659ad21..9a72e4c5 100644
--- a/Sources/SQLite/Core/Result.swift
+++ b/Sources/SQLite/Core/Result.swift
@@ -2,7 +2,7 @@
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif os(Linux)
+#elseif canImport(SwiftToolchainCSQLite)
 import SwiftToolchainCSQLite
 #else
 import SQLite3
diff --git a/Sources/SQLite/Core/Statement.swift b/Sources/SQLite/Core/Statement.swift
index 458e3d9c..82d535b9 100644
--- a/Sources/SQLite/Core/Statement.swift
+++ b/Sources/SQLite/Core/Statement.swift
@@ -26,7 +26,7 @@
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif os(Linux)
+#elseif canImport(SwiftToolchainCSQLite)
 import SwiftToolchainCSQLite
 #else
 import SQLite3
diff --git a/Sources/SQLite/Helpers.swift b/Sources/SQLite/Helpers.swift
index 00493f21..e3c84589 100644
--- a/Sources/SQLite/Helpers.swift
+++ b/Sources/SQLite/Helpers.swift
@@ -26,7 +26,7 @@
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif os(Linux)
+#elseif canImport(SwiftToolchainCSQLite)
 import SwiftToolchainCSQLite
 #else
 import SQLite3
diff --git a/Tests/SQLiteTests/Core/Connection+AttachTests.swift b/Tests/SQLiteTests/Core/Connection+AttachTests.swift
index 68618596..0e185da5 100644
--- a/Tests/SQLiteTests/Core/Connection+AttachTests.swift
+++ b/Tests/SQLiteTests/Core/Connection+AttachTests.swift
@@ -6,7 +6,7 @@ import Foundation
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif os(Linux)
+#elseif canImport(SwiftToolchainCSQLite)
 import SwiftToolchainCSQLite
 #else
 import SQLite3
diff --git a/Tests/SQLiteTests/Core/Connection+PragmaTests.swift b/Tests/SQLiteTests/Core/Connection+PragmaTests.swift
index bd29bd98..d1d4ab04 100644
--- a/Tests/SQLiteTests/Core/Connection+PragmaTests.swift
+++ b/Tests/SQLiteTests/Core/Connection+PragmaTests.swift
@@ -6,7 +6,7 @@ import Foundation
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif os(Linux)
+#elseif canImport(SwiftToolchainCSQLite)
 import SwiftToolchainCSQLite
 #else
 import SQLite3
diff --git a/Tests/SQLiteTests/Core/ConnectionTests.swift b/Tests/SQLiteTests/Core/ConnectionTests.swift
index 61083453..da50974a 100644
--- a/Tests/SQLiteTests/Core/ConnectionTests.swift
+++ b/Tests/SQLiteTests/Core/ConnectionTests.swift
@@ -7,7 +7,7 @@ import Dispatch
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif os(Linux)
+#elseif canImport(SwiftToolchainCSQLite)
 import SwiftToolchainCSQLite
 #else
 import SQLite3
diff --git a/Tests/SQLiteTests/Core/ResultTests.swift b/Tests/SQLiteTests/Core/ResultTests.swift
index b6a373f7..03415f3a 100644
--- a/Tests/SQLiteTests/Core/ResultTests.swift
+++ b/Tests/SQLiteTests/Core/ResultTests.swift
@@ -6,7 +6,7 @@ import Foundation
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif os(Linux)
+#elseif canImport(SwiftToolchainCSQLite)
 import SwiftToolchainCSQLite
 #else
 import SQLite3
diff --git a/Tests/SQLiteTests/Core/StatementTests.swift b/Tests/SQLiteTests/Core/StatementTests.swift
index ceaa8813..3c90d941 100644
--- a/Tests/SQLiteTests/Core/StatementTests.swift
+++ b/Tests/SQLiteTests/Core/StatementTests.swift
@@ -5,7 +5,7 @@ import XCTest
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif os(Linux)
+#elseif canImport(SwiftToolchainCSQLite)
 import SwiftToolchainCSQLite
 #else
 import SQLite3
diff --git a/Tests/SQLiteTests/Extensions/FTSIntegrationTests.swift b/Tests/SQLiteTests/Extensions/FTSIntegrationTests.swift
index 8a34e93b..b3b9e617 100644
--- a/Tests/SQLiteTests/Extensions/FTSIntegrationTests.swift
+++ b/Tests/SQLiteTests/Extensions/FTSIntegrationTests.swift
@@ -3,7 +3,7 @@ import XCTest
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif os(Linux)
+#elseif canImport(SwiftToolchainCSQLite)
 import SwiftToolchainCSQLite
 #else
 import SQLite3
diff --git a/Tests/SQLiteTests/Typed/CustomAggregationTests.swift b/Tests/SQLiteTests/Typed/CustomAggregationTests.swift
index 8b7ec09a..73a0767f 100644
--- a/Tests/SQLiteTests/Typed/CustomAggregationTests.swift
+++ b/Tests/SQLiteTests/Typed/CustomAggregationTests.swift
@@ -7,7 +7,7 @@ import Dispatch
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif os(Linux)
+#elseif canImport(SwiftToolchainCSQLite)
 import SwiftToolchainCSQLite
 #else
 import SQLite3
diff --git a/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift b/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
index 899bf354..cde5a0c3 100644
--- a/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
+++ b/Tests/SQLiteTests/Typed/QueryIntegrationTests.swift
@@ -3,7 +3,7 @@ import XCTest
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif os(Linux)
+#elseif canImport(SwiftToolchainCSQLite)
 import SwiftToolchainCSQLite
 #else
 import SQLite3
diff --git a/Tests/SQLiteTests/Typed/QueryTests.swift b/Tests/SQLiteTests/Typed/QueryTests.swift
index 7fc3dcf5..257b5245 100644
--- a/Tests/SQLiteTests/Typed/QueryTests.swift
+++ b/Tests/SQLiteTests/Typed/QueryTests.swift
@@ -3,7 +3,7 @@ import XCTest
 import sqlite3
 #elseif SQLITE_SWIFT_SQLCIPHER
 import SQLCipher
-#elseif os(Linux)
+#elseif canImport(SwiftToolchainCSQLite)
 import SwiftToolchainCSQLite
 #else
 import SQLite3

From 91a30a3535e74767372ef605751569299696d8d1 Mon Sep 17 00:00:00 2001
From: NathanFallet <contact@nathanfallet.me>
Date: Tue, 15 Jul 2025 13:54:04 +0200
Subject: [PATCH 682/685] add android ci

---
 .github/workflows/build.yml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 37f75476..f82a9c59 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -76,3 +76,9 @@ jobs:
       env:
         SPM: run
       run: ./run-tests.sh
+  build-android:
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v2
+    - name: Run tests
+      uses: skiptools/swift-android-action@v2

From 22d30c885f6ac1161ff5e88e32f054b4672963d2 Mon Sep 17 00:00:00 2001
From: NathanFallet <contact@nathanfallet.me>
Date: Wed, 16 Jul 2025 15:17:33 +0200
Subject: [PATCH 683/685] add SQLite. prefix for Expression in README

---
 README.md | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index 0e83504f..a52b7ae5 100644
--- a/README.md
+++ b/README.md
@@ -42,9 +42,9 @@ do {
     let db = try Connection("path/to/db.sqlite3")
 
     let users = Table("users")
-    let id = Expression<Int64>("id")
-    let name = Expression<String?>("name")
-    let email = Expression<String>("email")
+    let id = SQLite.Expression<Int64>("id")
+    let name = SQLite.Expression<String?>("name")
+    let email = SQLite.Expression<String>("email")
 
     try db.run(users.create { t in
         t.column(id, primaryKey: true)
@@ -83,6 +83,9 @@ do {
 }
 ```
 
+Note that `Expression` should be written as `SQLite.Expression` to avoid
+conflicts with the `SwiftUI.Expression` if you are using SwiftUI too.
+
 SQLite.swift also works as a lightweight, Swift-friendly wrapper over the C
 API.
 

From fee88af870ccf4f574607b1dc8f2835cb2aa0b36 Mon Sep 17 00:00:00 2001
From: hawk0620 <chenhao@weshot.cc>
Date: Thu, 17 Jul 2025 14:11:06 +0800
Subject: [PATCH 684/685] create index support array as parameters

---
 Sources/SQLite/Typed/Schema.swift | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/Sources/SQLite/Typed/Schema.swift b/Sources/SQLite/Typed/Schema.swift
index e162cf34..02f5b102 100644
--- a/Sources/SQLite/Typed/Schema.swift
+++ b/Sources/SQLite/Typed/Schema.swift
@@ -135,8 +135,8 @@ extension Table {
     }
 
     // MARK: - CREATE INDEX
-
-    public func createIndex(_ columns: Expressible..., unique: Bool = false, ifNotExists: Bool = false) -> String {
+    
+    public func createIndex(_ columns: [Expressible], unique: Bool = false, ifNotExists: Bool = false) -> String {
         let clauses: [Expressible?] = [
             create("INDEX", indexName(columns), unique ? .unique : nil, ifNotExists),
             Expression<Void>(literal: "ON"),
@@ -146,12 +146,20 @@ extension Table {
 
         return " ".join(clauses.compactMap { $0 }).asSQL()
     }
+    
+    public func createIndex(_ columns: Expressible..., unique: Bool = false, ifNotExists: Bool = false) -> String {
+        return createIndex(Array(columns), unique: unique, ifNotExists: ifNotExists)
+    }
 
     // MARK: - DROP INDEX
-
-    public func dropIndex(_ columns: Expressible..., ifExists: Bool = false) -> String {
+    
+    public func dropIndex(_ columns: [Expressible], ifExists: Bool = false) -> String {
         drop("INDEX", indexName(columns), ifExists)
     }
+    
+    public func dropIndex(_ columns: Expressible..., ifExists: Bool = false) -> String {
+        dropIndex(Array(columns), ifExists: ifExists)
+    }
 
     fileprivate func indexName(_ columns: [Expressible]) -> Expressible {
         let string = (["index", clauses.from.name, "on"] + columns.map { $0.expression.template }).joined(separator: " ").lowercased()

From 98d83a223db0d1a51c2d575f108c66b1b770b725 Mon Sep 17 00:00:00 2001
From: NathanFallet <contact@nathanfallet.me>
Date: Thu, 17 Jul 2025 13:42:49 +0200
Subject: [PATCH 685/685] fix linting

---
 Sources/SQLite/Typed/Query.swift    |  2 +-
 Sources/SQLite/Typed/Schema.swift   |  8 ++++----
 Tests/SQLiteTests/TestHelpers.swift | 10 ----------
 3 files changed, 5 insertions(+), 15 deletions(-)

diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift
index 2a83665c..6162fcc7 100644
--- a/Sources/SQLite/Typed/Query.swift
+++ b/Sources/SQLite/Typed/Query.swift
@@ -1055,7 +1055,7 @@ extension Connection {
             }
 
             func expandGlob(_ namespace: Bool) -> (QueryType) throws -> Void {
-                { (queryType: QueryType) throws -> Void in
+                { (queryType: QueryType) throws in
                     var query = type(of: queryType).init(queryType.clauses.from.name, database: queryType.clauses.from.database)
                     query.clauses.select = queryType.clauses.select
                     query.clauses.with = strip(queryType.clauses.with)
diff --git a/Sources/SQLite/Typed/Schema.swift b/Sources/SQLite/Typed/Schema.swift
index 02f5b102..919042ab 100644
--- a/Sources/SQLite/Typed/Schema.swift
+++ b/Sources/SQLite/Typed/Schema.swift
@@ -135,7 +135,7 @@ extension Table {
     }
 
     // MARK: - CREATE INDEX
-    
+
     public func createIndex(_ columns: [Expressible], unique: Bool = false, ifNotExists: Bool = false) -> String {
         let clauses: [Expressible?] = [
             create("INDEX", indexName(columns), unique ? .unique : nil, ifNotExists),
@@ -146,17 +146,17 @@ extension Table {
 
         return " ".join(clauses.compactMap { $0 }).asSQL()
     }
-    
+
     public func createIndex(_ columns: Expressible..., unique: Bool = false, ifNotExists: Bool = false) -> String {
         return createIndex(Array(columns), unique: unique, ifNotExists: ifNotExists)
     }
 
     // MARK: - DROP INDEX
-    
+
     public func dropIndex(_ columns: [Expressible], ifExists: Bool = false) -> String {
         drop("INDEX", indexName(columns), ifExists)
     }
-    
+
     public func dropIndex(_ columns: Expressible..., ifExists: Bool = false) -> String {
         dropIndex(Array(columns), ifExists: ifExists)
     }
diff --git a/Tests/SQLiteTests/TestHelpers.swift b/Tests/SQLiteTests/TestHelpers.swift
index 56415a59..e62b2a23 100644
--- a/Tests/SQLiteTests/TestHelpers.swift
+++ b/Tests/SQLiteTests/TestHelpers.swift
@@ -164,14 +164,4 @@ struct TestOptionalCodable: Codable, Equatable {
     let double: Double?
     let date: Date?
     let uuid: UUID?
-
-    init(int: Int?, string: String?, bool: Bool?, float: Float?, double: Double?, date: Date?, uuid: UUID?) {
-        self.int = int
-        self.string = string
-        self.bool = bool
-        self.float = float
-        self.double = double
-        self.date = date
-        self.uuid = uuid
-    }
 }
