Merge pull request #3959 from 1Dragoon/backports/2.1.4

Backports/2.1.4
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6b713b9..ae2ee4c 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -223,11 +223,11 @@
       - name: Test diesel-derives (nightly)
         if: matrix.rust == 'nightly'
         shell: bash
-        run: cargo +${{ matrix.rust }} test --manifest-path diesel_derives/Cargo.toml --no-default-features --features "diesel/${{ matrix.backend }} diesel/unstable diesel/time time diesel/chrono chrono"
+        run: cargo +${{ matrix.rust }} test --manifest-path diesel_derives/Cargo.toml --no-default-features --features "diesel/${{ matrix.backend }} diesel/unstable diesel/time time diesel/chrono chrono ${{ matrix.backend }}"
 
       - name: Test diesel-derives
         shell: bash
-        run: cargo +${{ matrix.rust }} test --manifest-path diesel_derives/Cargo.toml --no-default-features --features "diesel/${{ matrix.backend }}"
+        run: cargo +${{ matrix.rust }} test --manifest-path diesel_derives/Cargo.toml --no-default-features --features "diesel/${{ matrix.backend }} ${{ matrix.backend }}"
 
       - name: Test diesel-cli
         shell: bash
diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml
index e54b45f..3581b56 100644
--- a/.github/workflows/doc.yml
+++ b/.github/workflows/doc.yml
@@ -41,7 +41,7 @@
 
     - name: Publish documentation
       if: success()
