diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..1332f8eb5 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +version: 2 +updates: +- package-ecosystem: cargo + directory: "/" + schedule: + interval: daily + time: "13:00" + open-pull-requests-limit: 10 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4a95dbe0c..520d665f8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,16 +50,12 @@ jobs: test: name: test runs-on: ubuntu-latest - services: - postgres: - image: sfackler/rust-postgres-test:6 - ports: - - 5433:5433 steps: - uses: actions/checkout@v2 + - run: docker compose up -d - uses: sfackler/actions/rustup@master with: - version: 1.46.0 + version: 1.53.0 - run: echo "::set-output name=version::$(rustc --version)" id: rust-version - uses: actions/cache@v1 diff --git a/LICENSE b/LICENSE deleted file mode 100644 index c7e577c00..000000000 --- a/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013-2017 Steven Fackler - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 000000000..16fe87b06 --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 000000000..71803aea1 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2016 Steven Fackler + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/THIRD_PARTY b/THIRD_PARTY index 80336ea0f..05e5ac435 100644 --- a/THIRD_PARTY +++ b/THIRD_PARTY @@ -27,33 +27,3 @@ BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - -------------------------------------------------------------------------------- - -* src/url.rs has been copied from Rust - -Copyright (c) 2014 The Rust Project Developers - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml index 8ff4d58be..14bebccf2 100644 --- a/codegen/Cargo.toml +++ b/codegen/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" authors = ["Steven Fackler "] [dependencies] -phf_codegen = "0.8" +phf_codegen = "0.10" regex = "1.0" marksman_escape = "0.1" linked-hash-map = "0.5" diff --git a/codegen/src/sqlstate.rs b/codegen/src/sqlstate.rs index bb21be34f..d21b92eec 100644 --- a/codegen/src/sqlstate.rs +++ b/codegen/src/sqlstate.rs @@ -1,5 +1,4 @@ use linked_hash_map::LinkedHashMap; -use phf_codegen; use std::fs::File; use std::io::{BufWriter, Write}; @@ -11,7 +10,9 @@ pub fn build() { let codes = parse_codes(); make_type(&mut file); + make_code(&codes, &mut file); make_consts(&codes, &mut file); + make_inner(&codes, &mut file); make_map(&codes, &mut file); } @@ -38,26 +39,51 @@ fn make_type(file: &mut BufWriter) { write!( file, "// Autogenerated file - DO NOT EDIT -use std::borrow::Cow; /// A SQLSTATE error code #[derive(PartialEq, Eq, Clone, Debug)] -pub struct SqlState(Cow<'static, str>); +pub struct SqlState(Inner); impl SqlState {{ /// Creates a `SqlState` from its error code. pub fn from_code(s: &str) -> SqlState {{ match SQLSTATE_MAP.get(s) {{ Some(state) => state.clone(), - None => SqlState(Cow::Owned(s.to_string())), + None => SqlState(Inner::Other(s.into())), }} }} +" + ) + .unwrap(); +} +fn make_code(codes: &LinkedHashMap>, file: &mut BufWriter) { + write!( + file, + r#" /// Returns the error code corresponding to the `SqlState`. pub fn code(&self) -> &str {{ - &self.0 + match &self.0 {{"#, + ) + .unwrap(); + + for code in codes.keys() { + write!( + file, + r#" + Inner::E{code} => "{code}","#, + code = code, + ) + .unwrap(); + } + + write!( + file, + r#" + Inner::Other(code) => code, + }} }} -" + "# ) .unwrap(); } @@ -69,7 +95,7 @@ fn make_consts(codes: &LinkedHashMap>, file: &mut BufWriter< file, r#" /// {code} - pub const {name}: SqlState = SqlState(Cow::Borrowed("{code}")); + pub const {name}: SqlState = SqlState(Inner::E{code}); "#, name = name, code = code, @@ -81,6 +107,35 @@ fn make_consts(codes: &LinkedHashMap>, file: &mut BufWriter< write!(file, "}}").unwrap(); } +fn make_inner(codes: &LinkedHashMap>, file: &mut BufWriter) { + write!( + file, + r#" + +#[derive(PartialEq, Eq, Clone, Debug)] +#[allow(clippy::upper_case_acronyms)] +enum Inner {{"#, + ) + .unwrap(); + for code in codes.keys() { + write!( + file, + r#" + E{},"#, + code, + ) + .unwrap(); + } + write!( + file, + r#" + Other(Box), +}} + "#, + ) + .unwrap(); +} + fn make_map(codes: &LinkedHashMap>, file: &mut BufWriter) { let mut builder = phf_codegen::Map::new(); for (code, names) in codes { diff --git a/docker-compose.yml b/docker-compose.yml index d44fbe866..0ed44148d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,10 @@ version: '2' services: postgres: - image: "sfackler/rust-postgres-test:6" + image: postgres:14 ports: - - 5433:5433 + - 5433:5433 + volumes: + - ./docker/sql_setup.sh:/docker-entrypoint-initdb.d/sql_setup.sh + environment: + POSTGRES_PASSWORD: postgres diff --git a/docker/Dockerfile b/docker/Dockerfile deleted file mode 100644 index 1dd7f3db6..000000000 --- a/docker/Dockerfile +++ /dev/null @@ -1,3 +0,0 @@ -FROM postgres:12 - -COPY sql_setup.sh /docker-entrypoint-initdb.d/ diff --git a/docker/sql_setup.sh b/docker/sql_setup.sh index 422dcbda9..0315ac805 100755 --- a/docker/sql_setup.sh +++ b/docker/sql_setup.sh @@ -96,4 +96,5 @@ psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL CREATE ROLE ssl_user LOGIN; CREATE EXTENSION hstore; CREATE EXTENSION citext; + CREATE EXTENSION ltree; EOSQL diff --git a/postgres-derive-test/src/compile-fail/invalid-transparent.rs b/postgres-derive-test/src/compile-fail/invalid-transparent.rs new file mode 100644 index 000000000..43bd48266 --- /dev/null +++ b/postgres-derive-test/src/compile-fail/invalid-transparent.rs @@ -0,0 +1,35 @@ +use postgres_types::{FromSql, ToSql}; + +#[derive(ToSql, Debug)] +#[postgres(transparent)] +struct ToSqlTransparentStruct { + a: i32 +} + +#[derive(FromSql, Debug)] +#[postgres(transparent)] +struct FromSqlTransparentStruct { + a: i32 +} + +#[derive(ToSql, Debug)] +#[postgres(transparent)] +enum ToSqlTransparentEnum { + Foo +} + +#[derive(FromSql, Debug)] +#[postgres(transparent)] +enum FromSqlTransparentEnum { + Foo +} + +#[derive(ToSql, Debug)] +#[postgres(transparent)] +struct ToSqlTransparentTwoFieldTupleStruct(i32, i32); + +#[derive(FromSql, Debug)] +#[postgres(transparent)] +struct FromSqlTransparentTwoFieldTupleStruct(i32, i32); + +fn main() {} diff --git a/postgres-derive-test/src/compile-fail/invalid-transparent.stderr b/postgres-derive-test/src/compile-fail/invalid-transparent.stderr new file mode 100644 index 000000000..42e49f874 --- /dev/null +++ b/postgres-derive-test/src/compile-fail/invalid-transparent.stderr @@ -0,0 +1,49 @@ +error: #[postgres(transparent)] may only be applied to single field tuple structs + --> src/compile-fail/invalid-transparent.rs:4:1 + | +4 | / #[postgres(transparent)] +5 | | struct ToSqlTransparentStruct { +6 | | a: i32 +7 | | } + | |_^ + +error: #[postgres(transparent)] may only be applied to single field tuple structs + --> src/compile-fail/invalid-transparent.rs:10:1 + | +10 | / #[postgres(transparent)] +11 | | struct FromSqlTransparentStruct { +12 | | a: i32 +13 | | } + | |_^ + +error: #[postgres(transparent)] may only be applied to single field tuple structs + --> src/compile-fail/invalid-transparent.rs:16:1 + | +16 | / #[postgres(transparent)] +17 | | enum ToSqlTransparentEnum { +18 | | Foo +19 | | } + | |_^ + +error: #[postgres(transparent)] may only be applied to single field tuple structs + --> src/compile-fail/invalid-transparent.rs:22:1 + | +22 | / #[postgres(transparent)] +23 | | enum FromSqlTransparentEnum { +24 | | Foo +25 | | } + | |_^ + +error: #[postgres(transparent)] may only be applied to single field tuple structs + --> src/compile-fail/invalid-transparent.rs:28:1 + | +28 | / #[postgres(transparent)] +29 | | struct ToSqlTransparentTwoFieldTupleStruct(i32, i32); + | |_____________________________________________________^ + +error: #[postgres(transparent)] may only be applied to single field tuple structs + --> src/compile-fail/invalid-transparent.rs:32:1 + | +32 | / #[postgres(transparent)] +33 | | struct FromSqlTransparentTwoFieldTupleStruct(i32, i32); + | |_______________________________________________________^ diff --git a/postgres-derive-test/src/composites.rs b/postgres-derive-test/src/composites.rs index 5efd3944c..ed60bf48f 100644 --- a/postgres-derive-test/src/composites.rs +++ b/postgres-derive-test/src/composites.rs @@ -215,3 +215,26 @@ fn wrong_type() { .unwrap_err(); assert!(err.source().unwrap().is::()); } + +#[test] +fn raw_ident_field() { + #[derive(FromSql, ToSql, Debug, PartialEq)] + #[postgres(name = "inventory_item")] + struct InventoryItem { + r#type: String, + } + + let mut conn = Client::connect("user=postgres host=localhost port=5433", NoTls).unwrap(); + conn.batch_execute( + "CREATE TYPE pg_temp.inventory_item AS ( + type TEXT + )", + ) + .unwrap(); + + let item = InventoryItem { + r#type: "foo".to_owned(), + }; + + test_type(&mut conn, "inventory_item", &[(item, "ROW('foo')")]); +} diff --git a/postgres-derive-test/src/lib.rs b/postgres-derive-test/src/lib.rs index 7da75af8f..279ed1419 100644 --- a/postgres-derive-test/src/lib.rs +++ b/postgres-derive-test/src/lib.rs @@ -7,6 +7,7 @@ use std::fmt; mod composites; mod domains; mod enums; +mod transparent; pub fn test_type(conn: &mut Client, sql_type: &str, checks: &[(T, S)]) where diff --git a/postgres-derive-test/src/transparent.rs b/postgres-derive-test/src/transparent.rs new file mode 100644 index 000000000..1614553d2 --- /dev/null +++ b/postgres-derive-test/src/transparent.rs @@ -0,0 +1,18 @@ +use postgres::{Client, NoTls}; +use postgres_types::{FromSql, ToSql}; + +#[test] +fn round_trip() { + #[derive(FromSql, ToSql, Debug, PartialEq)] + #[postgres(transparent)] + struct UserId(i32); + + assert_eq!( + Client::connect("user=postgres host=localhost port=5433", NoTls) + .unwrap() + .query_one("SELECT $1::integer", &[&UserId(123)]) + .unwrap() + .get::<_, UserId>(0), + UserId(123) + ); +} diff --git a/postgres-derive/CHANGELOG.md b/postgres-derive/CHANGELOG.md index 354f6f277..9bb3a752f 100644 --- a/postgres-derive/CHANGELOG.md +++ b/postgres-derive/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## v0.4.1 - 2021-11-23 + +### Fixed + +* Fixed handling of struct fields using raw identifiers. + ## v0.4.0 - 2019-12-23 No changes diff --git a/postgres-derive/Cargo.toml b/postgres-derive/Cargo.toml index 293c294a0..1ce243a58 100644 --- a/postgres-derive/Cargo.toml +++ b/postgres-derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "postgres-derive" -version = "0.4.0" +version = "0.4.1" authors = ["Steven Fackler "] license = "MIT/Apache-2.0" edition = "2018" diff --git a/postgres-derive/LICENSE-APACHE b/postgres-derive/LICENSE-APACHE deleted file mode 100644 index 16fe87b06..000000000 --- a/postgres-derive/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/postgres-derive/LICENSE-APACHE b/postgres-derive/LICENSE-APACHE new file mode 120000 index 000000000..965b606f3 --- /dev/null +++ b/postgres-derive/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/postgres-derive/LICENSE-MIT b/postgres-derive/LICENSE-MIT deleted file mode 100644 index 71803aea1..000000000 --- a/postgres-derive/LICENSE-MIT +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 Steven Fackler - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/postgres-derive/LICENSE-MIT b/postgres-derive/LICENSE-MIT new file mode 120000 index 000000000..76219eb72 --- /dev/null +++ b/postgres-derive/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/postgres-derive/src/accepts.rs b/postgres-derive/src/accepts.rs index 530badd0b..63473863a 100644 --- a/postgres-derive/src/accepts.rs +++ b/postgres-derive/src/accepts.rs @@ -6,6 +6,14 @@ use syn::Ident; use crate::composites::Field; use crate::enums::Variant; +pub fn transparent_body(field: &syn::Field) -> TokenStream { + let ty = &field.ty; + + quote! { + <#ty as ::postgres_types::ToSql>::accepts(type_) + } +} + pub fn domain_body(name: &str, field: &syn::Field) -> TokenStream { let ty = &field.ty; diff --git a/postgres-derive/src/composites.rs b/postgres-derive/src/composites.rs index f5599d375..c1e495154 100644 --- a/postgres-derive/src/composites.rs +++ b/postgres-derive/src/composites.rs @@ -14,7 +14,13 @@ impl Field { let ident = raw.ident.as_ref().unwrap().clone(); Ok(Field { - name: overrides.name.unwrap_or_else(|| ident.to_string()), + name: overrides.name.unwrap_or_else(|| { + let name = ident.to_string(); + match name.strip_prefix("r#") { + Some(name) => name.to_string(), + None => name, + } + }), ident, type_: raw.ty.clone(), }) diff --git a/postgres-derive/src/fromsql.rs b/postgres-derive/src/fromsql.rs index e1ab6ffa7..c89cbb5e2 100644 --- a/postgres-derive/src/fromsql.rs +++ b/postgres-derive/src/fromsql.rs @@ -1,5 +1,5 @@ -use proc_macro2::{Span, TokenStream}; -use quote::quote; +use proc_macro2::TokenStream; +use quote::{format_ident, quote}; use std::iter; use syn::{Data, DataStruct, DeriveInput, Error, Fields, Ident}; @@ -11,9 +11,36 @@ use crate::overrides::Overrides; pub fn expand_derive_fromsql(input: DeriveInput) -> Result { let overrides = Overrides::extract(&input.attrs)?; + if overrides.name.is_some() && overrides.transparent { + return Err(Error::new_spanned( + &input, + "#[postgres(transparent)] is not allowed with #[postgres(name = \"...\")]", + )); + } + let name = overrides.name.unwrap_or_else(|| input.ident.to_string()); - let (accepts_body, to_sql_body) = match input.data { + let (accepts_body, to_sql_body) = if overrides.transparent { + match input.data { + Data::Struct(DataStruct { + fields: Fields::Unnamed(ref fields), + .. + }) if fields.unnamed.len() == 1 => { + let field = fields.unnamed.first().unwrap(); + ( + accepts::transparent_body(field), + transparent_body(&input.ident, field), + ) + } + _ => { + return Err(Error::new_spanned( + input, + "#[postgres(transparent)] may only be applied to single field tuple structs", + )) + } + } + } else { + match input.data { Data::Enum(ref data) => { let variants = data .variants @@ -55,6 +82,7 @@ pub fn expand_derive_fromsql(input: DeriveInput) -> Result { "#[derive(FromSql)] may only be applied to structs, single field tuple structs, and enums", )) } + } }; let ident = &input.ident; @@ -77,6 +105,13 @@ pub fn expand_derive_fromsql(input: DeriveInput) -> Result { Ok(out) } +fn transparent_body(ident: &Ident, field: &syn::Field) -> TokenStream { + let ty = &field.ty; + quote! { + <#ty as postgres_types::FromSql>::from_sql(_type, buf).map(#ident) + } +} + fn enum_body(ident: &Ident, variants: &[Variant]) -> TokenStream { let variant_names = variants.iter().map(|v| &v.name); let idents = iter::repeat(ident); @@ -119,7 +154,7 @@ fn domain_body(ident: &Ident, field: &syn::Field) -> TokenStream { fn composite_body(ident: &Ident, fields: &[Field]) -> TokenStream { let temp_vars = &fields .iter() - .map(|f| Ident::new(&format!("__{}", f.ident), Span::call_site())) + .map(|f| format_ident!("__{}", f.ident)) .collect::>(); let field_names = &fields.iter().map(|f| &f.name).collect::>(); let field_idents = &fields.iter().map(|f| &f.ident).collect::>(); diff --git a/postgres-derive/src/lib.rs b/postgres-derive/src/lib.rs index fd17b9de6..98e6add24 100644 --- a/postgres-derive/src/lib.rs +++ b/postgres-derive/src/lib.rs @@ -4,6 +4,7 @@ extern crate proc_macro; use proc_macro::TokenStream; +use syn::parse_macro_input; mod accepts; mod composites; @@ -14,7 +15,8 @@ mod tosql; #[proc_macro_derive(ToSql, attributes(postgres))] pub fn derive_tosql(input: TokenStream) -> TokenStream { - let input = syn::parse(input).unwrap(); + let input = parse_macro_input!(input); + tosql::expand_derive_tosql(input) .unwrap_or_else(|e| e.to_compile_error()) .into() @@ -22,7 +24,8 @@ pub fn derive_tosql(input: TokenStream) -> TokenStream { #[proc_macro_derive(FromSql, attributes(postgres))] pub fn derive_fromsql(input: TokenStream) -> TokenStream { - let input = syn::parse(input).unwrap(); + let input = parse_macro_input!(input); + fromsql::expand_derive_fromsql(input) .unwrap_or_else(|e| e.to_compile_error()) .into() diff --git a/postgres-derive/src/overrides.rs b/postgres-derive/src/overrides.rs index 08e6f3a77..c00d5a94b 100644 --- a/postgres-derive/src/overrides.rs +++ b/postgres-derive/src/overrides.rs @@ -2,17 +2,18 @@ use syn::{Attribute, Error, Lit, Meta, NestedMeta}; pub struct Overrides { pub name: Option, + pub transparent: bool, } impl Overrides { pub fn extract(attrs: &[Attribute]) -> Result { - let mut overrides = Overrides { name: None }; + let mut overrides = Overrides { + name: None, + transparent: false, + }; for attr in attrs { - let attr = match attr.parse_meta() { - Ok(meta) => meta, - Err(_) => continue, - }; + let attr = attr.parse_meta()?; if !attr.path().is_ident("postgres") { continue; @@ -39,7 +40,14 @@ impl Overrides { overrides.name = Some(value); } - bad => return Err(Error::new_spanned(bad, "expected a name-value meta item")), + NestedMeta::Meta(Meta::Path(ref path)) => { + if !path.is_ident("transparent") { + return Err(Error::new_spanned(path, "unknown override")); + } + + overrides.transparent = true; + } + bad => return Err(Error::new_spanned(bad, "unknown attribute")), } } } diff --git a/postgres-derive/src/tosql.rs b/postgres-derive/src/tosql.rs index a1c87b0ff..96f261385 100644 --- a/postgres-derive/src/tosql.rs +++ b/postgres-derive/src/tosql.rs @@ -11,46 +11,73 @@ use crate::overrides::Overrides; pub fn expand_derive_tosql(input: DeriveInput) -> Result { let overrides = Overrides::extract(&input.attrs)?; + if overrides.name.is_some() && overrides.transparent { + return Err(Error::new_spanned( + &input, + "#[postgres(transparent)] is not allowed with #[postgres(name = \"...\")]", + )); + } + let name = overrides.name.unwrap_or_else(|| input.ident.to_string()); - let (accepts_body, to_sql_body) = match input.data { - Data::Enum(ref data) => { - let variants = data - .variants - .iter() - .map(Variant::parse) - .collect::, _>>()?; - ( - accepts::enum_body(&name, &variants), - enum_body(&input.ident, &variants), - ) - } - Data::Struct(DataStruct { - fields: Fields::Unnamed(ref fields), - .. - }) if fields.unnamed.len() == 1 => { - let field = fields.unnamed.first().unwrap(); - (accepts::domain_body(&name, &field), domain_body()) - } - Data::Struct(DataStruct { - fields: Fields::Named(ref fields), - .. - }) => { - let fields = fields - .named - .iter() - .map(Field::parse) - .collect::, _>>()?; - ( - accepts::composite_body(&name, "ToSql", &fields), - composite_body(&fields), - ) + let (accepts_body, to_sql_body) = if overrides.transparent { + match input.data { + Data::Struct(DataStruct { + fields: Fields::Unnamed(ref fields), + .. + }) if fields.unnamed.len() == 1 => { + let field = fields.unnamed.first().unwrap(); + + (accepts::transparent_body(field), transparent_body()) + } + _ => { + return Err(Error::new_spanned( + input, + "#[postgres(transparent)] may only be applied to single field tuple structs", + )); + } } - _ => { - return Err(Error::new_spanned( - input, - "#[derive(ToSql)] may only be applied to structs, single field tuple structs, and enums", - )); + } else { + match input.data { + Data::Enum(ref data) => { + let variants = data + .variants + .iter() + .map(Variant::parse) + .collect::, _>>()?; + ( + accepts::enum_body(&name, &variants), + enum_body(&input.ident, &variants), + ) + } + Data::Struct(DataStruct { + fields: Fields::Unnamed(ref fields), + .. + }) if fields.unnamed.len() == 1 => { + let field = fields.unnamed.first().unwrap(); + + (accepts::domain_body(&name, field), domain_body()) + } + Data::Struct(DataStruct { + fields: Fields::Named(ref fields), + .. + }) => { + let fields = fields + .named + .iter() + .map(Field::parse) + .collect::, _>>()?; + ( + accepts::composite_body(&name, "ToSql", &fields), + composite_body(&fields), + ) + } + _ => { + return Err(Error::new_spanned( + input, + "#[derive(ToSql)] may only be applied to structs, single field tuple structs, and enums", + )); + } } }; @@ -78,6 +105,12 @@ pub fn expand_derive_tosql(input: DeriveInput) -> Result { Ok(out) } +fn transparent_body() -> TokenStream { + quote! { + postgres_types::ToSql::to_sql(&self.0, _type, buf) + } +} + fn enum_body(ident: &Ident, variants: &[Variant]) -> TokenStream { let idents = iter::repeat(ident); let variant_idents = variants.iter().map(|v| &v.ident); diff --git a/postgres-native-tls/LICENSE-APACHE b/postgres-native-tls/LICENSE-APACHE index b9e46b0fc..965b606f3 120000 --- a/postgres-native-tls/LICENSE-APACHE +++ b/postgres-native-tls/LICENSE-APACHE @@ -1 +1 @@ -../tokio-postgres/LICENSE-APACHE \ No newline at end of file +../LICENSE-APACHE \ No newline at end of file diff --git a/postgres-native-tls/LICENSE-MIT b/postgres-native-tls/LICENSE-MIT index 162832a42..76219eb72 120000 --- a/postgres-native-tls/LICENSE-MIT +++ b/postgres-native-tls/LICENSE-MIT @@ -1 +1 @@ -../tokio-postgres/LICENSE-MIT \ No newline at end of file +../LICENSE-MIT \ No newline at end of file diff --git a/postgres-native-tls/src/lib.rs b/postgres-native-tls/src/lib.rs index 70e34812d..a06f185b5 100644 --- a/postgres-native-tls/src/lib.rs +++ b/postgres-native-tls/src/lib.rs @@ -4,10 +4,12 @@ //! //! ```no_run //! use native_tls::{Certificate, TlsConnector}; +//! # #[cfg(feature = "runtime")] //! use postgres_native_tls::MakeTlsConnector; //! use std::fs; //! //! # fn main() -> Result<(), Box> { +//! # #[cfg(feature = "runtime")] { //! let cert = fs::read("database_cert.pem")?; //! let cert = Certificate::from_pem(&cert)?; //! let connector = TlsConnector::builder() @@ -19,6 +21,7 @@ //! "host=localhost user=postgres sslmode=require", //! connector, //! ); +//! # } //! //! // ... //! # Ok(()) @@ -27,10 +30,12 @@ //! //! ```no_run //! use native_tls::{Certificate, TlsConnector}; +//! # #[cfg(feature = "runtime")] //! use postgres_native_tls::MakeTlsConnector; //! use std::fs; //! //! # fn main() -> Result<(), Box> { +//! # #[cfg(feature = "runtime")] { //! let cert = fs::read("database_cert.pem")?; //! let cert = Certificate::from_pem(&cert)?; //! let connector = TlsConnector::builder() @@ -42,6 +47,7 @@ //! "host=localhost user=postgres sslmode=require", //! connector, //! )?; +//! # } //! # Ok(()) //! # } //! ``` @@ -51,7 +57,7 @@ use std::future::Future; use std::io; use std::pin::Pin; use std::task::{Context, Poll}; -use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; +use tokio::io::{AsyncRead, AsyncWrite, BufReader, ReadBuf}; use tokio_postgres::tls; #[cfg(feature = "runtime")] use tokio_postgres::tls::MakeTlsConnect; @@ -115,6 +121,7 @@ where type Future = Pin, native_tls::Error>> + Send>>; fn connect(self, stream: S) -> Self::Future { + let stream = BufReader::with_capacity(8192, stream); let future = async move { let stream = self.connector.connect(&self.domain, stream).await?; @@ -126,7 +133,7 @@ where } /// The stream returned by `TlsConnector`. -pub struct TlsStream(tokio_native_tls::TlsStream); +pub struct TlsStream(tokio_native_tls::TlsStream>); impl AsyncRead for TlsStream where diff --git a/postgres-openssl/LICENSE-APACHE b/postgres-openssl/LICENSE-APACHE index b9e46b0fc..965b606f3 120000 --- a/postgres-openssl/LICENSE-APACHE +++ b/postgres-openssl/LICENSE-APACHE @@ -1 +1 @@ -../tokio-postgres/LICENSE-APACHE \ No newline at end of file +../LICENSE-APACHE \ No newline at end of file diff --git a/postgres-openssl/LICENSE-MIT b/postgres-openssl/LICENSE-MIT index 162832a42..76219eb72 120000 --- a/postgres-openssl/LICENSE-MIT +++ b/postgres-openssl/LICENSE-MIT @@ -1 +1 @@ -../tokio-postgres/LICENSE-MIT \ No newline at end of file +../LICENSE-MIT \ No newline at end of file diff --git a/postgres-openssl/src/lib.rs b/postgres-openssl/src/lib.rs index dce3dff5d..49fc2807c 100644 --- a/postgres-openssl/src/lib.rs +++ b/postgres-openssl/src/lib.rs @@ -4,9 +4,11 @@ //! //! ```no_run //! use openssl::ssl::{SslConnector, SslMethod}; +//! # #[cfg(feature = "runtime")] //! use postgres_openssl::MakeTlsConnector; //! //! # fn main() -> Result<(), Box> { +//! # #[cfg(feature = "runtime")] { //! let mut builder = SslConnector::builder(SslMethod::tls())?; //! builder.set_ca_file("database_cert.pem")?; //! let connector = MakeTlsConnector::new(builder.build()); @@ -15,6 +17,7 @@ //! "host=localhost user=postgres sslmode=require", //! connector, //! ); +//! # } //! //! // ... //! # Ok(()) @@ -23,9 +26,11 @@ //! //! ```no_run //! use openssl::ssl::{SslConnector, SslMethod}; +//! # #[cfg(feature = "runtime")] //! use postgres_openssl::MakeTlsConnector; //! //! # fn main() -> Result<(), Box> { +//! # #[cfg(feature = "runtime")] { //! let mut builder = SslConnector::builder(SslMethod::tls())?; //! builder.set_ca_file("database_cert.pem")?; //! let connector = MakeTlsConnector::new(builder.build()); @@ -34,6 +39,7 @@ //! "host=localhost user=postgres sslmode=require", //! connector, //! )?; +//! # } //! //! // ... //! # Ok(()) @@ -57,7 +63,7 @@ use std::pin::Pin; #[cfg(feature = "runtime")] use std::sync::Arc; use std::task::{Context, Poll}; -use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; +use tokio::io::{AsyncRead, AsyncWrite, BufReader, ReadBuf}; use tokio_openssl::SslStream; use tokio_postgres::tls; #[cfg(feature = "runtime")] @@ -140,6 +146,7 @@ where type Future = Pin, Self::Error>> + Send>>; fn connect(self, stream: S) -> Self::Future { + let stream = BufReader::with_capacity(8192, stream); let future = async move { let ssl = self.ssl.into_ssl(&self.domain)?; let mut stream = SslStream::new(ssl, stream)?; @@ -182,7 +189,7 @@ impl Error for ConnectError { } /// The stream returned by `TlsConnector`. -pub struct TlsStream(SslStream); +pub struct TlsStream(SslStream>); impl AsyncRead for TlsStream where diff --git a/postgres-protocol/CHANGELOG.md b/postgres-protocol/CHANGELOG.md index 7a51cb192..5d9cecd01 100644 --- a/postgres-protocol/CHANGELOG.md +++ b/postgres-protocol/CHANGELOG.md @@ -1,5 +1,17 @@ # Change Log +## v0.6.3 - 2021-12-10 + +### Changed + +* Upgraded `hmac`, `md-5` and `sha`. + +## v0.6.2 - 2021-09-29 + +### Changed + +* Upgraded `hmac`. + ## v0.6.1 - 2021-04-03 ### Added diff --git a/postgres-protocol/Cargo.toml b/postgres-protocol/Cargo.toml index 4fd288697..a4716907b 100644 --- a/postgres-protocol/Cargo.toml +++ b/postgres-protocol/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "postgres-protocol" -version = "0.6.1" +version = "0.6.4" authors = ["Steven Fackler "] edition = "2018" description = "Low level Postgres protocol APIs" @@ -13,9 +13,9 @@ base64 = "0.13" byteorder = "1.0" bytes = "1.0" fallible-iterator = "0.2" -hmac = "0.10" -md-5 = "0.9" +hmac = "0.12" +md-5 = "0.10" memchr = "2.0" rand = "0.8" -sha2 = "0.9" +sha2 = "0.10" stringprep = "0.1" diff --git a/postgres-protocol/LICENSE-APACHE b/postgres-protocol/LICENSE-APACHE deleted file mode 100644 index 16fe87b06..000000000 --- a/postgres-protocol/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/postgres-protocol/LICENSE-APACHE b/postgres-protocol/LICENSE-APACHE new file mode 120000 index 000000000..965b606f3 --- /dev/null +++ b/postgres-protocol/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/postgres-protocol/LICENSE-MIT b/postgres-protocol/LICENSE-MIT deleted file mode 100644 index 71803aea1..000000000 --- a/postgres-protocol/LICENSE-MIT +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 Steven Fackler - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/postgres-protocol/LICENSE-MIT b/postgres-protocol/LICENSE-MIT new file mode 120000 index 000000000..76219eb72 --- /dev/null +++ b/postgres-protocol/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/postgres-protocol/src/authentication/sasl.rs b/postgres-protocol/src/authentication/sasl.rs index 7c0d1754f..ea2f55cad 100644 --- a/postgres-protocol/src/authentication/sasl.rs +++ b/postgres-protocol/src/authentication/sasl.rs @@ -1,6 +1,6 @@ //! SASL-based authentication support. -use hmac::{Hmac, Mac, NewMac}; +use hmac::{Hmac, Mac}; use rand::{self, Rng}; use sha2::digest::FixedOutput; use sha2::{Digest, Sha256}; @@ -33,7 +33,8 @@ fn normalize(pass: &[u8]) -> Vec { } pub(crate) fn hi(str: &[u8], salt: &[u8], i: u32) -> [u8; 32] { - let mut hmac = Hmac::::new_varkey(str).expect("HMAC is able to accept all key sizes"); + let mut hmac = + Hmac::::new_from_slice(str).expect("HMAC is able to accept all key sizes"); hmac.update(salt); hmac.update(&[0, 0, 0, 1]); let mut prev = hmac.finalize().into_bytes(); @@ -41,7 +42,7 @@ pub(crate) fn hi(str: &[u8], salt: &[u8], i: u32) -> [u8; 32] { let mut hi = prev; for _ in 1..i { - let mut hmac = Hmac::::new_varkey(str).expect("already checked above"); + let mut hmac = Hmac::::new_from_slice(str).expect("already checked above"); hmac.update(&prev); prev = hmac.finalize().into_bytes(); @@ -195,7 +196,7 @@ impl ScramSha256 { let salted_password = hi(&password, &salt, parsed.iteration_count); - let mut hmac = Hmac::::new_varkey(&salted_password) + let mut hmac = Hmac::::new_from_slice(&salted_password) .expect("HMAC is able to accept all key sizes"); hmac.update(b"Client Key"); let client_key = hmac.finalize().into_bytes(); @@ -214,8 +215,8 @@ impl ScramSha256 { let auth_message = format!("n=,r={},{},{}", client_nonce, message, self.message); - let mut hmac = - Hmac::::new_varkey(&stored_key).expect("HMAC is able to accept all key sizes"); + let mut hmac = Hmac::::new_from_slice(&stored_key) + .expect("HMAC is able to accept all key sizes"); hmac.update(auth_message.as_bytes()); let client_signature = hmac.finalize().into_bytes(); @@ -266,15 +267,15 @@ impl ScramSha256 { Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidInput, e)), }; - let mut hmac = Hmac::::new_varkey(&salted_password) + let mut hmac = Hmac::::new_from_slice(&salted_password) .expect("HMAC is able to accept all key sizes"); hmac.update(b"Server Key"); let server_key = hmac.finalize().into_bytes(); - let mut hmac = - Hmac::::new_varkey(&server_key).expect("HMAC is able to accept all key sizes"); + let mut hmac = Hmac::::new_from_slice(&server_key) + .expect("HMAC is able to accept all key sizes"); hmac.update(auth_message.as_bytes()); - hmac.verify(&verifier) + hmac.verify_slice(&verifier) .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "SCRAM verification error")) } } diff --git a/postgres-protocol/src/message/backend.rs b/postgres-protocol/src/message/backend.rs index 68b5aa6e5..45e5c4074 100644 --- a/postgres-protocol/src/message/backend.rs +++ b/postgres-protocol/src/message/backend.rs @@ -450,9 +450,9 @@ impl CopyDataBody { } pub struct CopyInResponseBody { - storage: Bytes, - len: u16, format: u8, + len: u16, + storage: Bytes, } impl CopyInResponseBody { @@ -504,9 +504,9 @@ impl<'a> FallibleIterator for ColumnFormats<'a> { } pub struct CopyOutResponseBody { - storage: Bytes, - len: u16, format: u8, + len: u16, + storage: Bytes, } impl CopyOutResponseBody { diff --git a/postgres-protocol/src/password/mod.rs b/postgres-protocol/src/password/mod.rs index ccb95c79b..a60687bbe 100644 --- a/postgres-protocol/src/password/mod.rs +++ b/postgres-protocol/src/password/mod.rs @@ -7,7 +7,7 @@ //! end up in logs pg_stat displays, etc. use crate::authentication::sasl; -use hmac::{Hmac, Mac, NewMac}; +use hmac::{Hmac, Mac}; use md5::Md5; use rand::RngCore; use sha2::digest::FixedOutput; @@ -61,8 +61,8 @@ pub(crate) fn scram_sha_256_salt(password: &[u8], salt: [u8; SCRAM_DEFAULT_SALT_ let salted_password = sasl::hi(&prepared, &salt, SCRAM_DEFAULT_ITERATIONS); // client key - let mut hmac = - Hmac::::new_varkey(&salted_password).expect("HMAC is able to accept all key sizes"); + let mut hmac = Hmac::::new_from_slice(&salted_password) + .expect("HMAC is able to accept all key sizes"); hmac.update(b"Client Key"); let client_key = hmac.finalize().into_bytes(); @@ -72,8 +72,8 @@ pub(crate) fn scram_sha_256_salt(password: &[u8], salt: [u8; SCRAM_DEFAULT_SALT_ let stored_key = hash.finalize_fixed(); // server key - let mut hmac = - Hmac::::new_varkey(&salted_password).expect("HMAC is able to accept all key sizes"); + let mut hmac = Hmac::::new_from_slice(&salted_password) + .expect("HMAC is able to accept all key sizes"); hmac.update(b"Server Key"); let server_key = hmac.finalize().into_bytes(); diff --git a/postgres-protocol/src/types/mod.rs b/postgres-protocol/src/types/mod.rs index a595f5a30..05f515f76 100644 --- a/postgres-protocol/src/types/mod.rs +++ b/postgres-protocol/src/types/mod.rs @@ -1059,3 +1059,60 @@ impl Inet { self.netmask } } + +/// Serializes a Postgres ltree string +#[inline] +pub fn ltree_to_sql(v: &str, buf: &mut BytesMut) { + // A version number is prepended to an ltree string per spec + buf.put_u8(1); + // Append the rest of the query + buf.put_slice(v.as_bytes()); +} + +/// Deserialize a Postgres ltree string +#[inline] +pub fn ltree_from_sql(buf: &[u8]) -> Result<&str, StdBox> { + match buf { + // Remove the version number from the front of the ltree per spec + [1u8, rest @ ..] => Ok(str::from_utf8(rest)?), + _ => Err("ltree version 1 only supported".into()), + } +} + +/// Serializes a Postgres lquery string +#[inline] +pub fn lquery_to_sql(v: &str, buf: &mut BytesMut) { + // A version number is prepended to an lquery string per spec + buf.put_u8(1); + // Append the rest of the query + buf.put_slice(v.as_bytes()); +} + +/// Deserialize a Postgres lquery string +#[inline] +pub fn lquery_from_sql(buf: &[u8]) -> Result<&str, StdBox> { + match buf { + // Remove the version number from the front of the lquery per spec + [1u8, rest @ ..] => Ok(str::from_utf8(rest)?), + _ => Err("lquery version 1 only supported".into()), + } +} + +/// Serializes a Postgres ltxtquery string +#[inline] +pub fn ltxtquery_to_sql(v: &str, buf: &mut BytesMut) { + // A version number is prepended to an ltxtquery string per spec + buf.put_u8(1); + // Append the rest of the query + buf.put_slice(v.as_bytes()); +} + +/// Deserialize a Postgres ltxtquery string +#[inline] +pub fn ltxtquery_from_sql(buf: &[u8]) -> Result<&str, StdBox> { + match buf { + // Remove the version number from the front of the ltxtquery per spec + [1u8, rest @ ..] => Ok(str::from_utf8(rest)?), + _ => Err("ltxtquery version 1 only supported".into()), + } +} diff --git a/postgres-protocol/src/types/test.rs b/postgres-protocol/src/types/test.rs index 8796ab31b..6f1851fc2 100644 --- a/postgres-protocol/src/types/test.rs +++ b/postgres-protocol/src/types/test.rs @@ -1,4 +1,4 @@ -use bytes::BytesMut; +use bytes::{Buf, BytesMut}; use fallible_iterator::FallibleIterator; use std::collections::HashMap; @@ -6,6 +6,7 @@ use super::*; use crate::IsNull; #[test] +#[allow(clippy::bool_assert_comparison)] fn bool() { let mut buf = BytesMut::new(); bool_to_sql(true, &mut buf); @@ -113,7 +114,7 @@ fn array() { .unwrap(); let array = array_from_sql(&buf).unwrap(); - assert_eq!(array.has_nulls(), true); + assert!(array.has_nulls()); assert_eq!(array.element_type(), 10); assert_eq!(array.dimensions().collect::>().unwrap(), dimensions); assert_eq!(array.values().collect::>().unwrap(), values); @@ -150,8 +151,92 @@ fn non_null_array() { .unwrap(); let array = array_from_sql(&buf).unwrap(); - assert_eq!(array.has_nulls(), false); + assert!(!array.has_nulls()); assert_eq!(array.element_type(), 10); assert_eq!(array.dimensions().collect::>().unwrap(), dimensions); assert_eq!(array.values().collect::>().unwrap(), values); } + +#[test] +fn ltree_sql() { + let mut query = vec![1u8]; + query.extend_from_slice("A.B.C".as_bytes()); + + let mut buf = BytesMut::new(); + + ltree_to_sql("A.B.C", &mut buf); + + assert_eq!(query.as_slice(), buf.chunk()); +} + +#[test] +fn ltree_str() { + let mut query = vec![1u8]; + query.extend_from_slice("A.B.C".as_bytes()); + + assert!(matches!(ltree_from_sql(query.as_slice()), Ok(_))) +} + +#[test] +fn ltree_wrong_version() { + let mut query = vec![2u8]; + query.extend_from_slice("A.B.C".as_bytes()); + + assert!(matches!(ltree_from_sql(query.as_slice()), Err(_))) +} + +#[test] +fn lquery_sql() { + let mut query = vec![1u8]; + query.extend_from_slice("A.B.C".as_bytes()); + + let mut buf = BytesMut::new(); + + lquery_to_sql("A.B.C", &mut buf); + + assert_eq!(query.as_slice(), buf.chunk()); +} + +#[test] +fn lquery_str() { + let mut query = vec![1u8]; + query.extend_from_slice("A.B.C".as_bytes()); + + assert!(matches!(lquery_from_sql(query.as_slice()), Ok(_))) +} + +#[test] +fn lquery_wrong_version() { + let mut query = vec![2u8]; + query.extend_from_slice("A.B.C".as_bytes()); + + assert!(matches!(lquery_from_sql(query.as_slice()), Err(_))) +} + +#[test] +fn ltxtquery_sql() { + let mut query = vec![1u8]; + query.extend_from_slice("a & b*".as_bytes()); + + let mut buf = BytesMut::new(); + + ltree_to_sql("a & b*", &mut buf); + + assert_eq!(query.as_slice(), buf.chunk()); +} + +#[test] +fn ltxtquery_str() { + let mut query = vec![1u8]; + query.extend_from_slice("a & b*".as_bytes()); + + assert!(matches!(ltree_from_sql(query.as_slice()), Ok(_))) +} + +#[test] +fn ltxtquery_wrong_version() { + let mut query = vec![2u8]; + query.extend_from_slice("a & b*".as_bytes()); + + assert!(matches!(ltree_from_sql(query.as_slice()), Err(_))) +} diff --git a/postgres-types/CHANGELOG.md b/postgres-types/CHANGELOG.md index 83bc4d1fd..f8b2835eb 100644 --- a/postgres-types/CHANGELOG.md +++ b/postgres-types/CHANGELOG.md @@ -1,5 +1,13 @@ # Change Log +## v0.2.2 - 2021-09-29 + +### Added + +* Added support for `eui48` 1.0 via the `with-eui48-1` feature. +* Added `ToSql` and `FromSql` implementations for array types via the `array-impls` feature. +* Added support for `time` 0.3 via the `with-time-0_3` feature. + ## v0.2.1 - 2021-04-03 ### Added diff --git a/postgres-types/Cargo.toml b/postgres-types/Cargo.toml index 1d7f2cc9a..000d71ea0 100644 --- a/postgres-types/Cargo.toml +++ b/postgres-types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "postgres-types" -version = "0.2.1" +version = "0.2.3" authors = ["Steven Fackler "] edition = "2018" license = "MIT/Apache-2.0" @@ -12,27 +12,35 @@ categories = ["database"] [features] derive = ["postgres-derive"] +array-impls = ["array-init"] with-bit-vec-0_6 = ["bit-vec-06"] +with-cidr-0_2 = ["cidr-02"] with-chrono-0_4 = ["chrono-04"] with-eui48-0_4 = ["eui48-04"] +with-eui48-1 = ["eui48-1"] with-geo-types-0_6 = ["geo-types-06"] with-geo-types-0_7 = ["geo-types-0_7"] with-serde_json-1 = ["serde-1", "serde_json-1"] with-uuid-0_8 = ["uuid-08"] with-time-0_2 = ["time-02"] +with-time-0_3 = ["time-03"] [dependencies] bytes = "1.0" fallible-iterator = "0.2" -postgres-protocol = { version = "0.6.1", path = "../postgres-protocol" } +postgres-protocol = { version = "0.6.4", path = "../postgres-protocol" } postgres-derive = { version = "0.4.0", optional = true, path = "../postgres-derive" } +array-init = { version = "2", optional = true } bit-vec-06 = { version = "0.6", package = "bit-vec", optional = true } chrono-04 = { version = "0.4.16", package = "chrono", default-features = false, features = ["clock"], optional = true } +cidr-02 = { version = "0.2", package = "cidr", optional = true } eui48-04 = { version = "0.4", package = "eui48", optional = true } +eui48-1 = { version = "1.0", package = "eui48", optional = true } geo-types-06 = { version = "0.6", package = "geo-types", optional = true } geo-types-0_7 = { version = "0.7", package = "geo-types", optional = true } serde-1 = { version = "1.0", package = "serde", optional = true } serde_json-1 = { version = "1.0", package = "serde_json", optional = true } uuid-08 = { version = "0.8", package = "uuid", optional = true } time-02 = { version = "0.2", package = "time", optional = true } +time-03 = { version = "0.3", package = "time", default-features = false, optional = true } diff --git a/postgres-types/LICENSE-APACHE b/postgres-types/LICENSE-APACHE deleted file mode 100644 index 16fe87b06..000000000 --- a/postgres-types/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/postgres-types/LICENSE-APACHE b/postgres-types/LICENSE-APACHE new file mode 120000 index 000000000..965b606f3 --- /dev/null +++ b/postgres-types/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/postgres-types/LICENSE-MIT b/postgres-types/LICENSE-MIT deleted file mode 100644 index 71803aea1..000000000 --- a/postgres-types/LICENSE-MIT +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 Steven Fackler - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/postgres-types/LICENSE-MIT b/postgres-types/LICENSE-MIT new file mode 120000 index 000000000..76219eb72 --- /dev/null +++ b/postgres-types/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/postgres-types/src/cidr_02.rs b/postgres-types/src/cidr_02.rs new file mode 100644 index 000000000..2de952c3c --- /dev/null +++ b/postgres-types/src/cidr_02.rs @@ -0,0 +1,44 @@ +use bytes::BytesMut; +use cidr_02::{IpCidr, IpInet}; +use postgres_protocol::types; +use std::error::Error; + +use crate::{FromSql, IsNull, ToSql, Type}; + +impl<'a> FromSql<'a> for IpCidr { + fn from_sql(_: &Type, raw: &[u8]) -> Result> { + let inet = types::inet_from_sql(raw)?; + Ok(IpCidr::new(inet.addr(), inet.netmask())?) + } + + accepts!(CIDR); +} + +impl ToSql for IpCidr { + fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result> { + types::inet_to_sql(self.first_address(), self.network_length(), w); + Ok(IsNull::No) + } + + accepts!(CIDR); + to_sql_checked!(); +} + +impl<'a> FromSql<'a> for IpInet { + fn from_sql(_: &Type, raw: &[u8]) -> Result> { + let inet = types::inet_from_sql(raw)?; + Ok(IpInet::new(inet.addr(), inet.netmask())?) + } + + accepts!(INET); +} + +impl ToSql for IpInet { + fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result> { + types::inet_to_sql(self.address(), self.network_length(), w); + Ok(IsNull::No) + } + + accepts!(INET); + to_sql_checked!(); +} diff --git a/postgres-types/src/eui48_1.rs b/postgres-types/src/eui48_1.rs new file mode 100644 index 000000000..4c35e63ce --- /dev/null +++ b/postgres-types/src/eui48_1.rs @@ -0,0 +1,27 @@ +use bytes::BytesMut; +use eui48_1::MacAddress; +use postgres_protocol::types; +use std::error::Error; + +use crate::{FromSql, IsNull, ToSql, Type}; + +impl<'a> FromSql<'a> for MacAddress { + fn from_sql(_: &Type, raw: &[u8]) -> Result> { + let bytes = types::macaddr_from_sql(raw)?; + Ok(MacAddress::new(bytes)) + } + + accepts!(MACADDR); +} + +impl ToSql for MacAddress { + fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result> { + let mut bytes = [0; 6]; + bytes.copy_from_slice(self.as_bytes()); + types::macaddr_to_sql(bytes, w); + Ok(IsNull::No) + } + + accepts!(MACADDR); + to_sql_checked!(); +} diff --git a/postgres-types/src/lib.rs b/postgres-types/src/lib.rs index 5c483bd76..d029d3948 100644 --- a/postgres-types/src/lib.rs +++ b/postgres-types/src/lib.rs @@ -6,7 +6,12 @@ //! # Derive //! //! If the `derive` cargo feature is enabled, you can derive `ToSql` and `FromSql` implementations for custom Postgres -//! types. +//! types. Explicitly, modify your `Cargo.toml` file to include the following: +//! +//! ```toml +//! [dependencies] +//! postgres-types = { version = "0.X.X", features = ["derive"] } +//! ``` //! //! ## Enums //! @@ -50,6 +55,21 @@ //! struct SessionId(Vec); //! ``` //! +//! ## Newtypes +//! +//! The `#[postgres(transparent)]` attribute can be used on a single-field tuple struct to create a +//! Rust-only wrapper type that will use the [`ToSql`] & [`FromSql`] implementation of the inner +//! value : +//! ```rust +//! # #[cfg(feature = "derive")] +//! use postgres_types::{ToSql, FromSql}; +//! +//! # #[cfg(feature = "derive")] +//! #[derive(Debug, ToSql, FromSql)] +//! #[postgres(transparent)] +//! struct UserId(i32); +//! ``` +//! //! ## Composites //! //! Postgres composite types correspond to structs in Rust: @@ -192,8 +212,12 @@ where mod bit_vec_06; #[cfg(feature = "with-chrono-0_4")] mod chrono_04; +#[cfg(feature = "with-cidr-0_2")] +mod cidr_02; #[cfg(feature = "with-eui48-0_4")] mod eui48_04; +#[cfg(feature = "with-eui48-1")] +mod eui48_1; #[cfg(feature = "with-geo-types-0_6")] mod geo_types_06; #[cfg(feature = "with-geo-types-0_7")] @@ -202,6 +226,8 @@ mod geo_types_07; mod serde_json_1; #[cfg(feature = "with-time-0_2")] mod time_02; +#[cfg(feature = "with-time-0_3")] +mod time_03; #[cfg(feature = "with-uuid-0_8")] mod uuid_08; @@ -381,6 +407,7 @@ impl WrongType { /// | `f32` | REAL | /// | `f64` | DOUBLE PRECISION | /// | `&str`/`String` | VARCHAR, CHAR(n), TEXT, CITEXT, NAME, UNKNOWN | +/// | | LTREE, LQUERY, LTXTQUERY | /// | `&[u8]`/`Vec` | BYTEA | /// | `HashMap>` | HSTORE | /// | `SystemTime` | TIMESTAMP, TIMESTAMP WITH TIME ZONE | @@ -412,6 +439,8 @@ impl WrongType { /// | `uuid::Uuid` | UUID | /// | `bit_vec::BitVec` | BIT, VARBIT | /// | `eui48::MacAddress` | MACADDR | +/// | `cidr::InetCidr` | CIDR | +/// | `cidr::InetAddr` | INET | /// /// # Nullability /// @@ -421,8 +450,10 @@ impl WrongType { /// /// # Arrays /// -/// `FromSql` is implemented for `Vec` where `T` implements `FromSql`, and -/// corresponds to one-dimensional Postgres arrays. +/// `FromSql` is implemented for `Vec` and `[T; N]` where `T` implements +/// `FromSql`, and corresponds to one-dimensional Postgres arrays. **Note:** +/// the impl for arrays only exist when the Cargo feature `array-impls` is +/// enabled. pub trait FromSql<'a>: Sized { /// Creates a new value of this type from a buffer of data of the specified /// Postgres `Type` in its binary format. @@ -506,6 +537,47 @@ impl<'a, T: FromSql<'a>> FromSql<'a> for Vec { } } +#[cfg(feature = "array-impls")] +impl<'a, T: FromSql<'a>, const N: usize> FromSql<'a> for [T; N] { + fn from_sql(ty: &Type, raw: &'a [u8]) -> Result> { + let member_type = match *ty.kind() { + Kind::Array(ref member) => member, + _ => panic!("expected array type"), + }; + + let array = types::array_from_sql(raw)?; + if array.dimensions().count()? > 1 { + return Err("array contains too many dimensions".into()); + } + + let mut values = array.values(); + let out = array_init::try_array_init(|i| { + let v = values + .next()? + .ok_or_else(|| -> Box { + format!("too few elements in array (expected {}, got {})", N, i).into() + })?; + T::from_sql_nullable(member_type, v) + })?; + if values.next()?.is_some() { + return Err(format!( + "excess elements in array (expected {}, got more than that)", + N, + ) + .into()); + } + + Ok(out) + } + + fn accepts(ty: &Type) -> bool { + match *ty.kind() { + Kind::Array(ref inner) => T::accepts(inner), + _ => false, + } + } +} + impl<'a> FromSql<'a> for Vec { fn from_sql(_: &Type, raw: &'a [u8]) -> Result, Box> { Ok(types::bytea_from_sql(raw).to_owned()) @@ -523,8 +595,20 @@ impl<'a> FromSql<'a> for &'a [u8] { } impl<'a> FromSql<'a> for String { - fn from_sql(_: &Type, raw: &'a [u8]) -> Result> { - types::text_from_sql(raw).map(ToString::to_string) + fn from_sql(ty: &Type, raw: &'a [u8]) -> Result> { + <&str as FromSql>::from_sql(ty, raw).map(ToString::to_string) + } + + fn accepts(ty: &Type) -> bool { + <&str as FromSql>::accepts(ty) + } +} + +impl<'a> FromSql<'a> for Box { + fn from_sql(ty: &Type, raw: &'a [u8]) -> Result, Box> { + <&str as FromSql>::from_sql(ty, raw) + .map(ToString::to_string) + .map(String::into_boxed_str) } fn accepts(ty: &Type) -> bool { @@ -533,14 +617,26 @@ impl<'a> FromSql<'a> for String { } impl<'a> FromSql<'a> for &'a str { - fn from_sql(_: &Type, raw: &'a [u8]) -> Result<&'a str, Box> { - types::text_from_sql(raw) + fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<&'a str, Box> { + match *ty { + ref ty if ty.name() == "ltree" => types::ltree_from_sql(raw), + ref ty if ty.name() == "lquery" => types::lquery_from_sql(raw), + ref ty if ty.name() == "ltxtquery" => types::ltxtquery_from_sql(raw), + _ => types::text_from_sql(raw), + } } fn accepts(ty: &Type) -> bool { match *ty { Type::VARCHAR | Type::TEXT | Type::BPCHAR | Type::NAME | Type::UNKNOWN => true, - ref ty if ty.name() == "citext" => true, + ref ty + if (ty.name() == "citext" + || ty.name() == "ltree" + || ty.name() == "lquery" + || ty.name() == "ltxtquery") => + { + true + } _ => false, } } @@ -644,6 +740,7 @@ pub enum IsNull { /// | `f32` | REAL | /// | `f64` | DOUBLE PRECISION | /// | `&str`/`String` | VARCHAR, CHAR(n), TEXT, CITEXT, NAME | +/// | | LTREE, LQUERY, LTXTQUERY | /// | `&[u8]`/`Vec` | BYTEA | /// | `HashMap>` | HSTORE | /// | `SystemTime` | TIMESTAMP, TIMESTAMP WITH TIME ZONE | @@ -684,8 +781,10 @@ pub enum IsNull { /// /// # Arrays /// -/// `ToSql` is implemented for `Vec` and `&[T]` where `T` implements `ToSql`, -/// and corresponds to one-dimensional Postgres arrays with an index offset of 1. +/// `ToSql` is implemented for `Vec`, `&[T]` and `[T; N]` where `T` +/// implements `ToSql`, and corresponds to one-dimensional Postgres arrays with +/// an index offset of 1. **Note:** the impl for arrays only exist when the +/// Cargo feature `array-impls` is enabled. pub trait ToSql: fmt::Debug { /// Converts the value of `self` into the binary format of the specified /// Postgres `Type`, appending it to `out`. @@ -801,6 +900,19 @@ impl<'a> ToSql for &'a [u8] { to_sql_checked!(); } +#[cfg(feature = "array-impls")] +impl ToSql for [T; N] { + fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result> { + <&[T] as ToSql>::to_sql(&&self[..], ty, w) + } + + fn accepts(ty: &Type) -> bool { + <&[T] as ToSql>::accepts(ty) + } + + to_sql_checked!(); +} + impl ToSql for Vec { fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result> { <&[T] as ToSql>::to_sql(&&**self, ty, w) @@ -826,15 +938,27 @@ impl ToSql for Vec { } impl<'a> ToSql for &'a str { - fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result> { - types::text_to_sql(*self, w); + fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result> { + match *ty { + ref ty if ty.name() == "ltree" => types::ltree_to_sql(*self, w), + ref ty if ty.name() == "lquery" => types::lquery_to_sql(*self, w), + ref ty if ty.name() == "ltxtquery" => types::ltxtquery_to_sql(*self, w), + _ => types::text_to_sql(*self, w), + } Ok(IsNull::No) } fn accepts(ty: &Type) -> bool { match *ty { Type::VARCHAR | Type::TEXT | Type::BPCHAR | Type::NAME | Type::UNKNOWN => true, - ref ty if ty.name() == "citext" => true, + ref ty + if (ty.name() == "citext" + || ty.name() == "ltree" + || ty.name() == "lquery" + || ty.name() == "ltxtquery") => + { + true + } _ => false, } } @@ -844,7 +968,7 @@ impl<'a> ToSql for &'a str { impl<'a> ToSql for Cow<'a, str> { fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result> { - <&str as ToSql>::to_sql(&&self.as_ref(), ty, w) + <&str as ToSql>::to_sql(&self.as_ref(), ty, w) } fn accepts(ty: &Type) -> bool { @@ -866,6 +990,18 @@ impl ToSql for String { to_sql_checked!(); } +impl ToSql for Box { + fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result> { + <&str as ToSql>::to_sql(&&**self, ty, w) + } + + fn accepts(ty: &Type) -> bool { + <&str as ToSql>::accepts(ty) + } + + to_sql_checked!(); +} + macro_rules! simple_to { ($t:ty, $f:ident, $($expected:ident),+) => { impl ToSql for $t { @@ -977,6 +1113,36 @@ impl BorrowToSql for &dyn ToSql { } } +impl sealed::Sealed for Box {} + +impl BorrowToSql for Box { + #[inline] + fn borrow_to_sql(&self) -> &dyn ToSql { + self.as_ref() + } +} + +impl sealed::Sealed for Box {} +impl BorrowToSql for Box { + #[inline] + fn borrow_to_sql(&self) -> &dyn ToSql { + self.as_ref() + } +} + +impl sealed::Sealed for &(dyn ToSql + Sync) {} + +/// In async contexts it is sometimes necessary to have the additional +/// Sync requirement on parameters for queries since this enables the +/// resulting Futures to be Send, hence usable in, e.g., tokio::spawn. +/// This instance is provided for those cases. +impl BorrowToSql for &(dyn ToSql + Sync) { + #[inline] + fn borrow_to_sql(&self) -> &dyn ToSql { + *self + } +} + impl sealed::Sealed for T where T: ToSql {} impl BorrowToSql for T diff --git a/postgres-types/src/time_03.rs b/postgres-types/src/time_03.rs new file mode 100644 index 000000000..f136fab7c --- /dev/null +++ b/postgres-types/src/time_03.rs @@ -0,0 +1,108 @@ +use bytes::BytesMut; +use postgres_protocol::types; +use std::convert::TryFrom; +use std::error::Error; +use time_03::{Date, Duration, OffsetDateTime, PrimitiveDateTime, Time, UtcOffset}; + +use crate::{FromSql, IsNull, ToSql, Type}; + +fn base() -> PrimitiveDateTime { + PrimitiveDateTime::new(Date::from_ordinal_date(2000, 1).unwrap(), Time::MIDNIGHT) +} + +impl<'a> FromSql<'a> for PrimitiveDateTime { + fn from_sql(_: &Type, raw: &[u8]) -> Result> { + let t = types::timestamp_from_sql(raw)?; + Ok(base() + Duration::microseconds(t)) + } + + accepts!(TIMESTAMP); +} + +impl ToSql for PrimitiveDateTime { + fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result> { + let time = match i64::try_from((*self - base()).whole_microseconds()) { + Ok(time) => time, + Err(_) => return Err("value too large to transmit".into()), + }; + types::timestamp_to_sql(time, w); + Ok(IsNull::No) + } + + accepts!(TIMESTAMP); + to_sql_checked!(); +} + +impl<'a> FromSql<'a> for OffsetDateTime { + fn from_sql(type_: &Type, raw: &[u8]) -> Result> { + let primitive = PrimitiveDateTime::from_sql(type_, raw)?; + Ok(primitive.assume_utc()) + } + + accepts!(TIMESTAMPTZ); +} + +impl ToSql for OffsetDateTime { + fn to_sql( + &self, + type_: &Type, + w: &mut BytesMut, + ) -> Result> { + let utc_datetime = self.to_offset(UtcOffset::UTC); + let date = utc_datetime.date(); + let time = utc_datetime.time(); + let primitive = PrimitiveDateTime::new(date, time); + primitive.to_sql(type_, w) + } + + accepts!(TIMESTAMPTZ); + to_sql_checked!(); +} + +impl<'a> FromSql<'a> for Date { + fn from_sql(_: &Type, raw: &[u8]) -> Result> { + let jd = types::date_from_sql(raw)?; + Ok(base().date() + Duration::days(i64::from(jd))) + } + + accepts!(DATE); +} + +impl ToSql for Date { + fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result> { + let jd = (*self - base().date()).whole_days(); + if jd > i64::from(i32::max_value()) || jd < i64::from(i32::min_value()) { + return Err("value too large to transmit".into()); + } + + types::date_to_sql(jd as i32, w); + Ok(IsNull::No) + } + + accepts!(DATE); + to_sql_checked!(); +} + +impl<'a> FromSql<'a> for Time { + fn from_sql(_: &Type, raw: &[u8]) -> Result> { + let usec = types::time_from_sql(raw)?; + Ok(Time::MIDNIGHT + Duration::microseconds(usec)) + } + + accepts!(TIME); +} + +impl ToSql for Time { + fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result> { + let delta = *self - Time::MIDNIGHT; + let time = match i64::try_from(delta.whole_microseconds()) { + Ok(time) => time, + Err(_) => return Err("value too large to transmit".into()), + }; + types::time_to_sql(time, w); + Ok(IsNull::No) + } + + accepts!(TIME); + to_sql_checked!(); +} diff --git a/postgres/CHANGELOG.md b/postgres/CHANGELOG.md index e68dedc5b..6af8d914b 100644 --- a/postgres/CHANGELOG.md +++ b/postgres/CHANGELOG.md @@ -1,5 +1,14 @@ # Change Log +## v0.19.2 - 2021-09-29 + +### Added + +* Added `SimpleQueryRow::columns`. +* Added support for `eui48` 1.0 via the `with-eui48-1` feature. +* Added `FromSql` and `ToSql` implementations for arrays via the `array-impls` feature. +* Added support for `time` 0.3 via the `with-time-0_3` feature. + ## v0.19.1 - 2021-04-03 ### Added diff --git a/postgres/Cargo.toml b/postgres/Cargo.toml index 18219782d..b61e42aca 100644 --- a/postgres/Cargo.toml +++ b/postgres/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "postgres" -version = "0.19.1" +version = "0.19.2" authors = ["Steven Fackler "] edition = "2018" license = "MIT/Apache-2.0" @@ -21,20 +21,23 @@ all-features = true circle-ci = { repository = "sfackler/rust-postgres" } [features] +array-impls = ["tokio-postgres/array-impls"] with-bit-vec-0_6 = ["tokio-postgres/with-bit-vec-0_6"] with-chrono-0_4 = ["tokio-postgres/with-chrono-0_4"] with-eui48-0_4 = ["tokio-postgres/with-eui48-0_4"] +with-eui48-1 = ["tokio-postgres/with-eui48-1"] with-geo-types-0_6 = ["tokio-postgres/with-geo-types-0_6"] with-geo-types-0_7 = ["tokio-postgres/with-geo-types-0_7"] with-serde_json-1 = ["tokio-postgres/with-serde_json-1"] with-uuid-0_8 = ["tokio-postgres/with-uuid-0_8"] with-time-0_2 = ["tokio-postgres/with-time-0_2"] +with-time-0_3 = ["tokio-postgres/with-time-0_3"] [dependencies] bytes = "1.0" fallible-iterator = "0.2" futures = "0.3" -tokio-postgres = { version = "0.7.1", path = "../tokio-postgres" } +tokio-postgres = { version = "0.7.2", path = "../tokio-postgres" } tokio = { version = "1.0", features = ["rt", "time"] } log = "0.4" diff --git a/postgres/LICENSE-APACHE b/postgres/LICENSE-APACHE deleted file mode 100644 index 16fe87b06..000000000 --- a/postgres/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/postgres/LICENSE-APACHE b/postgres/LICENSE-APACHE new file mode 120000 index 000000000..965b606f3 --- /dev/null +++ b/postgres/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/postgres/LICENSE-MIT b/postgres/LICENSE-MIT deleted file mode 100644 index 71803aea1..000000000 --- a/postgres/LICENSE-MIT +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 Steven Fackler - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/postgres/LICENSE-MIT b/postgres/LICENSE-MIT new file mode 120000 index 000000000..76219eb72 --- /dev/null +++ b/postgres/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/postgres/src/lib.rs b/postgres/src/lib.rs index 4513aeef7..a599532e4 100644 --- a/postgres/src/lib.rs +++ b/postgres/src/lib.rs @@ -55,12 +55,14 @@ //! | ------- | ----------- | ------------------ | ------- | //! | `with-bit-vec-0_6` | Enable support for the `bit-vec` crate. | [bit-vec](https://crates.io/crates/bit-vec) 0.6 | no | //! | `with-chrono-0_4` | Enable support for the `chrono` crate. | [chrono](https://crates.io/crates/chrono) 0.4 | no | -//! | `with-eui48-0_4` | Enable support for the `eui48` crate. | [eui48](https://crates.io/crates/eui48) 0.4 | no | +//! | `with-eui48-0_4` | Enable support for the 0.4 version of the `eui48` crate. | [eui48](https://crates.io/crates/eui48) 0.4 | no | +//! | `with-eui48-1` | Enable support for the 1.0 version of the `eui48` crate. | [eui48](https://crates.io/crates/eui48) 1.0 | no | //! | `with-geo-types-0_6` | Enable support for the 0.6 version of the `geo-types` crate. | [geo-types](https://crates.io/crates/geo-types/0.6.0) 0.6 | no | //! | `with-geo-types-0_7` | Enable support for the 0.7 version of the `geo-types` crate. | [geo-types](https://crates.io/crates/geo-types/0.7.0) 0.7 | no | //! | `with-serde_json-1` | Enable support for the `serde_json` crate. | [serde_json](https://crates.io/crates/serde_json) 1.0 | no | //! | `with-uuid-0_8` | Enable support for the `uuid` crate. | [uuid](https://crates.io/crates/uuid) 0.8 | no | -//! | `with-time-0_2` | Enable support for the `time` crate. | [time](https://crates.io/crates/time) 0.2 | no | +//! | `with-time-0_2` | Enable support for the 0.2 version of the `time` crate. | [time](https://crates.io/crates/time/0.2.0) 0.2 | no | +//! | `with-time-0_3` | Enable support for the 0.3 version of the `time` crate. | [time](https://crates.io/crates/time/0.3.0) 0.3 | no | #![warn(clippy::all, rust_2018_idioms, missing_docs)] pub use fallible_iterator; diff --git a/tokio-postgres/CHANGELOG.md b/tokio-postgres/CHANGELOG.md index 7cc6c7071..eca196f06 100644 --- a/tokio-postgres/CHANGELOG.md +++ b/tokio-postgres/CHANGELOG.md @@ -1,6 +1,37 @@ # Change Log -## v0.7.1 - 2020-04-03 +## v0.7.5 - 2021-10-29 + +### Fixed + +* Fixed a bug where the client could enter into a transaction if the `Client::transaction` future was dropped before completion. + +## v0.7.4 - 2021-10-19 + +### Fixed + +* Fixed reporting of commit-time errors triggered by deferred constraints. + +## v0.7.3 - 2021-09-29 + +### Fixed + +* Fixed a deadlock when pipelined requests concurrently prepare cached typeinfo queries. + +### Added + +* Added `SimpleQueryRow::columns`. +* Added support for `eui48` 1.0 via the `with-eui48-1` feature. +* Added `FromSql` and `ToSql` implementations for arrays via the `array-impls` feature. +* Added support for `time` 0.3 via the `with-time-0_3` feature. + +## v0.7.2 - 2021-04-25 + +### Fixed + +* `SqlState` constants can now be used in `match` patterns. + +## v0.7.1 - 2021-04-03 ### Added diff --git a/tokio-postgres/Cargo.toml b/tokio-postgres/Cargo.toml index b1d093d4b..82e71fb1c 100644 --- a/tokio-postgres/Cargo.toml +++ b/tokio-postgres/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tokio-postgres" -version = "0.7.1" +version = "0.7.6" authors = ["Steven Fackler "] edition = "2018" license = "MIT/Apache-2.0" @@ -27,14 +27,17 @@ circle-ci = { repository = "sfackler/rust-postgres" } default = ["runtime"] runtime = ["tokio/net", "tokio/time"] +array-impls = ["postgres-types/array-impls"] with-bit-vec-0_6 = ["postgres-types/with-bit-vec-0_6"] with-chrono-0_4 = ["postgres-types/with-chrono-0_4"] with-eui48-0_4 = ["postgres-types/with-eui48-0_4"] +with-eui48-1 = ["postgres-types/with-eui48-1"] with-geo-types-0_6 = ["postgres-types/with-geo-types-0_6"] with-geo-types-0_7 = ["postgres-types/with-geo-types-0_7"] with-serde_json-1 = ["postgres-types/with-serde_json-1"] with-uuid-0_8 = ["postgres-types/with-uuid-0_8"] with-time-0_2 = ["postgres-types/with-time-0_2"] +with-time-0_3 = ["postgres-types/with-time-0_3"] [dependencies] async-trait = "0.1" @@ -43,28 +46,29 @@ byteorder = "1.0" fallible-iterator = "0.2" futures = "0.3" log = "0.4" -parking_lot = "0.11" +parking_lot = "0.12" percent-encoding = "2.0" pin-project-lite = "0.2" -phf = "0.8" -postgres-protocol = { version = "0.6.1", path = "../postgres-protocol" } -postgres-types = { version = "0.2.1", path = "../postgres-types" } +phf = "0.10" +postgres-protocol = { version = "0.6.4", path = "../postgres-protocol" } +postgres-types = { version = "0.2.3", path = "../postgres-types" } socket2 = "0.4" tokio = { version = "1.0", features = ["io-util"] } -tokio-util = { version = "0.6", features = ["codec"] } +tokio-util = { version = "0.7", features = ["codec"] } [dev-dependencies] tokio = { version = "1.0", features = ["full"] } -env_logger = "0.8" +env_logger = "0.9" criterion = "0.3" bit-vec-06 = { version = "0.6", package = "bit-vec" } chrono-04 = { version = "0.4", package = "chrono", default-features = false } eui48-04 = { version = "0.4", package = "eui48" } +eui48-1 = { version = "1.0", package = "eui48" } geo-types-06 = { version = "0.6", package = "geo-types" } geo-types-07 = { version = "0.7", package = "geo-types" } serde-1 = { version = "1.0", package = "serde" } serde_json-1 = { version = "1.0", package = "serde_json" } uuid-08 = { version = "0.8", package = "uuid" } time-02 = { version = "0.2", package = "time" } - +time-03 = { version = "0.3", package = "time", features = ["parsing"] } diff --git a/tokio-postgres/LICENSE-APACHE b/tokio-postgres/LICENSE-APACHE deleted file mode 100644 index 16fe87b06..000000000 --- a/tokio-postgres/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/tokio-postgres/LICENSE-APACHE b/tokio-postgres/LICENSE-APACHE new file mode 120000 index 000000000..965b606f3 --- /dev/null +++ b/tokio-postgres/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/tokio-postgres/LICENSE-MIT b/tokio-postgres/LICENSE-MIT deleted file mode 100644 index 71803aea1..000000000 --- a/tokio-postgres/LICENSE-MIT +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 Steven Fackler - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/tokio-postgres/LICENSE-MIT b/tokio-postgres/LICENSE-MIT new file mode 120000 index 000000000..76219eb72 --- /dev/null +++ b/tokio-postgres/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/tokio-postgres/src/client.rs b/tokio-postgres/src/client.rs index c33cf8b33..79978be43 100644 --- a/tokio-postgres/src/client.rs +++ b/tokio-postgres/src/client.rs @@ -1,4 +1,4 @@ -use crate::codec::BackendMessages; +use crate::codec::{BackendMessages, FrontendMessage}; use crate::config::{Host, SslMode}; use crate::connection::{Request, RequestMessages}; use crate::copy_out::CopyOutStream; @@ -19,7 +19,7 @@ use fallible_iterator::FallibleIterator; use futures::channel::mpsc; use futures::{future, pin_mut, ready, StreamExt, TryStreamExt}; use parking_lot::Mutex; -use postgres_protocol::message::backend::Message; +use postgres_protocol::message::{backend::Message, frontend}; use postgres_types::BorrowToSql; use std::collections::HashMap; use std::fmt; @@ -54,17 +54,32 @@ impl Responses { } } -struct State { +/// A cache of type info and prepared statements for fetching type info +/// (corresponding to the queries in the [prepare](prepare) module). +#[derive(Default)] +struct CachedTypeInfo { + /// A statement for basic information for a type from its + /// OID. Corresponds to [TYPEINFO_QUERY](prepare::TYPEINFO_QUERY) (or its + /// fallback). typeinfo: Option, + /// A statement for getting information for a composite type from its OID. + /// Corresponds to [TYPEINFO_QUERY](prepare::TYPEINFO_COMPOSITE_QUERY). typeinfo_composite: Option, + /// A statement for getting information for a composite type from its OID. + /// Corresponds to [TYPEINFO_QUERY](prepare::TYPEINFO_COMPOSITE_QUERY) (or + /// its fallback). typeinfo_enum: Option, + + /// Cache of types already looked up. types: HashMap, - buf: BytesMut, } pub struct InnerClient { sender: mpsc::UnboundedSender, - state: Mutex, + cached_typeinfo: Mutex, + + /// A buffer to use when writing out postgres commands. + buffer: Mutex, pgbouncer_mode: bool, } @@ -83,16 +98,16 @@ impl InnerClient { } pub fn typeinfo(&self) -> Option { - if self.pgbouncer_mode { - None - } else { - self.state.lock().typeinfo.clone() - } + if self.pgbouncer_mode { + None + } else { + self.cached_typeinfo.lock().typeinfo.clone() + } } pub fn set_typeinfo(&self, statement: &Statement) { if !self.pgbouncer_mode { - self.state.lock().typeinfo = Some(statement.clone()); + self.cached_typeinfo.lock().typeinfo = Some(statement.clone()); } } @@ -100,49 +115,51 @@ impl InnerClient { if self.pgbouncer_mode { None } else { - self.state.lock().typeinfo_composite.clone() + self.cached_typeinfo.lock().typeinfo_composite.clone() } } pub fn set_typeinfo_composite(&self, statement: &Statement) { if !self.pgbouncer_mode { - self.state.lock().typeinfo_composite = Some(statement.clone()); + self.cached_typeinfo.lock().typeinfo_composite = Some(statement.clone()); } } pub fn typeinfo_enum(&self) -> Option { if self.pgbouncer_mode { - None + self.cached_typeinfo.lock().typeinfo_enum.clone() } else { - self.state.lock().typeinfo_enum.clone() + None } } pub fn set_typeinfo_enum(&self, statement: &Statement) { if !self.pgbouncer_mode { - self.state.lock().typeinfo_enum = Some(statement.clone()); + self.cached_typeinfo.lock().typeinfo_enum = Some(statement.clone()); } } pub fn type_(&self, oid: Oid) -> Option { - self.state.lock().types.get(&oid).cloned() + self.cached_typeinfo.lock().types.get(&oid).cloned() } pub fn set_type(&self, oid: Oid, type_: &Type) { - self.state.lock().types.insert(oid, type_.clone()); + self.cached_typeinfo.lock().types.insert(oid, type_.clone()); } pub fn clear_type_cache(&self) { - self.state.lock().types.clear(); + self.cached_typeinfo.lock().types.clear(); } + /// Call the given function with a buffer to be used when writing out + /// postgres commands. pub fn with_buf(&self, f: F) -> R where F: FnOnce(&mut BytesMut) -> R, { - let mut state = self.state.lock(); - let r = f(&mut state.buf); - state.buf.clear(); + let mut buffer = self.buffer.lock(); + let r = f(&mut buffer); + buffer.clear(); r } } @@ -180,13 +197,8 @@ impl Client { Client { inner: Arc::new(InnerClient { sender, - state: Mutex::new(State { - typeinfo: None, - typeinfo_composite: None, - typeinfo_enum: None, - types: HashMap::new(), - buf: BytesMut::new(), - }), + cached_typeinfo: Default::default(), + buffer: Default::default(), pgbouncer_mode, }), #[cfg(feature = "runtime")] @@ -497,7 +509,42 @@ impl Client { /// /// The transaction will roll back by default - use the `commit` method to commit it. pub async fn transaction(&mut self) -> Result, Error> { - self.batch_execute("BEGIN").await?; + struct RollbackIfNotDone<'me> { + client: &'me Client, + done: bool, + } + + impl<'a> Drop for RollbackIfNotDone<'a> { + fn drop(&mut self) { + if self.done { + return; + } + + let buf = self.client.inner().with_buf(|buf| { + frontend::query("ROLLBACK", buf).unwrap(); + buf.split().freeze() + }); + let _ = self + .client + .inner() + .send(RequestMessages::Single(FrontendMessage::Raw(buf))); + } + } + + // This is done, as `Future` created by this method can be dropped after + // `RequestMessages` is synchronously send to the `Connection` by + // `batch_execute()`, but before `Responses` is asynchronously polled to + // completion. In that case `Transaction` won't be created and thus + // won't be rolled back. + { + let mut cleaner = RollbackIfNotDone { + client: self, + done: false, + }; + self.batch_execute("BEGIN").await?; + cleaner.done = true; + } + Ok(Transaction::new(self)) } diff --git a/tokio-postgres/src/config.rs b/tokio-postgres/src/config.rs index 4947fa89b..19335dcc4 100644 --- a/tokio-postgres/src/config.rs +++ b/tokio-postgres/src/config.rs @@ -407,19 +407,19 @@ impl Config { fn param(&mut self, key: &str, value: &str) -> Result<(), Error> { match key { "user" => { - self.user(&value); + self.user(value); } "password" => { self.password(value); } "dbname" => { - self.dbname(&value); + self.dbname(value); } "options" => { - self.options(&value); + self.options(value); } "application_name" => { - self.application_name(&value); + self.application_name(value); } "sslmode" => { let mode = match value { @@ -797,7 +797,7 @@ impl<'a> UrlParser<'a> { } fn take_all(&mut self) -> &'a str { - mem::replace(&mut self.s, "") + mem::take(&mut self.s) } fn eat_byte(&mut self) { diff --git a/tokio-postgres/src/error/sqlstate.rs b/tokio-postgres/src/error/sqlstate.rs index 3a6ea0bdc..71648a948 100644 --- a/tokio-postgres/src/error/sqlstate.rs +++ b/tokio-postgres/src/error/sqlstate.rs @@ -1,1148 +1,1658 @@ // Autogenerated file - DO NOT EDIT -use std::borrow::Cow; /// A SQLSTATE error code #[derive(PartialEq, Eq, Clone, Debug)] -pub struct SqlState(Cow<'static, str>); +pub struct SqlState(Inner); impl SqlState { /// Creates a `SqlState` from its error code. pub fn from_code(s: &str) -> SqlState { match SQLSTATE_MAP.get(s) { Some(state) => state.clone(), - None => SqlState(Cow::Owned(s.to_string())), + None => SqlState(Inner::Other(s.into())), } } /// Returns the error code corresponding to the `SqlState`. pub fn code(&self) -> &str { - &self.0 + match &self.0 { + Inner::E00000 => "00000", + Inner::E01000 => "01000", + Inner::E0100C => "0100C", + Inner::E01008 => "01008", + Inner::E01003 => "01003", + Inner::E01007 => "01007", + Inner::E01006 => "01006", + Inner::E01004 => "01004", + Inner::E01P01 => "01P01", + Inner::E02000 => "02000", + Inner::E02001 => "02001", + Inner::E03000 => "03000", + Inner::E08000 => "08000", + Inner::E08003 => "08003", + Inner::E08006 => "08006", + Inner::E08001 => "08001", + Inner::E08004 => "08004", + Inner::E08007 => "08007", + Inner::E08P01 => "08P01", + Inner::E09000 => "09000", + Inner::E0A000 => "0A000", + Inner::E0B000 => "0B000", + Inner::E0F000 => "0F000", + Inner::E0F001 => "0F001", + Inner::E0L000 => "0L000", + Inner::E0LP01 => "0LP01", + Inner::E0P000 => "0P000", + Inner::E0Z000 => "0Z000", + Inner::E0Z002 => "0Z002", + Inner::E20000 => "20000", + Inner::E21000 => "21000", + Inner::E22000 => "22000", + Inner::E2202E => "2202E", + Inner::E22021 => "22021", + Inner::E22008 => "22008", + Inner::E22012 => "22012", + Inner::E22005 => "22005", + Inner::E2200B => "2200B", + Inner::E22022 => "22022", + Inner::E22015 => "22015", + Inner::E2201E => "2201E", + Inner::E22014 => "22014", + Inner::E22016 => "22016", + Inner::E2201F => "2201F", + Inner::E2201G => "2201G", + Inner::E22018 => "22018", + Inner::E22007 => "22007", + Inner::E22019 => "22019", + Inner::E2200D => "2200D", + Inner::E22025 => "22025", + Inner::E22P06 => "22P06", + Inner::E22010 => "22010", + Inner::E22023 => "22023", + Inner::E22013 => "22013", + Inner::E2201B => "2201B", + Inner::E2201W => "2201W", + Inner::E2201X => "2201X", + Inner::E2202H => "2202H", + Inner::E2202G => "2202G", + Inner::E22009 => "22009", + Inner::E2200C => "2200C", + Inner::E2200G => "2200G", + Inner::E22004 => "22004", + Inner::E22002 => "22002", + Inner::E22003 => "22003", + Inner::E2200H => "2200H", + Inner::E22026 => "22026", + Inner::E22001 => "22001", + Inner::E22011 => "22011", + Inner::E22027 => "22027", + Inner::E22024 => "22024", + Inner::E2200F => "2200F", + Inner::E22P01 => "22P01", + Inner::E22P02 => "22P02", + Inner::E22P03 => "22P03", + Inner::E22P04 => "22P04", + Inner::E22P05 => "22P05", + Inner::E2200L => "2200L", + Inner::E2200M => "2200M", + Inner::E2200N => "2200N", + Inner::E2200S => "2200S", + Inner::E2200T => "2200T", + Inner::E22030 => "22030", + Inner::E22031 => "22031", + Inner::E22032 => "22032", + Inner::E22033 => "22033", + Inner::E22034 => "22034", + Inner::E22035 => "22035", + Inner::E22036 => "22036", + Inner::E22037 => "22037", + Inner::E22038 => "22038", + Inner::E22039 => "22039", + Inner::E2203A => "2203A", + Inner::E2203B => "2203B", + Inner::E2203C => "2203C", + Inner::E2203D => "2203D", + Inner::E2203E => "2203E", + Inner::E2203F => "2203F", + Inner::E23000 => "23000", + Inner::E23001 => "23001", + Inner::E23502 => "23502", + Inner::E23503 => "23503", + Inner::E23505 => "23505", + Inner::E23514 => "23514", + Inner::E23P01 => "23P01", + Inner::E24000 => "24000", + Inner::E25000 => "25000", + Inner::E25001 => "25001", + Inner::E25002 => "25002", + Inner::E25008 => "25008", + Inner::E25003 => "25003", + Inner::E25004 => "25004", + Inner::E25005 => "25005", + Inner::E25006 => "25006", + Inner::E25007 => "25007", + Inner::E25P01 => "25P01", + Inner::E25P02 => "25P02", + Inner::E25P03 => "25P03", + Inner::E26000 => "26000", + Inner::E27000 => "27000", + Inner::E28000 => "28000", + Inner::E28P01 => "28P01", + Inner::E2B000 => "2B000", + Inner::E2BP01 => "2BP01", + Inner::E2D000 => "2D000", + Inner::E2F000 => "2F000", + Inner::E2F005 => "2F005", + Inner::E2F002 => "2F002", + Inner::E2F003 => "2F003", + Inner::E2F004 => "2F004", + Inner::E34000 => "34000", + Inner::E38000 => "38000", + Inner::E38001 => "38001", + Inner::E38002 => "38002", + Inner::E38003 => "38003", + Inner::E38004 => "38004", + Inner::E39000 => "39000", + Inner::E39001 => "39001", + Inner::E39004 => "39004", + Inner::E39P01 => "39P01", + Inner::E39P02 => "39P02", + Inner::E39P03 => "39P03", + Inner::E3B000 => "3B000", + Inner::E3B001 => "3B001", + Inner::E3D000 => "3D000", + Inner::E3F000 => "3F000", + Inner::E40000 => "40000", + Inner::E40002 => "40002", + Inner::E40001 => "40001", + Inner::E40003 => "40003", + Inner::E40P01 => "40P01", + Inner::E42000 => "42000", + Inner::E42601 => "42601", + Inner::E42501 => "42501", + Inner::E42846 => "42846", + Inner::E42803 => "42803", + Inner::E42P20 => "42P20", + Inner::E42P19 => "42P19", + Inner::E42830 => "42830", + Inner::E42602 => "42602", + Inner::E42622 => "42622", + Inner::E42939 => "42939", + Inner::E42804 => "42804", + Inner::E42P18 => "42P18", + Inner::E42P21 => "42P21", + Inner::E42P22 => "42P22", + Inner::E42809 => "42809", + Inner::E428C9 => "428C9", + Inner::E42703 => "42703", + Inner::E42883 => "42883", + Inner::E42P01 => "42P01", + Inner::E42P02 => "42P02", + Inner::E42704 => "42704", + Inner::E42701 => "42701", + Inner::E42P03 => "42P03", + Inner::E42P04 => "42P04", + Inner::E42723 => "42723", + Inner::E42P05 => "42P05", + Inner::E42P06 => "42P06", + Inner::E42P07 => "42P07", + Inner::E42712 => "42712", + Inner::E42710 => "42710", + Inner::E42702 => "42702", + Inner::E42725 => "42725", + Inner::E42P08 => "42P08", + Inner::E42P09 => "42P09", + Inner::E42P10 => "42P10", + Inner::E42611 => "42611", + Inner::E42P11 => "42P11", + Inner::E42P12 => "42P12", + Inner::E42P13 => "42P13", + Inner::E42P14 => "42P14", + Inner::E42P15 => "42P15", + Inner::E42P16 => "42P16", + Inner::E42P17 => "42P17", + Inner::E44000 => "44000", + Inner::E53000 => "53000", + Inner::E53100 => "53100", + Inner::E53200 => "53200", + Inner::E53300 => "53300", + Inner::E53400 => "53400", + Inner::E54000 => "54000", + Inner::E54001 => "54001", + Inner::E54011 => "54011", + Inner::E54023 => "54023", + Inner::E55000 => "55000", + Inner::E55006 => "55006", + Inner::E55P02 => "55P02", + Inner::E55P03 => "55P03", + Inner::E55P04 => "55P04", + Inner::E57000 => "57000", + Inner::E57014 => "57014", + Inner::E57P01 => "57P01", + Inner::E57P02 => "57P02", + Inner::E57P03 => "57P03", + Inner::E57P04 => "57P04", + Inner::E58000 => "58000", + Inner::E58030 => "58030", + Inner::E58P01 => "58P01", + Inner::E58P02 => "58P02", + Inner::E72000 => "72000", + Inner::EF0000 => "F0000", + Inner::EF0001 => "F0001", + Inner::EHV000 => "HV000", + Inner::EHV005 => "HV005", + Inner::EHV002 => "HV002", + Inner::EHV010 => "HV010", + Inner::EHV021 => "HV021", + Inner::EHV024 => "HV024", + Inner::EHV007 => "HV007", + Inner::EHV008 => "HV008", + Inner::EHV004 => "HV004", + Inner::EHV006 => "HV006", + Inner::EHV091 => "HV091", + Inner::EHV00B => "HV00B", + Inner::EHV00C => "HV00C", + Inner::EHV00D => "HV00D", + Inner::EHV090 => "HV090", + Inner::EHV00A => "HV00A", + Inner::EHV009 => "HV009", + Inner::EHV014 => "HV014", + Inner::EHV001 => "HV001", + Inner::EHV00P => "HV00P", + Inner::EHV00J => "HV00J", + Inner::EHV00K => "HV00K", + Inner::EHV00Q => "HV00Q", + Inner::EHV00R => "HV00R", + Inner::EHV00L => "HV00L", + Inner::EHV00M => "HV00M", + Inner::EHV00N => "HV00N", + Inner::EP0000 => "P0000", + Inner::EP0001 => "P0001", + Inner::EP0002 => "P0002", + Inner::EP0003 => "P0003", + Inner::EP0004 => "P0004", + Inner::EXX000 => "XX000", + Inner::EXX001 => "XX001", + Inner::EXX002 => "XX002", + Inner::Other(code) => code, + } } /// 00000 - pub const SUCCESSFUL_COMPLETION: SqlState = SqlState(Cow::Borrowed("00000")); + pub const SUCCESSFUL_COMPLETION: SqlState = SqlState(Inner::E00000); /// 01000 - pub const WARNING: SqlState = SqlState(Cow::Borrowed("01000")); + pub const WARNING: SqlState = SqlState(Inner::E01000); /// 0100C - pub const WARNING_DYNAMIC_RESULT_SETS_RETURNED: SqlState = SqlState(Cow::Borrowed("0100C")); + pub const WARNING_DYNAMIC_RESULT_SETS_RETURNED: SqlState = SqlState(Inner::E0100C); /// 01008 - pub const WARNING_IMPLICIT_ZERO_BIT_PADDING: SqlState = SqlState(Cow::Borrowed("01008")); + pub const WARNING_IMPLICIT_ZERO_BIT_PADDING: SqlState = SqlState(Inner::E01008); /// 01003 - pub const WARNING_NULL_VALUE_ELIMINATED_IN_SET_FUNCTION: SqlState = - SqlState(Cow::Borrowed("01003")); + pub const WARNING_NULL_VALUE_ELIMINATED_IN_SET_FUNCTION: SqlState = SqlState(Inner::E01003); /// 01007 - pub const WARNING_PRIVILEGE_NOT_GRANTED: SqlState = SqlState(Cow::Borrowed("01007")); + pub const WARNING_PRIVILEGE_NOT_GRANTED: SqlState = SqlState(Inner::E01007); /// 01006 - pub const WARNING_PRIVILEGE_NOT_REVOKED: SqlState = SqlState(Cow::Borrowed("01006")); + pub const WARNING_PRIVILEGE_NOT_REVOKED: SqlState = SqlState(Inner::E01006); /// 01004 - pub const WARNING_STRING_DATA_RIGHT_TRUNCATION: SqlState = SqlState(Cow::Borrowed("01004")); + pub const WARNING_STRING_DATA_RIGHT_TRUNCATION: SqlState = SqlState(Inner::E01004); /// 01P01 - pub const WARNING_DEPRECATED_FEATURE: SqlState = SqlState(Cow::Borrowed("01P01")); + pub const WARNING_DEPRECATED_FEATURE: SqlState = SqlState(Inner::E01P01); /// 02000 - pub const NO_DATA: SqlState = SqlState(Cow::Borrowed("02000")); + pub const NO_DATA: SqlState = SqlState(Inner::E02000); /// 02001 - pub const NO_ADDITIONAL_DYNAMIC_RESULT_SETS_RETURNED: SqlState = - SqlState(Cow::Borrowed("02001")); + pub const NO_ADDITIONAL_DYNAMIC_RESULT_SETS_RETURNED: SqlState = SqlState(Inner::E02001); /// 03000 - pub const SQL_STATEMENT_NOT_YET_COMPLETE: SqlState = SqlState(Cow::Borrowed("03000")); + pub const SQL_STATEMENT_NOT_YET_COMPLETE: SqlState = SqlState(Inner::E03000); /// 08000 - pub const CONNECTION_EXCEPTION: SqlState = SqlState(Cow::Borrowed("08000")); + pub const CONNECTION_EXCEPTION: SqlState = SqlState(Inner::E08000); /// 08003 - pub const CONNECTION_DOES_NOT_EXIST: SqlState = SqlState(Cow::Borrowed("08003")); + pub const CONNECTION_DOES_NOT_EXIST: SqlState = SqlState(Inner::E08003); /// 08006 - pub const CONNECTION_FAILURE: SqlState = SqlState(Cow::Borrowed("08006")); + pub const CONNECTION_FAILURE: SqlState = SqlState(Inner::E08006); /// 08001 - pub const SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION: SqlState = - SqlState(Cow::Borrowed("08001")); + pub const SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION: SqlState = SqlState(Inner::E08001); /// 08004 - pub const SQLSERVER_REJECTED_ESTABLISHMENT_OF_SQLCONNECTION: SqlState = - SqlState(Cow::Borrowed("08004")); + pub const SQLSERVER_REJECTED_ESTABLISHMENT_OF_SQLCONNECTION: SqlState = SqlState(Inner::E08004); /// 08007 - pub const TRANSACTION_RESOLUTION_UNKNOWN: SqlState = SqlState(Cow::Borrowed("08007")); + pub const TRANSACTION_RESOLUTION_UNKNOWN: SqlState = SqlState(Inner::E08007); /// 08P01 - pub const PROTOCOL_VIOLATION: SqlState = SqlState(Cow::Borrowed("08P01")); + pub const PROTOCOL_VIOLATION: SqlState = SqlState(Inner::E08P01); /// 09000 - pub const TRIGGERED_ACTION_EXCEPTION: SqlState = SqlState(Cow::Borrowed("09000")); + pub const TRIGGERED_ACTION_EXCEPTION: SqlState = SqlState(Inner::E09000); /// 0A000 - pub const FEATURE_NOT_SUPPORTED: SqlState = SqlState(Cow::Borrowed("0A000")); + pub const FEATURE_NOT_SUPPORTED: SqlState = SqlState(Inner::E0A000); /// 0B000 - pub const INVALID_TRANSACTION_INITIATION: SqlState = SqlState(Cow::Borrowed("0B000")); + pub const INVALID_TRANSACTION_INITIATION: SqlState = SqlState(Inner::E0B000); /// 0F000 - pub const LOCATOR_EXCEPTION: SqlState = SqlState(Cow::Borrowed("0F000")); + pub const LOCATOR_EXCEPTION: SqlState = SqlState(Inner::E0F000); /// 0F001 - pub const L_E_INVALID_SPECIFICATION: SqlState = SqlState(Cow::Borrowed("0F001")); + pub const L_E_INVALID_SPECIFICATION: SqlState = SqlState(Inner::E0F001); /// 0L000 - pub const INVALID_GRANTOR: SqlState = SqlState(Cow::Borrowed("0L000")); + pub const INVALID_GRANTOR: SqlState = SqlState(Inner::E0L000); /// 0LP01 - pub const INVALID_GRANT_OPERATION: SqlState = SqlState(Cow::Borrowed("0LP01")); + pub const INVALID_GRANT_OPERATION: SqlState = SqlState(Inner::E0LP01); /// 0P000 - pub const INVALID_ROLE_SPECIFICATION: SqlState = SqlState(Cow::Borrowed("0P000")); + pub const INVALID_ROLE_SPECIFICATION: SqlState = SqlState(Inner::E0P000); /// 0Z000 - pub const DIAGNOSTICS_EXCEPTION: SqlState = SqlState(Cow::Borrowed("0Z000")); + pub const DIAGNOSTICS_EXCEPTION: SqlState = SqlState(Inner::E0Z000); /// 0Z002 pub const STACKED_DIAGNOSTICS_ACCESSED_WITHOUT_ACTIVE_HANDLER: SqlState = - SqlState(Cow::Borrowed("0Z002")); + SqlState(Inner::E0Z002); /// 20000 - pub const CASE_NOT_FOUND: SqlState = SqlState(Cow::Borrowed("20000")); + pub const CASE_NOT_FOUND: SqlState = SqlState(Inner::E20000); /// 21000 - pub const CARDINALITY_VIOLATION: SqlState = SqlState(Cow::Borrowed("21000")); + pub const CARDINALITY_VIOLATION: SqlState = SqlState(Inner::E21000); /// 22000 - pub const DATA_EXCEPTION: SqlState = SqlState(Cow::Borrowed("22000")); + pub const DATA_EXCEPTION: SqlState = SqlState(Inner::E22000); /// 2202E - pub const ARRAY_ELEMENT_ERROR: SqlState = SqlState(Cow::Borrowed("2202E")); + pub const ARRAY_ELEMENT_ERROR: SqlState = SqlState(Inner::E2202E); /// 2202E - pub const ARRAY_SUBSCRIPT_ERROR: SqlState = SqlState(Cow::Borrowed("2202E")); + pub const ARRAY_SUBSCRIPT_ERROR: SqlState = SqlState(Inner::E2202E); /// 22021 - pub const CHARACTER_NOT_IN_REPERTOIRE: SqlState = SqlState(Cow::Borrowed("22021")); + pub const CHARACTER_NOT_IN_REPERTOIRE: SqlState = SqlState(Inner::E22021); /// 22008 - pub const DATETIME_FIELD_OVERFLOW: SqlState = SqlState(Cow::Borrowed("22008")); + pub const DATETIME_FIELD_OVERFLOW: SqlState = SqlState(Inner::E22008); /// 22008 - pub const DATETIME_VALUE_OUT_OF_RANGE: SqlState = SqlState(Cow::Borrowed("22008")); + pub const DATETIME_VALUE_OUT_OF_RANGE: SqlState = SqlState(Inner::E22008); /// 22012 - pub const DIVISION_BY_ZERO: SqlState = SqlState(Cow::Borrowed("22012")); + pub const DIVISION_BY_ZERO: SqlState = SqlState(Inner::E22012); /// 22005 - pub const ERROR_IN_ASSIGNMENT: SqlState = SqlState(Cow::Borrowed("22005")); + pub const ERROR_IN_ASSIGNMENT: SqlState = SqlState(Inner::E22005); /// 2200B - pub const ESCAPE_CHARACTER_CONFLICT: SqlState = SqlState(Cow::Borrowed("2200B")); + pub const ESCAPE_CHARACTER_CONFLICT: SqlState = SqlState(Inner::E2200B); /// 22022 - pub const INDICATOR_OVERFLOW: SqlState = SqlState(Cow::Borrowed("22022")); + pub const INDICATOR_OVERFLOW: SqlState = SqlState(Inner::E22022); /// 22015 - pub const INTERVAL_FIELD_OVERFLOW: SqlState = SqlState(Cow::Borrowed("22015")); + pub const INTERVAL_FIELD_OVERFLOW: SqlState = SqlState(Inner::E22015); /// 2201E - pub const INVALID_ARGUMENT_FOR_LOG: SqlState = SqlState(Cow::Borrowed("2201E")); + pub const INVALID_ARGUMENT_FOR_LOG: SqlState = SqlState(Inner::E2201E); /// 22014 - pub const INVALID_ARGUMENT_FOR_NTILE: SqlState = SqlState(Cow::Borrowed("22014")); + pub const INVALID_ARGUMENT_FOR_NTILE: SqlState = SqlState(Inner::E22014); /// 22016 - pub const INVALID_ARGUMENT_FOR_NTH_VALUE: SqlState = SqlState(Cow::Borrowed("22016")); + pub const INVALID_ARGUMENT_FOR_NTH_VALUE: SqlState = SqlState(Inner::E22016); /// 2201F - pub const INVALID_ARGUMENT_FOR_POWER_FUNCTION: SqlState = SqlState(Cow::Borrowed("2201F")); + pub const INVALID_ARGUMENT_FOR_POWER_FUNCTION: SqlState = SqlState(Inner::E2201F); /// 2201G - pub const INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION: SqlState = - SqlState(Cow::Borrowed("2201G")); + pub const INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION: SqlState = SqlState(Inner::E2201G); /// 22018 - pub const INVALID_CHARACTER_VALUE_FOR_CAST: SqlState = SqlState(Cow::Borrowed("22018")); + pub const INVALID_CHARACTER_VALUE_FOR_CAST: SqlState = SqlState(Inner::E22018); /// 22007 - pub const INVALID_DATETIME_FORMAT: SqlState = SqlState(Cow::Borrowed("22007")); + pub const INVALID_DATETIME_FORMAT: SqlState = SqlState(Inner::E22007); /// 22019 - pub const INVALID_ESCAPE_CHARACTER: SqlState = SqlState(Cow::Borrowed("22019")); + pub const INVALID_ESCAPE_CHARACTER: SqlState = SqlState(Inner::E22019); /// 2200D - pub const INVALID_ESCAPE_OCTET: SqlState = SqlState(Cow::Borrowed("2200D")); + pub const INVALID_ESCAPE_OCTET: SqlState = SqlState(Inner::E2200D); /// 22025 - pub const INVALID_ESCAPE_SEQUENCE: SqlState = SqlState(Cow::Borrowed("22025")); + pub const INVALID_ESCAPE_SEQUENCE: SqlState = SqlState(Inner::E22025); /// 22P06 - pub const NONSTANDARD_USE_OF_ESCAPE_CHARACTER: SqlState = SqlState(Cow::Borrowed("22P06")); + pub const NONSTANDARD_USE_OF_ESCAPE_CHARACTER: SqlState = SqlState(Inner::E22P06); /// 22010 - pub const INVALID_INDICATOR_PARAMETER_VALUE: SqlState = SqlState(Cow::Borrowed("22010")); + pub const INVALID_INDICATOR_PARAMETER_VALUE: SqlState = SqlState(Inner::E22010); /// 22023 - pub const INVALID_PARAMETER_VALUE: SqlState = SqlState(Cow::Borrowed("22023")); + pub const INVALID_PARAMETER_VALUE: SqlState = SqlState(Inner::E22023); /// 22013 - pub const INVALID_PRECEDING_OR_FOLLOWING_SIZE: SqlState = SqlState(Cow::Borrowed("22013")); + pub const INVALID_PRECEDING_OR_FOLLOWING_SIZE: SqlState = SqlState(Inner::E22013); /// 2201B - pub const INVALID_REGULAR_EXPRESSION: SqlState = SqlState(Cow::Borrowed("2201B")); + pub const INVALID_REGULAR_EXPRESSION: SqlState = SqlState(Inner::E2201B); /// 2201W - pub const INVALID_ROW_COUNT_IN_LIMIT_CLAUSE: SqlState = SqlState(Cow::Borrowed("2201W")); + pub const INVALID_ROW_COUNT_IN_LIMIT_CLAUSE: SqlState = SqlState(Inner::E2201W); /// 2201X - pub const INVALID_ROW_COUNT_IN_RESULT_OFFSET_CLAUSE: SqlState = - SqlState(Cow::Borrowed("2201X")); + pub const INVALID_ROW_COUNT_IN_RESULT_OFFSET_CLAUSE: SqlState = SqlState(Inner::E2201X); /// 2202H - pub const INVALID_TABLESAMPLE_ARGUMENT: SqlState = SqlState(Cow::Borrowed("2202H")); + pub const INVALID_TABLESAMPLE_ARGUMENT: SqlState = SqlState(Inner::E2202H); /// 2202G - pub const INVALID_TABLESAMPLE_REPEAT: SqlState = SqlState(Cow::Borrowed("2202G")); + pub const INVALID_TABLESAMPLE_REPEAT: SqlState = SqlState(Inner::E2202G); /// 22009 - pub const INVALID_TIME_ZONE_DISPLACEMENT_VALUE: SqlState = SqlState(Cow::Borrowed("22009")); + pub const INVALID_TIME_ZONE_DISPLACEMENT_VALUE: SqlState = SqlState(Inner::E22009); /// 2200C - pub const INVALID_USE_OF_ESCAPE_CHARACTER: SqlState = SqlState(Cow::Borrowed("2200C")); + pub const INVALID_USE_OF_ESCAPE_CHARACTER: SqlState = SqlState(Inner::E2200C); /// 2200G - pub const MOST_SPECIFIC_TYPE_MISMATCH: SqlState = SqlState(Cow::Borrowed("2200G")); + pub const MOST_SPECIFIC_TYPE_MISMATCH: SqlState = SqlState(Inner::E2200G); /// 22004 - pub const NULL_VALUE_NOT_ALLOWED: SqlState = SqlState(Cow::Borrowed("22004")); + pub const NULL_VALUE_NOT_ALLOWED: SqlState = SqlState(Inner::E22004); /// 22002 - pub const NULL_VALUE_NO_INDICATOR_PARAMETER: SqlState = SqlState(Cow::Borrowed("22002")); + pub const NULL_VALUE_NO_INDICATOR_PARAMETER: SqlState = SqlState(Inner::E22002); /// 22003 - pub const NUMERIC_VALUE_OUT_OF_RANGE: SqlState = SqlState(Cow::Borrowed("22003")); + pub const NUMERIC_VALUE_OUT_OF_RANGE: SqlState = SqlState(Inner::E22003); /// 2200H - pub const SEQUENCE_GENERATOR_LIMIT_EXCEEDED: SqlState = SqlState(Cow::Borrowed("2200H")); + pub const SEQUENCE_GENERATOR_LIMIT_EXCEEDED: SqlState = SqlState(Inner::E2200H); /// 22026 - pub const STRING_DATA_LENGTH_MISMATCH: SqlState = SqlState(Cow::Borrowed("22026")); + pub const STRING_DATA_LENGTH_MISMATCH: SqlState = SqlState(Inner::E22026); /// 22001 - pub const STRING_DATA_RIGHT_TRUNCATION: SqlState = SqlState(Cow::Borrowed("22001")); + pub const STRING_DATA_RIGHT_TRUNCATION: SqlState = SqlState(Inner::E22001); /// 22011 - pub const SUBSTRING_ERROR: SqlState = SqlState(Cow::Borrowed("22011")); + pub const SUBSTRING_ERROR: SqlState = SqlState(Inner::E22011); /// 22027 - pub const TRIM_ERROR: SqlState = SqlState(Cow::Borrowed("22027")); + pub const TRIM_ERROR: SqlState = SqlState(Inner::E22027); /// 22024 - pub const UNTERMINATED_C_STRING: SqlState = SqlState(Cow::Borrowed("22024")); + pub const UNTERMINATED_C_STRING: SqlState = SqlState(Inner::E22024); /// 2200F - pub const ZERO_LENGTH_CHARACTER_STRING: SqlState = SqlState(Cow::Borrowed("2200F")); + pub const ZERO_LENGTH_CHARACTER_STRING: SqlState = SqlState(Inner::E2200F); /// 22P01 - pub const FLOATING_POINT_EXCEPTION: SqlState = SqlState(Cow::Borrowed("22P01")); + pub const FLOATING_POINT_EXCEPTION: SqlState = SqlState(Inner::E22P01); /// 22P02 - pub const INVALID_TEXT_REPRESENTATION: SqlState = SqlState(Cow::Borrowed("22P02")); + pub const INVALID_TEXT_REPRESENTATION: SqlState = SqlState(Inner::E22P02); /// 22P03 - pub const INVALID_BINARY_REPRESENTATION: SqlState = SqlState(Cow::Borrowed("22P03")); + pub const INVALID_BINARY_REPRESENTATION: SqlState = SqlState(Inner::E22P03); /// 22P04 - pub const BAD_COPY_FILE_FORMAT: SqlState = SqlState(Cow::Borrowed("22P04")); + pub const BAD_COPY_FILE_FORMAT: SqlState = SqlState(Inner::E22P04); /// 22P05 - pub const UNTRANSLATABLE_CHARACTER: SqlState = SqlState(Cow::Borrowed("22P05")); + pub const UNTRANSLATABLE_CHARACTER: SqlState = SqlState(Inner::E22P05); /// 2200L - pub const NOT_AN_XML_DOCUMENT: SqlState = SqlState(Cow::Borrowed("2200L")); + pub const NOT_AN_XML_DOCUMENT: SqlState = SqlState(Inner::E2200L); /// 2200M - pub const INVALID_XML_DOCUMENT: SqlState = SqlState(Cow::Borrowed("2200M")); + pub const INVALID_XML_DOCUMENT: SqlState = SqlState(Inner::E2200M); /// 2200N - pub const INVALID_XML_CONTENT: SqlState = SqlState(Cow::Borrowed("2200N")); + pub const INVALID_XML_CONTENT: SqlState = SqlState(Inner::E2200N); /// 2200S - pub const INVALID_XML_COMMENT: SqlState = SqlState(Cow::Borrowed("2200S")); + pub const INVALID_XML_COMMENT: SqlState = SqlState(Inner::E2200S); /// 2200T - pub const INVALID_XML_PROCESSING_INSTRUCTION: SqlState = SqlState(Cow::Borrowed("2200T")); + pub const INVALID_XML_PROCESSING_INSTRUCTION: SqlState = SqlState(Inner::E2200T); /// 22030 - pub const DUPLICATE_JSON_OBJECT_KEY_VALUE: SqlState = SqlState(Cow::Borrowed("22030")); + pub const DUPLICATE_JSON_OBJECT_KEY_VALUE: SqlState = SqlState(Inner::E22030); /// 22031 - pub const INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION: SqlState = - SqlState(Cow::Borrowed("22031")); + pub const INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION: SqlState = SqlState(Inner::E22031); /// 22032 - pub const INVALID_JSON_TEXT: SqlState = SqlState(Cow::Borrowed("22032")); + pub const INVALID_JSON_TEXT: SqlState = SqlState(Inner::E22032); /// 22033 - pub const INVALID_SQL_JSON_SUBSCRIPT: SqlState = SqlState(Cow::Borrowed("22033")); + pub const INVALID_SQL_JSON_SUBSCRIPT: SqlState = SqlState(Inner::E22033); /// 22034 - pub const MORE_THAN_ONE_SQL_JSON_ITEM: SqlState = SqlState(Cow::Borrowed("22034")); + pub const MORE_THAN_ONE_SQL_JSON_ITEM: SqlState = SqlState(Inner::E22034); /// 22035 - pub const NO_SQL_JSON_ITEM: SqlState = SqlState(Cow::Borrowed("22035")); + pub const NO_SQL_JSON_ITEM: SqlState = SqlState(Inner::E22035); /// 22036 - pub const NON_NUMERIC_SQL_JSON_ITEM: SqlState = SqlState(Cow::Borrowed("22036")); + pub const NON_NUMERIC_SQL_JSON_ITEM: SqlState = SqlState(Inner::E22036); /// 22037 - pub const NON_UNIQUE_KEYS_IN_A_JSON_OBJECT: SqlState = SqlState(Cow::Borrowed("22037")); + pub const NON_UNIQUE_KEYS_IN_A_JSON_OBJECT: SqlState = SqlState(Inner::E22037); /// 22038 - pub const SINGLETON_SQL_JSON_ITEM_REQUIRED: SqlState = SqlState(Cow::Borrowed("22038")); + pub const SINGLETON_SQL_JSON_ITEM_REQUIRED: SqlState = SqlState(Inner::E22038); /// 22039 - pub const SQL_JSON_ARRAY_NOT_FOUND: SqlState = SqlState(Cow::Borrowed("22039")); + pub const SQL_JSON_ARRAY_NOT_FOUND: SqlState = SqlState(Inner::E22039); /// 2203A - pub const SQL_JSON_MEMBER_NOT_FOUND: SqlState = SqlState(Cow::Borrowed("2203A")); + pub const SQL_JSON_MEMBER_NOT_FOUND: SqlState = SqlState(Inner::E2203A); /// 2203B - pub const SQL_JSON_NUMBER_NOT_FOUND: SqlState = SqlState(Cow::Borrowed("2203B")); + pub const SQL_JSON_NUMBER_NOT_FOUND: SqlState = SqlState(Inner::E2203B); /// 2203C - pub const SQL_JSON_OBJECT_NOT_FOUND: SqlState = SqlState(Cow::Borrowed("2203C")); + pub const SQL_JSON_OBJECT_NOT_FOUND: SqlState = SqlState(Inner::E2203C); /// 2203D - pub const TOO_MANY_JSON_ARRAY_ELEMENTS: SqlState = SqlState(Cow::Borrowed("2203D")); + pub const TOO_MANY_JSON_ARRAY_ELEMENTS: SqlState = SqlState(Inner::E2203D); /// 2203E - pub const TOO_MANY_JSON_OBJECT_MEMBERS: SqlState = SqlState(Cow::Borrowed("2203E")); + pub const TOO_MANY_JSON_OBJECT_MEMBERS: SqlState = SqlState(Inner::E2203E); /// 2203F - pub const SQL_JSON_SCALAR_REQUIRED: SqlState = SqlState(Cow::Borrowed("2203F")); + pub const SQL_JSON_SCALAR_REQUIRED: SqlState = SqlState(Inner::E2203F); /// 23000 - pub const INTEGRITY_CONSTRAINT_VIOLATION: SqlState = SqlState(Cow::Borrowed("23000")); + pub const INTEGRITY_CONSTRAINT_VIOLATION: SqlState = SqlState(Inner::E23000); /// 23001 - pub const RESTRICT_VIOLATION: SqlState = SqlState(Cow::Borrowed("23001")); + pub const RESTRICT_VIOLATION: SqlState = SqlState(Inner::E23001); /// 23502 - pub const NOT_NULL_VIOLATION: SqlState = SqlState(Cow::Borrowed("23502")); + pub const NOT_NULL_VIOLATION: SqlState = SqlState(Inner::E23502); /// 23503 - pub const FOREIGN_KEY_VIOLATION: SqlState = SqlState(Cow::Borrowed("23503")); + pub const FOREIGN_KEY_VIOLATION: SqlState = SqlState(Inner::E23503); /// 23505 - pub const UNIQUE_VIOLATION: SqlState = SqlState(Cow::Borrowed("23505")); + pub const UNIQUE_VIOLATION: SqlState = SqlState(Inner::E23505); /// 23514 - pub const CHECK_VIOLATION: SqlState = SqlState(Cow::Borrowed("23514")); + pub const CHECK_VIOLATION: SqlState = SqlState(Inner::E23514); /// 23P01 - pub const EXCLUSION_VIOLATION: SqlState = SqlState(Cow::Borrowed("23P01")); + pub const EXCLUSION_VIOLATION: SqlState = SqlState(Inner::E23P01); /// 24000 - pub const INVALID_CURSOR_STATE: SqlState = SqlState(Cow::Borrowed("24000")); + pub const INVALID_CURSOR_STATE: SqlState = SqlState(Inner::E24000); /// 25000 - pub const INVALID_TRANSACTION_STATE: SqlState = SqlState(Cow::Borrowed("25000")); + pub const INVALID_TRANSACTION_STATE: SqlState = SqlState(Inner::E25000); /// 25001 - pub const ACTIVE_SQL_TRANSACTION: SqlState = SqlState(Cow::Borrowed("25001")); + pub const ACTIVE_SQL_TRANSACTION: SqlState = SqlState(Inner::E25001); /// 25002 - pub const BRANCH_TRANSACTION_ALREADY_ACTIVE: SqlState = SqlState(Cow::Borrowed("25002")); + pub const BRANCH_TRANSACTION_ALREADY_ACTIVE: SqlState = SqlState(Inner::E25002); /// 25008 - pub const HELD_CURSOR_REQUIRES_SAME_ISOLATION_LEVEL: SqlState = - SqlState(Cow::Borrowed("25008")); + pub const HELD_CURSOR_REQUIRES_SAME_ISOLATION_LEVEL: SqlState = SqlState(Inner::E25008); /// 25003 - pub const INAPPROPRIATE_ACCESS_MODE_FOR_BRANCH_TRANSACTION: SqlState = - SqlState(Cow::Borrowed("25003")); + pub const INAPPROPRIATE_ACCESS_MODE_FOR_BRANCH_TRANSACTION: SqlState = SqlState(Inner::E25003); /// 25004 pub const INAPPROPRIATE_ISOLATION_LEVEL_FOR_BRANCH_TRANSACTION: SqlState = - SqlState(Cow::Borrowed("25004")); + SqlState(Inner::E25004); /// 25005 - pub const NO_ACTIVE_SQL_TRANSACTION_FOR_BRANCH_TRANSACTION: SqlState = - SqlState(Cow::Borrowed("25005")); + pub const NO_ACTIVE_SQL_TRANSACTION_FOR_BRANCH_TRANSACTION: SqlState = SqlState(Inner::E25005); /// 25006 - pub const READ_ONLY_SQL_TRANSACTION: SqlState = SqlState(Cow::Borrowed("25006")); + pub const READ_ONLY_SQL_TRANSACTION: SqlState = SqlState(Inner::E25006); /// 25007 - pub const SCHEMA_AND_DATA_STATEMENT_MIXING_NOT_SUPPORTED: SqlState = - SqlState(Cow::Borrowed("25007")); + pub const SCHEMA_AND_DATA_STATEMENT_MIXING_NOT_SUPPORTED: SqlState = SqlState(Inner::E25007); /// 25P01 - pub const NO_ACTIVE_SQL_TRANSACTION: SqlState = SqlState(Cow::Borrowed("25P01")); + pub const NO_ACTIVE_SQL_TRANSACTION: SqlState = SqlState(Inner::E25P01); /// 25P02 - pub const IN_FAILED_SQL_TRANSACTION: SqlState = SqlState(Cow::Borrowed("25P02")); + pub const IN_FAILED_SQL_TRANSACTION: SqlState = SqlState(Inner::E25P02); /// 25P03 - pub const IDLE_IN_TRANSACTION_SESSION_TIMEOUT: SqlState = SqlState(Cow::Borrowed("25P03")); + pub const IDLE_IN_TRANSACTION_SESSION_TIMEOUT: SqlState = SqlState(Inner::E25P03); /// 26000 - pub const INVALID_SQL_STATEMENT_NAME: SqlState = SqlState(Cow::Borrowed("26000")); + pub const INVALID_SQL_STATEMENT_NAME: SqlState = SqlState(Inner::E26000); /// 26000 - pub const UNDEFINED_PSTATEMENT: SqlState = SqlState(Cow::Borrowed("26000")); + pub const UNDEFINED_PSTATEMENT: SqlState = SqlState(Inner::E26000); /// 27000 - pub const TRIGGERED_DATA_CHANGE_VIOLATION: SqlState = SqlState(Cow::Borrowed("27000")); + pub const TRIGGERED_DATA_CHANGE_VIOLATION: SqlState = SqlState(Inner::E27000); /// 28000 - pub const INVALID_AUTHORIZATION_SPECIFICATION: SqlState = SqlState(Cow::Borrowed("28000")); + pub const INVALID_AUTHORIZATION_SPECIFICATION: SqlState = SqlState(Inner::E28000); /// 28P01 - pub const INVALID_PASSWORD: SqlState = SqlState(Cow::Borrowed("28P01")); + pub const INVALID_PASSWORD: SqlState = SqlState(Inner::E28P01); /// 2B000 - pub const DEPENDENT_PRIVILEGE_DESCRIPTORS_STILL_EXIST: SqlState = - SqlState(Cow::Borrowed("2B000")); + pub const DEPENDENT_PRIVILEGE_DESCRIPTORS_STILL_EXIST: SqlState = SqlState(Inner::E2B000); /// 2BP01 - pub const DEPENDENT_OBJECTS_STILL_EXIST: SqlState = SqlState(Cow::Borrowed("2BP01")); + pub const DEPENDENT_OBJECTS_STILL_EXIST: SqlState = SqlState(Inner::E2BP01); /// 2D000 - pub const INVALID_TRANSACTION_TERMINATION: SqlState = SqlState(Cow::Borrowed("2D000")); + pub const INVALID_TRANSACTION_TERMINATION: SqlState = SqlState(Inner::E2D000); /// 2F000 - pub const SQL_ROUTINE_EXCEPTION: SqlState = SqlState(Cow::Borrowed("2F000")); + pub const SQL_ROUTINE_EXCEPTION: SqlState = SqlState(Inner::E2F000); /// 2F005 - pub const S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT: SqlState = - SqlState(Cow::Borrowed("2F005")); + pub const S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT: SqlState = SqlState(Inner::E2F005); /// 2F002 - pub const S_R_E_MODIFYING_SQL_DATA_NOT_PERMITTED: SqlState = SqlState(Cow::Borrowed("2F002")); + pub const S_R_E_MODIFYING_SQL_DATA_NOT_PERMITTED: SqlState = SqlState(Inner::E2F002); /// 2F003 - pub const S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED: SqlState = SqlState(Cow::Borrowed("2F003")); + pub const S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED: SqlState = SqlState(Inner::E2F003); /// 2F004 - pub const S_R_E_READING_SQL_DATA_NOT_PERMITTED: SqlState = SqlState(Cow::Borrowed("2F004")); + pub const S_R_E_READING_SQL_DATA_NOT_PERMITTED: SqlState = SqlState(Inner::E2F004); /// 34000 - pub const INVALID_CURSOR_NAME: SqlState = SqlState(Cow::Borrowed("34000")); + pub const INVALID_CURSOR_NAME: SqlState = SqlState(Inner::E34000); /// 34000 - pub const UNDEFINED_CURSOR: SqlState = SqlState(Cow::Borrowed("34000")); + pub const UNDEFINED_CURSOR: SqlState = SqlState(Inner::E34000); /// 38000 - pub const EXTERNAL_ROUTINE_EXCEPTION: SqlState = SqlState(Cow::Borrowed("38000")); + pub const EXTERNAL_ROUTINE_EXCEPTION: SqlState = SqlState(Inner::E38000); /// 38001 - pub const E_R_E_CONTAINING_SQL_NOT_PERMITTED: SqlState = SqlState(Cow::Borrowed("38001")); + pub const E_R_E_CONTAINING_SQL_NOT_PERMITTED: SqlState = SqlState(Inner::E38001); /// 38002 - pub const E_R_E_MODIFYING_SQL_DATA_NOT_PERMITTED: SqlState = SqlState(Cow::Borrowed("38002")); + pub const E_R_E_MODIFYING_SQL_DATA_NOT_PERMITTED: SqlState = SqlState(Inner::E38002); /// 38003 - pub const E_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED: SqlState = SqlState(Cow::Borrowed("38003")); + pub const E_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED: SqlState = SqlState(Inner::E38003); /// 38004 - pub const E_R_E_READING_SQL_DATA_NOT_PERMITTED: SqlState = SqlState(Cow::Borrowed("38004")); + pub const E_R_E_READING_SQL_DATA_NOT_PERMITTED: SqlState = SqlState(Inner::E38004); /// 39000 - pub const EXTERNAL_ROUTINE_INVOCATION_EXCEPTION: SqlState = SqlState(Cow::Borrowed("39000")); + pub const EXTERNAL_ROUTINE_INVOCATION_EXCEPTION: SqlState = SqlState(Inner::E39000); /// 39001 - pub const E_R_I_E_INVALID_SQLSTATE_RETURNED: SqlState = SqlState(Cow::Borrowed("39001")); + pub const E_R_I_E_INVALID_SQLSTATE_RETURNED: SqlState = SqlState(Inner::E39001); /// 39004 - pub const E_R_I_E_NULL_VALUE_NOT_ALLOWED: SqlState = SqlState(Cow::Borrowed("39004")); + pub const E_R_I_E_NULL_VALUE_NOT_ALLOWED: SqlState = SqlState(Inner::E39004); /// 39P01 - pub const E_R_I_E_TRIGGER_PROTOCOL_VIOLATED: SqlState = SqlState(Cow::Borrowed("39P01")); + pub const E_R_I_E_TRIGGER_PROTOCOL_VIOLATED: SqlState = SqlState(Inner::E39P01); /// 39P02 - pub const E_R_I_E_SRF_PROTOCOL_VIOLATED: SqlState = SqlState(Cow::Borrowed("39P02")); + pub const E_R_I_E_SRF_PROTOCOL_VIOLATED: SqlState = SqlState(Inner::E39P02); /// 39P03 - pub const E_R_I_E_EVENT_TRIGGER_PROTOCOL_VIOLATED: SqlState = SqlState(Cow::Borrowed("39P03")); + pub const E_R_I_E_EVENT_TRIGGER_PROTOCOL_VIOLATED: SqlState = SqlState(Inner::E39P03); /// 3B000 - pub const SAVEPOINT_EXCEPTION: SqlState = SqlState(Cow::Borrowed("3B000")); + pub const SAVEPOINT_EXCEPTION: SqlState = SqlState(Inner::E3B000); /// 3B001 - pub const S_E_INVALID_SPECIFICATION: SqlState = SqlState(Cow::Borrowed("3B001")); + pub const S_E_INVALID_SPECIFICATION: SqlState = SqlState(Inner::E3B001); /// 3D000 - pub const INVALID_CATALOG_NAME: SqlState = SqlState(Cow::Borrowed("3D000")); + pub const INVALID_CATALOG_NAME: SqlState = SqlState(Inner::E3D000); /// 3D000 - pub const UNDEFINED_DATABASE: SqlState = SqlState(Cow::Borrowed("3D000")); + pub const UNDEFINED_DATABASE: SqlState = SqlState(Inner::E3D000); /// 3F000 - pub const INVALID_SCHEMA_NAME: SqlState = SqlState(Cow::Borrowed("3F000")); + pub const INVALID_SCHEMA_NAME: SqlState = SqlState(Inner::E3F000); /// 3F000 - pub const UNDEFINED_SCHEMA: SqlState = SqlState(Cow::Borrowed("3F000")); + pub const UNDEFINED_SCHEMA: SqlState = SqlState(Inner::E3F000); /// 40000 - pub const TRANSACTION_ROLLBACK: SqlState = SqlState(Cow::Borrowed("40000")); + pub const TRANSACTION_ROLLBACK: SqlState = SqlState(Inner::E40000); /// 40002 - pub const T_R_INTEGRITY_CONSTRAINT_VIOLATION: SqlState = SqlState(Cow::Borrowed("40002")); + pub const T_R_INTEGRITY_CONSTRAINT_VIOLATION: SqlState = SqlState(Inner::E40002); /// 40001 - pub const T_R_SERIALIZATION_FAILURE: SqlState = SqlState(Cow::Borrowed("40001")); + pub const T_R_SERIALIZATION_FAILURE: SqlState = SqlState(Inner::E40001); /// 40003 - pub const T_R_STATEMENT_COMPLETION_UNKNOWN: SqlState = SqlState(Cow::Borrowed("40003")); + pub const T_R_STATEMENT_COMPLETION_UNKNOWN: SqlState = SqlState(Inner::E40003); /// 40P01 - pub const T_R_DEADLOCK_DETECTED: SqlState = SqlState(Cow::Borrowed("40P01")); + pub const T_R_DEADLOCK_DETECTED: SqlState = SqlState(Inner::E40P01); /// 42000 - pub const SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION: SqlState = SqlState(Cow::Borrowed("42000")); + pub const SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION: SqlState = SqlState(Inner::E42000); /// 42601 - pub const SYNTAX_ERROR: SqlState = SqlState(Cow::Borrowed("42601")); + pub const SYNTAX_ERROR: SqlState = SqlState(Inner::E42601); /// 42501 - pub const INSUFFICIENT_PRIVILEGE: SqlState = SqlState(Cow::Borrowed("42501")); + pub const INSUFFICIENT_PRIVILEGE: SqlState = SqlState(Inner::E42501); /// 42846 - pub const CANNOT_COERCE: SqlState = SqlState(Cow::Borrowed("42846")); + pub const CANNOT_COERCE: SqlState = SqlState(Inner::E42846); /// 42803 - pub const GROUPING_ERROR: SqlState = SqlState(Cow::Borrowed("42803")); + pub const GROUPING_ERROR: SqlState = SqlState(Inner::E42803); /// 42P20 - pub const WINDOWING_ERROR: SqlState = SqlState(Cow::Borrowed("42P20")); + pub const WINDOWING_ERROR: SqlState = SqlState(Inner::E42P20); /// 42P19 - pub const INVALID_RECURSION: SqlState = SqlState(Cow::Borrowed("42P19")); + pub const INVALID_RECURSION: SqlState = SqlState(Inner::E42P19); /// 42830 - pub const INVALID_FOREIGN_KEY: SqlState = SqlState(Cow::Borrowed("42830")); + pub const INVALID_FOREIGN_KEY: SqlState = SqlState(Inner::E42830); /// 42602 - pub const INVALID_NAME: SqlState = SqlState(Cow::Borrowed("42602")); + pub const INVALID_NAME: SqlState = SqlState(Inner::E42602); /// 42622 - pub const NAME_TOO_LONG: SqlState = SqlState(Cow::Borrowed("42622")); + pub const NAME_TOO_LONG: SqlState = SqlState(Inner::E42622); /// 42939 - pub const RESERVED_NAME: SqlState = SqlState(Cow::Borrowed("42939")); + pub const RESERVED_NAME: SqlState = SqlState(Inner::E42939); /// 42804 - pub const DATATYPE_MISMATCH: SqlState = SqlState(Cow::Borrowed("42804")); + pub const DATATYPE_MISMATCH: SqlState = SqlState(Inner::E42804); /// 42P18 - pub const INDETERMINATE_DATATYPE: SqlState = SqlState(Cow::Borrowed("42P18")); + pub const INDETERMINATE_DATATYPE: SqlState = SqlState(Inner::E42P18); /// 42P21 - pub const COLLATION_MISMATCH: SqlState = SqlState(Cow::Borrowed("42P21")); + pub const COLLATION_MISMATCH: SqlState = SqlState(Inner::E42P21); /// 42P22 - pub const INDETERMINATE_COLLATION: SqlState = SqlState(Cow::Borrowed("42P22")); + pub const INDETERMINATE_COLLATION: SqlState = SqlState(Inner::E42P22); /// 42809 - pub const WRONG_OBJECT_TYPE: SqlState = SqlState(Cow::Borrowed("42809")); + pub const WRONG_OBJECT_TYPE: SqlState = SqlState(Inner::E42809); /// 428C9 - pub const GENERATED_ALWAYS: SqlState = SqlState(Cow::Borrowed("428C9")); + pub const GENERATED_ALWAYS: SqlState = SqlState(Inner::E428C9); /// 42703 - pub const UNDEFINED_COLUMN: SqlState = SqlState(Cow::Borrowed("42703")); + pub const UNDEFINED_COLUMN: SqlState = SqlState(Inner::E42703); /// 42883 - pub const UNDEFINED_FUNCTION: SqlState = SqlState(Cow::Borrowed("42883")); + pub const UNDEFINED_FUNCTION: SqlState = SqlState(Inner::E42883); /// 42P01 - pub const UNDEFINED_TABLE: SqlState = SqlState(Cow::Borrowed("42P01")); + pub const UNDEFINED_TABLE: SqlState = SqlState(Inner::E42P01); /// 42P02 - pub const UNDEFINED_PARAMETER: SqlState = SqlState(Cow::Borrowed("42P02")); + pub const UNDEFINED_PARAMETER: SqlState = SqlState(Inner::E42P02); /// 42704 - pub const UNDEFINED_OBJECT: SqlState = SqlState(Cow::Borrowed("42704")); + pub const UNDEFINED_OBJECT: SqlState = SqlState(Inner::E42704); /// 42701 - pub const DUPLICATE_COLUMN: SqlState = SqlState(Cow::Borrowed("42701")); + pub const DUPLICATE_COLUMN: SqlState = SqlState(Inner::E42701); /// 42P03 - pub const DUPLICATE_CURSOR: SqlState = SqlState(Cow::Borrowed("42P03")); + pub const DUPLICATE_CURSOR: SqlState = SqlState(Inner::E42P03); /// 42P04 - pub const DUPLICATE_DATABASE: SqlState = SqlState(Cow::Borrowed("42P04")); + pub const DUPLICATE_DATABASE: SqlState = SqlState(Inner::E42P04); /// 42723 - pub const DUPLICATE_FUNCTION: SqlState = SqlState(Cow::Borrowed("42723")); + pub const DUPLICATE_FUNCTION: SqlState = SqlState(Inner::E42723); /// 42P05 - pub const DUPLICATE_PSTATEMENT: SqlState = SqlState(Cow::Borrowed("42P05")); + pub const DUPLICATE_PSTATEMENT: SqlState = SqlState(Inner::E42P05); /// 42P06 - pub const DUPLICATE_SCHEMA: SqlState = SqlState(Cow::Borrowed("42P06")); + pub const DUPLICATE_SCHEMA: SqlState = SqlState(Inner::E42P06); /// 42P07 - pub const DUPLICATE_TABLE: SqlState = SqlState(Cow::Borrowed("42P07")); + pub const DUPLICATE_TABLE: SqlState = SqlState(Inner::E42P07); /// 42712 - pub const DUPLICATE_ALIAS: SqlState = SqlState(Cow::Borrowed("42712")); + pub const DUPLICATE_ALIAS: SqlState = SqlState(Inner::E42712); /// 42710 - pub const DUPLICATE_OBJECT: SqlState = SqlState(Cow::Borrowed("42710")); + pub const DUPLICATE_OBJECT: SqlState = SqlState(Inner::E42710); /// 42702 - pub const AMBIGUOUS_COLUMN: SqlState = SqlState(Cow::Borrowed("42702")); + pub const AMBIGUOUS_COLUMN: SqlState = SqlState(Inner::E42702); /// 42725 - pub const AMBIGUOUS_FUNCTION: SqlState = SqlState(Cow::Borrowed("42725")); + pub const AMBIGUOUS_FUNCTION: SqlState = SqlState(Inner::E42725); /// 42P08 - pub const AMBIGUOUS_PARAMETER: SqlState = SqlState(Cow::Borrowed("42P08")); + pub const AMBIGUOUS_PARAMETER: SqlState = SqlState(Inner::E42P08); /// 42P09 - pub const AMBIGUOUS_ALIAS: SqlState = SqlState(Cow::Borrowed("42P09")); + pub const AMBIGUOUS_ALIAS: SqlState = SqlState(Inner::E42P09); /// 42P10 - pub const INVALID_COLUMN_REFERENCE: SqlState = SqlState(Cow::Borrowed("42P10")); + pub const INVALID_COLUMN_REFERENCE: SqlState = SqlState(Inner::E42P10); /// 42611 - pub const INVALID_COLUMN_DEFINITION: SqlState = SqlState(Cow::Borrowed("42611")); + pub const INVALID_COLUMN_DEFINITION: SqlState = SqlState(Inner::E42611); /// 42P11 - pub const INVALID_CURSOR_DEFINITION: SqlState = SqlState(Cow::Borrowed("42P11")); + pub const INVALID_CURSOR_DEFINITION: SqlState = SqlState(Inner::E42P11); /// 42P12 - pub const INVALID_DATABASE_DEFINITION: SqlState = SqlState(Cow::Borrowed("42P12")); + pub const INVALID_DATABASE_DEFINITION: SqlState = SqlState(Inner::E42P12); /// 42P13 - pub const INVALID_FUNCTION_DEFINITION: SqlState = SqlState(Cow::Borrowed("42P13")); + pub const INVALID_FUNCTION_DEFINITION: SqlState = SqlState(Inner::E42P13); /// 42P14 - pub const INVALID_PSTATEMENT_DEFINITION: SqlState = SqlState(Cow::Borrowed("42P14")); + pub const INVALID_PSTATEMENT_DEFINITION: SqlState = SqlState(Inner::E42P14); /// 42P15 - pub const INVALID_SCHEMA_DEFINITION: SqlState = SqlState(Cow::Borrowed("42P15")); + pub const INVALID_SCHEMA_DEFINITION: SqlState = SqlState(Inner::E42P15); /// 42P16 - pub const INVALID_TABLE_DEFINITION: SqlState = SqlState(Cow::Borrowed("42P16")); + pub const INVALID_TABLE_DEFINITION: SqlState = SqlState(Inner::E42P16); /// 42P17 - pub const INVALID_OBJECT_DEFINITION: SqlState = SqlState(Cow::Borrowed("42P17")); + pub const INVALID_OBJECT_DEFINITION: SqlState = SqlState(Inner::E42P17); /// 44000 - pub const WITH_CHECK_OPTION_VIOLATION: SqlState = SqlState(Cow::Borrowed("44000")); + pub const WITH_CHECK_OPTION_VIOLATION: SqlState = SqlState(Inner::E44000); /// 53000 - pub const INSUFFICIENT_RESOURCES: SqlState = SqlState(Cow::Borrowed("53000")); + pub const INSUFFICIENT_RESOURCES: SqlState = SqlState(Inner::E53000); /// 53100 - pub const DISK_FULL: SqlState = SqlState(Cow::Borrowed("53100")); + pub const DISK_FULL: SqlState = SqlState(Inner::E53100); /// 53200 - pub const OUT_OF_MEMORY: SqlState = SqlState(Cow::Borrowed("53200")); + pub const OUT_OF_MEMORY: SqlState = SqlState(Inner::E53200); /// 53300 - pub const TOO_MANY_CONNECTIONS: SqlState = SqlState(Cow::Borrowed("53300")); + pub const TOO_MANY_CONNECTIONS: SqlState = SqlState(Inner::E53300); /// 53400 - pub const CONFIGURATION_LIMIT_EXCEEDED: SqlState = SqlState(Cow::Borrowed("53400")); + pub const CONFIGURATION_LIMIT_EXCEEDED: SqlState = SqlState(Inner::E53400); /// 54000 - pub const PROGRAM_LIMIT_EXCEEDED: SqlState = SqlState(Cow::Borrowed("54000")); + pub const PROGRAM_LIMIT_EXCEEDED: SqlState = SqlState(Inner::E54000); /// 54001 - pub const STATEMENT_TOO_COMPLEX: SqlState = SqlState(Cow::Borrowed("54001")); + pub const STATEMENT_TOO_COMPLEX: SqlState = SqlState(Inner::E54001); /// 54011 - pub const TOO_MANY_COLUMNS: SqlState = SqlState(Cow::Borrowed("54011")); + pub const TOO_MANY_COLUMNS: SqlState = SqlState(Inner::E54011); /// 54023 - pub const TOO_MANY_ARGUMENTS: SqlState = SqlState(Cow::Borrowed("54023")); + pub const TOO_MANY_ARGUMENTS: SqlState = SqlState(Inner::E54023); /// 55000 - pub const OBJECT_NOT_IN_PREREQUISITE_STATE: SqlState = SqlState(Cow::Borrowed("55000")); + pub const OBJECT_NOT_IN_PREREQUISITE_STATE: SqlState = SqlState(Inner::E55000); /// 55006 - pub const OBJECT_IN_USE: SqlState = SqlState(Cow::Borrowed("55006")); + pub const OBJECT_IN_USE: SqlState = SqlState(Inner::E55006); /// 55P02 - pub const CANT_CHANGE_RUNTIME_PARAM: SqlState = SqlState(Cow::Borrowed("55P02")); + pub const CANT_CHANGE_RUNTIME_PARAM: SqlState = SqlState(Inner::E55P02); /// 55P03 - pub const LOCK_NOT_AVAILABLE: SqlState = SqlState(Cow::Borrowed("55P03")); + pub const LOCK_NOT_AVAILABLE: SqlState = SqlState(Inner::E55P03); /// 55P04 - pub const UNSAFE_NEW_ENUM_VALUE_USAGE: SqlState = SqlState(Cow::Borrowed("55P04")); + pub const UNSAFE_NEW_ENUM_VALUE_USAGE: SqlState = SqlState(Inner::E55P04); /// 57000 - pub const OPERATOR_INTERVENTION: SqlState = SqlState(Cow::Borrowed("57000")); + pub const OPERATOR_INTERVENTION: SqlState = SqlState(Inner::E57000); /// 57014 - pub const QUERY_CANCELED: SqlState = SqlState(Cow::Borrowed("57014")); + pub const QUERY_CANCELED: SqlState = SqlState(Inner::E57014); /// 57P01 - pub const ADMIN_SHUTDOWN: SqlState = SqlState(Cow::Borrowed("57P01")); + pub const ADMIN_SHUTDOWN: SqlState = SqlState(Inner::E57P01); /// 57P02 - pub const CRASH_SHUTDOWN: SqlState = SqlState(Cow::Borrowed("57P02")); + pub const CRASH_SHUTDOWN: SqlState = SqlState(Inner::E57P02); /// 57P03 - pub const CANNOT_CONNECT_NOW: SqlState = SqlState(Cow::Borrowed("57P03")); + pub const CANNOT_CONNECT_NOW: SqlState = SqlState(Inner::E57P03); /// 57P04 - pub const DATABASE_DROPPED: SqlState = SqlState(Cow::Borrowed("57P04")); + pub const DATABASE_DROPPED: SqlState = SqlState(Inner::E57P04); /// 58000 - pub const SYSTEM_ERROR: SqlState = SqlState(Cow::Borrowed("58000")); + pub const SYSTEM_ERROR: SqlState = SqlState(Inner::E58000); /// 58030 - pub const IO_ERROR: SqlState = SqlState(Cow::Borrowed("58030")); + pub const IO_ERROR: SqlState = SqlState(Inner::E58030); /// 58P01 - pub const UNDEFINED_FILE: SqlState = SqlState(Cow::Borrowed("58P01")); + pub const UNDEFINED_FILE: SqlState = SqlState(Inner::E58P01); /// 58P02 - pub const DUPLICATE_FILE: SqlState = SqlState(Cow::Borrowed("58P02")); + pub const DUPLICATE_FILE: SqlState = SqlState(Inner::E58P02); /// 72000 - pub const SNAPSHOT_TOO_OLD: SqlState = SqlState(Cow::Borrowed("72000")); + pub const SNAPSHOT_TOO_OLD: SqlState = SqlState(Inner::E72000); /// F0000 - pub const CONFIG_FILE_ERROR: SqlState = SqlState(Cow::Borrowed("F0000")); + pub const CONFIG_FILE_ERROR: SqlState = SqlState(Inner::EF0000); /// F0001 - pub const LOCK_FILE_EXISTS: SqlState = SqlState(Cow::Borrowed("F0001")); + pub const LOCK_FILE_EXISTS: SqlState = SqlState(Inner::EF0001); /// HV000 - pub const FDW_ERROR: SqlState = SqlState(Cow::Borrowed("HV000")); + pub const FDW_ERROR: SqlState = SqlState(Inner::EHV000); /// HV005 - pub const FDW_COLUMN_NAME_NOT_FOUND: SqlState = SqlState(Cow::Borrowed("HV005")); + pub const FDW_COLUMN_NAME_NOT_FOUND: SqlState = SqlState(Inner::EHV005); /// HV002 - pub const FDW_DYNAMIC_PARAMETER_VALUE_NEEDED: SqlState = SqlState(Cow::Borrowed("HV002")); + pub const FDW_DYNAMIC_PARAMETER_VALUE_NEEDED: SqlState = SqlState(Inner::EHV002); /// HV010 - pub const FDW_FUNCTION_SEQUENCE_ERROR: SqlState = SqlState(Cow::Borrowed("HV010")); + pub const FDW_FUNCTION_SEQUENCE_ERROR: SqlState = SqlState(Inner::EHV010); /// HV021 - pub const FDW_INCONSISTENT_DESCRIPTOR_INFORMATION: SqlState = SqlState(Cow::Borrowed("HV021")); + pub const FDW_INCONSISTENT_DESCRIPTOR_INFORMATION: SqlState = SqlState(Inner::EHV021); /// HV024 - pub const FDW_INVALID_ATTRIBUTE_VALUE: SqlState = SqlState(Cow::Borrowed("HV024")); + pub const FDW_INVALID_ATTRIBUTE_VALUE: SqlState = SqlState(Inner::EHV024); /// HV007 - pub const FDW_INVALID_COLUMN_NAME: SqlState = SqlState(Cow::Borrowed("HV007")); + pub const FDW_INVALID_COLUMN_NAME: SqlState = SqlState(Inner::EHV007); /// HV008 - pub const FDW_INVALID_COLUMN_NUMBER: SqlState = SqlState(Cow::Borrowed("HV008")); + pub const FDW_INVALID_COLUMN_NUMBER: SqlState = SqlState(Inner::EHV008); /// HV004 - pub const FDW_INVALID_DATA_TYPE: SqlState = SqlState(Cow::Borrowed("HV004")); + pub const FDW_INVALID_DATA_TYPE: SqlState = SqlState(Inner::EHV004); /// HV006 - pub const FDW_INVALID_DATA_TYPE_DESCRIPTORS: SqlState = SqlState(Cow::Borrowed("HV006")); + pub const FDW_INVALID_DATA_TYPE_DESCRIPTORS: SqlState = SqlState(Inner::EHV006); /// HV091 - pub const FDW_INVALID_DESCRIPTOR_FIELD_IDENTIFIER: SqlState = SqlState(Cow::Borrowed("HV091")); + pub const FDW_INVALID_DESCRIPTOR_FIELD_IDENTIFIER: SqlState = SqlState(Inner::EHV091); /// HV00B - pub const FDW_INVALID_HANDLE: SqlState = SqlState(Cow::Borrowed("HV00B")); + pub const FDW_INVALID_HANDLE: SqlState = SqlState(Inner::EHV00B); /// HV00C - pub const FDW_INVALID_OPTION_INDEX: SqlState = SqlState(Cow::Borrowed("HV00C")); + pub const FDW_INVALID_OPTION_INDEX: SqlState = SqlState(Inner::EHV00C); /// HV00D - pub const FDW_INVALID_OPTION_NAME: SqlState = SqlState(Cow::Borrowed("HV00D")); + pub const FDW_INVALID_OPTION_NAME: SqlState = SqlState(Inner::EHV00D); /// HV090 - pub const FDW_INVALID_STRING_LENGTH_OR_BUFFER_LENGTH: SqlState = - SqlState(Cow::Borrowed("HV090")); + pub const FDW_INVALID_STRING_LENGTH_OR_BUFFER_LENGTH: SqlState = SqlState(Inner::EHV090); /// HV00A - pub const FDW_INVALID_STRING_FORMAT: SqlState = SqlState(Cow::Borrowed("HV00A")); + pub const FDW_INVALID_STRING_FORMAT: SqlState = SqlState(Inner::EHV00A); /// HV009 - pub const FDW_INVALID_USE_OF_NULL_POINTER: SqlState = SqlState(Cow::Borrowed("HV009")); + pub const FDW_INVALID_USE_OF_NULL_POINTER: SqlState = SqlState(Inner::EHV009); /// HV014 - pub const FDW_TOO_MANY_HANDLES: SqlState = SqlState(Cow::Borrowed("HV014")); + pub const FDW_TOO_MANY_HANDLES: SqlState = SqlState(Inner::EHV014); /// HV001 - pub const FDW_OUT_OF_MEMORY: SqlState = SqlState(Cow::Borrowed("HV001")); + pub const FDW_OUT_OF_MEMORY: SqlState = SqlState(Inner::EHV001); /// HV00P - pub const FDW_NO_SCHEMAS: SqlState = SqlState(Cow::Borrowed("HV00P")); + pub const FDW_NO_SCHEMAS: SqlState = SqlState(Inner::EHV00P); /// HV00J - pub const FDW_OPTION_NAME_NOT_FOUND: SqlState = SqlState(Cow::Borrowed("HV00J")); + pub const FDW_OPTION_NAME_NOT_FOUND: SqlState = SqlState(Inner::EHV00J); /// HV00K - pub const FDW_REPLY_HANDLE: SqlState = SqlState(Cow::Borrowed("HV00K")); + pub const FDW_REPLY_HANDLE: SqlState = SqlState(Inner::EHV00K); /// HV00Q - pub const FDW_SCHEMA_NOT_FOUND: SqlState = SqlState(Cow::Borrowed("HV00Q")); + pub const FDW_SCHEMA_NOT_FOUND: SqlState = SqlState(Inner::EHV00Q); /// HV00R - pub const FDW_TABLE_NOT_FOUND: SqlState = SqlState(Cow::Borrowed("HV00R")); + pub const FDW_TABLE_NOT_FOUND: SqlState = SqlState(Inner::EHV00R); /// HV00L - pub const FDW_UNABLE_TO_CREATE_EXECUTION: SqlState = SqlState(Cow::Borrowed("HV00L")); + pub const FDW_UNABLE_TO_CREATE_EXECUTION: SqlState = SqlState(Inner::EHV00L); /// HV00M - pub const FDW_UNABLE_TO_CREATE_REPLY: SqlState = SqlState(Cow::Borrowed("HV00M")); + pub const FDW_UNABLE_TO_CREATE_REPLY: SqlState = SqlState(Inner::EHV00M); /// HV00N - pub const FDW_UNABLE_TO_ESTABLISH_CONNECTION: SqlState = SqlState(Cow::Borrowed("HV00N")); + pub const FDW_UNABLE_TO_ESTABLISH_CONNECTION: SqlState = SqlState(Inner::EHV00N); /// P0000 - pub const PLPGSQL_ERROR: SqlState = SqlState(Cow::Borrowed("P0000")); + pub const PLPGSQL_ERROR: SqlState = SqlState(Inner::EP0000); /// P0001 - pub const RAISE_EXCEPTION: SqlState = SqlState(Cow::Borrowed("P0001")); + pub const RAISE_EXCEPTION: SqlState = SqlState(Inner::EP0001); /// P0002 - pub const NO_DATA_FOUND: SqlState = SqlState(Cow::Borrowed("P0002")); + pub const NO_DATA_FOUND: SqlState = SqlState(Inner::EP0002); /// P0003 - pub const TOO_MANY_ROWS: SqlState = SqlState(Cow::Borrowed("P0003")); + pub const TOO_MANY_ROWS: SqlState = SqlState(Inner::EP0003); /// P0004 - pub const ASSERT_FAILURE: SqlState = SqlState(Cow::Borrowed("P0004")); + pub const ASSERT_FAILURE: SqlState = SqlState(Inner::EP0004); /// XX000 - pub const INTERNAL_ERROR: SqlState = SqlState(Cow::Borrowed("XX000")); + pub const INTERNAL_ERROR: SqlState = SqlState(Inner::EXX000); /// XX001 - pub const DATA_CORRUPTED: SqlState = SqlState(Cow::Borrowed("XX001")); + pub const DATA_CORRUPTED: SqlState = SqlState(Inner::EXX001); /// XX002 - pub const INDEX_CORRUPTED: SqlState = SqlState(Cow::Borrowed("XX002")); + pub const INDEX_CORRUPTED: SqlState = SqlState(Inner::EXX002); +} + +#[derive(PartialEq, Eq, Clone, Debug)] +#[allow(clippy::upper_case_acronyms)] +enum Inner { + E00000, + E01000, + E0100C, + E01008, + E01003, + E01007, + E01006, + E01004, + E01P01, + E02000, + E02001, + E03000, + E08000, + E08003, + E08006, + E08001, + E08004, + E08007, + E08P01, + E09000, + E0A000, + E0B000, + E0F000, + E0F001, + E0L000, + E0LP01, + E0P000, + E0Z000, + E0Z002, + E20000, + E21000, + E22000, + E2202E, + E22021, + E22008, + E22012, + E22005, + E2200B, + E22022, + E22015, + E2201E, + E22014, + E22016, + E2201F, + E2201G, + E22018, + E22007, + E22019, + E2200D, + E22025, + E22P06, + E22010, + E22023, + E22013, + E2201B, + E2201W, + E2201X, + E2202H, + E2202G, + E22009, + E2200C, + E2200G, + E22004, + E22002, + E22003, + E2200H, + E22026, + E22001, + E22011, + E22027, + E22024, + E2200F, + E22P01, + E22P02, + E22P03, + E22P04, + E22P05, + E2200L, + E2200M, + E2200N, + E2200S, + E2200T, + E22030, + E22031, + E22032, + E22033, + E22034, + E22035, + E22036, + E22037, + E22038, + E22039, + E2203A, + E2203B, + E2203C, + E2203D, + E2203E, + E2203F, + E23000, + E23001, + E23502, + E23503, + E23505, + E23514, + E23P01, + E24000, + E25000, + E25001, + E25002, + E25008, + E25003, + E25004, + E25005, + E25006, + E25007, + E25P01, + E25P02, + E25P03, + E26000, + E27000, + E28000, + E28P01, + E2B000, + E2BP01, + E2D000, + E2F000, + E2F005, + E2F002, + E2F003, + E2F004, + E34000, + E38000, + E38001, + E38002, + E38003, + E38004, + E39000, + E39001, + E39004, + E39P01, + E39P02, + E39P03, + E3B000, + E3B001, + E3D000, + E3F000, + E40000, + E40002, + E40001, + E40003, + E40P01, + E42000, + E42601, + E42501, + E42846, + E42803, + E42P20, + E42P19, + E42830, + E42602, + E42622, + E42939, + E42804, + E42P18, + E42P21, + E42P22, + E42809, + E428C9, + E42703, + E42883, + E42P01, + E42P02, + E42704, + E42701, + E42P03, + E42P04, + E42723, + E42P05, + E42P06, + E42P07, + E42712, + E42710, + E42702, + E42725, + E42P08, + E42P09, + E42P10, + E42611, + E42P11, + E42P12, + E42P13, + E42P14, + E42P15, + E42P16, + E42P17, + E44000, + E53000, + E53100, + E53200, + E53300, + E53400, + E54000, + E54001, + E54011, + E54023, + E55000, + E55006, + E55P02, + E55P03, + E55P04, + E57000, + E57014, + E57P01, + E57P02, + E57P03, + E57P04, + E58000, + E58030, + E58P01, + E58P02, + E72000, + EF0000, + EF0001, + EHV000, + EHV005, + EHV002, + EHV010, + EHV021, + EHV024, + EHV007, + EHV008, + EHV004, + EHV006, + EHV091, + EHV00B, + EHV00C, + EHV00D, + EHV090, + EHV00A, + EHV009, + EHV014, + EHV001, + EHV00P, + EHV00J, + EHV00K, + EHV00Q, + EHV00R, + EHV00L, + EHV00M, + EHV00N, + EP0000, + EP0001, + EP0002, + EP0003, + EP0004, + EXX000, + EXX001, + EXX002, + Other(Box), } + #[rustfmt::skip] static SQLSTATE_MAP: phf::Map<&'static str, SqlState> = ::phf::Map { - key: 732231254413039614, - disps: ::phf::Slice::Static(&[ - (0, 6), + key: 12913932095322966823, + disps: &[ + (0, 12), + (0, 18), + (0, 25), + (0, 109), + (0, 147), + (0, 74), (0, 0), - (0, 218), - (0, 11), - (0, 31), - (0, 91), - (0, 55), + (7, 117), + (5, 221), + (0, 26), + (1, 45), + (0, 93), + (0, 25), + (0, 61), + (1, 221), + (10, 17), (0, 77), - (0, 72), + (2, 3), + (0, 216), + (0, 0), (0, 1), - (0, 73), - (1, 159), - (4, 4), - (0, 18), - (2, 100), - (0, 19), - (0, 16), - (0, 22), - (0, 51), + (1, 168), + (0, 64), + (0, 2), + (0, 7), + (1, 37), + (0, 83), + (3, 24), (0, 0), + (0, 109), + (18, 9), + (1, 230), (0, 0), - (1, 2), - (2, 177), - (0, 10), - (1, 192), + (0, 4), + (0, 171), (0, 0), - (5, 245), - (0, 106), - (6, 243), - (47, 195), - (0, 146), - (4, 154), - (0, 2), - (4, 78), - (0, 196), - (0, 8), - (2, 146), - (0, 15), - (0, 170), - (0, 5), - (10, 18), - (0, 30), - (0, 33), - (0, 2), + (34, 97), + (2, 126), + (44, 49), + (5, 182), + (0, 1), + (0, 1), + (0, 71), + (0, 4), + (5, 164), (0, 0), - (47, 181), - (0, 144), - (39, 231), - (39, 173), - (0, 57), - (0, 7), - (1, 154), - ]), - entries: ::phf::Slice::Static(&[ - ("22P04", SqlState::BAD_COPY_FILE_FORMAT), - ("39001", SqlState::E_R_I_E_INVALID_SQLSTATE_RETURNED), - ("2201F", SqlState::INVALID_ARGUMENT_FOR_POWER_FUNCTION), - ("54000", SqlState::PROGRAM_LIMIT_EXCEEDED), - ("2200T", SqlState::INVALID_XML_PROCESSING_INSTRUCTION), - ("01000", SqlState::WARNING), - ("02000", SqlState::NO_DATA), - ("40003", SqlState::T_R_STATEMENT_COMPLETION_UNKNOWN), - ("42702", SqlState::AMBIGUOUS_COLUMN), - ("HV000", SqlState::FDW_ERROR), - ("2203A", SqlState::SQL_JSON_MEMBER_NOT_FOUND), - ("22021", SqlState::CHARACTER_NOT_IN_REPERTOIRE), - ("HV006", SqlState::FDW_INVALID_DATA_TYPE_DESCRIPTORS), - ("40000", SqlState::TRANSACTION_ROLLBACK), - ("57P01", SqlState::ADMIN_SHUTDOWN), + (0, 96), + (13, 58), + (0, 58), + (0, 242), + (0, 72), + (16, 53), + ], + entries: &[ ("22034", SqlState::MORE_THAN_ONE_SQL_JSON_ITEM), - ("54023", SqlState::TOO_MANY_ARGUMENTS), - ("22027", SqlState::TRIM_ERROR), - ("2203C", SqlState::SQL_JSON_OBJECT_NOT_FOUND), - ("22P06", SqlState::NONSTANDARD_USE_OF_ESCAPE_CHARACTER), - ("72000", SqlState::SNAPSHOT_TOO_OLD), - ("25004", SqlState::INAPPROPRIATE_ISOLATION_LEVEL_FOR_BRANCH_TRANSACTION), - ("2BP01", SqlState::DEPENDENT_OBJECTS_STILL_EXIST), - ("42P11", SqlState::INVALID_CURSOR_DEFINITION), - ("HV00J", SqlState::FDW_OPTION_NAME_NOT_FOUND), - ("42804", SqlState::DATATYPE_MISMATCH), - ("39004", SqlState::E_R_I_E_NULL_VALUE_NOT_ALLOWED), + ("40P01", SqlState::T_R_DEADLOCK_DETECTED), ("42703", SqlState::UNDEFINED_COLUMN), - ("2203E", SqlState::TOO_MANY_JSON_OBJECT_MEMBERS), - ("42P12", SqlState::INVALID_DATABASE_DEFINITION), - ("23503", SqlState::FOREIGN_KEY_VIOLATION), - ("25003", SqlState::INAPPROPRIATE_ACCESS_MODE_FOR_BRANCH_TRANSACTION), - ("22P03", SqlState::INVALID_BINARY_REPRESENTATION), - ("40002", SqlState::T_R_INTEGRITY_CONSTRAINT_VIOLATION), - ("58030", SqlState::IO_ERROR), - ("01004", SqlState::WARNING_STRING_DATA_RIGHT_TRUNCATION), - ("22019", SqlState::INVALID_ESCAPE_CHARACTER), - ("42P20", SqlState::WINDOWING_ERROR), - ("3D000", SqlState::INVALID_CATALOG_NAME), - ("22001", SqlState::STRING_DATA_RIGHT_TRUNCATION), - ("F0000", SqlState::CONFIG_FILE_ERROR), - ("25005", SqlState::NO_ACTIVE_SQL_TRANSACTION_FOR_BRANCH_TRANSACTION), - ("42883", SqlState::UNDEFINED_FUNCTION), - ("42P06", SqlState::DUPLICATE_SCHEMA), - ("42P17", SqlState::INVALID_OBJECT_DEFINITION), - ("HV002", SqlState::FDW_DYNAMIC_PARAMETER_VALUE_NEEDED), - ("0F001", SqlState::L_E_INVALID_SPECIFICATION), - ("57014", SqlState::QUERY_CANCELED), - ("22033", SqlState::INVALID_SQL_JSON_SUBSCRIPT), - ("2F004", SqlState::S_R_E_READING_SQL_DATA_NOT_PERMITTED), - ("42611", SqlState::INVALID_COLUMN_DEFINITION), - ("42939", SqlState::RESERVED_NAME), - ("0P000", SqlState::INVALID_ROLE_SPECIFICATION), - ("53200", SqlState::OUT_OF_MEMORY), - ("42809", SqlState::WRONG_OBJECT_TYPE), - ("2202H", SqlState::INVALID_TABLESAMPLE_ARGUMENT), - ("42P16", SqlState::INVALID_TABLE_DEFINITION), - ("24000", SqlState::INVALID_CURSOR_STATE), - ("42P13", SqlState::INVALID_FUNCTION_DEFINITION), - ("22007", SqlState::INVALID_DATETIME_FORMAT), - ("2D000", SqlState::INVALID_TRANSACTION_TERMINATION), - ("53100", SqlState::DISK_FULL), - ("P0003", SqlState::TOO_MANY_ROWS), - ("22016", SqlState::INVALID_ARGUMENT_FOR_NTH_VALUE), - ("2F002", SqlState::S_R_E_MODIFYING_SQL_DATA_NOT_PERMITTED), - ("42830", SqlState::INVALID_FOREIGN_KEY), - ("27000", SqlState::TRIGGERED_DATA_CHANGE_VIOLATION), - ("0Z002", SqlState::STACKED_DIAGNOSTICS_ACCESSED_WITHOUT_ACTIVE_HANDLER), - ("53000", SqlState::INSUFFICIENT_RESOURCES), - ("23502", SqlState::NOT_NULL_VIOLATION), - ("XX000", SqlState::INTERNAL_ERROR), - ("58P01", SqlState::UNDEFINED_FILE), - ("42601", SqlState::SYNTAX_ERROR), - ("02001", SqlState::NO_ADDITIONAL_DYNAMIC_RESULT_SETS_RETURNED), - ("42P09", SqlState::AMBIGUOUS_ALIAS), - ("22P02", SqlState::INVALID_TEXT_REPRESENTATION), - ("55P02", SqlState::CANT_CHANGE_RUNTIME_PARAM), - ("2F003", SqlState::S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED), - ("53300", SqlState::TOO_MANY_CONNECTIONS), - ("25P02", SqlState::IN_FAILED_SQL_TRANSACTION), - ("42P03", SqlState::DUPLICATE_CURSOR), - ("XX002", SqlState::INDEX_CORRUPTED), - ("22010", SqlState::INVALID_INDICATOR_PARAMETER_VALUE), - ("01006", SqlState::WARNING_PRIVILEGE_NOT_REVOKED), - ("3B001", SqlState::S_E_INVALID_SPECIFICATION), - ("42P21", SqlState::COLLATION_MISMATCH), ("42P07", SqlState::DUPLICATE_TABLE), - ("22013", SqlState::INVALID_PRECEDING_OR_FOLLOWING_SIZE), - ("0Z000", SqlState::DIAGNOSTICS_EXCEPTION), ("55P04", SqlState::UNSAFE_NEW_ENUM_VALUE_USAGE), - ("42000", SqlState::SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), - ("XX001", SqlState::DATA_CORRUPTED), - ("25008", SqlState::HELD_CURSOR_REQUIRES_SAME_ISOLATION_LEVEL), - ("HV00M", SqlState::FDW_UNABLE_TO_CREATE_REPLY), - ("39000", SqlState::EXTERNAL_ROUTINE_INVOCATION_EXCEPTION), - ("22032", SqlState::INVALID_JSON_TEXT), ("25006", SqlState::READ_ONLY_SQL_TRANSACTION), - ("01P01", SqlState::WARNING_DEPRECATED_FEATURE), - ("42725", SqlState::AMBIGUOUS_FUNCTION), - ("42602", SqlState::INVALID_NAME), - ("2201W", SqlState::INVALID_ROW_COUNT_IN_LIMIT_CLAUSE), - ("42P05", SqlState::DUPLICATE_PSTATEMENT), + ("2201X", SqlState::INVALID_ROW_COUNT_IN_RESULT_OFFSET_CLAUSE), ("HV021", SqlState::FDW_INCONSISTENT_DESCRIPTOR_INFORMATION), - ("57P03", SqlState::CANNOT_CONNECT_NOW), - ("58P02", SqlState::DUPLICATE_FILE), - ("42P22", SqlState::INDETERMINATE_COLLATION), - ("0B000", SqlState::INVALID_TRANSACTION_INITIATION), - ("0100C", SqlState::WARNING_DYNAMIC_RESULT_SETS_RETURNED), - ("22015", SqlState::INTERVAL_FIELD_OVERFLOW), - ("2200S", SqlState::INVALID_XML_COMMENT), - ("2200M", SqlState::INVALID_XML_DOCUMENT), - ("HV001", SqlState::FDW_OUT_OF_MEMORY), - ("25001", SqlState::ACTIVE_SQL_TRANSACTION), - ("22002", SqlState::NULL_VALUE_NO_INDICATOR_PARAMETER), + ("42P02", SqlState::UNDEFINED_PARAMETER), + ("HV00C", SqlState::FDW_INVALID_OPTION_INDEX), + ("08003", SqlState::CONNECTION_DOES_NOT_EXIST), + ("02000", SqlState::NO_DATA), + ("24000", SqlState::INVALID_CURSOR_STATE), + ("2203C", SqlState::SQL_JSON_OBJECT_NOT_FOUND), + ("42601", SqlState::SYNTAX_ERROR), + ("22012", SqlState::DIVISION_BY_ZERO), + ("2203B", SqlState::SQL_JSON_NUMBER_NOT_FOUND), + ("P0003", SqlState::TOO_MANY_ROWS), + ("57P04", SqlState::DATABASE_DROPPED), + ("27000", SqlState::TRIGGERED_DATA_CHANGE_VIOLATION), + ("42P08", SqlState::AMBIGUOUS_PARAMETER), + ("3F000", SqlState::INVALID_SCHEMA_NAME), + ("42883", SqlState::UNDEFINED_FUNCTION), + ("20000", SqlState::CASE_NOT_FOUND), + ("2200G", SqlState::MOST_SPECIFIC_TYPE_MISMATCH), + ("42939", SqlState::RESERVED_NAME), + ("42602", SqlState::INVALID_NAME), + ("HV004", SqlState::FDW_INVALID_DATA_TYPE), + ("HV007", SqlState::FDW_INVALID_COLUMN_NAME), ("2F005", SqlState::S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT), - ("428C9", SqlState::GENERATED_ALWAYS), - ("25P01", SqlState::NO_ACTIVE_SQL_TRANSACTION), - ("HV091", SqlState::FDW_INVALID_DESCRIPTOR_FIELD_IDENTIFIER), - ("2200C", SqlState::INVALID_USE_OF_ESCAPE_CHARACTER), - ("HV008", SqlState::FDW_INVALID_COLUMN_NUMBER), - ("2200F", SqlState::ZERO_LENGTH_CHARACTER_STRING), - ("54001", SqlState::STATEMENT_TOO_COMPLEX), + ("22030", SqlState::DUPLICATE_JSON_OBJECT_KEY_VALUE), + ("53100", SqlState::DISK_FULL), + ("HV005", SqlState::FDW_COLUMN_NAME_NOT_FOUND), + ("2200H", SqlState::SEQUENCE_GENERATOR_LIMIT_EXCEEDED), + ("2201W", SqlState::INVALID_ROW_COUNT_IN_LIMIT_CLAUSE), ("42712", SqlState::DUPLICATE_ALIAS), - ("HV00A", SqlState::FDW_INVALID_STRING_FORMAT), - ("42710", SqlState::DUPLICATE_OBJECT), - ("54011", SqlState::TOO_MANY_COLUMNS), - ("42P19", SqlState::INVALID_RECURSION), - ("42501", SqlState::INSUFFICIENT_PRIVILEGE), + ("42622", SqlState::NAME_TOO_LONG), + ("22035", SqlState::NO_SQL_JSON_ITEM), + ("42P18", SqlState::INDETERMINATE_DATATYPE), + ("39P01", SqlState::E_R_I_E_TRIGGER_PROTOCOL_VIOLATED), + ("01000", SqlState::WARNING), + ("2F004", SqlState::S_R_E_READING_SQL_DATA_NOT_PERMITTED), + ("22023", SqlState::INVALID_PARAMETER_VALUE), + ("2200T", SqlState::INVALID_XML_PROCESSING_INSTRUCTION), + ("22013", SqlState::INVALID_PRECEDING_OR_FOLLOWING_SIZE), + ("57P01", SqlState::ADMIN_SHUTDOWN), + ("2202E", SqlState::ARRAY_ELEMENT_ERROR), + ("22018", SqlState::INVALID_CHARACTER_VALUE_FOR_CAST), + ("0F000", SqlState::LOCATOR_EXCEPTION), + ("2D000", SqlState::INVALID_TRANSACTION_TERMINATION), + ("HV009", SqlState::FDW_INVALID_USE_OF_NULL_POINTER), ("57000", SqlState::OPERATOR_INTERVENTION), ("25002", SqlState::BRANCH_TRANSACTION_ALREADY_ACTIVE), - ("22039", SqlState::SQL_JSON_ARRAY_NOT_FOUND), - ("P0002", SqlState::NO_DATA_FOUND), + ("25004", SqlState::INAPPROPRIATE_ISOLATION_LEVEL_FOR_BRANCH_TRANSACTION), + ("22009", SqlState::INVALID_TIME_ZONE_DISPLACEMENT_VALUE), + ("HV090", SqlState::FDW_INVALID_STRING_LENGTH_OR_BUFFER_LENGTH), + ("42725", SqlState::AMBIGUOUS_FUNCTION), + ("2F003", SqlState::S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED), + ("44000", SqlState::WITH_CHECK_OPTION_VIOLATION), + ("22032", SqlState::INVALID_JSON_TEXT), + ("22036", SqlState::NON_NUMERIC_SQL_JSON_ITEM), + ("2201E", SqlState::INVALID_ARGUMENT_FOR_LOG), + ("25P02", SqlState::IN_FAILED_SQL_TRANSACTION), + ("22001", SqlState::STRING_DATA_RIGHT_TRUNCATION), + ("2201F", SqlState::INVALID_ARGUMENT_FOR_POWER_FUNCTION), + ("01006", SqlState::WARNING_PRIVILEGE_NOT_REVOKED), + ("428C9", SqlState::GENERATED_ALWAYS), + ("22003", SqlState::NUMERIC_VALUE_OUT_OF_RANGE), + ("22P01", SqlState::FLOATING_POINT_EXCEPTION), + ("HV00M", SqlState::FDW_UNABLE_TO_CREATE_REPLY), ("2201G", SqlState::INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION), - ("22012", SqlState::DIVISION_BY_ZERO), - ("42P10", SqlState::INVALID_COLUMN_REFERENCE), + ("34000", SqlState::INVALID_CURSOR_NAME), + ("42846", SqlState::CANNOT_COERCE), + ("2201B", SqlState::INVALID_REGULAR_EXPRESSION), + ("2202G", SqlState::INVALID_TABLESAMPLE_REPEAT), + ("42704", SqlState::UNDEFINED_OBJECT), + ("72000", SqlState::SNAPSHOT_TOO_OLD), + ("53400", SqlState::CONFIGURATION_LIMIT_EXCEEDED), + ("HV00L", SqlState::FDW_UNABLE_TO_CREATE_EXECUTION), + ("2B000", SqlState::DEPENDENT_PRIVILEGE_DESCRIPTORS_STILL_EXIST), + ("22010", SqlState::INVALID_INDICATOR_PARAMETER_VALUE), + ("54001", SqlState::STATEMENT_TOO_COMPLEX), + ("53200", SqlState::OUT_OF_MEMORY), + ("38001", SqlState::E_R_E_CONTAINING_SQL_NOT_PERMITTED), + ("22022", SqlState::INDICATOR_OVERFLOW), + ("2203E", SqlState::TOO_MANY_JSON_OBJECT_MEMBERS), + ("XX000", SqlState::INTERNAL_ERROR), + ("22025", SqlState::INVALID_ESCAPE_SEQUENCE), + ("09000", SqlState::TRIGGERED_ACTION_EXCEPTION), + ("HV008", SqlState::FDW_INVALID_COLUMN_NUMBER), + ("25P01", SqlState::NO_ACTIVE_SQL_TRANSACTION), + ("23505", SqlState::UNIQUE_VIOLATION), + ("3B000", SqlState::SAVEPOINT_EXCEPTION), + ("F0000", SqlState::CONFIG_FILE_ERROR), + ("54011", SqlState::TOO_MANY_COLUMNS), + ("XX002", SqlState::INDEX_CORRUPTED), + ("2203F", SqlState::SQL_JSON_SCALAR_REQUIRED), + ("42P12", SqlState::INVALID_DATABASE_DEFINITION), ("HV00B", SqlState::FDW_INVALID_HANDLE), - ("38003", SqlState::E_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED), + ("55006", SqlState::OBJECT_IN_USE), + ("42P01", SqlState::UNDEFINED_TABLE), ("25P03", SqlState::IDLE_IN_TRANSACTION_SESSION_TIMEOUT), - ("F0001", SqlState::LOCK_FILE_EXISTS), - ("08001", SqlState::SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION), - ("2203D", SqlState::TOO_MANY_JSON_ARRAY_ELEMENTS), - ("P0000", SqlState::PLPGSQL_ERROR), - ("28000", SqlState::INVALID_AUTHORIZATION_SPECIFICATION), - ("2200D", SqlState::INVALID_ESCAPE_OCTET), - ("55P03", SqlState::LOCK_NOT_AVAILABLE), - ("23505", SqlState::UNIQUE_VIOLATION), - ("39P01", SqlState::E_R_I_E_TRIGGER_PROTOCOL_VIOLATED), - ("44000", SqlState::WITH_CHECK_OPTION_VIOLATION), - ("22030", SqlState::DUPLICATE_JSON_OBJECT_KEY_VALUE), + ("22037", SqlState::NON_UNIQUE_KEYS_IN_A_JSON_OBJECT), + ("2203A", SqlState::SQL_JSON_MEMBER_NOT_FOUND), ("P0004", SqlState::ASSERT_FAILURE), - ("2200G", SqlState::MOST_SPECIFIC_TYPE_MISMATCH), - ("2F000", SqlState::SQL_ROUTINE_EXCEPTION), - ("26000", SqlState::INVALID_SQL_STATEMENT_NAME), - ("2202G", SqlState::INVALID_TABLESAMPLE_REPEAT), - ("22003", SqlState::NUMERIC_VALUE_OUT_OF_RANGE), + ("58000", SqlState::SYSTEM_ERROR), + ("42P21", SqlState::COLLATION_MISMATCH), + ("57P02", SqlState::CRASH_SHUTDOWN), + ("42830", SqlState::INVALID_FOREIGN_KEY), + ("0LP01", SqlState::INVALID_GRANT_OPERATION), + ("22P02", SqlState::INVALID_TEXT_REPRESENTATION), + ("22039", SqlState::SQL_JSON_ARRAY_NOT_FOUND), + ("28P01", SqlState::INVALID_PASSWORD), + ("22011", SqlState::SUBSTRING_ERROR), + ("HV00J", SqlState::FDW_OPTION_NAME_NOT_FOUND), + ("2200C", SqlState::INVALID_USE_OF_ESCAPE_CHARACTER), + ("08006", SqlState::CONNECTION_FAILURE), + ("22021", SqlState::CHARACTER_NOT_IN_REPERTOIRE), ("21000", SqlState::CARDINALITY_VIOLATION), - ("0A000", SqlState::FEATURE_NOT_SUPPORTED), - ("HV014", SqlState::FDW_TOO_MANY_HANDLES), - ("08004", SqlState::SQLSERVER_REJECTED_ESTABLISHMENT_OF_SQLCONNECTION), - ("38001", SqlState::E_R_E_CONTAINING_SQL_NOT_PERMITTED), - ("01003", SqlState::WARNING_NULL_VALUE_ELIMINATED_IN_SET_FUNCTION), - ("08007", SqlState::TRANSACTION_RESOLUTION_UNKNOWN), - ("HV00D", SqlState::FDW_INVALID_OPTION_NAME), + ("42803", SqlState::GROUPING_ERROR), + ("00000", SqlState::SUCCESSFUL_COMPLETION), + ("42P16", SqlState::INVALID_TABLE_DEFINITION), ("38002", SqlState::E_R_E_MODIFYING_SQL_DATA_NOT_PERMITTED), + ("57P03", SqlState::CANNOT_CONNECT_NOW), + ("01004", SqlState::WARNING_STRING_DATA_RIGHT_TRUNCATION), ("HV00K", SqlState::FDW_REPLY_HANDLE), - ("23P01", SqlState::EXCLUSION_VIOLATION), - ("42P04", SqlState::DUPLICATE_DATABASE), - ("22025", SqlState::INVALID_ESCAPE_SEQUENCE), - ("HV007", SqlState::FDW_INVALID_COLUMN_NAME), - ("34000", SqlState::INVALID_CURSOR_NAME), - ("HV00L", SqlState::FDW_UNABLE_TO_CREATE_EXECUTION), - ("HV009", SqlState::FDW_INVALID_USE_OF_NULL_POINTER), - ("38000", SqlState::EXTERNAL_ROUTINE_EXCEPTION), - ("2B000", SqlState::DEPENDENT_PRIVILEGE_DESCRIPTORS_STILL_EXIST), - ("00000", SqlState::SUCCESSFUL_COMPLETION), - ("58000", SqlState::SYSTEM_ERROR), - ("2201E", SqlState::INVALID_ARGUMENT_FOR_LOG), - ("HV024", SqlState::FDW_INVALID_ATTRIBUTE_VALUE), + ("42P06", SqlState::DUPLICATE_SCHEMA), + ("54000", SqlState::PROGRAM_LIMIT_EXCEEDED), + ("2200S", SqlState::INVALID_XML_COMMENT), + ("42000", SqlState::SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + ("42P03", SqlState::DUPLICATE_CURSOR), + ("HV002", SqlState::FDW_DYNAMIC_PARAMETER_VALUE_NEEDED), + ("2202H", SqlState::INVALID_TABLESAMPLE_ARGUMENT), + ("08001", SqlState::SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION), + ("0L000", SqlState::INVALID_GRANTOR), ("2200L", SqlState::NOT_AN_XML_DOCUMENT), - ("2203B", SqlState::SQL_JSON_NUMBER_NOT_FOUND), - ("42846", SqlState::CANNOT_COERCE), - ("22035", SqlState::NO_SQL_JSON_ITEM), - ("HV005", SqlState::FDW_COLUMN_NAME_NOT_FOUND), - ("20000", SqlState::CASE_NOT_FOUND), - ("40001", SqlState::T_R_SERIALIZATION_FAILURE), + ("HV006", SqlState::FDW_INVALID_DATA_TYPE_DESCRIPTORS), + ("55000", SqlState::OBJECT_NOT_IN_PREREQUISITE_STATE), + ("58P01", SqlState::UNDEFINED_FILE), + ("0B000", SqlState::INVALID_TRANSACTION_INITIATION), ("22000", SqlState::DATA_EXCEPTION), + ("HV00R", SqlState::FDW_TABLE_NOT_FOUND), + ("2F002", SqlState::S_R_E_MODIFYING_SQL_DATA_NOT_PERMITTED), + ("01007", SqlState::WARNING_PRIVILEGE_NOT_GRANTED), + ("42P19", SqlState::INVALID_RECURSION), + ("22016", SqlState::INVALID_ARGUMENT_FOR_NTH_VALUE), + ("42702", SqlState::AMBIGUOUS_COLUMN), + ("25005", SqlState::NO_ACTIVE_SQL_TRANSACTION_FOR_BRANCH_TRANSACTION), + ("22004", SqlState::NULL_VALUE_NOT_ALLOWED), + ("42P05", SqlState::DUPLICATE_PSTATEMENT), + ("39001", SqlState::E_R_I_E_INVALID_SQLSTATE_RETURNED), ("22038", SqlState::SINGLETON_SQL_JSON_ITEM_REQUIRED), - ("42P14", SqlState::INVALID_PSTATEMENT_DEFINITION), + ("22008", SqlState::DATETIME_FIELD_OVERFLOW), + ("38003", SqlState::E_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED), + ("53000", SqlState::INSUFFICIENT_RESOURCES), + ("3B001", SqlState::S_E_INVALID_SPECIFICATION), + ("28000", SqlState::INVALID_AUTHORIZATION_SPECIFICATION), + ("P0000", SqlState::PLPGSQL_ERROR), + ("38000", SqlState::EXTERNAL_ROUTINE_EXCEPTION), + ("22019", SqlState::INVALID_ESCAPE_CHARACTER), + ("22015", SqlState::INTERVAL_FIELD_OVERFLOW), + ("42710", SqlState::DUPLICATE_OBJECT), + ("2200M", SqlState::INVALID_XML_DOCUMENT), + ("HV000", SqlState::FDW_ERROR), + ("22P05", SqlState::UNTRANSLATABLE_CHARACTER), + ("0100C", SqlState::WARNING_DYNAMIC_RESULT_SETS_RETURNED), + ("55P02", SqlState::CANT_CHANGE_RUNTIME_PARAM), + ("01003", SqlState::WARNING_NULL_VALUE_ELIMINATED_IN_SET_FUNCTION), + ("2200N", SqlState::INVALID_XML_CONTENT), + ("2F000", SqlState::SQL_ROUTINE_EXCEPTION), + ("08007", SqlState::TRANSACTION_RESOLUTION_UNKNOWN), + ("2200B", SqlState::ESCAPE_CHARACTER_CONFLICT), + ("22P03", SqlState::INVALID_BINARY_REPRESENTATION), + ("42P09", SqlState::AMBIGUOUS_ALIAS), + ("39004", SqlState::E_R_I_E_NULL_VALUE_NOT_ALLOWED), + ("23502", SqlState::NOT_NULL_VIOLATION), + ("2203D", SqlState::TOO_MANY_JSON_ARRAY_ELEMENTS), + ("42P15", SqlState::INVALID_SCHEMA_DEFINITION), + ("08004", SqlState::SQLSERVER_REJECTED_ESTABLISHMENT_OF_SQLCONNECTION), + ("HV00N", SqlState::FDW_UNABLE_TO_ESTABLISH_CONNECTION), + ("0A000", SqlState::FEATURE_NOT_SUPPORTED), + ("57014", SqlState::QUERY_CANCELED), + ("22033", SqlState::INVALID_SQL_JSON_SUBSCRIPT), + ("0F001", SqlState::L_E_INVALID_SPECIFICATION), + ("HV00A", SqlState::FDW_INVALID_STRING_FORMAT), ("39P02", SqlState::E_R_I_E_SRF_PROTOCOL_VIOLATED), + ("42701", SqlState::DUPLICATE_COLUMN), + ("42611", SqlState::INVALID_COLUMN_DEFINITION), + ("HV001", SqlState::FDW_OUT_OF_MEMORY), + ("HV091", SqlState::FDW_INVALID_DESCRIPTOR_FIELD_IDENTIFIER), + ("23P01", SqlState::EXCLUSION_VIOLATION), + ("F0001", SqlState::LOCK_FILE_EXISTS), + ("42501", SqlState::INSUFFICIENT_PRIVILEGE), + ("22026", SqlState::STRING_DATA_LENGTH_MISMATCH), + ("54023", SqlState::TOO_MANY_ARGUMENTS), ("01008", SqlState::WARNING_IMPLICIT_ZERO_BIT_PADDING), - ("42P15", SqlState::INVALID_SCHEMA_DEFINITION), - ("55006", SqlState::OBJECT_IN_USE), - ("2203F", SqlState::SQL_JSON_SCALAR_REQUIRED), - ("22014", SqlState::INVALID_ARGUMENT_FOR_NTILE), + ("42P04", SqlState::DUPLICATE_DATABASE), + ("22027", SqlState::TRIM_ERROR), + ("53300", SqlState::TOO_MANY_CONNECTIONS), + ("0Z002", SqlState::STACKED_DIAGNOSTICS_ACCESSED_WITHOUT_ACTIVE_HANDLER), + ("42P14", SqlState::INVALID_PSTATEMENT_DEFINITION), + ("P0001", SqlState::RAISE_EXCEPTION), + ("HV014", SqlState::FDW_TOO_MANY_HANDLES), + ("40002", SqlState::T_R_INTEGRITY_CONSTRAINT_VIOLATION), + ("3D000", SqlState::INVALID_CATALOG_NAME), ("03000", SqlState::SQL_STATEMENT_NOT_YET_COMPLETE), - ("22008", SqlState::DATETIME_FIELD_OVERFLOW), - ("08006", SqlState::CONNECTION_FAILURE), - ("42P01", SqlState::UNDEFINED_TABLE), - ("40P01", SqlState::T_R_DEADLOCK_DETECTED), - ("0L000", SqlState::INVALID_GRANTOR), + ("22024", SqlState::UNTERMINATED_C_STRING), + ("42P13", SqlState::INVALID_FUNCTION_DEFINITION), + ("08000", SqlState::CONNECTION_EXCEPTION), + ("25007", SqlState::SCHEMA_AND_DATA_STATEMENT_MIXING_NOT_SUPPORTED), + ("40001", SqlState::T_R_SERIALIZATION_FAILURE), + ("25001", SqlState::ACTIVE_SQL_TRANSACTION), + ("HV00Q", SqlState::FDW_SCHEMA_NOT_FOUND), + ("22P04", SqlState::BAD_COPY_FILE_FORMAT), + ("XX001", SqlState::DATA_CORRUPTED), + ("23503", SqlState::FOREIGN_KEY_VIOLATION), + ("23514", SqlState::CHECK_VIOLATION), + ("42809", SqlState::WRONG_OBJECT_TYPE), + ("2200F", SqlState::ZERO_LENGTH_CHARACTER_STRING), + ("2BP01", SqlState::DEPENDENT_OBJECTS_STILL_EXIST), + ("25008", SqlState::HELD_CURSOR_REQUIRES_SAME_ISOLATION_LEVEL), + ("55P03", SqlState::LOCK_NOT_AVAILABLE), + ("42P22", SqlState::INDETERMINATE_COLLATION), + ("HV00D", SqlState::FDW_INVALID_OPTION_NAME), + ("42P17", SqlState::INVALID_OBJECT_DEFINITION), + ("23001", SqlState::RESTRICT_VIOLATION), + ("22P06", SqlState::NONSTANDARD_USE_OF_ESCAPE_CHARACTER), + ("22031", SqlState::INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION), + ("2200D", SqlState::INVALID_ESCAPE_OCTET), + ("0Z000", SqlState::DIAGNOSTICS_EXCEPTION), + ("HV024", SqlState::FDW_INVALID_ATTRIBUTE_VALUE), ("22005", SqlState::ERROR_IN_ASSIGNMENT), - ("42622", SqlState::NAME_TOO_LONG), - ("57P04", SqlState::DATABASE_DROPPED), - ("42803", SqlState::GROUPING_ERROR), - ("22P01", SqlState::FLOATING_POINT_EXCEPTION), - ("42P18", SqlState::INDETERMINATE_DATATYPE), + ("58P02", SqlState::DUPLICATE_FILE), + ("HV00P", SqlState::FDW_NO_SCHEMAS), + ("42P10", SqlState::INVALID_COLUMN_REFERENCE), + ("42P20", SqlState::WINDOWING_ERROR), + ("25000", SqlState::INVALID_TRANSACTION_STATE), ("38004", SqlState::E_R_E_READING_SQL_DATA_NOT_PERMITTED), - ("39P03", SqlState::E_R_I_E_EVENT_TRIGGER_PROTOCOL_VIOLATED), - ("2200N", SqlState::INVALID_XML_CONTENT), - ("57P02", SqlState::CRASH_SHUTDOWN), + ("01P01", SqlState::WARNING_DEPRECATED_FEATURE), + ("40000", SqlState::TRANSACTION_ROLLBACK), + ("58030", SqlState::IO_ERROR), + ("26000", SqlState::INVALID_SQL_STATEMENT_NAME), + ("22007", SqlState::INVALID_DATETIME_FORMAT), ("23000", SqlState::INTEGRITY_CONSTRAINT_VIOLATION), - ("0F000", SqlState::LOCATOR_EXCEPTION), - ("08000", SqlState::CONNECTION_EXCEPTION), - ("2202E", SqlState::ARRAY_ELEMENT_ERROR), - ("22024", SqlState::UNTERMINATED_C_STRING), + ("0P000", SqlState::INVALID_ROLE_SPECIFICATION), + ("22014", SqlState::INVALID_ARGUMENT_FOR_NTILE), + ("P0002", SqlState::NO_DATA_FOUND), + ("39P03", SqlState::E_R_I_E_EVENT_TRIGGER_PROTOCOL_VIOLATED), + ("39000", SqlState::EXTERNAL_ROUTINE_INVOCATION_EXCEPTION), + ("42P11", SqlState::INVALID_CURSOR_DEFINITION), + ("HV010", SqlState::FDW_FUNCTION_SEQUENCE_ERROR), + ("22002", SqlState::NULL_VALUE_NO_INDICATOR_PARAMETER), ("08P01", SqlState::PROTOCOL_VIOLATION), - ("22023", SqlState::INVALID_PARAMETER_VALUE), - ("22031", SqlState::INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION), - ("HV00P", SqlState::FDW_NO_SCHEMAS), - ("23514", SqlState::CHECK_VIOLATION), - ("HV00Q", SqlState::FDW_SCHEMA_NOT_FOUND), - ("22P05", SqlState::UNTRANSLATABLE_CHARACTER), - ("53400", SqlState::CONFIGURATION_LIMIT_EXCEEDED), - ("3F000", SqlState::INVALID_SCHEMA_NAME), - ("22037", SqlState::NON_UNIQUE_KEYS_IN_A_JSON_OBJECT), - ("22004", SqlState::NULL_VALUE_NOT_ALLOWED), - ("2200B", SqlState::ESCAPE_CHARACTER_CONFLICT), - ("HV090", SqlState::FDW_INVALID_STRING_LENGTH_OR_BUFFER_LENGTH), - ("HV00R", SqlState::FDW_TABLE_NOT_FOUND), ("42723", SqlState::DUPLICATE_FUNCTION), - ("22009", SqlState::INVALID_TIME_ZONE_DISPLACEMENT_VALUE), - ("HV00N", SqlState::FDW_UNABLE_TO_ESTABLISH_CONNECTION), - ("3B000", SqlState::SAVEPOINT_EXCEPTION), - ("22018", SqlState::INVALID_CHARACTER_VALUE_FOR_CAST), - ("HV004", SqlState::FDW_INVALID_DATA_TYPE), - ("08003", SqlState::CONNECTION_DOES_NOT_EXIST), - ("42P02", SqlState::UNDEFINED_PARAMETER), - ("23001", SqlState::RESTRICT_VIOLATION), - ("HV00C", SqlState::FDW_INVALID_OPTION_INDEX), - ("HV010", SqlState::FDW_FUNCTION_SEQUENCE_ERROR), - ("28P01", SqlState::INVALID_PASSWORD), - ("55000", SqlState::OBJECT_NOT_IN_PREREQUISITE_STATE), - ("2201X", SqlState::INVALID_ROW_COUNT_IN_RESULT_OFFSET_CLAUSE), - ("P0001", SqlState::RAISE_EXCEPTION), - ("25000", SqlState::INVALID_TRANSACTION_STATE), - ("42704", SqlState::UNDEFINED_OBJECT), - ("22022", SqlState::INDICATOR_OVERFLOW), - ("09000", SqlState::TRIGGERED_ACTION_EXCEPTION), - ("22026", SqlState::STRING_DATA_LENGTH_MISMATCH), - ("01007", SqlState::WARNING_PRIVILEGE_NOT_GRANTED), - ("2200H", SqlState::SEQUENCE_GENERATOR_LIMIT_EXCEEDED), - ("25007", SqlState::SCHEMA_AND_DATA_STATEMENT_MIXING_NOT_SUPPORTED), - ("42701", SqlState::DUPLICATE_COLUMN), - ("42P08", SqlState::AMBIGUOUS_PARAMETER), - ("2201B", SqlState::INVALID_REGULAR_EXPRESSION), - ("22036", SqlState::NON_NUMERIC_SQL_JSON_ITEM), - ("22011", SqlState::SUBSTRING_ERROR), - ("0LP01", SqlState::INVALID_GRANT_OPERATION), - ]), + ("40003", SqlState::T_R_STATEMENT_COMPLETION_UNKNOWN), + ("25003", SqlState::INAPPROPRIATE_ACCESS_MODE_FOR_BRANCH_TRANSACTION), + ("02001", SqlState::NO_ADDITIONAL_DYNAMIC_RESULT_SETS_RETURNED), + ("42804", SqlState::DATATYPE_MISMATCH), + ], }; diff --git a/tokio-postgres/src/lib.rs b/tokio-postgres/src/lib.rs index 77713bb11..e9516e0b3 100644 --- a/tokio-postgres/src/lib.rs +++ b/tokio-postgres/src/lib.rs @@ -106,12 +106,14 @@ //! | `runtime` | Enable convenience API for the connection process based on the `tokio` crate. | [tokio](https://crates.io/crates/tokio) 1.0 with the features `net` and `time` | yes | //! | `with-bit-vec-0_6` | Enable support for the `bit-vec` crate. | [bit-vec](https://crates.io/crates/bit-vec) 0.6 | no | //! | `with-chrono-0_4` | Enable support for the `chrono` crate. | [chrono](https://crates.io/crates/chrono) 0.4 | no | -//! | `with-eui48-0_4` | Enable support for the `eui48` crate. | [eui48](https://crates.io/crates/eui48) 0.4 | no | +//! | `with-eui48-0_4` | Enable support for the 0.4 version of the `eui48` crate. | [eui48](https://crates.io/crates/eui48) 0.4 | no | +//! | `with-eui48-1` | Enable support for the 1.0 version of the `eui48` crate. | [eui48](https://crates.io/crates/eui48) 1.0 | no | //! | `with-geo-types-0_6` | Enable support for the 0.6 version of the `geo-types` crate. | [geo-types](https://crates.io/crates/geo-types/0.6.0) 0.6 | no | //! | `with-geo-types-0_7` | Enable support for the 0.7 version of the `geo-types` crate. | [geo-types](https://crates.io/crates/geo-types/0.7.0) 0.7 | no | //! | `with-serde_json-1` | Enable support for the `serde_json` crate. | [serde_json](https://crates.io/crates/serde_json) 1.0 | no | //! | `with-uuid-0_8` | Enable support for the `uuid` crate. | [uuid](https://crates.io/crates/uuid) 0.8 | no | -//! | `with-time-0_2` | Enable support for the `time` crate. | [time](https://crates.io/crates/time) 0.2 | no | +//! | `with-time-0_2` | Enable support for the 0.2 version of the `time` crate. | [time](https://crates.io/crates/time/0.2.0) 0.2 | no | +//! | `with-time-0_3` | Enable support for the 0.3 version of the `time` crate. | [time](https://crates.io/crates/time/0.3.0) 0.3 | no | #![doc(html_root_url = "https://docs.rs/tokio-postgres/0.7")] #![warn(rust_2018_idioms, clippy::all, missing_docs)] diff --git a/tokio-postgres/src/prepare.rs b/tokio-postgres/src/prepare.rs index 49397debf..7a6163415 100644 --- a/tokio-postgres/src/prepare.rs +++ b/tokio-postgres/src/prepare.rs @@ -86,7 +86,7 @@ pub async fn prepare( let mut parameters = vec![]; let mut it = parameter_description.parameters(); while let Some(oid) = it.next().map_err(Error::parse)? { - let type_ = get_type(&client, oid).await?; + let type_ = get_type(client, oid).await?; parameters.push(type_); } @@ -94,13 +94,13 @@ pub async fn prepare( if let Some(row_description) = row_description { let mut it = row_description.fields(); while let Some(field) = it.next().map_err(Error::parse)? { - let type_ = get_type(&client, field.type_oid()).await?; + let type_ = get_type(client, field.type_oid()).await?; let column = Column::new(field.name().to_string(), type_); columns.push(column); } } - Ok(Statement::new(&client, name, parameters, columns)) + Ok(Statement::new(client, name, parameters, columns)) } fn prepare_rec<'a>( @@ -120,7 +120,7 @@ fn encode(client: &InnerClient, name: &str, query: &str, types: &[Type]) -> Resu client.with_buf(|buf| { frontend::parse(name, query, types.iter().map(Type::oid), buf).map_err(Error::encode)?; - frontend::describe(b'S', &name, buf).map_err(Error::encode)?; + frontend::describe(b'S', name, buf).map_err(Error::encode)?; frontend::sync(buf); Ok(buf.split().freeze()) }) diff --git a/tokio-postgres/src/query.rs b/tokio-postgres/src/query.rs index f139ed915..cdb952190 100644 --- a/tokio-postgres/src/query.rs +++ b/tokio-postgres/src/query.rs @@ -99,11 +99,12 @@ where }; let mut responses = start(client, buf).await?; + let mut rows = 0; loop { match responses.next().await? { Message::DataRow(_) => {} Message::CommandComplete(body) => { - let rows = body + rows = body .tag() .map_err(Error::parse)? .rsplit(' ') @@ -111,9 +112,9 @@ where .unwrap() .parse() .unwrap_or(0); - return Ok(rows); } - Message::EmptyQueryResponse => return Ok(0), + Message::EmptyQueryResponse => rows = 0, + Message::ReadyForQuery(_) => return Ok(rows), _ => return Err(Error::unexpected_message()), } } @@ -203,15 +204,17 @@ impl Stream for RowStream { fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); - match ready!(this.responses.poll_next(cx)?) { - Message::DataRow(body) => { - Poll::Ready(Some(Ok(Row::new(this.statement.clone(), body)?))) + loop { + match ready!(this.responses.poll_next(cx)?) { + Message::DataRow(body) => { + return Poll::Ready(Some(Ok(Row::new(this.statement.clone(), body)?))) + } + Message::EmptyQueryResponse + | Message::CommandComplete(_) + | Message::PortalSuspended => {} + Message::ReadyForQuery(_) => return Poll::Ready(None), + _ => return Poll::Ready(Some(Err(Error::unexpected_message()))), } - Message::EmptyQueryResponse - | Message::CommandComplete(_) - | Message::PortalSuspended => Poll::Ready(None), - Message::ErrorResponse(body) => Poll::Ready(Some(Err(Error::db(body)))), - _ => Poll::Ready(Some(Err(Error::unexpected_message()))), } } } diff --git a/tokio-postgres/src/row.rs b/tokio-postgres/src/row.rs index 842216ad2..e3ed696c1 100644 --- a/tokio-postgres/src/row.rs +++ b/tokio-postgres/src/row.rs @@ -1,6 +1,7 @@ //! Rows. use crate::row::sealed::{AsName, Sealed}; +use crate::simple_query::SimpleColumn; use crate::statement::Column; use crate::types::{FromSql, Type, WrongType}; use crate::{Error, Statement}; @@ -188,16 +189,25 @@ impl Row { } } +impl AsName for SimpleColumn { + fn as_name(&self) -> &str { + self.name() + } +} + /// A row of data returned from the database by a simple query. pub struct SimpleQueryRow { - columns: Arc<[String]>, + columns: Arc<[SimpleColumn]>, body: DataRowBody, ranges: Vec>>, } impl SimpleQueryRow { #[allow(clippy::new_ret_no_self)] - pub(crate) fn new(columns: Arc<[String]>, body: DataRowBody) -> Result { + pub(crate) fn new( + columns: Arc<[SimpleColumn]>, + body: DataRowBody, + ) -> Result { let ranges = body.ranges().collect().map_err(Error::parse)?; Ok(SimpleQueryRow { columns, @@ -206,6 +216,11 @@ impl SimpleQueryRow { }) } + /// Returns information about the columns of data in the row. + pub fn columns(&self) -> &[SimpleColumn] { + &self.columns + } + /// Determines if the row contains no values. pub fn is_empty(&self) -> bool { self.len() == 0 diff --git a/tokio-postgres/src/simple_query.rs b/tokio-postgres/src/simple_query.rs index 82ac35664..ade2e1d6d 100644 --- a/tokio-postgres/src/simple_query.rs +++ b/tokio-postgres/src/simple_query.rs @@ -14,6 +14,22 @@ use std::pin::Pin; use std::sync::Arc; use std::task::{Context, Poll}; +/// Information about a column of a single query row. +pub struct SimpleColumn { + name: String, +} + +impl SimpleColumn { + pub(crate) fn new(name: String) -> SimpleColumn { + SimpleColumn { name } + } + + /// Returns the name of the column. + pub fn name(&self) -> &str { + &self.name + } +} + pub async fn simple_query(client: &InnerClient, query: &str) -> Result { debug!("executing simple query: {}", query); @@ -56,7 +72,7 @@ pin_project! { /// A stream of simple query results. pub struct SimpleQueryStream { responses: Responses, - columns: Option>, + columns: Option>, #[pin] _p: PhantomPinned, } @@ -86,10 +102,11 @@ impl Stream for SimpleQueryStream { Message::RowDescription(body) => { let columns = body .fields() - .map(|f| Ok(f.name().to_string())) + .map(|f| Ok(SimpleColumn::new(f.name().to_string()))) .collect::>() .map_err(Error::parse)? .into(); + *this.columns = Some(columns); } Message::DataRow(body) => { diff --git a/tokio-postgres/src/to_statement.rs b/tokio-postgres/src/to_statement.rs index 3ff82493c..427f77dd7 100644 --- a/tokio-postgres/src/to_statement.rs +++ b/tokio-postgres/src/to_statement.rs @@ -47,3 +47,11 @@ impl ToStatement for str { } impl Sealed for str {} + +impl ToStatement for String { + fn __convert(&self) -> ToStatementType<'_> { + ToStatementType::Query(self) + } +} + +impl Sealed for String {} diff --git a/tokio-postgres/src/transaction.rs b/tokio-postgres/src/transaction.rs index a1aa7611f..b72b119bf 100644 --- a/tokio-postgres/src/transaction.rs +++ b/tokio-postgres/src/transaction.rs @@ -201,7 +201,7 @@ impl<'a> Transaction<'a> { I: IntoIterator, I::IntoIter: ExactSizeIterator, { - let statement = statement.__convert().into_statement(&self.client).await?; + let statement = statement.__convert().into_statement(self.client).await?; bind::bind(self.client.inner(), statement, params).await } diff --git a/tokio-postgres/tests/test/main.rs b/tokio-postgres/tests/test/main.rs index c367dbea3..dcfbc5308 100644 --- a/tokio-postgres/tests/test/main.rs +++ b/tokio-postgres/tests/test/main.rs @@ -3,9 +3,12 @@ use bytes::{Bytes, BytesMut}; use futures::channel::mpsc; use futures::{ - future, join, pin_mut, stream, try_join, FutureExt, SinkExt, StreamExt, TryStreamExt, + future, join, pin_mut, stream, try_join, Future, FutureExt, SinkExt, StreamExt, TryStreamExt, }; +use pin_project_lite::pin_project; use std::fmt::Write; +use std::pin::Pin; +use std::task::{Context, Poll}; use std::time::Duration; use tokio::net::TcpStream; use tokio::time; @@ -22,6 +25,35 @@ mod parse; mod runtime; mod types; +pin_project! { + /// Polls `F` at most `polls_left` times returning `Some(F::Output)` if + /// [`Future`] returned [`Poll::Ready`] or [`None`] otherwise. + struct Cancellable { + #[pin] + fut: F, + polls_left: usize, + } +} + +impl Future for Cancellable { + type Output = Option; + + fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll { + let this = self.project(); + match this.fut.poll(ctx) { + Poll::Ready(r) => Poll::Ready(Some(r)), + Poll::Pending => { + *this.polls_left = this.polls_left.saturating_sub(1); + if *this.polls_left == 0 { + Poll::Ready(None) + } else { + Poll::Pending + } + } + } + } +} + async fn connect_raw(s: &str) -> Result<(Client, Connection), Error> { let socket = TcpStream::connect("127.0.0.1:5433").await.unwrap(); let config = s.parse::().unwrap(); @@ -35,6 +67,20 @@ async fn connect(s: &str) -> Client { client } +async fn current_transaction_id(client: &Client) -> i64 { + client + .query("SELECT txid_current()", &[]) + .await + .unwrap() + .pop() + .unwrap() + .get::<_, i64>("txid_current") +} + +async fn in_transaction(client: &Client) -> bool { + current_transaction_id(client).await == current_transaction_id(client).await +} + #[tokio::test] async fn plain_password_missing() { connect_raw("user=pass_user dbname=postgres") @@ -282,6 +328,8 @@ async fn simple_query() { } match &messages[2] { SimpleQueryMessage::Row(row) => { + assert_eq!(row.columns().get(0).map(|c| c.name()), Some("id")); + assert_eq!(row.columns().get(1).map(|c| c.name()), Some("name")); assert_eq!(row.get(0), Some("1")); assert_eq!(row.get(1), Some("steven")); } @@ -289,6 +337,8 @@ async fn simple_query() { } match &messages[3] { SimpleQueryMessage::Row(row) => { + assert_eq!(row.columns().get(0).map(|c| c.name()), Some("id")); + assert_eq!(row.columns().get(1).map(|c| c.name()), Some("name")); assert_eq!(row.get(0), Some("2")); assert_eq!(row.get(1), Some("joe")); } @@ -373,6 +423,80 @@ async fn transaction_rollback() { assert_eq!(rows.len(), 0); } +#[tokio::test] +async fn transaction_future_cancellation() { + let mut client = connect("user=postgres").await; + + for i in 0.. { + let done = { + let txn = client.transaction(); + let fut = Cancellable { + fut: txn, + polls_left: i, + }; + fut.await + .map(|res| res.expect("transaction failed")) + .is_some() + }; + + assert!(!in_transaction(&client).await); + + if done { + break; + } + } +} + +#[tokio::test] +async fn transaction_commit_future_cancellation() { + let mut client = connect("user=postgres").await; + + for i in 0.. { + let done = { + let txn = client.transaction().await.unwrap(); + let commit = txn.commit(); + let fut = Cancellable { + fut: commit, + polls_left: i, + }; + fut.await + .map(|res| res.expect("transaction failed")) + .is_some() + }; + + assert!(!in_transaction(&client).await); + + if done { + break; + } + } +} + +#[tokio::test] +async fn transaction_rollback_future_cancellation() { + let mut client = connect("user=postgres").await; + + for i in 0.. { + let done = { + let txn = client.transaction().await.unwrap(); + let rollback = txn.rollback(); + let fut = Cancellable { + fut: rollback, + polls_left: i, + }; + fut.await + .map(|res| res.expect("transaction failed")) + .is_some() + }; + + assert!(!in_transaction(&client).await); + + if done { + break; + } + } +} + #[tokio::test] async fn transaction_rollback_drop() { let mut client = connect("user=postgres").await; @@ -801,3 +925,29 @@ async fn query_opt() { .err() .unwrap(); } + +#[tokio::test] +async fn deferred_constraint() { + let client = connect("user=postgres").await; + + client + .batch_execute( + " + CREATE TEMPORARY TABLE t ( + i INT, + UNIQUE (i) DEFERRABLE INITIALLY DEFERRED + ); + ", + ) + .await + .unwrap(); + + client + .execute("INSERT INTO t (i) VALUES (1)", &[]) + .await + .unwrap(); + client + .execute("INSERT INTO t (i) VALUES (1)", &[]) + .await + .unwrap_err(); +} diff --git a/tokio-postgres/tests/test/types/eui48_1.rs b/tokio-postgres/tests/test/types/eui48_1.rs new file mode 100644 index 000000000..0c22e9e87 --- /dev/null +++ b/tokio-postgres/tests/test/types/eui48_1.rs @@ -0,0 +1,18 @@ +use eui48_1::MacAddress; + +use crate::types::test_type; + +#[tokio::test] +async fn test_eui48_params() { + test_type( + "MACADDR", + &[ + ( + Some(MacAddress::parse_str("12-34-56-AB-CD-EF").unwrap()), + "'12-34-56-ab-cd-ef'", + ), + (None, "NULL"), + ], + ) + .await +} diff --git a/tokio-postgres/tests/test/types/mod.rs b/tokio-postgres/tests/test/types/mod.rs index bc31ece71..de700d791 100644 --- a/tokio-postgres/tests/test/types/mod.rs +++ b/tokio-postgres/tests/test/types/mod.rs @@ -19,6 +19,8 @@ mod bit_vec_06; mod chrono_04; #[cfg(feature = "with-eui48-0_4")] mod eui48_04; +#[cfg(feature = "with-eui48-1")] +mod eui48_1; #[cfg(feature = "with-geo-types-0_6")] mod geo_types_06; #[cfg(feature = "with-geo-types-0_7")] @@ -27,6 +29,8 @@ mod geo_types_07; mod serde_json_1; #[cfg(feature = "with-time-0_2")] mod time_02; +#[cfg(feature = "with-time-0_3")] +mod time_03; #[cfg(feature = "with-uuid-0_8")] mod uuid_08; @@ -348,7 +352,7 @@ async fn test_hstore_params() { } #[tokio::test] -async fn test_array_params() { +async fn test_array_vec_params() { test_type( "integer[]", &[ @@ -361,6 +365,18 @@ async fn test_array_params() { .await; } +#[cfg(feature = "array-impls")] +#[tokio::test] +async fn test_array_array_params() { + test_type("integer[]", &[(Some([1i32, 2i32]), "ARRAY[1,2]")]).await; + test_type("text[]", &[(Some(["peter".to_string()]), "ARRAY['peter']")]).await; + test_type( + "integer[]", + &[(Some([] as [i32; 0]), "ARRAY[]"), (None, "NULL")], + ) + .await; +} + #[allow(clippy::eq_op)] async fn test_nan_param(sql_type: &str) where @@ -632,3 +648,90 @@ async fn inet() { ) .await; } + +#[tokio::test] +async fn ltree() { + test_type( + "ltree", + &[(Some("b.c.d".to_owned()), "'b.c.d'"), (None, "NULL")], + ) + .await; +} + +#[tokio::test] +async fn ltree_any() { + test_type( + "ltree[]", + &[ + (Some(vec![]), "ARRAY[]"), + (Some(vec!["a.b.c".to_string()]), "ARRAY['a.b.c']"), + ( + Some(vec!["a.b.c".to_string(), "e.f.g".to_string()]), + "ARRAY['a.b.c','e.f.g']", + ), + (None, "NULL"), + ], + ) + .await; +} + +#[tokio::test] +async fn lquery() { + test_type( + "lquery", + &[ + (Some("b.c.d".to_owned()), "'b.c.d'"), + (Some("b.c.*".to_owned()), "'b.c.*'"), + (Some("b.*{1,2}.d|e".to_owned()), "'b.*{1,2}.d|e'"), + (None, "NULL"), + ], + ) + .await; +} + +#[tokio::test] +async fn lquery_any() { + test_type( + "lquery[]", + &[ + (Some(vec![]), "ARRAY[]"), + (Some(vec!["b.c.*".to_string()]), "ARRAY['b.c.*']"), + ( + Some(vec!["b.c.*".to_string(), "b.*{1,2}.d|e".to_string()]), + "ARRAY['b.c.*','b.*{1,2}.d|e']", + ), + (None, "NULL"), + ], + ) + .await; +} + +#[tokio::test] +async fn ltxtquery() { + test_type( + "ltxtquery", + &[ + (Some("b & c & d".to_owned()), "'b & c & d'"), + (Some("b@* & !c".to_owned()), "'b@* & !c'"), + (None, "NULL"), + ], + ) + .await; +} + +#[tokio::test] +async fn ltxtquery_any() { + test_type( + "ltxtquery[]", + &[ + (Some(vec![]), "ARRAY[]"), + (Some(vec!["b & c & d".to_string()]), "ARRAY['b & c & d']"), + ( + Some(vec!["b & c & d".to_string(), "b@* & !c".to_string()]), + "ARRAY['b & c & d','b@* & !c']", + ), + (None, "NULL"), + ], + ) + .await; +} diff --git a/tokio-postgres/tests/test/types/time_03.rs b/tokio-postgres/tests/test/types/time_03.rs new file mode 100644 index 000000000..df013c9bf --- /dev/null +++ b/tokio-postgres/tests/test/types/time_03.rs @@ -0,0 +1,149 @@ +use time_03::{format_description, OffsetDateTime, PrimitiveDateTime}; +use tokio_postgres::types::{Date, Timestamp}; + +use crate::types::test_type; + +// time 0.2 does not [yet?] support parsing fractional seconds +// https://github.com/time-rs/time/issues/226 + +#[tokio::test] +async fn test_primitive_date_time_params() { + fn make_check(time: &str) -> (Option, &str) { + let format = + format_description::parse("'[year]-[month]-[day] [hour]:[minute]:[second]'").unwrap(); + (Some(PrimitiveDateTime::parse(time, &format).unwrap()), time) + } + test_type( + "TIMESTAMP", + &[ + make_check("'1970-01-01 00:00:00'"), // .010000000 + make_check("'1965-09-25 11:19:33'"), // .100314000 + make_check("'2010-02-09 23:11:45'"), // .120200000 + (None, "NULL"), + ], + ) + .await; +} + +#[tokio::test] +async fn test_with_special_primitive_date_time_params() { + fn make_check(time: &str) -> (Timestamp, &str) { + let format = + format_description::parse("'[year]-[month]-[day] [hour]:[minute]:[second]'").unwrap(); + ( + Timestamp::Value(PrimitiveDateTime::parse(time, &format).unwrap()), + time, + ) + } + test_type( + "TIMESTAMP", + &[ + make_check("'1970-01-01 00:00:00'"), // .010000000 + make_check("'1965-09-25 11:19:33'"), // .100314000 + make_check("'2010-02-09 23:11:45'"), // .120200000 + (Timestamp::PosInfinity, "'infinity'"), + (Timestamp::NegInfinity, "'-infinity'"), + ], + ) + .await; +} + +#[tokio::test] +async fn test_offset_date_time_params() { + fn make_check(time: &str) -> (Option, &str) { + let format = + format_description::parse("'[year]-[month]-[day] [hour]:[minute]:[second] [offset_hour sign:mandatory][offset_minute]'").unwrap(); + (Some(OffsetDateTime::parse(time, &format).unwrap()), time) + } + test_type( + "TIMESTAMP WITH TIME ZONE", + &[ + make_check("'1970-01-01 00:00:00 +0000'"), // .010000000 + make_check("'1965-09-25 11:19:33 +0000'"), // .100314000 + make_check("'2010-02-09 23:11:45 +0000'"), // .120200000 + (None, "NULL"), + ], + ) + .await; +} + +#[tokio::test] +async fn test_with_special_offset_date_time_params() { + fn make_check(time: &str) -> (Timestamp, &str) { + let format = + format_description::parse("'[year]-[month]-[day] [hour]:[minute]:[second] [offset_hour sign:mandatory][offset_minute]'").unwrap(); + ( + Timestamp::Value(OffsetDateTime::parse(time, &format).unwrap()), + time, + ) + } + test_type( + "TIMESTAMP WITH TIME ZONE", + &[ + make_check("'1970-01-01 00:00:00 +0000'"), // .010000000 + make_check("'1965-09-25 11:19:33 +0000'"), // .100314000 + make_check("'2010-02-09 23:11:45 +0000'"), // .120200000 + (Timestamp::PosInfinity, "'infinity'"), + (Timestamp::NegInfinity, "'-infinity'"), + ], + ) + .await; +} + +#[tokio::test] +async fn test_date_params() { + fn make_check(date: &str) -> (Option, &str) { + let format = format_description::parse("'[year]-[month]-[day]'").unwrap(); + (Some(time_03::Date::parse(date, &format).unwrap()), date) + } + test_type( + "DATE", + &[ + make_check("'1970-01-01'"), + make_check("'1965-09-25'"), + make_check("'2010-02-09'"), + (None, "NULL"), + ], + ) + .await; +} + +#[tokio::test] +async fn test_with_special_date_params() { + fn make_check(date: &str) -> (Date, &str) { + let format = format_description::parse("'[year]-[month]-[day]'").unwrap(); + ( + Date::Value(time_03::Date::parse(date, &format).unwrap()), + date, + ) + } + test_type( + "DATE", + &[ + make_check("'1970-01-01'"), + make_check("'1965-09-25'"), + make_check("'2010-02-09'"), + (Date::PosInfinity, "'infinity'"), + (Date::NegInfinity, "'-infinity'"), + ], + ) + .await; +} + +#[tokio::test] +async fn test_time_params() { + fn make_check(time: &str) -> (Option, &str) { + let format = format_description::parse("'[hour]:[minute]:[second]'").unwrap(); + (Some(time_03::Time::parse(time, &format).unwrap()), time) + } + test_type( + "TIME", + &[ + make_check("'00:00:00'"), // .010000000 + make_check("'11:19:33'"), // .100314000 + make_check("'23:11:45'"), // .120200000 + (None, "NULL"), + ], + ) + .await; +}