Repository: blackbeam/rust-mysql-simple (language: rust)

Issue:
conn.query_map(),sencond param, compiler error with 19 feilds
mysql version 22.1.0
struct TucPriv with 6 feilds,can run;
with 19 feilds,compiler error
![1](https://user-images.githubusercontent.com/13061179/174516621-368a8a47-0d81-44cd-b95a-6306f9cc218b.png)



Discussion / hints:

Fix patch:
diff --git a/Cargo.toml b/Cargo.toml
index b0af201..5a891ed 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "mysql"
-version = "22.1.0"
+version = "22.2.0"
 authors = ["blackbeam"]
 description = "Mysql client library implemented in rust"
 license = "MIT/Apache-2.0"
@@ -50,6 +50,7 @@ lazy_static = "1.4.0"
 rand = "0.8.2"
 serde_derive = "1"
 time = "0.3"
+frunk = "0.4"
 
 [dependencies]
 bufstream = "~0.1"
@@ -78,7 +79,7 @@ features = ["dangerous_configuration"]
 optional = true
 
 [dependencies.rustls-pemfile]
-version = "0.2.1"
+version = "1.0.0"
 optional = true
 
 [dependencies.webpki]
diff --git a/README.md b/README.md
index 4958c47..83904d3 100644
--- a/README.md
+++ b/README.md
@@ -50,53 +50,59 @@ struct Payment {
     account_name: Option<String>,
 }
 
-let url = "mysql://root:password@localhost:3307/db_name";
 
-let pool = Pool::new(url)?;
-
-let mut conn = pool.get_conn()?;
-
-// Let's create a table for payments.
-conn.query_drop(
-    r"CREATE TEMPORARY TABLE payment (
-        customer_id int not null,
-        amount int not null,
-        account_name text
-    )")?;
-
-let payments = vec![
-    Payment { customer_id: 1, amount: 2, account_name: None },
-    Payment { customer_id: 3, amount: 4, account_name: Some("foo".into()) },
-    Payment { customer_id: 5, amount: 6, account_name: None },
-    Payment { customer_id: 7, amount: 8, account_name: None },
-    Payment { customer_id: 9, amount: 10, account_name: Some("bar".into()) },
-];
-
-// Now let's insert payments to the database
-conn.exec_batch(
-    r"INSERT INTO payment (customer_id, amount, account_name)
-      VALUES (:customer_id, :amount, :account_name)",
-    payments.iter().map(|p| params! {
-        "customer_id" => p.customer_id,
-        "amount" => p.amount,
-        "account_name" => &p.account_name,
-    })
-)?;
-
-// Let's select payments from database. Type inference should do the trick here.
-let selected_payments = conn
-    .query_map(
-        "SELECT customer_id, amount, account_name from payment",
-        |(customer_id, amount, account_name)| {
-            Payment { customer_id, amount, account_name }
-        },
+fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
+    let url = "mysql://root:password@localhost:3307/db_name";
+    # Opts::try_from(url)?;
+    # let url = get_opts();
+    let pool = Pool::new(url)?;
+
+    let mut conn = pool.get_conn()?;
+
+    // Let's create a table for payments.
+    conn.query_drop(
+        r"CREATE TEMPORARY TABLE payment (
+            customer_id int not null,
+            amount int not null,
+            account_name text
+        )")?;
+
+    let payments = vec![
+        Payment { customer_id: 1, amount: 2, account_name: None },
+        Payment { customer_id: 3, amount: 4, account_name: Some("foo".into()) },
+        Payment { customer_id: 5, amount: 6, account_name: None },
+        Payment { customer_id: 7, amount: 8, account_name: None },
+        Payment { customer_id: 9, amount: 10, account_name: Some("bar".into()) },
+    ];
+
+    // Now let's insert payments to the database
+    conn.exec_batch(
+        r"INSERT INTO payment (customer_id, amount, account_name)
+          VALUES (:customer_id, :amount, :account_name)",
+        payments.iter().map(|p| params! {
+            "customer_id" => p.customer_id,
+            "amount" => p.amount,
+            "account_name" => &p.account_name,
+        })
     )?;
 
-// Let's make sure, that `payments` equals to `selected_payments`.
-// Mysql gives no guaranties on order of returned rows
-// without `ORDER BY`, so assume we are lucky.
-assert_eq!(payments, selected_payments);
-println!("Yay!");
+    // Let's select payments from database. Type inference should do the trick here.
+    let selected_payments = conn
+        .query_map(
+            "SELECT customer_id, amount, account_name from payment",
+            |(customer_id, amount, account_name)| {
+                Payment { customer_id, amount, account_name }
+            },
+        )?;
+
+    // Let's make sure, that `payments` equals to `selected_payments`.
+    // Mysql gives no guaranties on order of returned rows
+    // without `ORDER BY`, so assume we are lucky.
+    assert_eq!(payments, selected_payments);
+    println!("Yay!");
+
+    Ok(())
+}
 ```
 
 ### Crate Features
@@ -404,6 +410,17 @@ for i in 0..row.len() {
     assert_eq!(row[i], Value::Int(i as i64));
 }
 
+// Another way to handle wide rows is to use HList (requires `mysql_common/frunk` feature)
+use frunk::{HList, hlist, hlist_pat};
+let query = "select 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15";
+type RowType = HList!(u8, u16, u32, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8);
+let first_three_columns = conn.query_map(query, |row: RowType| {
+    // do something with the row (see the `frunk` crate documentation)
+    let hlist_pat![c1, c2, c3, ...] = row;
+    (c1, c2, c3)
+});
+assert_eq!(first_three_columns.unwrap(), vec![(0_u8, 1_u16, 2_u32)]);
+
 // Some unknown row
 let row: Row = conn.query_first(
     // ...
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index e344988..9733c1d 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -45,11 +45,11 @@ jobs:
           SSL=false COMPRESS=true cargo test
           SSL=true COMPRESS=true cargo test
 
-          SSL=true COMPRESS=false cargo test --no-default-features --features rustls-tls,flate2/zlib,mysql_common/time03
-          SSL=true COMPRESS=true cargo test --no-default-features --features rustls-tls,flate2/zlib,mysql_common/time03
+          SSL=true COMPRESS=false cargo test --no-default-features --features rustls-tls,flate2/zlib,mysql_common/time03,mysql_common/frunk
+          SSL=true COMPRESS=true cargo test --no-default-features --features rustls-tls,flate2/zlib,mysql_common/time03,mysql_common/frunk
 
-          SSL=false COMPRESS=true cargo test --no-default-features --features flate2/zlib,mysql_common/time03
-          SSL=false COMPRESS=false cargo test --no-default-features --features flate2/zlib,mysql_common/time03
+          SSL=false COMPRESS=true cargo test --no-default-features --features flate2/zlib,mysql_common/time03,mysql_common/frunk
+          SSL=false COMPRESS=false cargo test --no-default-features --features flate2/zlib,mysql_common/time03,mysql_common/frunk
         env:
           RUST_BACKTRACE: 1
           DATABASE_URL: mysql://root:root@localhost:3306/mysql
@@ -91,11 +91,11 @@ jobs:
           SSL=false COMPRESS=true cargo test
           SSL=true COMPRESS=true cargo test
 
-          SSL=true COMPRESS=false cargo test --no-default-features --features rustls-tls,flate2/zlib,mysql_common/time03
-          SSL=true COMPRESS=true cargo test --no-default-features --features rustls-tls,flate2/zlib,mysql_common/time03
+          SSL=true COMPRESS=false cargo test --no-default-features --features rustls-tls,flate2/zlib,mysql_common/time03,mysql_common/frunk
+          SSL=true COMPRESS=true cargo test --no-default-features --features rustls-tls,flate2/zlib,mysql_common/time03,mysql_common/frunk
 
-          SSL=false COMPRESS=true cargo test --no-default-features --features flate2/zlib,mysql_common/time03
-          SSL=false COMPRESS=false cargo test --no-default-features --features flate2/zlib,mysql_common/time03
+          SSL=false COMPRESS=true cargo test --no-default-features --features flate2/zlib,mysql_common/time03,mysql_common/frunk
+          SSL=false COMPRESS=false cargo test --no-default-features --features flate2/zlib,mysql_common/time03,mysql_common/frunk
         env:
           RUST_BACKTRACE: 1
           DATABASE_URL: mysql://root@localhost/mysql
@@ -142,11 +142,11 @@ jobs:
           SSL=false COMPRESS=true cargo test
           SSL=true COMPRESS=true cargo test
 
-          SSL=true COMPRESS=false cargo test --no-default-features --features rustls-tls,flate2/zlib,mysql_common/time03
-          SSL=true COMPRESS=true cargo test --no-default-features --features rustls-tls,flate2/zlib,mysql_common/time03
+          SSL=true COMPRESS=false cargo test --no-default-features --features rustls-tls,flate2/zlib,mysql_common/time03,mysql_common/frunk
+          SSL=true COMPRESS=true cargo test --no-default-features --features rustls-tls,flate2/zlib,mysql_common/time03,mysql_common/frunk
 
-          SSL=false COMPRESS=true cargo test --no-default-features --features flate2/zlib,mysql_common/time03
-          SSL=false COMPRESS=false cargo test --no-default-features --features flate2/zlib,mysql_common/time03
+          SSL=false COMPRESS=true cargo test --no-default-features --features flate2/zlib,mysql_common/time03,mysql_common/frunk
+          SSL=false COMPRESS=false cargo test --no-default-features --features flate2/zlib,mysql_common/time03,mysql_common/frunk
         env:
           RUST_BACKTRACE: 1
           DATABASE_URL: mysql://root:password@localhost/mysql
@@ -214,11 +214,11 @@ jobs:
           docker exec container bash -l -c "cd \$HOME && DATABASE_URL=$DATABASE_URL SSL=$SSL cargo test"
           docker exec container bash -l -c "cd \$HOME && DATABASE_URL=$DATABASE_URL SSL=$SSL COMPRESS=true cargo test"
 
-          docker exec container bash -l -c "cd \$HOME && DATABASE_URL=$DATABASE_URL SSL=true COMPRESS=false cargo test --no-default-features --features rustls-tls,flate2/zlib,mysql_common/time03"
-          docker exec container bash -l -c "cd \$HOME && DATABASE_URL=$DATABASE_URL SSL=true COMPRESS=true cargo test --no-default-features --features rustls-tls,flate2/zlib,mysql_common/time03"
+          docker exec container bash -l -c "cd \$HOME && DATABASE_URL=$DATABASE_URL SSL=true COMPRESS=false cargo test --no-default-features --features rustls-tls,flate2/zlib,mysql_common/time03,mysql_common/frunk"
+          docker exec container bash -l -c "cd \$HOME && DATABASE_URL=$DATABASE_URL SSL=true COMPRESS=true cargo test --no-default-features --features rustls-tls,flate2/zlib,mysql_common/time03,mysql_common/frunk"
 
-          docker exec container bash -l -c "cd \$HOME && DATABASE_URL=$DATABASE_URL SSL=false COMPRESS=true cargo test --no-default-features --features flate2/zlib,mysql_common/time03"
-          docker exec container bash -l -c "cd \$HOME && DATABASE_URL=$DATABASE_URL SSL=false COMPRESS=false cargo test --no-default-features --features flate2/zlib,mysql_common/time03"
+          docker exec container bash -l -c "cd \$HOME && DATABASE_URL=$DATABASE_URL SSL=false COMPRESS=true cargo test --no-default-features --features flate2/zlib,mysql_common/time03,mysql_common/frunk"
+          docker exec container bash -l -c "cd \$HOME && DATABASE_URL=$DATABASE_URL SSL=false COMPRESS=false cargo test --no-default-features --features flate2/zlib,mysql_common/time03,mysql_common/frunk"
         env:
           RUST_BACKTRACE: 1
           DATABASE_URL: mysql://root:password@localhost/mysql
@@ -286,11 +286,11 @@ jobs:
           docker exec container bash -l -c "cd \$HOME && DATABASE_URL=$DATABASE_URL SSL=true cargo test"
           docker exec container bash -l -c "cd \$HOME && DATABASE_URL=$DATABASE_URL SSL=true COMPRESS=true cargo test"
 
-          docker exec container bash -l -c "cd \$HOME && DATABASE_URL=$DATABASE_URL SSL=true COMPRESS=false cargo test --no-default-features --features rustls-tls,flate2/zlib,mysql_common/time03"
-          docker exec container bash -l -c "cd \$HOME && DATABASE_URL=$DATABASE_URL SSL=true COMPRESS=true cargo test --no-default-features --features rustls-tls,flate2/zlib,mysql_common/time03"
+          docker exec container bash -l -c "cd \$HOME && DATABASE_URL=$DATABASE_URL SSL=true COMPRESS=false cargo test --no-default-features --features rustls-tls,flate2/zlib,mysql_common/time03,mysql_common/frunk"
+          docker exec container bash -l -c "cd \$HOME && DATABASE_URL=$DATABASE_URL SSL=true COMPRESS=true cargo test --no-default-features --features rustls-tls,flate2/zlib,mysql_common/time03,mysql_common/frunk"
 
-          docker exec container bash -l -c "cd \$HOME && DATABASE_URL=$DATABASE_URL SSL=false COMPRESS=true cargo test --no-default-features --features flate2/zlib,mysql_common/time03"
-          docker exec container bash -l -c "cd \$HOME && DATABASE_URL=$DATABASE_URL SSL=false COMPRESS=false cargo test --no-default-features --features flate2/zlib,mysql_common/time03"
+          docker exec container bash -l -c "cd \$HOME && DATABASE_URL=$DATABASE_URL SSL=false COMPRESS=true cargo test --no-default-features --features flate2/zlib,mysql_common/time03,mysql_common/frunk"
+          docker exec container bash -l -c "cd \$HOME && DATABASE_URL=$DATABASE_URL SSL=false COMPRESS=false cargo test --no-default-features --features flate2/zlib,mysql_common/time03,mysql_common/frunk"
         env:
           RUST_BACKTRACE: 1
           DATABASE_URL: mysql://root:password@localhost/mysql
diff --git a/src/lib.rs b/src/lib.rs
index 6b00c06..95feaa2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -41,7 +41,6 @@
 //! ## Example
 //!
 //! ```rust
-//! # mysql::doctest_wrapper!(__result, {
 //! use mysql::*;
 //! use mysql::prelude::*;
 //!
@@ -52,56 +51,60 @@
 //!     account_name: Option<String>,
 //! }
 //!
-//! let url = "mysql://root:password@localhost:3307/db_name";
-//! # Opts::try_from(url)?;
-//! # let url = get_opts();
-//!
-//! let pool = Pool::new(url)?;
-//!
-//! let mut conn = pool.get_conn()?;
-//!
-//! // Let's create a table for payments.
-//! conn.query_drop(
-//!     r"CREATE TEMPORARY TABLE payment (
-//!         customer_id int not null,
-//!         amount int not null,
-//!         account_name text
-//!     )")?;
-//!
-//! let payments = vec![
-//!     Payment { customer_id: 1, amount: 2, account_name: None },
-//!     Payment { customer_id: 3, amount: 4, account_name: Some("foo".into()) },
-//!     Payment { customer_id: 5, amount: 6, account_name: None },
-//!     Payment { customer_id: 7, amount: 8, account_name: None },
-//!     Payment { customer_id: 9, amount: 10, account_name: Some("bar".into()) },
-//! ];
-//!
-//! // Now let's insert payments to the database
-//! conn.exec_batch(
-//!     r"INSERT INTO payment (customer_id, amount, account_name)
-//!       VALUES (:customer_id, :amount, :account_name)",
-//!     payments.iter().map(|p| params! {
-//!         "customer_id" => p.customer_id,
-//!         "amount" => p.amount,
-//!         "account_name" => &p.account_name,
-//!     })
-//! )?;
-//!
-//! // Let's select payments from database. Type inference should do the trick here.
-//! let selected_payments = conn
-//!     .query_map(
-//!         "SELECT customer_id, amount, account_name from payment",
-//!         |(customer_id, amount, account_name)| {
-//!             Payment { customer_id, amount, account_name }
-//!         },
+//! # def_get_opts!();
+//!
+//! fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
+//!     let url = "mysql://root:password@localhost:3307/db_name";
+//!     # Opts::try_from(url)?;
+//!     # let url = get_opts();
+//!     let pool = Pool::new(url)?;
+//!
+//!     let mut conn = pool.get_conn()?;
+//!
+//!     // Let's create a table for payments.
+//!     conn.query_drop(
+//!         r"CREATE TEMPORARY TABLE payment (
+//!             customer_id int not null,
+//!             amount int not null,
+//!             account_name text
+//!         )")?;
+//!
+//!     let payments = vec![
+//!         Payment { customer_id: 1, amount: 2, account_name: None },
+//!         Payment { customer_id: 3, amount: 4, account_name: Some("foo".into()) },
+//!         Payment { customer_id: 5, amount: 6, account_name: None },
+//!         Payment { customer_id: 7, amount: 8, account_name: None },
+//!         Payment { customer_id: 9, amount: 10, account_name: Some("bar".into()) },
+//!     ];
+//!
+//!     // Now let's insert payments to the database
+//!     conn.exec_batch(
+//!         r"INSERT INTO payment (customer_id, amount, account_name)
+//!           VALUES (:customer_id, :amount, :account_name)",
+//!         payments.iter().map(|p| params! {
+//!             "customer_id" => p.customer_id,
+//!             "amount" => p.amount,
+//!             "account_name" => &p.account_name,
+//!         })
 //!     )?;
 //!
-//! // Let's make sure, that `payments` equals to `selected_payments`.
-//! // Mysql gives no guaranties on order of returned rows
-//! // without `ORDER BY`, so assume we are lucky.
-//! assert_eq!(payments, selected_payments);
-//! println!("Yay!");
-//! # });
+//!     // Let's select payments from database. Type inference should do the trick here.
+//!     let selected_payments = conn
+//!         .query_map(
+//!             "SELECT customer_id, amount, account_name from payment",
+//!             |(customer_id, amount, account_name)| {
+//!                 Payment { customer_id, amount, account_name }
+//!             },
+//!         )?;
+//!
+//!     // Let's make sure, that `payments` equals to `selected_payments`.
+//!     // Mysql gives no guaranties on order of returned rows
+//!     // without `ORDER BY`, so assume we are lucky.
+//!     assert_eq!(payments, selected_payments);
+//!     println!("Yay!");
+//!
+//!     Ok(())
+//! }
 //! ```
 //!
 //! ## Crate Features
@@ -129,17 +132,17 @@
 //!         *   **mysql_common/uuid** – the `uuid` is enabled by default
 //!         *   **mysql_common/frunk** – the `frunk` is enabled by default
 //!
-//! Please note, that you'll need to reenable external features if you are using `no-default-features = true`:
+//! Please note, that you'll need to reenable external features if you are using `default-features = false`:
 //!
 //! ```toml
 //! [dependencies]
 //! # Lets say that we want to use the `rustls-tls` feature:
-//! mysql = { version = "*", no-default-features = true, features = ["rustls-tls", "buffer-pool"] }
+//! mysql = { version = "*", default-features = false, features = ["rustls-tls", "buffer-pool"] }
 //! # Previous line disables default mysql features,
 //! # so now we have to choose the flate2 backend (this is necessary),
 //! # as well as the desired set of mysql_common features:
-//! flate2 = { version = "*", no-default-features = true, features = ["zlib"] }
-//! mysql_common = { version = "*", no-default-features = true, features = ["bigdecimal03", "time03", "uuid"]}
+//! flate2 = { version = "*", default-features = false, features = ["zlib"] }
+//! mysql_common = { version = "*", default-features = false, features = ["bigdecimal03", "time03", "uuid"]}
 //! ```
 //!
 //! ## API Documentation
@@ -425,6 +428,17 @@
 //!     assert_eq!(row[i], Value::Int(i as i64));
 //! }
 //!
+//! // Another way to handle wide rows is to use HList (requires `mysql_common/frunk` feature)
+//! use frunk::{HList, hlist, hlist_pat};
+//! let query = "select 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15";
+//! type RowType = HList!(u8, u16, u32, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8);
+//! let first_three_columns = conn.query_map(query, |row: RowType| {
+//!     // do something with the row (see the `frunk` crate documentation)
+//!     let hlist_pat![c1, c2, c3, ...] = row;
+//!     (c1, c2, c3)
+//! });
+//! assert_eq!(first_three_columns.unwrap(), vec![(0_u8, 1_u16, 2_u32)]);
+//!
 //! // Some unknown row
 //! let row: Row = conn.query_first(
 //!     // ...


Test patch: