{"id":13439067,"url":"https://github.com/blackbeam/rust-mysql-simple","last_synced_at":"2026-01-17T05:03:46.864Z","repository":{"id":14249976,"uuid":"16957443","full_name":"blackbeam/rust-mysql-simple","owner":"blackbeam","description":"Mysql client library implemented in rust.","archived":false,"fork":false,"pushed_at":"2026-01-15T13:39:14.000Z","size":2285,"stargazers_count":689,"open_issues_count":12,"forks_count":149,"subscribers_count":8,"default_branch":"master","last_synced_at":"2026-01-15T17:41:04.287Z","etag":null,"topics":["database","driver","mysql","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/blackbeam.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2014-02-18T17:36:44.000Z","updated_at":"2026-01-15T13:39:32.000Z","dependencies_parsed_at":"2024-05-20T13:36:14.402Z","dependency_job_id":"bb6d01d7-a996-4082-aeee-2df68b3fecd3","html_url":"https://github.com/blackbeam/rust-mysql-simple","commit_stats":{"total_commits":964,"total_committers":61,"mean_commits":15.80327868852459,"dds":0.2904564315352697,"last_synced_commit":"45ae0067991b0bf26fe433d3c119af6978ae2364"},"previous_names":[],"tags_count":67,"template":false,"template_full_name":null,"purl":"pkg:github/blackbeam/rust-mysql-simple","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blackbeam%2Frust-mysql-simple","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blackbeam%2Frust-mysql-simple/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blackbeam%2Frust-mysql-simple/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blackbeam%2Frust-mysql-simple/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/blackbeam","download_url":"https://codeload.github.com/blackbeam/rust-mysql-simple/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blackbeam%2Frust-mysql-simple/sbom","scorecard":{"id":241980,"data":{"date":"2025-08-11","repo":{"name":"github.com/blackbeam/rust-mysql-simple","commit":"398819314a2a374f80f80850519cc75e11a4f829"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.9,"checks":[{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":4,"reason":"Found 4/10 approved changesets -- score normalized to 4","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":10,"reason":"9 commit(s) and 3 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE-APACHE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE-APACHE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'","Warn: branch protection not enabled for branch 'v15.1.-'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 27 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-17T06:49:31.144Z","repository_id":14249976,"created_at":"2025-08-17T06:49:31.144Z","updated_at":"2025-08-17T06:49:31.144Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28497997,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T04:31:57.058Z","status":"ssl_error","status_checked_at":"2026-01-17T04:31:45.816Z","response_time":85,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","driver","mysql","rust"],"created_at":"2024-07-31T03:01:10.855Z","updated_at":"2026-01-17T05:03:46.840Z","avatar_url":"https://github.com/blackbeam.png","language":"Rust","funding_links":[],"categories":["Libraries","代码","Database libraries","库 Libraries","Rust","库"],"sub_categories":["Database","数据库","数据库 Database"],"readme":"[![Gitter](https://badges.gitter.im/rust-mysql/community.svg)](https://gitter.im/rust-mysql/community?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge)\n\n[![Crates.io](https://img.shields.io/crates/v/mysql.svg)](https://crates.io/crates/mysql)\n[![Build Status](https://dev.azure.com/aikorsky/mysql%20Rust/_apis/build/status/blackbeam%2Erust%2Dmysql%2Dsimple)](https://dev.azure.com/aikorsky/mysql%20Rust/_build/latest?definitionId=1)\n\n# mysql\n\nThis crate offers:\n\n*   MySql database driver in pure rust;\n*   connection pool.\n\nFeatures:\n\n*   macOS, Windows and Linux support;\n*   TLS support via **native-tls** or **rustls** (see the [SSL Support](#ssl-support) section);\n*   MySql text protocol support, i.e. support of simple text queries and text result sets;\n*   MySql binary protocol support, i.e. support of prepared statements and binary result sets;\n*   support of multi-result sets;\n*   support of named parameters for prepared statements (see the [Named Parameters](#named-parameters) section);\n*   per-connection cache of prepared statements (see the [Statement Cache](#statement-cache) section);\n*   buffer pool (see the [Buffer Pool](#buffer-pool) section);\n*   support of MySql packets larger than 2^24;\n*   support of Unix sockets and Windows named pipes;\n*   support of custom LOCAL INFILE handlers;\n*   support of MySql protocol compression;\n*   support of auth plugins:\n    *   **mysql_native_password** - for MySql prior to v8;\n    *   **caching_sha2_password** - for MySql v8 and higher;\n    *   **mysql_clear_password** - opt-in (see [`Opts::get_enable_cleartext_plugin`].\n\n### Installation\n\nPut the desired version of the crate into the `dependencies` section of your `Cargo.toml`:\n\n```toml\n[dependencies]\nmysql = \"*\"\n```\n\n### Example\n\n```rust\nuse mysql::*;\nuse mysql::prelude::*;\n\n#[derive(Debug, PartialEq, Eq)]\nstruct Payment {\n    customer_id: i32,\n    amount: i32,\n    account_name: Option\u003cString\u003e,\n}\n\n\nfn main() -\u003e std::result::Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    let url = \"mysql://root:password@localhost:3307/db_name\";\n    # Opts::try_from(url)?;\n    # let url = get_opts();\n    let pool = Pool::new(url)?;\n\n    let mut conn = pool.get_conn()?;\n\n    // Let's create a table for payments.\n    conn.query_drop(\n        r\"CREATE TEMPORARY TABLE payment (\n            customer_id int not null,\n            amount int not null,\n            account_name text\n        )\")?;\n\n    let payments = vec![\n        Payment { customer_id: 1, amount: 2, account_name: None },\n        Payment { customer_id: 3, amount: 4, account_name: Some(\"foo\".into()) },\n        Payment { customer_id: 5, amount: 6, account_name: None },\n        Payment { customer_id: 7, amount: 8, account_name: None },\n        Payment { customer_id: 9, amount: 10, account_name: Some(\"bar\".into()) },\n    ];\n\n    // Now let's insert payments to the database\n    conn.exec_batch(\n        r\"INSERT INTO payment (customer_id, amount, account_name)\n          VALUES (:customer_id, :amount, :account_name)\",\n        payments.iter().map(|p| params! {\n            \"customer_id\" =\u003e p.customer_id,\n            \"amount\" =\u003e p.amount,\n            \"account_name\" =\u003e \u0026p.account_name,\n        })\n    )?;\n\n    // Let's select payments from database. Type inference should do the trick here.\n    let selected_payments = conn\n        .query_map(\n            \"SELECT customer_id, amount, account_name from payment\",\n            |(customer_id, amount, account_name)| {\n                Payment { customer_id, amount, account_name }\n            },\n        )?;\n\n    // Let's make sure, that `payments` equals to `selected_payments`.\n    // Mysql gives no guaranties on order of returned rows\n    // without `ORDER BY`, so assume we are lucky.\n    assert_eq!(payments, selected_payments);\n    println!(\"Yay!\");\n\n    Ok(())\n}\n```\n\n### Crate Features\n\n* feature sets:\n\n    *   **default** – includes `buffer-pool` `flate2/zlib` and `derive`\n    *   **default-rust** - same as `default` but with `flate2/rust_backend` instead of `flate2/zlib`\n    *   **minimal** - includes `flate2/zlib` only\n    *   **minimal-rust** - includes `flate2/rust_backend` only\n\n* features:\n    *   **buffer-pool** – enables buffer pooling\n        (see the [Buffer Pool](#buffer-pool) section)\n    *   **derive** – reexports derive macros under `prelude`\n        (see [corresponding section][derive_docs] in the `mysql_common` documentation)\n\n* TLS/SSL related features:\n\n    *   **native-tls** – specifies `native-tls` as the TLS backend\n        (see the [SSL Support](#ssl-support) section)\n    *   **rustls-tls** – specifies `rustls` as the TLS backend using `aws-lc-rs` crypto provider\n        (see the [SSL Support](#ssl-support) section)\n    *   **rustls-tls-ring** – specifies `rustls` as the TLS backend using `ring` crypto provider\n        (see the [SSL Support](#ssl-support) section)\n    *   **rustls** - specifies `rustls` as the TLS backend without crypto provider\n        (see the [SSL Support](#ssl-support) section)\n\n* features proxied from `mysql_common`:\n\n    * **derive** - see [this table][common_features].\n    * **chrono** - see [this table][common_features].\n    * **time** - see [this table][common_features].\n    * **bigdecimal** - see [this table][common_features].\n    * **rust_decimal** - see [this table][common_features].\n    * **frunk** - see [this table][common_features].\n    * **binlog** - see [this table][common_features].\n\nPlease note, that you'll need to reenable required features if you are using `default-features = false`:\n\n```toml\n[dependencies]\n# Lets say that we want to use only the `rustls-tls` feature:\nmysql = { version = \"*\", default-features = false, features = [\"minimal-rust\", \"rustls-tls\"] }\n```\n\n### API Documentation\n\nPlease refer to the [crate docs].\n\n### Basic structures\n\n#### `Opts`\n\nThis structure holds server host name, client username/password and other settings,\nthat controls client behavior.\n\n##### URL-based connection string\n\nNote, that you can use URL-based connection string as a source of an `Opts` instance.\nURL schema must be `mysql`. Host, port and credentials, as well as query parameters,\nshould be given in accordance with the RFC 3986.\n\nExamples:\n\n```rust\nlet _ = Opts::from_url(\"mysql://localhost/some_db\")?;\nlet _ = Opts::from_url(\"mysql://[::1]/some_db\")?;\nlet _ = Opts::from_url(\"mysql://user:pass%20word@127.0.0.1:3307/some_db?\")?;\n```\n\nSupported URL parameters (for the meaning of each field please refer to the docs on `Opts`\nstructure in the create API docs):\n\n*   `user: string` – MySql client user name\n*   `password: string` – MySql client password;\n*   `db_name: string` – MySql database name;\n*   `host: Host` – MySql server hostname/ip;\n*   `port: u16` – MySql server port;\n*   `pool_min: usize` – see [`PoolConstraints::min`];\n*   `pool_max: usize` – see [`PoolConstraints::max`];\n*   `prefer_socket: true | false` - see [`Opts::get_prefer_socket`];\n*   `tcp_keepalive_time_ms: u32` - defines the value (in milliseconds)\n    of the `tcp_keepalive_time` field in the `Opts` structure;\n*   `tcp_keepalive_probe_interval_secs: u32` - defines the value\n    of the `tcp_keepalive_probe_interval_secs` field in the `Opts` structure;\n*   `tcp_keepalive_probe_count: u32` - defines the value\n    of the `tcp_keepalive_probe_count` field in the `Opts` structure;\n*   `tcp_connect_timeout_ms: u64` - defines the value (in milliseconds)\n    of the `tcp_connect_timeout` field in the `Opts` structure;\n*   `tcp_user_timeout_ms` - defines the value (in milliseconds)\n    of the `tcp_user_timeout` field in the `Opts` structure;\n*   `stmt_cache_size: u32` - defines the value of the same field in the `Opts` structure;\n*   `enable_cleartext_plugin` – see [`Opts::get_enable_cleartext_plugin`];\n*   `secure_auth` – see [`Opts::get_secure_auth`];\n*   `reset_connection` – see [`PoolOpts::reset_connection`];\n*   `check_health` – see [`PoolOpts::check_health`];\n*   `compress` - defines the value of the same field in the `Opts` structure.\n    Supported value are:\n    *  `true` - enables compression with the default compression level;\n    *  `fast` - enables compression with \"fast\" compression level;\n    *  `best` - enables compression with \"best\" compression level;\n    *  `1`..`9` - enables compression with the given compression level.\n*   `socket` - socket path on UNIX, or pipe name on Windows.\n\n#### `OptsBuilder`\n\nIt's a convenient builder for the `Opts` structure. It defines setters for fields\nof the `Opts` structure.\n\n```rust\nlet opts = OptsBuilder::new()\n    .user(Some(\"foo\"))\n    .db_name(Some(\"bar\"));\nlet _ = Conn::new(opts)?;\n```\n\n#### `Conn`\n\nThis structure represents an active MySql connection. It also holds statement cache\nand metadata for the last result set.\n\nConn's destructor will gracefully disconnect it from the server.\n\n#### `Transaction`\n\nIt's a simple wrapper on top of a routine, that starts with `START TRANSACTION`\nand ends with `COMMIT` or `ROLLBACK`.\n\n```rust\nuse mysql::*;\nuse mysql::prelude::*;\n\nlet pool = Pool::new(get_opts())?;\nlet mut conn = pool.get_conn()?;\n\nlet mut tx = conn.start_transaction(TxOpts::default())?;\ntx.query_drop(\"CREATE TEMPORARY TABLE tmp (TEXT a)\")?;\ntx.exec_drop(\"INSERT INTO tmp (a) VALUES (?)\", (\"foo\",))?;\nlet val: Option\u003cString\u003e = tx.query_first(\"SELECT a from tmp\")?;\nassert_eq!(val.unwrap(), \"foo\");\n// Note, that transaction will be rolled back implicitly on Drop, if not committed.\ntx.rollback();\n\nlet val: Option\u003cString\u003e = conn.query_first(\"SELECT a from tmp\")?;\nassert_eq!(val, None);\n```\n\n#### `Pool`\n\nIt's a reference to a connection pool, that can be cloned and shared between threads.\n\n```rust\nuse mysql::*;\nuse mysql::prelude::*;\n\nuse std::thread::spawn;\n\nlet pool = Pool::new(get_opts())?;\n\nlet handles = (0..4).map(|i| {\n    spawn({\n        let pool = pool.clone();\n        move || {\n            let mut conn = pool.get_conn()?;\n            conn.exec_first::\u003cu32, _, _\u003e(\"SELECT ? * 10\", (i,))\n                .map(Option::unwrap)\n        }\n    })\n});\n\nlet result: Result\u003cVec\u003cu32\u003e\u003e = handles.map(|handle| handle.join().unwrap()).collect();\n\nassert_eq!(result.unwrap(), vec![0, 10, 20, 30]);\n```\n\n#### `Statement`\n\nStatement, actually, is just an identifier coupled with statement metadata, i.e an information\nabout its parameters and columns. Internally the `Statement` structure also holds additional\ndata required to support named parameters (see bellow).\n\n```rust\nuse mysql::*;\nuse mysql::prelude::*;\n\nlet pool = Pool::new(get_opts())?;\nlet mut conn = pool.get_conn()?;\n\nlet stmt = conn.prep(\"DO ?\")?;\n\n// The prepared statement will return no columns.\nassert!(stmt.columns().is_empty());\n\n// The prepared statement have one parameter.\nlet param = stmt.params().get(0).unwrap();\nassert_eq!(param.schema_str(), \"\");\nassert_eq!(param.table_str(), \"\");\nassert_eq!(param.name_str(), \"?\");\n```\n\n#### `Value`\n\nThis enumeration represents the raw value of a MySql cell. Library offers conversion between\n`Value` and different rust types via `FromValue` trait described below.\n\n##### `FromValue` trait\n\nThis trait is reexported from **mysql_common** create. Please refer to its\n[crate docs][mysql_common docs] for the list of supported conversions.\n\nTrait offers conversion in two flavours:\n\n*   `from_value(Value) -\u003e T` - convenient, but panicking conversion.\n\n    Note, that for any variant of `Value` there exist a type, that fully covers its domain,\n    i.e. for any variant of `Value` there exist `T: FromValue` such that `from_value` will never\n    panic. This means, that if your database schema is known, then it's possible to write your\n    application using only `from_value` with no fear of runtime panic.\n\n*   `from_value_opt(Value) -\u003e Option\u003cT\u003e` - non-panicking, but less convenient conversion.\n\n    This function is useful to probe conversion in cases, where source database schema\n    is unknown.\n\n```rust\nuse mysql::*;\nuse mysql::prelude::*;\n\nlet via_test_protocol: u32 = from_value(Value::Bytes(b\"65536\".to_vec()));\nlet via_bin_protocol: u32 = from_value(Value::UInt(65536));\nassert_eq!(via_test_protocol, via_bin_protocol);\n\nlet unknown_val = // ...\n\n// Maybe it is a float?\nlet unknown_val = match from_value_opt::\u003cf64\u003e(unknown_val) {\n    Ok(float) =\u003e {\n        println!(\"A float value: {}\", float);\n        return Ok(());\n    }\n    Err(FromValueError(unknown_val)) =\u003e unknown_val,\n};\n\n// Or a string?\nlet unknown_val = match from_value_opt::\u003cString\u003e(unknown_val) {\n    Ok(string) =\u003e {\n        println!(\"A string value: {}\", string);\n        return Ok(());\n    }\n    Err(FromValueError(unknown_val)) =\u003e unknown_val,\n};\n\n// Screw this, I'll simply match on it\nmatch unknown_val {\n    val @ Value::NULL =\u003e {\n        println!(\"An empty value: {:?}\", from_value::\u003cOption\u003cu8\u003e\u003e(val))\n    },\n    val @ Value::Bytes(..) =\u003e {\n        // It's non-utf8 bytes, since we already tried to convert it to String\n        println!(\"Bytes: {:?}\", from_value::\u003cVec\u003cu8\u003e\u003e(val))\n    }\n    val @ Value::Int(..) =\u003e {\n        println!(\"A signed integer: {}\", from_value::\u003ci64\u003e(val))\n    }\n    val @ Value::UInt(..) =\u003e {\n        println!(\"An unsigned integer: {}\", from_value::\u003cu64\u003e(val))\n    }\n    Value::Float(..) =\u003e unreachable!(\"already tried\"),\n    val @ Value::Double(..) =\u003e {\n        println!(\"A double precision float value: {}\", from_value::\u003cf64\u003e(val))\n    }\n    val @ Value::Date(..) =\u003e {\n        use time::PrimitiveDateTime;\n        println!(\"A date value: {}\", from_value::\u003cPrimitiveDateTime\u003e(val))\n    }\n    val @ Value::Time(..) =\u003e {\n        use std::time::Duration;\n        println!(\"A time value: {:?}\", from_value::\u003cDuration\u003e(val))\n    }\n}\n```\n\n#### `Row`\n\nInternally `Row` is a vector of `Value`s, that also allows indexing by a column name/offset,\nand stores row metadata. Library offers conversion between `Row` and sequences of Rust types\nvia `FromRow` trait described below.\n\n##### `FromRow` trait\n\nThis trait is reexported from **mysql_common** create. Please refer to its\n[crate docs][mysql_common docs] for the list of supported conversions.\n\nThis conversion is based on the `FromValue` and so comes in two similar flavours:\n\n*   `from_row(Row) -\u003e T` - same as `from_value`, but for rows;\n*   `from_row_opt(Row) -\u003e Option\u003cT\u003e` - same as `from_value_opt`, but for rows.\n\n[`Queryable`](#queryable)\ntrait offers implicit conversion for rows of a query result,\nthat is based on this trait.\n\n```rust\nuse mysql::*;\nuse mysql::prelude::*;\n\nlet mut conn = Conn::new(get_opts())?;\n\n// Single-column row can be converted to a singular value:\nlet val: Option\u003cString\u003e = conn.query_first(\"SELECT 'foo'\")?;\nassert_eq!(val.unwrap(), \"foo\");\n\n// Example of a multi-column row conversion to an inferred type:\nlet row = conn.query_first(\"SELECT 255, 256\")?;\nassert_eq!(row, Some((255u8, 256u16)));\n\n// The FromRow trait does not support to-tuple conversion for rows with more than 12 columns,\n// but you can do this by hand using row indexing or `Row::take` method:\nlet row: Row = conn.exec_first(\"select 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12\", ())?.unwrap();\nfor i in 0..row.len() {\n    assert_eq!(row[i], Value::Int(i as i64));\n}\n\n// Another way to handle wide rows is to use HList (requires `mysql_common/frunk` feature)\nuse frunk::{HList, hlist, hlist_pat};\nlet query = \"select 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15\";\ntype RowType = HList!(u8, u16, u32, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8);\nlet first_three_columns = conn.query_map(query, |row: RowType| {\n    // do something with the row (see the `frunk` crate documentation)\n    let hlist_pat![c1, c2, c3, ...] = row;\n    (c1, c2, c3)\n});\nassert_eq!(first_three_columns.unwrap(), vec![(0_u8, 1_u16, 2_u32)]);\n\n// Some unknown row\nlet row: Row = conn.query_first(\n    // ...\n    # \"SELECT 255, Null\",\n)?.unwrap();\n\nfor column in row.columns_ref() {\n    // Cells in a row can be indexed by numeric index or by column name\n    let column_value = \u0026row[column.name_str().as_ref()];\n\n    println!(\n        \"Column {} of type {:?} with value {:?}\",\n        column.name_str(),\n        column.column_type(),\n        column_value,\n    );\n}\n```\n\n#### `Params`\n\nRepresents parameters of a prepared statement, but this type won't appear directly in your code\nbecause binary protocol API will ask for `T: Into\u003cParams\u003e`, where `Into\u003cParams\u003e` is implemented:\n\n*   for tuples of `Into\u003cValue\u003e` types up to arity 12;\n\n    **Note:** singular tuple requires extra comma, e.g. `(\"foo\",)`;\n\n*   for `IntoIterator\u003cItem: Into\u003cValue\u003e\u003e` for cases, when your statement takes more\n    than 12 parameters;\n*   for named parameters representation (the value of the `params!` macro, described below).\n\n```rust\nuse mysql::*;\nuse mysql::prelude::*;\n\nlet mut conn = Conn::new(get_opts())?;\n\n// Singular tuple requires extra comma:\nlet row: Option\u003cu8\u003e = conn.exec_first(\"SELECT ?\", (0,))?;\nassert_eq!(row.unwrap(), 0);\n\n// More than 12 parameters:\nlet row: Option\u003cu8\u003e = conn.exec_first(\n    \"SELECT CONVERT(? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ?, UNSIGNED)\",\n    (0..16).collect::\u003cVec\u003c_\u003e\u003e(),\n)?;\nassert_eq!(row.unwrap(), 120);\n```\n\n**Note:** Please refer to the [**mysql_common** crate docs][mysql_common docs] for the list\nof types, that implements `Into\u003cValue\u003e`.\n\n##### `Serialized`, `Deserialized`\n\nWrapper structures for cases, when you need to provide a value for a JSON cell,\nor when you need to parse JSON cell as a struct.\n\n```rust\nuse mysql::*;\nuse mysql::prelude::*;\nuse serde::{Deserialize, Serialize};\n\n/// Serializable structure.\n#[derive(Debug, PartialEq, Serialize, Deserialize)]\nstruct Example {\n    foo: u32,\n}\n\n// Value::from for Serialized will emit json string.\nlet value = Value::from(Serialized(Example { foo: 42 }));\nassert_eq!(value, Value::Bytes(br#\"{\"foo\":42}\"#.to_vec()));\n\n// from_value for Deserialized will parse json string.\nlet structure: Deserialized\u003cExample\u003e = from_value(value);\nassert_eq!(structure, Deserialized(Example { foo: 42 }));\n```\n\n#### [`QueryResult`]\n\nIt's an iterator over rows of a query result with support of multi-result sets. It's intended\nfor cases when you need full control during result set iteration. For other cases\n[`Queryable`](#queryable) provides a set of methods that will immediately consume\nthe first result set and drop everything else.\n\nThis iterator is lazy so it won't read the result from server until you iterate over it.\nMySql protocol is strictly sequential, so `Conn` will be mutably borrowed until the result\nis fully consumed (please also look at [`QueryResult::iter`] docs).\n\n```rust\nuse mysql::*;\nuse mysql::prelude::*;\n\nlet mut conn = Conn::new(get_opts())?;\n\n// This query will emit two result sets.\nlet mut result = conn.query_iter(\"SELECT 1, 2; SELECT 3, 3.14;\")?;\n\nlet mut sets = 0;\nwhile let Some(result_set) = result.iter() {\n    sets += 1;\n\n    println!(\"Result set columns: {:?}\", result_set.columns());\n    println!(\n        \"Result set meta: {}, {:?}, {} {}\",\n        result_set.affected_rows(),\n        result_set.last_insert_id(),\n        result_set.warnings(),\n        result_set.info_str(),\n    );\n\n    for row in result_set {\n        match sets {\n            1 =\u003e {\n                // First result set will contain two numbers.\n                assert_eq!((1_u8, 2_u8), from_row(row?));\n            }\n            2 =\u003e {\n                // Second result set will contain a number and a float.\n                assert_eq!((3_u8, 3.14), from_row(row?));\n            }\n            _ =\u003e unreachable!(),\n        }\n    }\n}\n\nassert_eq!(sets, 2);\n```\n\n### Text protocol\n\nMySql text protocol is implemented in the set of `Queryable::query*` methods. It's useful when your\nquery doesn't have parameters.\n\n**Note:** All values of a text protocol result set will be encoded as strings by the server,\nso `from_value` conversion may lead to additional parsing costs.\n\nExamples:\n\n```rust\nlet pool = Pool::new(get_opts())?;\nlet val = pool.get_conn()?.query_first(\"SELECT POW(2, 16)\")?;\n\n// Text protocol returns bytes even though the result of POW\n// is actually a floating point number.\nassert_eq!(val, Some(Value::Bytes(\"65536\".as_bytes().to_vec())));\n```\n\n#### The `TextQuery` trait.\n\nThe `TextQuery` trait covers the set of `Queryable::query*` methods from the perspective\nof a query, i.e. `TextQuery` is something, that can be performed if suitable connection\nis given. Suitable connections are:\n\n*   `\u0026Pool`\n*   `Conn`\n*   `PooledConn`\n*   `\u0026mut Conn`\n*   `\u0026mut PooledConn`\n*   `\u0026mut Transaction`\n\nThe unique characteristic of this trait, is that you can give away the connection\nand thus produce `QueryResult` that satisfies `'static`:\n\n```rust\nuse mysql::*;\nuse mysql::prelude::*;\n\nfn iter(pool: \u0026Pool) -\u003e Result\u003cimpl Iterator\u003cItem=Result\u003cu32\u003e\u003e\u003e {\n    let result = \"SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3\".run(pool)?;\n    Ok(result.map(|row| row.map(from_row)))\n}\n\nlet pool = Pool::new(get_opts())?;\n\nlet it = iter(\u0026pool)?;\n\nassert_eq!(it.collect::\u003cResult\u003cVec\u003cu32\u003e\u003e\u003e()?, vec![1, 2, 3]);\n```\n\n### Binary protocol and prepared statements.\n\nMySql binary protocol is implemented in `prep`, `close` and the set of `exec*` methods,\ndefined on the [`Queryable`](#queryable) trait. Prepared statements is the only way to\npass rust value to the MySql server. MySql uses `?` symbol as a parameter placeholder\nand it's only possible to use parameters where a single MySql value is expected.\nFor example:\n\n```rust\nlet pool = Pool::new(get_opts())?;\nlet val = pool.get_conn()?.exec_first(\"SELECT POW(?, ?)\", (2, 16))?;\n\nassert_eq!(val, Some(Value::Double(65536.0)));\n```\n\n#### Statements\n\nIn MySql each prepared statement belongs to a particular connection and can't be executed\non another connection. Trying to do so will lead to an error. The driver won't tie statement\nto its connection in any way, but one can look on to the connection id, contained\n in the `Statement` structure.\n\n```rust\nlet pool = Pool::new(get_opts())?;\n\nlet mut conn_1 = pool.get_conn()?;\nlet mut conn_2 = pool.get_conn()?;\n\nlet stmt_1 = conn_1.prep(\"SELECT ?\")?;\n\n// stmt_1 is for the conn_1, ..\nassert!(stmt_1.connection_id() == conn_1.connection_id());\nassert!(stmt_1.connection_id() != conn_2.connection_id());\n\n// .. so stmt_1 will execute only on conn_1\nassert!(conn_1.exec_drop(\u0026stmt_1, (\"foo\",)).is_ok());\nassert!(conn_2.exec_drop(\u0026stmt_1, (\"foo\",)).is_err());\n```\n\n#### Statement cache\n\n##### Note\n\nStatement cache only works for:\n1.  for raw [`Conn`]\n2.  for [`PooledConn`]:\n    * within its lifetime if [`PoolOpts::reset_connection`] is `true`\n    * within the lifetime of a wrapped [`Conn`] if [`PoolOpts::reset_connection`] is `false`\n\n##### Description\n\n`Conn` will manage the cache of prepared statements on the client side, so subsequent calls\nto prepare with the same statement won't lead to a client-server roundtrip. Cache size\nfor each connection is determined by the `stmt_cache_size` field of the `Opts` structure.\nStatements, that are out of this boundary will be closed in LRU order.\n\nStatement cache is completely disabled if `stmt_cache_size` is zero.\n\n**Caveats:**\n\n*   disabled statement cache means, that you have to close statements yourself using\n    `Conn::close`, or they'll exhaust server limits/resources;\n\n*   you should be aware of the [`max_prepared_stmt_count`][max_prepared_stmt_count]\n    option of the MySql server. If the number of active connections times the value\n    of `stmt_cache_size` is greater, than you could receive an error while preparing\n    another statement.\n\n#### Named parameters\n\nMySql itself doesn't have named parameters support, so it's implemented on the client side.\nOne should use `:name` as a placeholder syntax for a named parameter. Named parameters uses\nthe following naming convention:\n\n* parameter name must start with either `_` or `a..z`\n* parameter name may continue with `_`, `a..z` and `0..9`\n\nNamed parameters may be repeated within the statement, e.g `SELECT :foo, :foo` will require\na single named parameter `foo` that will be repeated on the corresponding positions during\nstatement execution.\n\nOne should use the `params!` macro to build parameters for execution.\n\n**Note:** Positional and named parameters can't be mixed within the single statement.\n\nExamples:\n\n```rust\nlet pool = Pool::new(get_opts())?;\n\nlet mut conn = pool.get_conn()?;\nlet stmt = conn.prep(\"SELECT :foo, :bar, :foo\")?;\n\nlet foo = 42;\n\nlet val_13 = conn.exec_first(\u0026stmt, params! { \"foo\" =\u003e 13, \"bar\" =\u003e foo })?.unwrap();\n// Short syntax is available when param name is the same as variable name:\nlet val_42 = conn.exec_first(\u0026stmt, params! { foo, \"bar\" =\u003e 13 })?.unwrap();\n\nassert_eq!((foo, 13, foo), val_42);\nassert_eq!((13, foo, 13), val_13);\n```\n\n#### Buffer pool\n\nCrate uses the global lock-free buffer pool for the purpose of IO and data serialization/deserialization,\nthat helps to avoid allocations for basic scenarios. You can control its characteristics using\nthe following environment variables:\n\n*   `RUST_MYSQL_BUFFER_POOL_CAP` (defaults to 128) – controls the pool capacity. Dropped buffer will\n    be immediately deallocated if the pool is full. Set it to `0` to disable the pool at runtime.\n\n*   `RUST_MYSQL_BUFFER_SIZE_CAP` (defaults to 4MiB) – controls the maximum capacity of a buffer\n    stored in the pool. Capacity of a dropped buffer will be shrunk to this value when buffer\n    is returned to the pool.\n\nTo completely disable the pool (say you are using jemalloc) please remove the `buffer-pool` feature\nfrom the set of default crate features (see the [Crate Features](#crate-features) section).\n\n#### `BinQuery` and `BatchQuery` traits.\n\n`BinQuery` and `BatchQuery` traits covers the set of `Queryable::exec*` methods from\nthe perspective of a query, i.e. `BinQuery` is something, that can be performed if suitable\nconnection is given (see [`TextQuery`](#the-textquery-trait) section for the list\nof suitable connections).\n\nAs with the [`TextQuery`](#the-textquery-trait) you can give away the connection and acquire\n`QueryResult` that satisfies `'static`.\n\n`BinQuery` is for prepared statements, and prepared statements requires a set of parameters,\nso `BinQuery` is implemented for `QueryWithParams` structure, that can be acquired, using\n`WithParams` trait.\n\nExample:\n\n```rust\nuse mysql::*;\nuse mysql::prelude::*;\n\nlet pool = Pool::new(get_opts())?;\n\nlet result: Option\u003c(u8, u8, u8)\u003e = \"SELECT ?, ?, ?\"\n    .with((1, 2, 3)) // \u003c- WithParams::with will construct an instance of QueryWithParams\n    .first(\u0026pool)?;  // \u003c- QueryWithParams is executed on the given pool\n\nassert_eq!(result.unwrap(), (1, 2, 3));\n```\n\nThe `BatchQuery` trait is a helper for batch statement execution. It's implemented for\n`QueryWithParams` where parameters is an iterator over parameters:\n\n```rust\nuse mysql::*;\nuse mysql::prelude::*;\n\nlet pool = Pool::new(get_opts())?;\nlet mut conn = pool.get_conn()?;\n\n\"CREATE TEMPORARY TABLE batch (x INT)\".run(\u0026mut conn)?;\n\"INSERT INTO batch (x) VALUES (?)\"\n    .with((0..3).map(|x| (x,))) // \u003c- QueryWithParams constructed with an iterator\n    .batch(\u0026mut conn)?;         // \u003c- batch execution is preformed here\n\nlet result: Vec\u003cu8\u003e = \"SELECT x FROM batch\".fetch(conn)?;\n\nassert_eq!(result, vec![0, 1, 2]);\n```\n\n#### `Queryable`\n\nThe `Queryable` trait defines common methods for `Conn`, `PooledConn` and `Transaction`.\nThe set of basic methods consts of:\n\n*   `query_iter` - basic methods to execute text query and get `QueryResult`;\n*   `prep` - basic method to prepare a statement;\n*   `exec_iter` - basic method to execute statement and get `QueryResult`;\n*   `close` - basic method to close the statement;\n\nThe trait also defines the set of helper methods, that is based on basic methods.\nThese methods will consume only the first result set, other result sets will be dropped:\n\n*   `{query|exec}` - to collect the result into a `Vec\u003cT: FromRow\u003e`;\n*   `{query|exec}_first` - to get the first `T: FromRow`, if any;\n*   `{query|exec}_map` - to map each `T: FromRow` to some `U`;\n*   `{query|exec}_fold` - to fold the set of `T: FromRow` to a single value;\n*   `{query|exec}_drop` - to immediately drop the result.\n\nThe trait also defines the `exec_batch` function, which is a helper for batch statement\nexecution.\n\n### SSL Support\n\nSSL support comes in two flavors:\n\n1.  Based on the `native-tls` crate – native TLS backend.\n\n    This uses the native OS SSL/TLS provider. Enabled by the **rustls-tls** feature.\n\n2.  Based on the `rustls` – TLS backend written in Rust. You have three options here:\n\n    1.  **rustls-tls** feature enables `rustls` backend with `aws-lc-rs` crypto provider\n    2.  **rustls-tls-ring** feature enables `rustls` backend with `ring` crypto provider\n    3.  **rustls** feature enables `rustls` backend without crypto provider — you have to\n        install your own provider to avoid \"no process-level CryptoProvider available\" error\n        (see relevant section of the [`rustls` crate docs](https://docs.rs/rustls))\n\n    Please also note a few things about **rustls**:\n\n    *   it will fail if you'll try to connect to the server by its IP address, hostname is required;\n    *   it, most likely, won't work on windows, at least with default server certs, generated by the\n        MySql installer.\n\n[crate docs]: https://docs.rs/mysql\n[mysql_common docs]: https://docs.rs/mysql_common\n[max_prepared_stmt_count]: https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_max_prepared_stmt_count\n[derive_docs]: https://docs.rs/mysql_common/latest/mysql_common/#derive-macros\n[common_features]: https://docs.rs/mysql_common/latest/mysql_common/#crate-features\n\n## Changelog\n\nAvailable [here](https://github.com/blackbeam/rust-mysql-simple/releases)\n\n## License\n\nLicensed under either of\n\n* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)\n* MIT license ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT)\n\nat your option.\n\n### Contribution\n\nUnless you explicitly state otherwise, any contribution intentionally\nsubmitted for inclusion in the work by you, as defined in the Apache-2.0\nlicense, shall be dual licensed as above, without any additional terms or\nconditions.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblackbeam%2Frust-mysql-simple","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fblackbeam%2Frust-mysql-simple","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblackbeam%2Frust-mysql-simple/lists"}