-      uses: JamesIves/github-pages-deploy-action@v4.2.5
+      uses: JamesIves/github-pages-deploy-action@v4
       with:
         token: ${{ secrets.GITHUB_TOKEN }}
         branch: gh-pages # The branch the action should deploy to.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 21ad992..7d937c3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,13 +3,22 @@
 All user visible changes to this project will be documented in this file.
 This project adheres to [Semantic Versioning](http://semver.org/), as described
 for Rust libraries in [RFC #1105](https://github.com/rust-lang/rfcs/blob/master/text/1105-api-evolution.md)
-For any named minimal supported Rust version we guarantee that it is possible to build Diesel with the 
-default features enabled using some set of dependencies. Those set of dependencies is not necessarily 
-an up to date version of the specific dependency. We check this by using the unstable `-Z minimal-version` cargo flag. 
+For any named minimal supported Rust version we guarantee that it is possible to build Diesel with the
+default features enabled using some set of dependencies. Those set of dependencies is not necessarily
+an up to date version of the specific dependency. We check this by using the unstable `-Z minimal-version` cargo flag.
 Increasing the minimal supported Rust version will always be coupled at least with a minor release.
 
 ## Unreleased
 
+## [2.1.5] 2024-03-15
+
+* Fix `impl SqlOrd` postgres > postgres_backend feature flag.
+* Allow `Queryable` to be used with multiple table names.
+* Fix an inconsistent unit test
+* Fix a clippy lint
+* Fix ./bin/test feature flag calls.
+* Update `libsqlite3-sys` to allow version 0.28 as well
+
 ## [2.1.4] 2023-11-14
 
 * Update `libsqlite3-sys` to allow version 0.27 as well
@@ -23,7 +32,7 @@
 ## Fixed
 
 * Fixed another potential breaking chaneg around queries containing `DISTINCT ON` and `ORDER BY` clauses consisting of custom sql expressions (e.g. `.nullable()`)
-* Fixed an issue where `#[derive(Selectable)]` and `#[diesel(check_for_backend)]` generates invalid rust code if the struct contains lifetimes/generic types 
+* Fixed an issue where `#[derive(Selectable)]` and `#[diesel(check_for_backend)]` generates invalid rust code if the struct contains lifetimes/generic types
 
 ## [2.1.1] 2023-08-25
 
@@ -36,22 +45,23 @@
 * Fixed an issue where `#[diesel(check_for_backend)]` ignored `#[diesel(deserialize_as)]` attributes
 * Fixed several issues with the new `#[derive(MultiConnection)]` feature
 * Fixed some edge cases in our sqlite timestamp parsing behaviour
-* `diesel migration generate --diff-schema` now respects table filters as setup for `print-schema` via `diesel.toml` 
+* `diesel migration generate --diff-schema` now respects table filters as setup for `print-schema` via `diesel.toml`
 * Fixed a potential breaking change around queries containing `DISTINCT ON` and `ORDER BY` clauses consisting of custom sql expressions (e.g. `diesel::dsl::sql`)
 
-## Added 
+## Added
 
 * Support for bigdecimal 0.4
 
-
 ## [2.1.0] 2023-05-26
 
-### Changed 
+### Changed
 
 * The minimal officially supported rustc version is now 1.65.0
 
 ### Added
 
+* Added `serialize_database_to_buffer` and `deserialize_readonly_database_from_buffer` methods in `SqliteConnection` to support serialization/deserialization of SQLite databases to and from byte buffers.
+* Added `SerializedDatabase` wrapper type for a serialized database that is dynamically allocated by calling `serialize_database_to_buffer`. This RAII wrapper deallocates the memory when it goes out of scope with `sqlite3_free`.
 * Added the `custom_type_derives` config option to customize the derives for SQL
   type definitions automatically generated by Diesel CLI.
 * Add a `#[derive(MultiConnection)]` proc-macro that lets you easily implement `diesel::Connection`
@@ -280,7 +290,7 @@
   and a bound to `QueryableByName<DB>` with `FromSqlRow<Untyped, DB>`. 
 
 * CLI flags of `only-tables` and `except-tables` are now interpreted as regular expressions.
-  Similarly, `only_tabels` and `except_tables` in `diesel.toml` are treated as regular expressions.
+  Similarly, `only_tables` and `except_tables` in `diesel.toml` are treated as regular expressions.
 
 * Now you can sort column fields by name with the `column-sorting` option. 
   It can be set to either `ordinal_position` (default) or `name`.
@@ -2052,14 +2062,15 @@
 [1.4.8]: https://github.com/diesel-rs/diesel/compare/v1.4.7...v1.4.8
 [2.0.0 Rc0]: https://github.com/diesel-rs/diesel/compare/v.1.4.0...v2.0.0-rc0
 [2.0.0 Rc1]: https://github.com/diesel-rs/diesel/compare/v.2.0.0-rc0...v2.0.0-rc1
-[2.0.0]: https://github.com/diesel-rs/diesel/compare/v1.4.0...v2.0.0
-[2.0.1]: https://github.com/diesel-rs/diesel/compare/v2.0.0...v2.0.1
-[2.0.2]: https://github.com/diesel-rs/diesel/compare/v2.0.1...v2.0.2
+[2.0.0]: https://github.com/diesel-rs/diesel/compare/v.1.4.0...v2.0.0
+[2.0.1]: https://github.com/diesel-rs/diesel/compare/v.2.0.0...v2.0.1
+[2.0.2]: https://github.com/diesel-rs/diesel/compare/v.2.0.1...v2.0.2
 [diesel_derives 2.0.2]: https://github.com/diesel-rs/diesel/compare/v.2.0.2...diesel_derives_v2.0.2
-[2.0.3]: https://github.com/diesel-rs/diesel/compare/v2.0.2...v2.0.3
-[2.0.4]: https://github.com/diesel-rs/diesel/compare/v2.0.3...v2.0.4
-[2.1.0]: https://github.com/diesel-rs/diesel/compare/v2.0.0...v2.1.0
-[2.1.1]: https://github.com/diesel-rs/diesel/compare/v2.1.0...v2.1.1
-[2.1.2]: https://github.com/diesel-rs/diesel/compare/v2.1.1...v2.1.2
-[2.1.3]: https://github.com/diesel-rs/diesel/compare/v2.1.2...v2.1.3
-[2.1.4]: https://github.com/diesel-rs/diesel/compare/v2.1.3...v2.1.4
+[2.0.3]: https://github.com/diesel-rs/diesel/compare/v.2.0.2...v2.0.3
+[2.0.4]: https://github.com/diesel-rs/diesel/compare/v.2.0.3...v2.0.4
+[2.1.0]: https://github.com/diesel-rs/diesel/compare/v.2.0.0...v2.1.0
+[2.1.1]: https://github.com/diesel-rs/diesel/compare/v.2.1.0...v2.1.1
+[2.1.2]: https://github.com/diesel-rs/diesel/compare/v.2.1.1...v2.1.2
+[2.1.3]: https://github.com/diesel-rs/diesel/compare/v.2.1.2...v2.1.3
+[2.1.4]: https://github.com/diesel-rs/diesel/compare/v.2.1.3...v2.1.4
+[2.1.5]: https://github.com/diesel-rs/diesel/compare/v.2.1.4...v2.1.5
diff --git a/Cargo.toml b/Cargo.toml
index 2263bd3..94fa653e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,4 +1,5 @@
 [workspace]
+resolver = "2"
 members = [
     "diesel",
     "diesel_cli",
diff --git a/bin/test b/bin/test
index 1a05a26..793b596 100755
--- a/bin/test
+++ b/bin/test
@@ -24,14 +24,14 @@
     (cd diesel_cli && cargo test --features "sqlite" --no-default-features "$*")
     (cd diesel_migrations && cargo test --features "sqlite diesel/sqlite" "$*")
     (cd diesel_migrations && cargo test --features "sqlite diesel/sqlite" "$*")
-    (cd diesel_derives && cargo test --features "diesel/sqlite" "$*")
+    (cd diesel_derives && cargo test --features "sqlite diesel/sqlite" "$*")
     (cd diesel_tests && cargo test --features "sqlite" --no-default-features "$*")
     (cd diesel_dynamic_schema && cargo test --features "sqlite diesel/sqlite" "$*")
     (cd diesel_bench && cargo test --features "sqlite" --benches "$*")
 
     (cd diesel_migrations && cargo test --features "postgres diesel/postgres" "$*")
     (cd diesel_migrations/migrations_macros && cargo test --features "diesel/postgres postgres" "$*")
-    (cd diesel_derives && cargo test --features "diesel/postgres" "$*")
+    (cd diesel_derives && cargo test --features "postgres diesel/postgres" "$*")
     (cd diesel_cli && cargo test --features "postgres" --no-default-features "$*")
     (cd diesel_tests && cargo test --features "postgres" --no-default-features "$*")
     (cd diesel_dynamic_schema && cargo test --features "postgres diesel/postgres" "$*")
@@ -39,7 +39,7 @@
 
     (cd diesel_migrations && cargo test --features "mysql diesel/mysql" "$*" -- --test-threads 1)
     (cd diesel_migrations/migrations_macros && cargo test --features "diesel/mysql mysql" "$*" -- --test-threads 1)
-    (cd diesel_derives && cargo test --features "diesel/mysql" "$*" -- --test-threads 1)
+    (cd diesel_derives && cargo test --features "mysql diesel/mysql" "$*" -- --test-threads 1)
     (cd diesel_cli && cargo test --features "mysql" --no-default-features "$*" -- --test-threads 1)
     (cd diesel_tests && cargo test --features "mysql" --no-default-features "$*" -- --test-threads 1)
     (cd diesel_dynamic_schema && cargo test --features "mysql diesel/mysql" "$*" -- --test-threads 1)
diff --git a/diesel/Cargo.toml b/diesel/Cargo.toml
index 4939e9c..0eb4b6d 100644
--- a/diesel/Cargo.toml
+++ b/diesel/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "diesel"
-version = "2.1.4"
+version = "2.1.5"
 license = "MIT OR Apache-2.0"
 description = "A safe, extensible ORM and Query Builder for PostgreSQL, SQLite, and MySQL"
 readme = "README.md"
@@ -16,7 +16,7 @@
 byteorder = { version = "1.0", optional = true }
 chrono = { version = "0.4.20", optional = true, default-features = false, features = ["clock", "std"] }
 libc = { version = "0.2.0", optional = true }
-libsqlite3-sys = { version = ">=0.17.2, <0.28.0", optional = true, features = ["bundled_bindings"] }
+libsqlite3-sys = { version = ">=0.17.2, <0.29.0", optional = true, features = ["bundled_bindings"] }
 mysqlclient-sys = { version = "0.2.5", optional = true }
 pq-sys = { version = "0.4.0", optional = true }
 quickcheck = { version = "1.0.3", optional = true }
diff --git a/diesel/src/connection/mod.rs b/diesel/src/connection/mod.rs
index e8189b2..788014c 100644
--- a/diesel/src/connection/mod.rs
+++ b/diesel/src/connection/mod.rs
@@ -232,7 +232,7 @@
     /// If the transaction fails to commit due to a `SerializationFailure` or a
     /// `ReadOnlyTransaction` a rollback will be attempted.
     /// If the rollback fails, the error will be returned in a
-    /// [`Error::RollbackErrorOnCommit`](crate::result::Error::RollbackErrorOnCommit),
+    /// [`Error::RollbackErrorOnCommit`],
     /// from which you will be able to extract both the original commit error and
     /// the rollback error.
     /// In addition, the connection will be considered broken
diff --git a/diesel/src/connection/statement_cache.rs b/diesel/src/connection/statement_cache.rs
index 4487bd6..414e483 100644
--- a/diesel/src/connection/statement_cache.rs
+++ b/diesel/src/connection/statement_cache.rs
@@ -216,8 +216,8 @@
 
 /// Wraps a possibly cached prepared statement
 ///
-/// Essentially a customized version of [`Cow`](std::borrow::Cow)
-/// that does not depend on [`ToOwned`](std::borrow::ToOwned)
+/// Essentially a customized version of [`Cow`]
+/// that does not depend on [`ToOwned`]
 #[allow(missing_debug_implementations, unreachable_pub)]
 #[cfg_attr(
     doc_cfg,
diff --git a/diesel/src/lib.rs b/diesel/src/lib.rs
index 83736ae..41cfb40 100644
--- a/diesel/src/lib.rs
+++ b/diesel/src/lib.rs
@@ -186,7 +186,7 @@
 //! `64-column-tables` feature. Enabling this feature will increase your compile times significantly.
 //! - `i-implement-a-third-party-backend-and-opt-into-breaking-changes`: This feature opens up some otherwise
 //! private API, that can be useful to implement a third party [`Backend`](crate::backend::Backend)
-//! or write a custom [`Connection`](crate::connection::Connection) implementation. **Do not use this feature for
+//! or write a custom [`Connection`] implementation. **Do not use this feature for
 //! any other usecase**. By enabling this feature you explicitly opt out diesel stability guarantees. We explicitly
 //! reserve us the right to break API's exported under this feature flag in any upcoming minor version release.
 //! If you publish a crate depending on this feature flag consider to restrict the supported diesel version to the
diff --git a/diesel/src/mysql/types/date_and_time/chrono.rs b/diesel/src/mysql/types/date_and_time/chrono.rs
index 141ca4c..786dcd3 100644
--- a/diesel/src/mysql/types/date_and_time/chrono.rs
+++ b/diesel/src/mysql/types/date_and_time/chrono.rs
@@ -32,6 +32,7 @@
             hour: self.hour() as libc::c_uint,
             minute: self.minute() as libc::c_uint,
             second: self.second() as libc::c_uint,
+            #[allow(deprecated)] // otherwise we would need to bump our minimal chrono version
             second_part: libc::c_ulong::from(self.timestamp_subsec_micros()),
             neg: false,
             time_type: MysqlTimestampType::MYSQL_TIMESTAMP_DATETIME,
@@ -162,11 +163,11 @@
     #[test]
     fn times_relative_to_now_encode_correctly() {
         let connection = &mut connection();
-        let time = Utc::now().naive_utc() + Duration::days(1);
+        let time = Utc::now().naive_utc() + Duration::try_days(1).unwrap();
         let query = select(now.lt(time));
         assert!(query.get_result::<bool>(connection).unwrap());
 
-        let time = Utc::now().naive_utc() - Duration::days(1);
+        let time = Utc::now().naive_utc() - Duration::try_days(1).unwrap();
         let query = select(now.gt(time));
         assert!(query.get_result::<bool>(connection).unwrap());
     }
diff --git a/diesel/src/pg/types/date_and_time/chrono.rs b/diesel/src/pg/types/date_and_time/chrono.rs
index 6dc9bef..38bddfd 100644
--- a/diesel/src/pg/types/date_and_time/chrono.rs
+++ b/diesel/src/pg/types/date_and_time/chrono.rs
@@ -124,7 +124,9 @@
 impl FromSql<Date, Pg> for NaiveDate {
     fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
         let PgDate(offset) = FromSql::<Date, Pg>::from_sql(bytes)?;
-        match pg_epoch_date().checked_add_signed(Duration::days(i64::from(offset))) {
+        #[allow(deprecated)] // otherwise we would need to bump our minimal chrono version
+        let duration = Duration::days(i64::from(offset));
+        match pg_epoch_date().checked_add_signed(duration) {
             Some(date) => Ok(date),
             None => {
                 let error_message = format!(
@@ -205,11 +207,11 @@
     #[test]
     fn times_relative_to_now_encode_correctly() {
         let connection = &mut connection();
-        let time = Utc::now().naive_utc() + Duration::seconds(60);
+        let time = Utc::now().naive_utc() + Duration::try_seconds(60).unwrap();
         let query = select(now.at_time_zone("utc").lt(time));
         assert!(query.get_result::<bool>(connection).unwrap());
 
-        let time = Utc::now().naive_utc() - Duration::seconds(60);
+        let time = Utc::now().naive_utc() - Duration::try_seconds(60).unwrap();
         let query = select(now.at_time_zone("utc").gt(time));
         assert!(query.get_result::<bool>(connection).unwrap());
     }
@@ -280,8 +282,8 @@
         let query = select(sql::<Date>("'J0'::date").eq(julian_epoch));
         assert!(query.get_result::<bool>(connection).unwrap());
 
-        let max_date = NaiveDate::MAX;
-        let query = select(sql::<Date>("'262143-12-31'::date").eq(max_date));
+        let max_date = NaiveDate::from_ymd_opt(262142, 12, 31).unwrap();
+        let query = select(sql::<Date>("'262142-12-31'::date").eq(max_date));
         assert!(query.get_result::<bool>(connection).unwrap());
 
         let january_first_2018 = NaiveDate::from_ymd_opt(2018, 1, 1).unwrap();
@@ -311,8 +313,8 @@
         let query = select(sql::<Date>("'J0'::date"));
         assert_eq!(Ok(julian_epoch), query.get_result::<NaiveDate>(connection));
 
-        let max_date = NaiveDate::MAX;
-        let query = select(sql::<Date>("'262143-12-31'::date"));
+        let max_date = NaiveDate::from_ymd_opt(262142, 12, 31).unwrap();
+        let query = select(sql::<Date>("'262142-12-31'::date"));
         assert_eq!(Ok(max_date), query.get_result::<NaiveDate>(connection));
 
         let january_first_2018 = NaiveDate::from_ymd_opt(2018, 1, 1).unwrap();
diff --git a/diesel/src/pg/types/json.rs b/diesel/src/pg/types/json.rs
index 059c863..9f43add 100644
--- a/diesel/src/pg/types/json.rs
+++ b/diesel/src/pg/types/json.rs
@@ -46,9 +46,13 @@
     }
 }
 
-#[cfg(tests)]
+#[cfg(test)]
 mod tests {
-    use crate::query_builder::bind_types::ByteWrapper;
+    use crate::deserialize::FromSql;
+    use crate::pg::{Pg, PgValue};
+    use crate::query_builder::bind_collector::ByteWrapper;
+    use crate::serialize::{Output, ToSql};
+    use crate::sql_types;
 
     #[test]
     fn json_to_sql() {
diff --git a/diesel/src/query_dsl/mod.rs b/diesel/src/query_dsl/mod.rs
index a8c7eab..c4ff253 100644
--- a/diesel/src/query_dsl/mod.rs
+++ b/diesel/src/query_dsl/mod.rs
@@ -1268,13 +1268,12 @@
     /// # }
     /// ```
     ///
-    /// Diesel queries also have a similar problem to [`Iterator`][iterator], where
+    /// Diesel queries also have a similar problem to [`Iterator`], where
     /// returning them from a function requires exposing the implementation of that
     /// function. The [`helper_types`][helper_types] module exists to help with this,
     /// but you might want to hide the return type or have it conditionally change.
     /// Boxing can achieve both.
     ///
-    /// [iterator]: std::iter::Iterator
     /// [helper_types]: crate::helper_types
     ///
     /// ### Example
diff --git a/diesel/src/sql_types/mod.rs b/diesel/src/sql_types/mod.rs
index d74b4d0..bfe5509 100644
--- a/diesel/src/sql_types/mod.rs
+++ b/diesel/src/sql_types/mod.rs
@@ -196,14 +196,13 @@
 ///
 /// ### [`ToSql`](crate::serialize::ToSql) impls
 ///
-/// - [`String`][String]
+/// - [`String`]
 /// - [`&str`][str]
 ///
 /// ### [`FromSql`](crate::deserialize::FromSql) impls
 ///
-/// - [`String`][String]
+/// - [`String`]
 ///
-/// [String]: std::string::String
 /// [str]: https://doc.rust-lang.org/nightly/std/primitive.str.html
 #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)]
 #[diesel(postgres_type(oid = 25, array_oid = 1009))]
diff --git a/diesel/src/sql_types/ord.rs b/diesel/src/sql_types/ord.rs
index 81b83bb..7cf27a4 100644
--- a/diesel/src/sql_types/ord.rs
+++ b/diesel/src/sql_types/ord.rs
@@ -15,9 +15,9 @@
 impl SqlOrd for sql_types::Timestamp {}
 impl<T> SqlOrd for sql_types::Nullable<T> where T: SqlOrd + SqlType<IsNull = is_nullable::NotNull> {}
 
-#[cfg(feature = "postgres")]
+#[cfg(feature = "postgres_backend")]
 impl SqlOrd for sql_types::Timestamptz {}
-#[cfg(feature = "postgres")]
+#[cfg(feature = "postgres_backend")]
 impl<T: SqlOrd> SqlOrd for sql_types::Array<T> {}
 
 #[cfg(feature = "mysql_backend")]
diff --git a/diesel/src/sqlite/types/date_and_time/chrono.rs b/diesel/src/sqlite/types/date_and_time/chrono.rs
index 3877253..d6aa1bc 100644
--- a/diesel/src/sqlite/types/date_and_time/chrono.rs
+++ b/diesel/src/sqlite/types/date_and_time/chrono.rs
@@ -75,6 +75,7 @@
     let timestamp = (julian_days - EPOCH_IN_JULIAN_DAYS) * SECONDS_IN_DAY;
     let seconds = timestamp as i64;
     let nanos = (timestamp.fract() * 1E9) as u32;
+    #[allow(deprecated)] // otherwise we would need to bump our minimal chrono version
     NaiveDateTime::from_timestamp_opt(seconds, nanos)
 }
 
@@ -325,11 +326,11 @@
     #[test]
     fn times_relative_to_now_encode_correctly() {
         let connection = &mut connection();
-        let time = Utc::now().naive_utc() + Duration::seconds(60);
+        let time = Utc::now().naive_utc() + Duration::try_seconds(60).unwrap();
         let query = select(now.lt(time));
         assert_eq!(Ok(true), query.get_result(connection));
 
-        let time = Utc::now().naive_utc() - Duration::seconds(600);
+        let time = Utc::now().naive_utc() - Duration::try_seconds(600).unwrap();
         let query = select(now.gt(time));
         assert_eq!(Ok(true), query.get_result(connection));
     }
diff --git a/diesel_cli/Cargo.toml b/diesel_cli/Cargo.toml
index c877248..01a1970 100644
--- a/diesel_cli/Cargo.toml
+++ b/diesel_cli/Cargo.toml
@@ -27,7 +27,7 @@
 serde = { version = "1.0.0", features = ["derive"] }
 toml = "0.7"
 url = { version = "2.2.2" }
-libsqlite3-sys = { version = ">=0.17.2, <0.28.0", optional = true }
+libsqlite3-sys = { version = ">=0.17.2, <0.29.0", optional = true }
 diffy = "0.3.0"
 regex = "1.0.6"
 serde_regex = "1.1"
diff --git a/diesel_cli/src/infer_schema_internals/foreign_keys.rs b/diesel_cli/src/infer_schema_internals/foreign_keys.rs
index 35c7b65..9c1d751 100644
--- a/diesel_cli/src/infer_schema_internals/foreign_keys.rs
+++ b/diesel_cli/src/infer_schema_internals/foreign_keys.rs
@@ -33,7 +33,7 @@
                 "Error loading primary keys for `{}`",
                 fk.parent_table
             ));
-            pk_columns.len() == 1 && Some(&pk_columns[0]) == fk.primary_key_columns.get(0)
+            pk_columns.len() == 1 && Some(&pk_columns[0]) == fk.primary_key_columns.first()
         })
         .filter(|fk| !duplicates.contains(&fk.ordered_tables()))
         .cloned()
diff --git a/diesel_compile_tests/Cargo.lock b/diesel_compile_tests/Cargo.lock
index 021b16f..21f0529 100644
--- a/diesel_compile_tests/Cargo.lock
+++ b/diesel_compile_tests/Cargo.lock
@@ -64,7 +64,7 @@
 
 [[package]]
 name = "diesel"
-version = "2.0.2"
+version = "2.1.5"
 dependencies = [
  "bigdecimal",
  "bitflags 2.2.1",
@@ -98,7 +98,7 @@
 
 [[package]]
 name = "diesel_derives"
-version = "2.0.2"
+version = "2.1.3"
 dependencies = [
  "diesel_table_macro_syntax",
  "proc-macro2",
diff --git a/diesel_compile_tests/tests/fail/derive/multiple_table_names.stderr b/diesel_compile_tests/tests/fail/derive/multiple_table_names.stderr
index fbfa5de..335db0f 100644
--- a/diesel_compile_tests/tests/fail/derive/multiple_table_names.stderr
+++ b/diesel_compile_tests/tests/fail/derive/multiple_table_names.stderr
@@ -25,10 +25,3 @@
    |
 52 | #[diesel(table_name = users_)]
    |          ^^^^^^^^^^
-
-error: expected a single table name attribute
-       note: remove this attribute
-  --> tests/fail/derive/multiple_table_names.rs:59:30
-   |
-59 | #[diesel(table_name = users, table_name = users_)]
-   |                              ^^^^^^^^^^
diff --git a/diesel_derives/Cargo.toml b/diesel_derives/Cargo.toml
index 69ad560..b2b4fcc 100644
--- a/diesel_derives/Cargo.toml
+++ b/diesel_derives/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "diesel_derives"
-version = "2.1.2"
+version = "2.1.3"
 license = "MIT OR Apache-2.0"
 description = "You should not use this crate directly, it is internal to Diesel."
 documentation = "https://diesel.rs/guides/"
diff --git a/diesel_derives/src/queryable.rs b/diesel_derives/src/queryable.rs
index c58b046..ac42136 100644
--- a/diesel_derives/src/queryable.rs
+++ b/diesel_derives/src/queryable.rs
@@ -7,7 +7,7 @@
 use crate::util::wrap_in_dummy_mod;
 
 pub fn derive(item: DeriveInput) -> Result<TokenStream> {
-    let model = Model::from_item(&item, false, false)?;
+    let model = Model::from_item(&item, false, true)?;
 
     let struct_name = &item.ident;
     let field_ty = &model
diff --git a/diesel_derives/tests/queryable.rs b/diesel_derives/tests/queryable.rs
index c76382f..0b29a13 100644
--- a/diesel_derives/tests/queryable.rs
+++ b/diesel_derives/tests/queryable.rs
@@ -39,3 +39,27 @@
     let data = select(sql::<(Integer, Integer)>("1, 2")).get_result(conn);
     assert_eq!(Ok(MyStruct(1, 2)), data);
 }
+
+#[test]
+fn multiple_tables() {
+    #[derive(Debug, Clone, PartialEq, Eq, Queryable)]
+    #[diesel(table_name = users)]
+    #[diesel(table_name = users_)]
+    struct NewUser {
+        name: String,
+        hair_color: String,
+    }
+
+    let conn = &mut connection();
+    let data = select(sql::<(diesel::sql_types::Text, diesel::sql_types::Text)>(
+        "'red', 'red'",
+    ))
+    .get_result(conn);
+    assert_eq!(
+        Ok(NewUser {
+            name: "red".to_string(),
+            hair_color: "red".to_string()
+        }),
+        data
+    );
+}
diff --git a/diesel_tests/Cargo.toml b/diesel_tests/Cargo.toml
index 5fdd4a5..1d4d232 100644
--- a/diesel_tests/Cargo.toml
+++ b/diesel_tests/Cargo.toml
@@ -21,7 +21,7 @@
 ipnetwork = ">=0.12.2, <0.21.0"
 bigdecimal = ">= 0.0.13, < 0.5.0"
 rand = "0.8.4"
-libsqlite3-sys = { version = "0.27", optional = true }
+libsqlite3-sys = { version = "0.28", optional = true }
 
 [features]
 default = []
diff --git a/diesel_tests/tests/joins.rs b/diesel_tests/tests/joins.rs
index bc4a447..85b1c5c 100644
--- a/diesel_tests/tests/joins.rs
+++ b/diesel_tests/tests/joins.rs
@@ -44,7 +44,8 @@
     let select_title = source.select(posts::title);
 
     let expected_names = vec!["Sean".to_string(), "Tess".to_string()];
-    let actual_names: Vec<String> = select_name.load(connection).unwrap();
+    let mut actual_names: Vec<String> = select_name.load(connection).unwrap();
+    actual_names.sort();
 
     assert_eq!(expected_names, actual_names);
 
diff --git a/diesel_tests/tests/types_roundtrip.rs b/diesel_tests/tests/types_roundtrip.rs
index 3b09824..f8b9f74 100644
--- a/diesel_tests/tests/types_roundtrip.rs
+++ b/diesel_tests/tests/types_roundtrip.rs
@@ -465,7 +465,7 @@
             t.hour(),
             t.minute(),
             t.second(),
-            t.timestamp_subsec_micros() as _,
+            t.and_utc().timestamp_subsec_micros() as _,
             false,
             MysqlTimestampType::MYSQL_TIMESTAMP_DATETIME,
             0,
@@ -481,7 +481,7 @@
             t.hour(),
             t.minute(),
             t.second(),
-            t.timestamp_subsec_micros() as _,
+            t.and_utc().timestamp_subsec_micros() as _,
             false,
             MysqlTimestampType::MYSQL_TIMESTAMP_DATETIME,
             0,
@@ -508,10 +508,12 @@
             .unwrap();
 
         if seconds != 0 {
-            seconds = earliest_mysql_date.timestamp()
-                + ((latest_mysql_date.timestamp() - earliest_mysql_date.timestamp()) % seconds);
+            seconds = earliest_mysql_date.and_utc().timestamp()
+                + ((latest_mysql_date.and_utc().timestamp()
+                    - earliest_mysql_date.and_utc().timestamp())
+                    % seconds);
         } else {
-            seconds = earliest_mysql_date.timestamp();
+            seconds = earliest_mysql_date.and_utc().timestamp();
         }
 
         let r = mk_naive_datetime((seconds, nanos));
@@ -607,7 +609,7 @@
         break;
     }
 
-    NaiveDateTime::from_timestamp_opt(secs, nano).unwrap()
+    DateTime::from_timestamp(secs, nano).unwrap().naive_utc()
 }
 
 pub fn mk_naive_time((mut seconds, mut nano): (u32, u32)) -> NaiveTime {
@@ -647,7 +649,7 @@
     let num_days_representable = latest_chrono_date
         .signed_duration_since(earliest_pg_date)
         .num_days();
-    earliest_pg_date + Duration::days(days as i64 % num_days_representable)
+    earliest_pg_date + Duration::try_days(days as i64 % num_days_representable).unwrap()
 }
 
 #[cfg(feature = "mysql")]
@@ -657,7 +659,7 @@
     let num_days_representable = latest_mysql_date
         .signed_duration_since(earliest_mysql_date)
         .num_days();
-    earliest_mysql_date + Duration::days(days as i64 % num_days_representable)
+    earliest_mysql_date + Duration::try_days(days as i64 % num_days_representable).unwrap()
 }
 
 #[cfg(feature = "sqlite")]
@@ -667,7 +669,7 @@
     let num_days_representable = latest_sqlite_date
         .signed_duration_since(earliest_sqlite_date)
         .num_days();
-    earliest_sqlite_date + Duration::days(days as i64 % num_days_representable)
+    earliest_sqlite_date + Duration::try_days(days as i64 % num_days_representable).unwrap()
 }
 
 #[derive(Debug, Clone, Copy)]
diff --git a/examples/mysql/getting_started_step_1/src/schema.rs b/examples/mysql/getting_started_step_1/src/schema.rs
index 54b162b..bde3174 100644
--- a/examples/mysql/getting_started_step_1/src/schema.rs
+++ b/examples/mysql/getting_started_step_1/src/schema.rs
@@ -3,6 +3,7 @@
 diesel::table! {
     posts (id) {
         id -> Integer,
+        #[max_length = 255]
         title -> Varchar,
         body -> Text,
         published -> Bool,
diff --git a/examples/mysql/getting_started_step_2/src/schema.rs b/examples/mysql/getting_started_step_2/src/schema.rs
index 54b162b..bde3174 100644
--- a/examples/mysql/getting_started_step_2/src/schema.rs
+++ b/examples/mysql/getting_started_step_2/src/schema.rs
@@ -3,6 +3,7 @@
 diesel::table! {
     posts (id) {
         id -> Integer,
+        #[max_length = 255]
         title -> Varchar,
         body -> Text,
         published -> Bool,
diff --git a/examples/mysql/getting_started_step_3/src/schema.rs b/examples/mysql/getting_started_step_3/src/schema.rs
index 54b162b..bde3174 100644
--- a/examples/mysql/getting_started_step_3/src/schema.rs
+++ b/examples/mysql/getting_started_step_3/src/schema.rs
@@ -3,6 +3,7 @@
 diesel::table! {
     posts (id) {
         id -> Integer,
+        #[max_length = 255]
         title -> Varchar,
         body -> Text,
         published -> Bool,
diff --git a/examples/postgres/advanced-blog-cli/Cargo.toml b/examples/postgres/advanced-blog-cli/Cargo.toml
index db5cbdd..6630d22 100644
--- a/examples/postgres/advanced-blog-cli/Cargo.toml
+++ b/examples/postgres/advanced-blog-cli/Cargo.toml
@@ -9,7 +9,7 @@
 chrono = { version = "0.4.20", default-features = false, features = ["clock", "std"] }
 diesel = { version = "2.1.0", path = "../../../diesel", features = ["postgres", "chrono"] }
 dotenvy = "0.15"
-clap = { version = "4.2.7", features = ["derive"] }
+clap = { version = "4.0.0", features = ["derive"] }
 tempfile = "3.1.0"
 
 [dev-dependencies]
diff --git a/examples/postgres/advanced-blog-cli/src/pagination.rs b/examples/postgres/advanced-blog-cli/src/pagination.rs
index fca9846..ba23332 100644
--- a/examples/postgres/advanced-blog-cli/src/pagination.rs
+++ b/examples/postgres/advanced-blog-cli/src/pagination.rs
@@ -44,7 +44,7 @@
     {
         let per_page = self.per_page;
         let results = self.load::<(U, i64)>(conn)?;
-        let total = results.get(0).map(|x| x.1).unwrap_or(0);
+        let total = results.first().map(|x| x.1).unwrap_or(0);
         let records = results.into_iter().map(|x| x.0).collect();
         let total_pages = (total as f64 / per_page as f64).ceil() as i64;
         Ok((records, total_pages))
diff --git a/examples/sqlite/all_about_inserts/Cargo.toml b/examples/sqlite/all_about_inserts/Cargo.toml
index 80f6e61..00ff023 100644
--- a/examples/sqlite/all_about_inserts/Cargo.toml
+++ b/examples/sqlite/all_about_inserts/Cargo.toml
@@ -9,7 +9,7 @@
 serde = { version = "1.0.130", features = ["derive"] }
 serde_json = "1.0.68"
 chrono = { version = "0.4.20", default-features = false, features = ["clock", "std"] }
-libsqlite3-sys = { version = "0.27.0", features = ["bundled"] }
+libsqlite3-sys = { version = "0.28.0", features = ["bundled"] }
 
 [lib]
 doc = false
diff --git a/examples/sqlite/getting_started_step_1/Cargo.toml b/examples/sqlite/getting_started_step_1/Cargo.toml
index a53a790..a72fddd 100644
--- a/examples/sqlite/getting_started_step_1/Cargo.toml
+++ b/examples/sqlite/getting_started_step_1/Cargo.toml
@@ -9,7 +9,7 @@
 [dependencies]
 diesel = { version = "2.1.0", path = "../../../diesel", features = ["sqlite"] }
 dotenvy = "0.15"
-libsqlite3-sys = { version = "0.27.0", features = ["bundled"] }
+libsqlite3-sys = { version = "0.28.0", features = ["bundled"] }
 
 [[bin]]
 name = "show_posts"
diff --git a/examples/sqlite/getting_started_step_2/Cargo.toml b/examples/sqlite/getting_started_step_2/Cargo.toml
index ad212b0..9d64521 100644
--- a/examples/sqlite/getting_started_step_2/Cargo.toml
+++ b/examples/sqlite/getting_started_step_2/Cargo.toml
@@ -8,7 +8,7 @@
 [dependencies]
 diesel = { version = "2.1.0", path = "../../../diesel", features = ["sqlite", "returning_clauses_for_sqlite_3_35"] }
 dotenvy = "0.15"
-libsqlite3-sys = { version = "0.27.0", features = ["bundled"] }
+libsqlite3-sys = { version = "0.28.0", features = ["bundled"] }
 
 [[bin]]
 name = "show_posts"
diff --git a/examples/sqlite/getting_started_step_3/Cargo.toml b/examples/sqlite/getting_started_step_3/Cargo.toml
index 44be61c..140058f 100644
--- a/examples/sqlite/getting_started_step_3/Cargo.toml
+++ b/examples/sqlite/getting_started_step_3/Cargo.toml
@@ -8,7 +8,7 @@
 [dependencies]
 diesel = { version = "2.1.0", path = "../../../diesel", features = ["sqlite", "returning_clauses_for_sqlite_3_35"] }
 dotenvy = "0.15"
-libsqlite3-sys = { version = "0.27.0", features = ["bundled"] }
+libsqlite3-sys = { version = "0.28.0", features = ["bundled"] }
 
 [[bin]]
 name = "show_posts"
diff --git a/rust-toolchain b/rust-toolchain
index ee2f4ca..32a6ce3 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1 +1 @@
-1.68.0
+1.76.0