From c1039e78d0b6ea83afa77582ad8593cf09b48828 Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Thu, 5 Sep 2024 12:41:42 +0300 Subject: [PATCH 1/9] Changed query methods to accept slices --- pgrx-examples/pgtrybuilder/Cargo.lock | 2019 ++++++++++++++++++ pgrx-examples/spi/src/lib.rs | 11 +- pgrx-tests/src/tests/aggregate_tests.rs | 4 +- pgrx-tests/src/tests/anyelement_tests.rs | 2 +- pgrx-tests/src/tests/anynumeric_tests.rs | 2 +- pgrx-tests/src/tests/array_tests.rs | 5 +- pgrx-tests/src/tests/bgworker_tests.rs | 6 +- pgrx-tests/src/tests/json_tests.rs | 4 +- pgrx-tests/src/tests/proptests.rs | 2 +- pgrx-tests/src/tests/roundtrip_tests.rs | 2 +- pgrx-tests/src/tests/spi_tests.rs | 17 +- pgrx-tests/tests/todo/roundtrip-tests.rs | 4 +- pgrx-tests/tests/todo/roundtrip-tests.stderr | 6 +- pgrx/src/spi.rs | 10 +- pgrx/src/spi/client.rs | 16 +- pgrx/src/spi/query.rs | 57 +- 16 files changed, 2096 insertions(+), 71 deletions(-) create mode 100644 pgrx-examples/pgtrybuilder/Cargo.lock diff --git a/pgrx-examples/pgtrybuilder/Cargo.lock b/pgrx-examples/pgtrybuilder/Cargo.lock new file mode 100644 index 000000000..69562292b --- /dev/null +++ b/pgrx-examples/pgtrybuilder/Cargo.lock @@ -0,0 +1,2019 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstyle" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" + +[[package]] +name = "anyhow" +version = "1.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f00e1f6e58a40e807377c75c6a7f97bf9044fab57816f2414e6f5f4499d7b8" + +[[package]] +name = "async-trait" +version = "0.1.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atomic-traits" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b29ec3788e96fb4fdb275ccb9d62811f2fa903d76c5eb4dd6fe7d09a7ed5871f" +dependencies = [ + "cfg-if", + "rustc_version", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bindgen" +version = "0.69.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", +] + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" + +[[package]] +name = "camino" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver 1.0.23", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cargo_toml" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a98356df42a2eb1bd8f1793ae4ee4de48e384dd974ce5eac8eee802edb7492be" +dependencies = [ + "serde", + "toml", +] + +[[package]] +name = "cc" +version = "1.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" +dependencies = [ + "shlex", +] + +[[package]] +name = "cee-scape" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d67dfb052149f779f77e9ce089cea126e00657e8f0d11dafc7901fde4291101" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "4.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap-cargo" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2ea69cefa96b848b73ad516ad1d59a195cdf9263087d977f648a818c8b43e" +dependencies = [ + "anstyle", + "cargo_metadata", + "clap", +] + +[[package]] +name = "clap_builder" +version = "4.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" +dependencies = [ + "anstyle", + "clap_lex", +] + +[[package]] +name = "clap_derive" +version = "4.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "enum-map" +version = "2.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9" +dependencies = [ + "enum-map-derive", +] + +[[package]] +name = "enum-map-derive" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-macro", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "half" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "stable_deref_trait", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[package]] +name = "indexmap" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "is-terminal" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +dependencies = [ + "hermit-abi 0.4.0", + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "is_ci" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "libloading" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +dependencies = [ + "cfg-if", + "windows-targets", +] + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "ntapi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +dependencies = [ + "winapi", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "object" +version = "0.36.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "owo-colors" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caff54706df99d2a78a5a4e3455ff45448d81ef1bb63c22cd14052ca0e993a3f" +dependencies = [ + "supports-color", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pathsearch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da983bc5e582ab17179c190b4b66c7d76c5943a69c6d34df2a2b6bf8a2977b05" +dependencies = [ + "anyhow", + "libc", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pest" +version = "2.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c73c26c01b8c87956cea613c907c9d6ecffd8d18a2a5908e5de0adfaa185cea" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "pgrx" +version = "0.12.3" +dependencies = [ + "atomic-traits", + "bitflags", + "bitvec", + "enum-map", + "heapless", + "libc", + "once_cell", + "pgrx-macros", + "pgrx-pg-sys", + "pgrx-sql-entity-graph", + "seahash", + "serde", + "serde_cbor", + "serde_json", + "thiserror", + "uuid", +] + +[[package]] +name = "pgrx-bindgen" +version = "0.12.3" +dependencies = [ + "bindgen", + "clang-sys", + "eyre", + "pgrx-pg-config", + "proc-macro2", + "quote", + "shlex", + "syn", + "walkdir", +] + +[[package]] +name = "pgrx-macros" +version = "0.12.3" +dependencies = [ + "pgrx-sql-entity-graph", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pgrx-pg-config" +version = "0.12.3" +dependencies = [ + "cargo_toml", + "eyre", + "home", + "owo-colors", + "pathsearch", + "serde", + "serde_json", + "thiserror", + "toml", + "url", +] + +[[package]] +name = "pgrx-pg-sys" +version = "0.12.3" +dependencies = [ + "cee-scape", + "libc", + "pgrx-bindgen", + "pgrx-macros", + "pgrx-sql-entity-graph", + "serde", + "sptr", +] + +[[package]] +name = "pgrx-sql-entity-graph" +version = "0.12.3" +dependencies = [ + "convert_case", + "eyre", + "petgraph", + "proc-macro2", + "quote", + "syn", + "thiserror", + "unescape", +] + +[[package]] +name = "pgrx-tests" +version = "0.12.3" +dependencies = [ + "clap-cargo", + "eyre", + "libc", + "owo-colors", + "paste", + "pgrx", + "pgrx-macros", + "pgrx-pg-config", + "postgres", + "proptest", + "rand", + "regex", + "serde", + "serde_json", + "sysinfo", + "thiserror", +] + +[[package]] +name = "pgtrybuilder" +version = "0.0.0" +dependencies = [ + "pgrx", + "pgrx-tests", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "postgres" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c9ec84ab55b0f9e418675de50052d494ba893fd28c65769a6e68fcdacbee2b8" +dependencies = [ + "bytes", + "fallible-iterator", + "futures-util", + "log", + "tokio", + "tokio-postgres", +] + +[[package]] +name = "postgres-protocol" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acda0ebdebc28befa84bee35e651e4c5f09073d668c7aed4cf7e23c3cda84b23" +dependencies = [ + "base64", + "byteorder", + "bytes", + "fallible-iterator", + "hmac", + "md-5", + "memchr", + "rand", + "sha2", + "stringprep", +] + +[[package]] +name = "postgres-types" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02048d9e032fb3cc3413bbf7b83a15d84a5d419778e2628751896d856498eee9" +dependencies = [ + "bytes", + "fallible-iterator", + "postgres-protocol", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + +[[package]] +name = "rustix" +version = "0.38.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f55e80d50763938498dd5ebb18647174e0c76dc38c5505294bb224624f30f36" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +dependencies = [ + "serde", +] + +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +dependencies = [ + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "sptr" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b9b39299b249ad65f3b7e96443bad61c02ca5cd3589f46cb6d610a0fd6c0d6a" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "supports-color" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6398cde53adc3c4557306a96ce67b302968513830a77a95b2b17305d9719a89" +dependencies = [ + "is-terminal", + "is_ci", +] + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sysinfo" +version = "0.30.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a5b4ddaee55fb2bea2bf0e5000747e5f5c0de765e5a5ff87f4cd106439f4bb3" +dependencies = [ + "cfg-if", + "core-foundation-sys", + "libc", + "ntapi", + "once_cell", + "rayon", + "windows", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "thiserror" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-postgres" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03adcf0147e203b6032c0b2d30be1415ba03bc348901f3ff1cc0df6a733e60c3" +dependencies = [ + "async-trait", + "byteorder", + "bytes", + "fallible-iterator", + "futures-channel", + "futures-util", + "log", + "parking_lot", + "percent-encoding", + "phf", + "pin-project-lite", + "postgres-protocol", + "postgres-types", + "rand", + "socket2", + "tokio", + "tokio-util", + "whoami", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unescape" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccb97dac3243214f8d8507998906ca3e2e0b900bf9bf4870477f125b82e68f6e" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-properties" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ea75f83c0137a9b98608359a5f1af8144876eb67bcb1ce837368e906a9f524" + +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "uuid" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +dependencies = [ + "getrandom", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "web-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "whoami" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" +dependencies = [ + "redox_syscall", + "wasite", + "web-sys", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core", + "windows-targets", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/pgrx-examples/spi/src/lib.rs b/pgrx-examples/spi/src/lib.rs index aa9c23e46..a8667050f 100644 --- a/pgrx-examples/spi/src/lib.rs +++ b/pgrx-examples/spi/src/lib.rs @@ -64,7 +64,7 @@ fn spi_query_random_id() -> Result, pgrx::spi::Error> { fn spi_query_title(title: &str) -> Result, pgrx::spi::Error> { Spi::get_one_with_args( "SELECT id FROM spi.spi_example WHERE title = $1;", - vec![(PgBuiltInOids::TEXTOID.oid(), title.into_datum())], + &[(PgBuiltInOids::TEXTOID.oid(), title.into_datum())], ) } @@ -75,7 +75,7 @@ fn spi_query_by_id(id: i64) -> Result, spi::Error> { .select( "SELECT id, title FROM spi.spi_example WHERE id = $1", None, - Some(vec![(PgBuiltInOids::INT8OID.oid(), id.into_datum())]), + Some(&[(PgBuiltInOids::INT8OID.oid(), id.into_datum())]), )? .first(); @@ -90,7 +90,7 @@ fn spi_query_by_id(id: i64) -> Result, spi::Error> { fn spi_insert_title(title: &str) -> Result, spi::Error> { Spi::get_one_with_args( "INSERT INTO spi.spi_example(title) VALUES ($1) RETURNING id", - vec![(PgBuiltInOids::TEXTOID.oid(), title.into_datum())], + &[(PgBuiltInOids::TEXTOID.oid(), title.into_datum())], ) } @@ -100,7 +100,7 @@ fn spi_insert_title2( ) -> TableIterator<(name!(id, Option), name!(title, Option))> { let tuple = Spi::get_two_with_args( "INSERT INTO spi.spi_example(title) VALUES ($1) RETURNING id, title", - vec![(PgBuiltInOids::TEXTOID.oid(), title.into_datum())], + &[(PgBuiltInOids::TEXTOID.oid(), title.into_datum())], ) .unwrap(); @@ -110,7 +110,8 @@ fn spi_insert_title2( #[pg_extern] fn issue1209_fixed() -> Result, Box> { let res = Spi::connect(|c| { - let mut cursor = c.open_cursor("SELECT 'hello' FROM generate_series(1, 10000)", None); + let mut cursor = + c.try_open_cursor("SELECT 'hello' FROM generate_series(1, 10000)", None)?; let table = cursor.fetch(10000)?; table.into_iter().map(|row| row.get::<&str>(1)).collect::, _>>() })?; diff --git a/pgrx-tests/src/tests/aggregate_tests.rs b/pgrx-tests/src/tests/aggregate_tests.rs index a92ca61fa..7b7a4e48b 100644 --- a/pgrx-tests/src/tests/aggregate_tests.rs +++ b/pgrx-tests/src/tests/aggregate_tests.rs @@ -263,7 +263,7 @@ mod tests { fn aggregate_first_json() -> Result<(), pgrx::spi::Error> { let retval = Spi::get_one_with_args::( "SELECT FirstJson(value) FROM UNNEST(ARRAY [$1, $2]) as value;", - vec![ + &[ ( PgBuiltInOids::JSONOID.oid(), pgrx::Json(serde_json::json!({ "foo": "one" })).into_datum(), @@ -285,7 +285,7 @@ mod tests { fn aggregate_first_jsonb() -> Result<(), pgrx::spi::Error> { let retval = Spi::get_one_with_args::( "SELECT FirstJsonB(value) FROM UNNEST(ARRAY [$1, $2]) as value;", - vec![ + &[ ( PgBuiltInOids::JSONBOID.oid(), pgrx::JsonB(serde_json::json!({ "foo": "one" })).into_datum(), diff --git a/pgrx-tests/src/tests/anyelement_tests.rs b/pgrx-tests/src/tests/anyelement_tests.rs index 3ebf81a30..f4355a30c 100644 --- a/pgrx-tests/src/tests/anyelement_tests.rs +++ b/pgrx-tests/src/tests/anyelement_tests.rs @@ -17,7 +17,7 @@ mod tests { fn test_anyelement_arg() -> Result<(), pgrx::spi::Error> { let element = Spi::get_one_with_args::( "SELECT anyelement_arg($1);", - vec![(PgBuiltInOids::ANYELEMENTOID.oid(), 123.into_datum())], + &[(PgBuiltInOids::ANYELEMENTOID.oid(), 123.into_datum())], )? .map(|e| e.datum()); diff --git a/pgrx-tests/src/tests/anynumeric_tests.rs b/pgrx-tests/src/tests/anynumeric_tests.rs index 307931faa..5685ab901 100644 --- a/pgrx-tests/src/tests/anynumeric_tests.rs +++ b/pgrx-tests/src/tests/anynumeric_tests.rs @@ -17,7 +17,7 @@ mod tests { fn test_anynumeric_arg() -> Result<(), pgrx::spi::Error> { let numeric = Spi::get_one_with_args::( "SELECT anynumeric_arg($1);", - vec![(PgBuiltInOids::INT4OID.oid(), 123.into_datum())], + &[(PgBuiltInOids::INT4OID.oid(), 123.into_datum())], )? .map(|n| n.normalize().to_string()); diff --git a/pgrx-tests/src/tests/array_tests.rs b/pgrx-tests/src/tests/array_tests.rs index 855f284a0..9d475ab76 100644 --- a/pgrx-tests/src/tests/array_tests.rs +++ b/pgrx-tests/src/tests/array_tests.rs @@ -300,10 +300,7 @@ mod tests { .select( "SELECT serde_serialize_array_i32($1)", None, - Some(vec![( - PgBuiltInOids::INT4ARRAYOID.oid(), - owned_vec.as_slice().into_datum(), - )]), + Some(&[(PgBuiltInOids::INT4ARRAYOID.oid(), owned_vec.as_slice().into_datum())]), )? .first() .get_one::() diff --git a/pgrx-tests/src/tests/bgworker_tests.rs b/pgrx-tests/src/tests/bgworker_tests.rs index 1846bd366..2b785658b 100644 --- a/pgrx-tests/src/tests/bgworker_tests.rs +++ b/pgrx-tests/src/tests/bgworker_tests.rs @@ -30,7 +30,7 @@ pub extern "C" fn bgworker(arg: pg_sys::Datum) { .update( "INSERT INTO tests.bgworker_test VALUES ($1);", None, - Some(vec![(PgOid::BuiltIn(PgBuiltInOids::INT4OID), arg.into_datum())]), + Some(&[(PgOid::BuiltIn(PgBuiltInOids::INT4OID), arg.into_datum())]), ) .map(|_| ()) }) @@ -63,7 +63,7 @@ pub extern "C" fn bgworker_return_value(arg: pg_sys::Datum) { Spi::run("CREATE TABLE tests.bgworker_test_return (v INTEGER);")?; Spi::get_one_with_args::( "SELECT $1", - vec![(PgOid::BuiltIn(PgBuiltInOids::INT4OID), arg.into_datum())], + &[(PgOid::BuiltIn(PgBuiltInOids::INT4OID), arg.into_datum())], ) }) .expect("bgworker transaction failed") @@ -77,7 +77,7 @@ pub extern "C" fn bgworker_return_value(arg: pg_sys::Datum) { c.update( "INSERT INTO tests.bgworker_test_return VALUES ($1)", None, - Some(vec![(PgOid::BuiltIn(PgBuiltInOids::INT4OID), val.into_datum())]), + Some(&[(PgOid::BuiltIn(PgBuiltInOids::INT4OID), val.into_datum())]), ) .map(|_| ()) }) diff --git a/pgrx-tests/src/tests/json_tests.rs b/pgrx-tests/src/tests/json_tests.rs index 7a54cc766..c481a9147 100644 --- a/pgrx-tests/src/tests/json_tests.rs +++ b/pgrx-tests/src/tests/json_tests.rs @@ -79,7 +79,7 @@ mod tests { fn test_json_arg() -> Result<(), pgrx::spi::Error> { let json = Spi::get_one_with_args::( "SELECT json_arg($1);", - vec![( + &[( PgBuiltInOids::JSONOID.oid(), Json(serde_json::json!({ "foo": "bar" })).into_datum(), )], @@ -95,7 +95,7 @@ mod tests { fn test_jsonb_arg() -> Result<(), pgrx::spi::Error> { let json = Spi::get_one_with_args::( "SELECT jsonb_arg($1);", - vec![( + &[( PgBuiltInOids::JSONBOID.oid(), JsonB(serde_json::json!({ "foo": "bar" })).into_datum(), )], diff --git a/pgrx-tests/src/tests/proptests.rs b/pgrx-tests/src/tests/proptests.rs index 49e79a3f7..fabab034d 100644 --- a/pgrx-tests/src/tests/proptests.rs +++ b/pgrx-tests/src/tests/proptests.rs @@ -32,7 +32,7 @@ pub fn [<$datetime_ty:lower _spi_roundtrip>] () { .run(&strat, |datetime| { let query = concat!("SELECT ", stringify!($nop_fn), "($1)"); let builtin_oid = PgOid::BuiltIn(pg_sys::BuiltinOid::from_u32(<$datetime_ty as IntoDatum>::type_oid().as_u32()).unwrap()); - let args = vec![(builtin_oid, datetime.into_datum())]; + let args = &[(builtin_oid, datetime.into_datum())]; let spi_ret: $datetime_ty = Spi::get_one_with_args(query, args).unwrap().unwrap(); // 5. A condition on which the test is accepted or rejected: // this is easily done via `prop_assert!` and its friends, diff --git a/pgrx-tests/src/tests/roundtrip_tests.rs b/pgrx-tests/src/tests/roundtrip_tests.rs index e8ee4f740..935ed16ca 100644 --- a/pgrx-tests/src/tests/roundtrip_tests.rs +++ b/pgrx-tests/src/tests/roundtrip_tests.rs @@ -79,7 +79,7 @@ mod tests { let expected: $rtype = Clone::clone(&value); let result: $rtype = Spi::get_one_with_args( &format!("SELECT {}($1)", stringify!(tests.$fname)), - vec![(PgOid::from(<$rtype>::type_oid()), value.into_datum())], + &[(PgOid::from(<$rtype>::type_oid()), value.into_datum())], )? .unwrap(); diff --git a/pgrx-tests/src/tests/spi_tests.rs b/pgrx-tests/src/tests/spi_tests.rs index 23cd16fba..cfd0b2ae2 100644 --- a/pgrx-tests/src/tests/spi_tests.rs +++ b/pgrx-tests/src/tests/spi_tests.rs @@ -137,7 +137,7 @@ mod tests { assert!(Spi::run_with_args( "SELECT $1 + $2 = 3", - Some(vec![ + Some(&[ (PgBuiltInOids::INT4OID.oid(), Some(i.into())), (PgBuiltInOids::INT8OID.oid(), Some(j.into())), ]), @@ -159,7 +159,7 @@ mod tests { let result = Spi::explain_with_args( "SELECT $1 + $2 = 3", - Some(vec![ + Some(&[ (PgBuiltInOids::INT4OID.oid(), Some(i.into())), (PgBuiltInOids::INT8OID.oid(), Some(j.into())), ]), @@ -187,7 +187,7 @@ mod tests { assert_eq!( Spi::get_one_with_args::( "INSERT INTO tests.null_test VALUES ($1) RETURNING 1", - vec![(PgBuiltInOids::UUIDOID.oid(), None)], + &[(PgBuiltInOids::UUIDOID.oid(), None)], )? .unwrap(), 1 @@ -252,17 +252,16 @@ mod tests { #[pg_test] #[should_panic(expected = "PreparedStatementArgumentMismatch { expected: 1, got: 0 }")] fn test_cursor_prepared_statement_panics_less_args() -> Result<(), pgrx::spi::Error> { - test_cursor_prepared_statement_panics_impl(Some([].to_vec())) + test_cursor_prepared_statement_panics_impl(Some(&[][..])) } #[pg_test] #[should_panic(expected = "PreparedStatementArgumentMismatch { expected: 1, got: 2 }")] fn test_cursor_prepared_statement_panics_more_args() -> Result<(), pgrx::spi::Error> { - test_cursor_prepared_statement_panics_impl(Some([None, None].to_vec())) + test_cursor_prepared_statement_panics_impl(Some(&[None, None])) } - fn test_cursor_prepared_statement_panics_impl( - args: Option>>, + args: Option<&[Option]>, ) -> Result<(), pgrx::spi::Error> { Spi::connect(|mut client| { client.update("CREATE TABLE tests.cursor_table (id int)", None, None)?; @@ -397,7 +396,7 @@ mod tests { let rc = Spi::connect(|client| { let prepared = client.prepare("SELECT $1", Some(vec![PgOid::BuiltIn(PgBuiltInOids::INT4OID)]))?; - client.select(&prepared, None, Some(vec![42.into_datum()]))?.first().get::(1) + client.select(&prepared, None, Some(&[42.into_datum()]))?.first().get::(1) })?; assert_eq!(42, rc.expect("SPI failed to return proper value")); @@ -429,7 +428,7 @@ mod tests { ) })?; let rc = Spi::connect(|client| { - client.select(&prepared, None, Some(vec![42.into_datum()]))?.first().get::(1) + client.select(&prepared, None, Some(&[42.into_datum()]))?.first().get::(1) })?; assert_eq!(Some(42), rc); diff --git a/pgrx-tests/tests/todo/roundtrip-tests.rs b/pgrx-tests/tests/todo/roundtrip-tests.rs index 0379ba5fd..b0072e6ba 100644 --- a/pgrx-tests/tests/todo/roundtrip-tests.rs +++ b/pgrx-tests/tests/todo/roundtrip-tests.rs @@ -1,9 +1,9 @@ fn main() {} mod tests { + use pgrx::prelude::*; use std::error::Error; use std::ffi::CStr; - use pgrx::prelude::*; #[allow(unused_imports)] use crate as pgrx_tests; @@ -35,7 +35,7 @@ mod tests { let expected: $rtype = Clone::clone(&value); let result: $rtype = Spi::get_one_with_args( &format!("SELECT {}($1)", stringify!(tests.$fname)), - vec![(PgOid::from(<$rtype>::type_oid()), value.into_datum())], + &[(PgOid::from(<$rtype>::type_oid()), value.into_datum())], )? .unwrap(); diff --git a/pgrx-tests/tests/todo/roundtrip-tests.stderr b/pgrx-tests/tests/todo/roundtrip-tests.stderr index 3f2467398..71a7a418a 100644 --- a/pgrx-tests/tests/todo/roundtrip-tests.stderr +++ b/pgrx-tests/tests/todo/roundtrip-tests.stderr @@ -79,7 +79,7 @@ error[E0277]: the trait bound `Vec>: FromDatum` is not satisfied 36 | let result: $rtype = Spi::get_one_with_args( | ______________________________________^ 37 | | &format!("SELECT {}($1)", stringify!(tests.$fname)), -38 | | vec![(PgOid::from(<$rtype>::type_oid()), value.into_datum())], +38 | | &[(PgOid::from(<$rtype>::type_oid()), value.into_datum())], 39 | | )? | |_________________^ the trait `FromDatum` is not implemented for `Vec>` ... @@ -109,7 +109,7 @@ error[E0277]: the trait bound `Vec>: FromDatum` is not satisfied 36 | let result: $rtype = Spi::get_one_with_args( | ______________________________________^ 37 | | &format!("SELECT {}($1)", stringify!(tests.$fname)), -38 | | vec![(PgOid::from(<$rtype>::type_oid()), value.into_datum())], +38 | | &[(PgOid::from(<$rtype>::type_oid()), value.into_datum())], 39 | | )? | |_________________^ the trait `FromDatum` is not implemented for `Vec>` ... @@ -164,7 +164,7 @@ error[E0277]: the trait bound `Vec>: FromDatum` is not satisfied 36 | let result: $rtype = Spi::get_one_with_args( | ______________________________________^ 37 | | &format!("SELECT {}($1)", stringify!(tests.$fname)), -38 | | vec![(PgOid::from(<$rtype>::type_oid()), value.into_datum())], +38 | | &[(PgOid::from(<$rtype>::type_oid()), value.into_datum())], 39 | | )? | |_________________^ the trait `FromDatum` is not implemented for `Vec>` ... diff --git a/pgrx/src/spi.rs b/pgrx/src/spi.rs index 9aa260d04..1239b89c3 100644 --- a/pgrx/src/spi.rs +++ b/pgrx/src/spi.rs @@ -261,14 +261,14 @@ impl Spi { pub fn get_one_with_args( query: &str, - args: Vec<(PgOid, Option)>, + args: &[(PgOid, Option)], ) -> Result> { Spi::connect(|mut client| client.update(query, Some(1), Some(args))?.first().get_one()) } pub fn get_two_with_args( query: &str, - args: Vec<(PgOid, Option)>, + args: &[(PgOid, Option)], ) -> Result<(Option, Option)> { Spi::connect(|mut client| { client.update(query, Some(1), Some(args))?.first().get_two::() @@ -281,7 +281,7 @@ impl Spi { C: FromDatum + IntoDatum, >( query: &str, - args: Vec<(PgOid, Option)>, + args: &[(PgOid, Option)], ) -> Result<(Option, Option, Option)> { Spi::connect(|mut client| { client.update(query, Some(1), Some(args))?.first().get_three::() @@ -304,7 +304,7 @@ impl Spi { /// The statement runs in read/write mode pub fn run_with_args( query: &str, - args: Option)>>, + args: Option<&[(PgOid, Option)]>, ) -> std::result::Result<(), Error> { Spi::connect(|mut client| client.update(query, None, args).map(|_| ())) } @@ -317,7 +317,7 @@ impl Spi { /// explain a query with args, returning its result in json form pub fn explain_with_args( query: &str, - args: Option)>>, + args: Option<&[(PgOid, Option)]>, ) -> Result { Ok(Spi::connect(|mut client| { client diff --git a/pgrx/src/spi/client.rs b/pgrx/src/spi/client.rs index e32728d74..4a66d3f41 100644 --- a/pgrx/src/spi/client.rs +++ b/pgrx/src/spi/client.rs @@ -74,7 +74,7 @@ impl<'conn> SpiClient<'conn> { &self, query: Q, limit: Option, - args: Q::Arguments, + args: Option<&[Q::Argument]>, ) -> SpiResult> { query.execute(self, limit, args) } @@ -84,7 +84,7 @@ impl<'conn> SpiClient<'conn> { &mut self, query: Q, limit: Option, - args: Q::Arguments, + args: Option<&[Q::Argument]>, ) -> SpiResult> { Spi::mark_mutable(); query.execute(self, limit, args) @@ -123,7 +123,11 @@ impl<'conn> SpiClient<'conn> { /// # Panics /// /// Panics if a cursor wasn't opened. - pub fn open_cursor>(&self, query: Q, args: Q::Arguments) -> SpiCursor<'conn> { + pub fn open_cursor>( + &self, + query: Q, + args: Option<&[Q::Argument]>, + ) -> SpiCursor<'conn> { self.try_open_cursor(query, args).unwrap() } @@ -135,7 +139,7 @@ impl<'conn> SpiClient<'conn> { pub fn try_open_cursor>( &self, query: Q, - args: Q::Arguments, + args: Option<&[Q::Argument]>, ) -> SpiResult> { query.try_open_cursor(self, args) } @@ -154,7 +158,7 @@ impl<'conn> SpiClient<'conn> { pub fn open_cursor_mut>( &mut self, query: Q, - args: Q::Arguments, + args: Option<&[Q::Argument]>, ) -> SpiCursor<'conn> { Spi::mark_mutable(); self.try_open_cursor_mut(query, args).unwrap() @@ -168,7 +172,7 @@ impl<'conn> SpiClient<'conn> { pub fn try_open_cursor_mut>( &mut self, query: Q, - args: Q::Arguments, + args: Option<&[Q::Argument]>, ) -> SpiResult> { Spi::mark_mutable(); query.try_open_cursor(self, args) diff --git a/pgrx/src/spi/query.rs b/pgrx/src/spi/query.rs index 2f4178bf4..1948e4e6f 100644 --- a/pgrx/src/spi/query.rs +++ b/pgrx/src/spi/query.rs @@ -14,14 +14,14 @@ use crate::pg_sys::{self, PgOid}; /// one-off statements and prepared statements, but it can potentially /// be implemented for other types, provided they can be converted into a query. pub trait Query<'conn>: Sized { - type Arguments; + type Argument; /// Execute a query given a client and other arguments. fn execute( self, client: &SpiClient<'conn>, limit: Option, - args: Self::Arguments, + args: Option<&[Self::Argument]>, ) -> SpiResult>; /// Open a cursor for the query. @@ -29,7 +29,12 @@ pub trait Query<'conn>: Sized { /// # Panics /// /// Panics if a cursor wasn't opened. - fn open_cursor(self, client: &SpiClient<'conn>, args: Self::Arguments) -> SpiCursor<'conn> { + #[deprecated(since = "0.12.2", note = "undefined behavior")] + fn open_cursor( + self, + client: &SpiClient<'conn>, + args: Option<&[Self::Argument]>, + ) -> SpiCursor<'conn> { self.try_open_cursor(client, args).unwrap() } @@ -37,18 +42,18 @@ pub trait Query<'conn>: Sized { fn try_open_cursor( self, client: &SpiClient<'conn>, - args: Self::Arguments, + args: Option<&[Self::Argument]>, ) -> SpiResult>; } impl<'conn> Query<'conn> for &String { - type Arguments = Option)>>; + type Argument = (PgOid, Option); fn execute( self, client: &SpiClient<'conn>, limit: Option, - args: Self::Arguments, + args: Option<&[Self::Argument]>, ) -> SpiResult> { self.as_str().execute(client, limit, args) } @@ -56,21 +61,21 @@ impl<'conn> Query<'conn> for &String { fn try_open_cursor( self, client: &SpiClient<'conn>, - args: Self::Arguments, + args: Option<&[Self::Argument]>, ) -> SpiResult> { self.as_str().try_open_cursor(client, args) } } -fn prepare_datum(datum: Option) -> (pg_sys::Datum, std::os::raw::c_char) { +fn prepare_datum(datum: &Option) -> (pg_sys::Datum, std::os::raw::c_char) { match datum { - Some(datum) => (datum, ' ' as std::os::raw::c_char), + Some(datum) => (*datum, ' ' as std::os::raw::c_char), None => (pg_sys::Datum::from(0usize), 'n' as std::os::raw::c_char), } } fn args_to_datums( - args: Vec<(PgOid, Option)>, + args: &[(PgOid, Option)], ) -> (Vec, Vec, Vec) { let mut argtypes = Vec::with_capacity(args.len()); let mut datums = Vec::with_capacity(args.len()); @@ -88,7 +93,7 @@ fn args_to_datums( } impl<'conn> Query<'conn> for &str { - type Arguments = Option)>>; + type Argument = (PgOid, Option); /// # Panics /// @@ -97,7 +102,7 @@ impl<'conn> Query<'conn> for &str { self, _client: &SpiClient<'conn>, limit: Option, - args: Self::Arguments, + args: Option<&[Self::Argument]>, ) -> SpiResult> { // SAFETY: no concurrent access unsafe { @@ -139,7 +144,7 @@ impl<'conn> Query<'conn> for &str { fn try_open_cursor( self, _client: &SpiClient<'conn>, - args: Self::Arguments, + args: Option<&[Self::Argument]>, ) -> SpiResult> { let src = CString::new(self).expect("query contained a null byte"); let args = args.unwrap_or_default(); @@ -192,13 +197,13 @@ impl Drop for OwnedPreparedStatement { } impl<'conn> Query<'conn> for &OwnedPreparedStatement { - type Arguments = Option>>; + type Argument = <::Target as Query<'static>>::Argument; fn execute( self, client: &SpiClient<'conn>, limit: Option, - args: Self::Arguments, + args: Option<&[Self::Argument]>, ) -> SpiResult> { (&self.0).execute(client, limit, args) } @@ -206,20 +211,20 @@ impl<'conn> Query<'conn> for &OwnedPreparedStatement { fn try_open_cursor( self, client: &SpiClient<'conn>, - args: Self::Arguments, + args: Option<&[Self::Argument]>, ) -> SpiResult> { (&self.0).try_open_cursor(client, args) } } impl<'conn> Query<'conn> for OwnedPreparedStatement { - type Arguments = Option>>; + type Argument = <::Target as Query<'static>>::Argument; fn execute( self, client: &SpiClient<'conn>, limit: Option, - args: Self::Arguments, + args: Option<&[Self::Argument]>, ) -> SpiResult> { (&self.0).execute(client, limit, args) } @@ -227,7 +232,7 @@ impl<'conn> Query<'conn> for OwnedPreparedStatement { fn try_open_cursor( self, client: &SpiClient<'conn>, - args: Self::Arguments, + args: Option<&[Self::Argument]>, ) -> SpiResult> { (&self.0).try_open_cursor(client, args) } @@ -253,7 +258,7 @@ impl<'conn> PreparedStatement<'conn> { fn args_to_datums( &self, - args: >::Arguments, + args: Option<&[>::Argument]>, ) -> SpiResult<(Vec, Vec)> { let args = args.unwrap_or_default(); @@ -269,13 +274,13 @@ impl<'conn> PreparedStatement<'conn> { } impl<'conn: 'stmt, 'stmt> Query<'conn> for &'stmt PreparedStatement<'conn> { - type Arguments = Option>>; + type Argument = Option; fn execute( self, _client: &SpiClient<'conn>, limit: Option, - args: Self::Arguments, + args: Option<&[Self::Argument]>, ) -> SpiResult> { // SAFETY: no concurrent access unsafe { @@ -301,7 +306,7 @@ impl<'conn: 'stmt, 'stmt> Query<'conn> for &'stmt PreparedStatement<'conn> { fn try_open_cursor( self, _client: &SpiClient<'conn>, - args: Self::Arguments, + args: Option<&[Self::Argument]>, ) -> SpiResult> { let (mut datums, nulls) = self.args_to_datums(args)?; @@ -321,13 +326,13 @@ impl<'conn: 'stmt, 'stmt> Query<'conn> for &'stmt PreparedStatement<'conn> { } impl<'conn> Query<'conn> for PreparedStatement<'conn> { - type Arguments = Option>>; + type Argument = Option; fn execute( self, client: &SpiClient<'conn>, limit: Option, - args: Self::Arguments, + args: Option<&[Self::Argument]>, ) -> SpiResult> { (&self).execute(client, limit, args) } @@ -335,7 +340,7 @@ impl<'conn> Query<'conn> for PreparedStatement<'conn> { fn try_open_cursor( self, client: &SpiClient<'conn>, - args: Self::Arguments, + args: Option<&[Self::Argument]>, ) -> SpiResult> { (&self).try_open_cursor(client, args) } From 9e5c28b0209009f1866782fead812400c2458039 Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Mon, 9 Sep 2024 15:57:51 +0300 Subject: [PATCH 2/9] Passing command arguments without Option --- pgrx-examples/bgworker/src/lib.rs | 2 +- pgrx-examples/custom_sql/src/lib.rs | 2 +- pgrx-examples/schemas/src/lib.rs | 4 +- pgrx-examples/spi/src/lib.rs | 6 +- pgrx-examples/spi_srf/src/lib.rs | 4 +- pgrx-tests/src/tests/array_tests.rs | 2 +- pgrx-tests/src/tests/bgworker_tests.rs | 4 +- pgrx-tests/src/tests/heap_tuple.rs | 2 +- pgrx-tests/src/tests/pg_cast_tests.rs | 8 +- pgrx-tests/src/tests/spi_tests.rs | 121 +++++++++--------- pgrx-tests/src/tests/srf_tests.rs | 21 +-- pgrx-tests/src/tests/struct_type_tests.rs | 6 +- .../escaping-spiclient-1209-cursor.rs | 4 +- .../escaping-spiclient-1209-cursor.stderr | 14 +- .../escaping-spiclient-1209-prep-stmt.rs | 2 +- pgrx/src/spi.rs | 27 ++-- pgrx/src/spi/client.rs | 16 +-- pgrx/src/spi/cursor.rs | 4 +- pgrx/src/spi/query.rs | 60 ++++----- 19 files changed, 148 insertions(+), 161 deletions(-) diff --git a/pgrx-examples/bgworker/src/lib.rs b/pgrx-examples/bgworker/src/lib.rs index 0f8ac54dd..16770ddcf 100644 --- a/pgrx-examples/bgworker/src/lib.rs +++ b/pgrx-examples/bgworker/src/lib.rs @@ -69,7 +69,7 @@ pub extern "C" fn background_worker_main(arg: pg_sys::Datum) { let tuple_table = client.select( "SELECT 'Hi', id, ''||a FROM (SELECT id, 42 from generate_series(1,10) id) a ", None, - None, + &[][..], )?; for tuple in tuple_table { let a = tuple.get_datum_by_ordinal(1)?.value::()?; diff --git a/pgrx-examples/custom_sql/src/lib.rs b/pgrx-examples/custom_sql/src/lib.rs index 5f2a1be98..602f67c6a 100644 --- a/pgrx-examples/custom_sql/src/lib.rs +++ b/pgrx-examples/custom_sql/src/lib.rs @@ -89,7 +89,7 @@ mod tests { let buf = Spi::connect(|client| { Ok::<_, spi::Error>( client - .select("SELECT * FROM extension_sql", None, None)? + .select("SELECT * FROM extension_sql", None, &[][..])? .flat_map(|tup| { tup.get_datum_by_ordinal(1) .ok() diff --git a/pgrx-examples/schemas/src/lib.rs b/pgrx-examples/schemas/src/lib.rs index ec67c7f1a..5b83373dc 100644 --- a/pgrx-examples/schemas/src/lib.rs +++ b/pgrx-examples/schemas/src/lib.rs @@ -103,10 +103,10 @@ mod tests { fn test_my_some_schema_type() -> Result<(), spi::Error> { Spi::connect(|mut c| { // "MySomeSchemaType" is in 'some_schema', so it needs to be discoverable - c.update("SET search_path TO some_schema,public", None, None)?; + c.update("SET search_path TO some_schema,public", None, &[][..])?; assert_eq!( String::from("test"), - c.select("SELECT '\"test\"'::MySomeSchemaType", None, None)? + c.select("SELECT '\"test\"'::MySomeSchemaType", None, &[][..])? .first() .get_one::() .expect("get_one::() failed") diff --git a/pgrx-examples/spi/src/lib.rs b/pgrx-examples/spi/src/lib.rs index a8667050f..8a1b5a08d 100644 --- a/pgrx-examples/spi/src/lib.rs +++ b/pgrx-examples/spi/src/lib.rs @@ -48,7 +48,7 @@ fn spi_return_query() -> Result< Spi::connect(|client| { client - .select(query, None, None)? + .select(query, None, &[][..])? .map(|row| Ok((row["oid"].value()?, row[2].value()?))) .collect::, _>>() }) @@ -75,7 +75,7 @@ fn spi_query_by_id(id: i64) -> Result, spi::Error> { .select( "SELECT id, title FROM spi.spi_example WHERE id = $1", None, - Some(&[(PgBuiltInOids::INT8OID.oid(), id.into_datum())]), + &[(PgBuiltInOids::INT8OID.oid(), id.into_datum())], )? .first(); @@ -111,7 +111,7 @@ fn spi_insert_title2( fn issue1209_fixed() -> Result, Box> { let res = Spi::connect(|c| { let mut cursor = - c.try_open_cursor("SELECT 'hello' FROM generate_series(1, 10000)", None)?; + c.try_open_cursor("SELECT 'hello' FROM generate_series(1, 10000)", &[][..])?; let table = cursor.fetch(10000)?; table.into_iter().map(|row| row.get::<&str>(1)).collect::, _>>() })?; diff --git a/pgrx-examples/spi_srf/src/lib.rs b/pgrx-examples/spi_srf/src/lib.rs index f1f2a9a17..125ec0c65 100644 --- a/pgrx-examples/spi_srf/src/lib.rs +++ b/pgrx-examples/spi_srf/src/lib.rs @@ -55,7 +55,7 @@ fn calculate_human_years() -> Result< Spi::connect(|client| { let mut results = Vec::new(); - let tup_table = client.select(query, None, None)?; + let tup_table = client.select(query, None, &[][..])?; for row in tup_table { let dog_name = row["dog_name"].value::(); @@ -92,7 +92,7 @@ fn filter_by_breed( let args = vec![(PgBuiltInOids::TEXTOID.oid(), breed.into_datum())]; Spi::connect(|client| { - let tup_table = client.select(query, None, Some(args))?; + let tup_table = client.select(query, None, &args)?; let filtered = tup_table .map(|row| { diff --git a/pgrx-tests/src/tests/array_tests.rs b/pgrx-tests/src/tests/array_tests.rs index 9d475ab76..b5bbae76b 100644 --- a/pgrx-tests/src/tests/array_tests.rs +++ b/pgrx-tests/src/tests/array_tests.rs @@ -300,7 +300,7 @@ mod tests { .select( "SELECT serde_serialize_array_i32($1)", None, - Some(&[(PgBuiltInOids::INT4ARRAYOID.oid(), owned_vec.as_slice().into_datum())]), + &[(PgBuiltInOids::INT4ARRAYOID.oid(), owned_vec.as_slice().into_datum())], )? .first() .get_one::() diff --git a/pgrx-tests/src/tests/bgworker_tests.rs b/pgrx-tests/src/tests/bgworker_tests.rs index 2b785658b..03509c290 100644 --- a/pgrx-tests/src/tests/bgworker_tests.rs +++ b/pgrx-tests/src/tests/bgworker_tests.rs @@ -30,7 +30,7 @@ pub extern "C" fn bgworker(arg: pg_sys::Datum) { .update( "INSERT INTO tests.bgworker_test VALUES ($1);", None, - Some(&[(PgOid::BuiltIn(PgBuiltInOids::INT4OID), arg.into_datum())]), + &[(PgOid::BuiltIn(PgBuiltInOids::INT4OID), arg.into_datum())], ) .map(|_| ()) }) @@ -77,7 +77,7 @@ pub extern "C" fn bgworker_return_value(arg: pg_sys::Datum) { c.update( "INSERT INTO tests.bgworker_test_return VALUES ($1)", None, - Some(&[(PgOid::BuiltIn(PgBuiltInOids::INT4OID), val.into_datum())]), + &[(PgOid::BuiltIn(PgBuiltInOids::INT4OID), val.into_datum())], ) .map(|_| ()) }) diff --git a/pgrx-tests/src/tests/heap_tuple.rs b/pgrx-tests/src/tests/heap_tuple.rs index 02efaab99..17a0db09f 100644 --- a/pgrx-tests/src/tests/heap_tuple.rs +++ b/pgrx-tests/src/tests/heap_tuple.rs @@ -881,7 +881,7 @@ mod tests { fn test_tuple_desc_clone() -> Result<(), spi::Error> { let result = Spi::connect(|client| { let query = "select * from generate_lots_of_dogs()"; - client.select(query, None, None).map(|table| table.len()) + client.select(query, None, &[][..]).map(|table| table.len()) })?; assert_eq!(result, 10_000); Ok(()) diff --git a/pgrx-tests/src/tests/pg_cast_tests.rs b/pgrx-tests/src/tests/pg_cast_tests.rs index 12178050c..a27f9c5be 100644 --- a/pgrx-tests/src/tests/pg_cast_tests.rs +++ b/pgrx-tests/src/tests/pg_cast_tests.rs @@ -48,8 +48,12 @@ mod tests { #[pg_test] fn test_pg_cast_assignment_type_cast() { let _ = Spi::connect(|mut client| { - client.update("CREATE TABLE test_table(value int4);", None, None)?; - client.update("INSERT INTO test_table VALUES('{\"a\": 1}'::json->'a');", None, None)?; + client.update("CREATE TABLE test_table(value int4);", None, &[][..])?; + client.update( + "INSERT INTO test_table VALUES('{\"a\": 1}'::json->'a');", + None, + &[][..], + )?; Ok::<_, spi::Error>(()) }); diff --git a/pgrx-tests/src/tests/spi_tests.rs b/pgrx-tests/src/tests/spi_tests.rs index cfd0b2ae2..8ef08e7d3 100644 --- a/pgrx-tests/src/tests/spi_tests.rs +++ b/pgrx-tests/src/tests/spi_tests.rs @@ -21,7 +21,7 @@ mod tests { #[pg_test(error = "syntax error at or near \"THIS\"")] fn test_spi_failure() -> Result<(), spi::Error> { - Spi::connect(|client| client.select("THIS IS NOT A VALID QUERY", None, None).map(|_| ())) + Spi::connect(|client| client.select("THIS IS NOT A VALID QUERY", None, &[][..]).map(|_| ())) } #[pg_test] @@ -33,8 +33,9 @@ mod tests { #[pg_test] fn test_spi_returns_primitive() -> Result<(), spi::Error> { - let rc = - Spi::connect(|client| client.select("SELECT 42", None, None)?.first().get::(1))?; + let rc = Spi::connect(|client| { + client.select("SELECT 42", None, &[][..])?.first().get::(1) + })?; assert_eq!(Some(42), rc); Ok(()) @@ -43,7 +44,7 @@ mod tests { #[pg_test] fn test_spi_returns_str() -> Result<(), spi::Error> { let rc = Spi::connect(|client| { - client.select("SELECT 'this is a test'", None, None)?.first().get::<&str>(1) + client.select("SELECT 'this is a test'", None, &[][..])?.first().get::<&str>(1) })?; assert_eq!(Some("this is a test"), rc); @@ -53,7 +54,7 @@ mod tests { #[pg_test] fn test_spi_returns_string() -> Result<(), spi::Error> { let rc = Spi::connect(|client| { - client.select("SELECT 'this is a test'", None, None)?.first().get::<&str>(1) + client.select("SELECT 'this is a test'", None, &[][..])?.first().get::<&str>(1) })?; assert_eq!(Some("this is a test"), rc); @@ -63,7 +64,7 @@ mod tests { #[pg_test] fn test_spi_get_one() -> Result<(), spi::Error> { Spi::connect(|client| { - let i = client.select("SELECT 42::bigint", None, None)?.first().get_one::()?; + let i = client.select("SELECT 42::bigint", None, &[][..])?.first().get_one::()?; assert_eq!(Some(42), i); Ok(()) }) @@ -72,8 +73,10 @@ mod tests { #[pg_test] fn test_spi_get_two() -> Result<(), spi::Error> { Spi::connect(|client| { - let (i, s) = - client.select("SELECT 42, 'test'", None, None)?.first().get_two::()?; + let (i, s) = client + .select("SELECT 42, 'test'", None, &[][..])? + .first() + .get_two::()?; assert_eq!(Some(42), i); assert_eq!(Some("test"), s); @@ -85,7 +88,7 @@ mod tests { fn test_spi_get_three() -> Result<(), spi::Error> { Spi::connect(|client| { let (i, s, b) = client - .select("SELECT 42, 'test', true", None, None)? + .select("SELECT 42, 'test', true", None, &[][..])? .first() .get_three::()?; @@ -100,7 +103,7 @@ mod tests { fn test_spi_get_two_with_failure() -> Result<(), spi::Error> { Spi::connect(|client| { assert!(client - .select("SELECT 42", None, None)? + .select("SELECT 42", None, &[][..])? .first() .get_two::() .is_err()); @@ -112,7 +115,7 @@ mod tests { fn test_spi_get_three_failure() -> Result<(), spi::Error> { Spi::connect(|client| { assert!(client - .select("SELECT 42, 'test'", None, None)? + .select("SELECT 42, 'test'", None, &[][..])? .first() .get_three::() .is_err()); @@ -137,10 +140,10 @@ mod tests { assert!(Spi::run_with_args( "SELECT $1 + $2 = 3", - Some(&[ + &[ (PgBuiltInOids::INT4OID.oid(), Some(i.into())), (PgBuiltInOids::INT8OID.oid(), Some(j.into())), - ]), + ], ) .is_ok()); } @@ -159,10 +162,10 @@ mod tests { let result = Spi::explain_with_args( "SELECT $1 + $2 = 3", - Some(&[ + &[ (PgBuiltInOids::INT4OID.oid(), Some(i.into())), (PgBuiltInOids::INT8OID.oid(), Some(j.into())), - ]), + ], )?; assert!(result.0.get(0).unwrap().get("Plan").is_some()); @@ -182,7 +185,7 @@ mod tests { #[pg_test] fn test_inserting_null() -> Result<(), pgrx::spi::Error> { Spi::connect(|mut client| { - client.update("CREATE TABLE tests.null_test (id uuid)", None, None).map(|_| ()) + client.update("CREATE TABLE tests.null_test (id uuid)", None, &[][..]).map(|_| ()) })?; assert_eq!( Spi::get_one_with_args::( @@ -205,14 +208,14 @@ mod tests { #[pg_test] fn test_cursor() -> Result<(), spi::Error> { Spi::connect(|mut client| { - client.update("CREATE TABLE tests.cursor_table (id int)", None, None)?; + client.update("CREATE TABLE tests.cursor_table (id int)", None, &[][..])?; client.update( "INSERT INTO tests.cursor_table (id) \ SELECT i FROM generate_series(1, 10) AS t(i)", None, - None, + &[][..], )?; - let mut portal = client.open_cursor("SELECT * FROM tests.cursor_table", None); + let mut portal = client.open_cursor("SELECT * FROM tests.cursor_table", &[][..]); assert_eq!(sum_all(portal.fetch(3)?), 1 + 2 + 3); assert_eq!(sum_all(portal.fetch(3)?), 4 + 5 + 6); @@ -225,15 +228,15 @@ mod tests { #[pg_test] fn test_cursor_prepared_statement() -> Result<(), pgrx::spi::Error> { Spi::connect(|mut client| { - client.update("CREATE TABLE tests.cursor_table (id int)", None, None)?; + client.update("CREATE TABLE tests.cursor_table (id int)", None, &[][..])?; client.update( "INSERT INTO tests.cursor_table (id) \ SELECT i FROM generate_series(1, 10) AS t(i)", None, - None, + &[][..], )?; let prepared = client.prepare("SELECT * FROM tests.cursor_table", None)?; - let mut portal = client.open_cursor(&prepared, None); + let mut portal = client.open_cursor(&prepared, &[][..]); assert_eq!(sum_all(portal.fetch(3)?), 1 + 2 + 3); assert_eq!(sum_all(portal.fetch(3)?), 4 + 5 + 6); @@ -243,33 +246,28 @@ mod tests { }) } - #[pg_test] - #[should_panic(expected = "PreparedStatementArgumentMismatch { expected: 1, got: 0 }")] - fn test_cursor_prepared_statement_panics_none_args() -> Result<(), pgrx::spi::Error> { - test_cursor_prepared_statement_panics_impl(None) - } - #[pg_test] #[should_panic(expected = "PreparedStatementArgumentMismatch { expected: 1, got: 0 }")] fn test_cursor_prepared_statement_panics_less_args() -> Result<(), pgrx::spi::Error> { - test_cursor_prepared_statement_panics_impl(Some(&[][..])) + test_cursor_prepared_statement_panics_impl(&[][..]) } #[pg_test] #[should_panic(expected = "PreparedStatementArgumentMismatch { expected: 1, got: 2 }")] fn test_cursor_prepared_statement_panics_more_args() -> Result<(), pgrx::spi::Error> { - test_cursor_prepared_statement_panics_impl(Some(&[None, None])) + test_cursor_prepared_statement_panics_impl(&[None, None]) } + fn test_cursor_prepared_statement_panics_impl( - args: Option<&[Option]>, + args: &[Option], ) -> Result<(), pgrx::spi::Error> { Spi::connect(|mut client| { - client.update("CREATE TABLE tests.cursor_table (id int)", None, None)?; + client.update("CREATE TABLE tests.cursor_table (id int)", None, &[][..])?; client.update( "INSERT INTO tests.cursor_table (id) \ SELECT i FROM generate_series(1, 10) AS t(i)", None, - None, + &[][..], )?; let prepared = client.prepare( "SELECT * FROM tests.cursor_table WHERE id = $1", @@ -283,14 +281,14 @@ mod tests { #[pg_test] fn test_cursor_by_name() -> Result<(), pgrx::spi::Error> { let cursor_name = Spi::connect(|mut client| { - client.update("CREATE TABLE tests.cursor_table (id int)", None, None)?; + client.update("CREATE TABLE tests.cursor_table (id int)", None, &[][..])?; client.update( "INSERT INTO tests.cursor_table (id) \ SELECT i FROM generate_series(1, 10) AS t(i)", None, - None, + &[][..], )?; - let mut cursor = client.open_cursor("SELECT * FROM tests.cursor_table", None); + let mut cursor = client.open_cursor("SELECT * FROM tests.cursor_table", &[][..]); assert_eq!(sum_all(cursor.fetch(3)?), 1 + 2 + 3); Ok::<_, spi::Error>(cursor.detach_into_name()) })?; @@ -314,7 +312,7 @@ mod tests { #[pg_test(error = "syntax error at or near \"THIS\"")] fn test_cursor_failure() { Spi::connect(|client| { - client.open_cursor("THIS IS NOT SQL", None); + client.open_cursor("THIS IS NOT SQL", &[][..]); }) } @@ -326,7 +324,7 @@ mod tests { #[pg_test] fn test_columns() -> Result<(), spi::Error> { Spi::connect(|client| { - let res = client.select("SELECT 42 AS a, 'test' AS b", None, None)?; + let res = client.select("SELECT 42 AS a, 'test' AS b", None, &[][..])?; assert_eq!(Ok(2), res.columns()); assert_eq!(res.column_type_oid(1).unwrap(), PgOid::BuiltIn(PgBuiltInOids::INT4OID)); @@ -337,7 +335,7 @@ mod tests { })?; Spi::connect(|mut client| { - let res = client.update("SET TIME ZONE 'PST8PDT'", None, None)?; + let res = client.update("SET TIME ZONE 'PST8PDT'", None, &[][..])?; assert_eq!(Err(spi::Error::NoTupleTable), res.columns()); Ok(()) @@ -354,8 +352,8 @@ mod tests { fn test_spi_non_mut() -> Result<(), pgrx::spi::Error> { // Ensures update and cursor APIs do not need mutable reference to SpiClient Spi::connect(|mut client| { - client.update("SELECT 1", None, None).expect("SPI failed"); - let cursor = client.open_cursor("SELECT 1", None).detach_into_name(); + client.update("SELECT 1", None, &[][..]).expect("SPI failed"); + let cursor = client.open_cursor("SELECT 1", &[][..]).detach_into_name(); client.find_cursor(&cursor).map(|_| ()) }) } @@ -365,8 +363,8 @@ mod tests { // Regression test to ensure a new `SpiTupTable` instance does not override the // effective length of an already open one due to misuse of Spi statics Spi::connect(|client| { - let a = client.select("SELECT 1", None, None)?.first(); - let _b = client.select("SELECT 1 WHERE 'f'", None, None)?; + let a = client.select("SELECT 1", None, &[][..])?.first(); + let _b = client.select("SELECT 1 WHERE 'f'", None, &[][..])?; assert!(!a.is_empty()); assert_eq!(1, a.len()); assert!(a.get_heap_tuple().is_ok()); @@ -381,8 +379,8 @@ mod tests { // effective length of an already open one. // Same as `test_open_multiple_tuptables`, but with the second tuptable being empty Spi::connect(|client| { - let a = client.select("SELECT 1 WHERE 'f'", None, None)?.first(); - let _b = client.select("SELECT 1", None, None)?; + let a = client.select("SELECT 1 WHERE 'f'", None, &[][..])?.first(); + let _b = client.select("SELECT 1", None, &[][..])?; assert!(a.is_empty()); assert_eq!(0, a.len()); assert!(a.get_heap_tuple().is_ok()); @@ -396,7 +394,7 @@ mod tests { let rc = Spi::connect(|client| { let prepared = client.prepare("SELECT $1", Some(vec![PgOid::BuiltIn(PgBuiltInOids::INT4OID)]))?; - client.select(&prepared, None, Some(&[42.into_datum()]))?.first().get::(1) + client.select(&prepared, None, &[42.into_datum()])?.first().get::(1) })?; assert_eq!(42, rc.expect("SPI failed to return proper value")); @@ -408,7 +406,7 @@ mod tests { let err = Spi::connect(|client| { let prepared = client.prepare("SELECT $1", Some(vec![PgOid::BuiltIn(PgBuiltInOids::INT4OID)]))?; - client.select(&prepared, None, None).map(|_| ()) + client.select(&prepared, None, &[][..]).map(|_| ()) }) .unwrap_err(); @@ -428,7 +426,7 @@ mod tests { ) })?; let rc = Spi::connect(|client| { - client.select(&prepared, None, Some(&[42.into_datum()]))?.first().get::(1) + client.select(&prepared, None, &[42.into_datum()])?.first().get::(1) })?; assert_eq!(Some(42), rc); @@ -443,16 +441,16 @@ mod tests { #[pg_test(error = "CREATE TABLE is not allowed in a non-volatile function")] fn test_readwrite_in_readonly() -> Result<(), spi::Error> { // This is supposed to run in read-only - Spi::connect(|client| client.select("CREATE TABLE a ()", None, None).map(|_| ())) + Spi::connect(|client| client.select("CREATE TABLE a ()", None, &[][..]).map(|_| ())) } #[pg_test] fn test_readwrite_in_select_readwrite() -> Result<(), spi::Error> { Spi::connect(|mut client| { // This is supposed to switch connection to read-write and run it there - client.update("CREATE TABLE a (id INT)", None, None)?; + client.update("CREATE TABLE a (id INT)", None, &[][..])?; // This is supposed to run in read-write - client.select("INSERT INTO a VALUES (1)", None, None)?; + client.select("INSERT INTO a VALUES (1)", None, &[][..])?; Ok(()) }) } @@ -462,7 +460,7 @@ mod tests { Spi::connect(|client| { let stmt = client.prepare("CREATE TABLE a ()", None)?; // This is supposed to run in read-only - stmt.execute(&client, Some(1), None)?; + stmt.execute(&client, Some(1), &[][..])?; Ok(()) }) } @@ -472,7 +470,7 @@ mod tests { Spi::connect(|client| { let stmt = client.prepare_mut("CREATE TABLE a ()", None)?; // This is supposed to run in read-write - stmt.execute(&client, Some(1), None)?; + stmt.execute(&client, Some(1), &[][..])?; Ok(()) }) } @@ -480,9 +478,9 @@ mod tests { #[pg_test] fn test_spi_select_sees_update() -> spi::Result<()> { let with_select = Spi::connect(|mut client| { - client.update("CREATE TABLE asd(id int)", None, None)?; - client.update("INSERT INTO asd(id) VALUES (1)", None, None)?; - client.select("SELECT COUNT(*) FROM asd", None, None)?.first().get_one::() + client.update("CREATE TABLE asd(id int)", None, &[][..])?; + client.update("INSERT INTO asd(id) VALUES (1)", None, &[][..])?; + client.select("SELECT COUNT(*) FROM asd", None, &[][..])?.first().get_one::() })?; let with_get_one = Spi::get_one::("SELECT COUNT(*) FROM asd")?; @@ -495,7 +493,7 @@ mod tests { Spi::run("CREATE TABLE asd(id int)")?; Spi::run("INSERT INTO asd(id) VALUES (1)")?; let with_select = Spi::connect(|client| { - client.select("SELECT COUNT(*) FROM asd", None, None)?.first().get_one::() + client.select("SELECT COUNT(*) FROM asd", None, &[][..])?.first().get_one::() })?; let with_get_one = Spi::get_one::("SELECT COUNT(*) FROM asd")?; @@ -506,12 +504,12 @@ mod tests { #[pg_test] fn test_spi_select_sees_update_in_other_session() -> spi::Result<()> { Spi::connect::, _>(|mut client| { - client.update("CREATE TABLE asd(id int)", None, None)?; - client.update("INSERT INTO asd(id) VALUES (1)", None, None)?; + client.update("CREATE TABLE asd(id int)", None, &[][..])?; + client.update("INSERT INTO asd(id) VALUES (1)", None, &[][..])?; Ok(()) })?; let with_select = Spi::connect(|client| { - client.select("SELECT COUNT(*) FROM asd", None, None)?.first().get_one::() + client.select("SELECT COUNT(*) FROM asd", None, &[][..])?.first().get_one::() })?; let with_get_one = Spi::get_one::("SELECT COUNT(*) FROM asd")?; @@ -571,7 +569,8 @@ mod tests { #[pg_test] fn can_return_borrowed_str() -> Result<(), Box> { let res = Spi::connect(|c| { - let mut cursor = c.open_cursor("SELECT 'hello' FROM generate_series(1, 10000)", None); + let mut cursor = + c.open_cursor("SELECT 'hello' FROM generate_series(1, 10000)", &[][..]); let table = cursor.fetch(10000)?; table.into_iter().map(|row| row.get::<&str>(1)).collect::, _>>() })?; diff --git a/pgrx-tests/src/tests/srf_tests.rs b/pgrx-tests/src/tests/srf_tests.rs index 0bb74a8c6..3f5554fb2 100644 --- a/pgrx-tests/src/tests/srf_tests.rs +++ b/pgrx-tests/src/tests/srf_tests.rs @@ -154,7 +154,7 @@ mod tests { fn test_generate_series() { let cnt = Spi::connect(|client| { let mut table = - client.select("SELECT * FROM example_generate_series(1, 10)", None, None)?; + client.select("SELECT * FROM example_generate_series(1, 10)", None, &[][..])?; let mut expect = 0; while table.next().is_some() { @@ -174,7 +174,8 @@ mod tests { #[pg_test] fn test_composite_set() { let cnt = Spi::connect(|client| { - let mut table = client.select("SELECT * FROM example_composite_set()", None, None)?; + let mut table = + client.select("SELECT * FROM example_composite_set()", None, &[][..])?; let mut expect = 0; while table.next().is_some() { @@ -200,7 +201,7 @@ mod tests { #[pg_test] fn test_return_table_iterator() { let cnt = Spi::connect(|client| { - let table = client.select("SELECT * from return_table_iterator();", None, None)?; + let table = client.select("SELECT * from return_table_iterator();", None, &[][..])?; Ok::<_, spi::Error>(table.len() as i64) }); @@ -211,7 +212,7 @@ mod tests { #[pg_test] fn test_return_empty_iterator() { let cnt = Spi::connect(|client| { - let table = client.select("SELECT * from return_empty_iterator();", None, None)?; + let table = client.select("SELECT * from return_empty_iterator();", None, &[][..])?; Ok::<_, spi::Error>(table.len() as i64) }); @@ -222,7 +223,7 @@ mod tests { #[pg_test] fn test_return_setof_iterator() { let cnt = Spi::connect(|client| { - let table = client.select("SELECT * from return_setof_iterator();", None, None)?; + let table = client.select("SELECT * from return_setof_iterator();", None, &[][..])?; Ok::<_, spi::Error>(table.len() as i64) }); @@ -234,7 +235,7 @@ mod tests { fn test_return_empty_setof_iterator() { let cnt = Spi::connect(|client| { let table = - client.select("SELECT * from return_empty_setof_iterator();", None, None)?; + client.select("SELECT * from return_empty_setof_iterator();", None, &[][..])?; Ok::<_, spi::Error>(table.len() as i64) }); @@ -246,13 +247,13 @@ mod tests { fn test_srf_setof_datum_detoasting_with_borrow() { let cnt = Spi::connect(|mut client| { // build up a table with one large column that Postgres will be forced to TOAST - client.update("CREATE TABLE test_srf_datum_detoasting AS SELECT array_to_string(array_agg(g),' ') s FROM (SELECT 'a' g FROM generate_series(1, 1000)) x;", None, None)?; + client.update("CREATE TABLE test_srf_datum_detoasting AS SELECT array_to_string(array_agg(g),' ') s FROM (SELECT 'a' g FROM generate_series(1, 1000)) x;", None, &[][..])?; // and make sure we can use the DETOASTED value with our SRF function let table = client.select( "SELECT split_set_with_borrow(s, ' ') FROM test_srf_datum_detoasting", None, - None, + &[][..], )?; Ok::<_, spi::Error>(table.len() as i64) @@ -264,13 +265,13 @@ mod tests { fn test_srf_table_datum_detoasting_with_borrow() { let cnt = Spi::connect(|mut client| { // build up a table with one large column that Postgres will be forced to TOAST - client.update("CREATE TABLE test_srf_datum_detoasting AS SELECT array_to_string(array_agg(g),' ') s FROM (SELECT 'a' g FROM generate_series(1, 1000)) x;", None, None)?; + client.update("CREATE TABLE test_srf_datum_detoasting AS SELECT array_to_string(array_agg(g),' ') s FROM (SELECT 'a' g FROM generate_series(1, 1000)) x;", None, &[][..])?; // and make sure we can use the DETOASTED value with our SRF function let table = client.select( "SELECT split_table_with_borrow(s, ' ') FROM test_srf_datum_detoasting", None, - None, + &[][..], )?; Ok::<_, spi::Error>(table.len() as i64) diff --git a/pgrx-tests/src/tests/struct_type_tests.rs b/pgrx-tests/src/tests/struct_type_tests.rs index 4f3f721fd..32a90ccbd 100644 --- a/pgrx-tests/src/tests/struct_type_tests.rs +++ b/pgrx-tests/src/tests/struct_type_tests.rs @@ -22,7 +22,7 @@ mod tests { fn test_complex_in() -> Result<(), pgrx::spi::Error> { Spi::connect(|client| { let complex = client - .select("SELECT '1.1,2.2'::complex;", None, None)? + .select("SELECT '1.1,2.2'::complex;", None, &[][..])? .first() .get_one::>()? .expect("datum was null"); @@ -44,7 +44,7 @@ mod tests { fn test_complex_from_text() -> Result<(), pgrx::spi::Error> { Spi::connect(|client| { let complex = client - .select("SELECT '1.1, 2.2'::complex;", None, None)? + .select("SELECT '1.1, 2.2'::complex;", None, &[][..])? .first() .get_one::>()? .expect("datum was null"); @@ -60,7 +60,7 @@ mod tests { let complex = Spi::connect(|mut client| { client.update( "CREATE TABLE complex_test AS SELECT s as id, (s || '.0, 2.0' || s)::complex as value FROM generate_series(1, 1000) s;\ - SELECT value FROM complex_test ORDER BY id;", None, None)?.first().get_one::>() + SELECT value FROM complex_test ORDER BY id;", None, &[][..])?.first().get_one::>() })?.expect("datum was null"); assert_eq!(&complex.r, &1.0); diff --git a/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-cursor.rs b/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-cursor.rs index 14559f5ee..a1ccd41c6 100644 --- a/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-cursor.rs +++ b/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-cursor.rs @@ -6,14 +6,14 @@ use std::error::Error; fn issue1209() -> Result, Box> { // create the cursor we actually care about let mut res = Spi::connect(|c| { - c.open_cursor("select 'hello world' from generate_series(1, 1000)", None) + c.open_cursor("select 'hello world' from generate_series(1, 1000)", &[][..]) .fetch(1000) .unwrap() }); // here we just perform some allocations to make sure that the previous cursor gets invalidated for _ in 0..100 { - Spi::connect(|c| c.open_cursor("select 1", None).fetch(1).unwrap()); + Spi::connect(|c| c.open_cursor("select 1", &[][..]).fetch(1).unwrap()); } // later elements are probably more likely to point to deallocated memory diff --git a/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-cursor.stderr b/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-cursor.stderr index 6ef22bc8e..fba9f322f 100644 --- a/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-cursor.stderr +++ b/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-cursor.stderr @@ -5,7 +5,7 @@ error: lifetime may not live long enough | -- return type of closure is SpiTupleTable<'2> | | | has type `SpiClient<'1>` -9 | / c.open_cursor("select 'hello world' from generate_series(1, 1000)", None) +9 | / c.open_cursor("select 'hello world' from generate_series(1, 1000)", &[][..]) 10 | | .fetch(1000) 11 | | .unwrap() | |_____________________^ returning this value requires that `'1` must outlive `'2` @@ -13,8 +13,8 @@ error: lifetime may not live long enough error[E0515]: cannot return value referencing temporary value --> tests/compile-fail/escaping-spiclient-1209-cursor.rs:9:9 | -9 | c.open_cursor("select 'hello world' from generate_series(1, 1000)", None) - | ^------------------------------------------------------------------------ +9 | c.open_cursor("select 'hello world' from generate_series(1, 1000)", &[][..]) + | ^--------------------------------------------------------------------------- | | | _________temporary value created here | | @@ -27,8 +27,8 @@ error[E0515]: cannot return value referencing temporary value error: lifetime may not live long enough --> tests/compile-fail/escaping-spiclient-1209-cursor.rs:16:26 | -16 | Spi::connect(|c| c.open_cursor("select 1", None).fetch(1).unwrap()); - | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2` +16 | Spi::connect(|c| c.open_cursor("select 1", &[][..]).fetch(1).unwrap()); + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2` | || | |return type of closure is SpiTupleTable<'2> | has type `SpiClient<'1>` @@ -36,8 +36,8 @@ error: lifetime may not live long enough error[E0515]: cannot return value referencing temporary value --> tests/compile-fail/escaping-spiclient-1209-cursor.rs:16:26 | -16 | Spi::connect(|c| c.open_cursor("select 1", None).fetch(1).unwrap()); - | -------------------------------^^^^^^^^^^^^^^^^^^ +16 | Spi::connect(|c| c.open_cursor("select 1", &[][..]).fetch(1).unwrap()); + | ----------------------------------^^^^^^^^^^^^^^^^^^ | | | returns a value referencing data owned by the current function | temporary value created here diff --git a/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-prep-stmt.rs b/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-prep-stmt.rs index 9d5838ef7..07bda1498 100644 --- a/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-prep-stmt.rs +++ b/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-prep-stmt.rs @@ -7,7 +7,7 @@ fn issue1209_prepared_stmt(q: &str) -> Result, Box> { let prepared = { Spi::connect(|c| c.prepare(q, None))? }; - Ok(Spi::connect(|c| prepared.execute(&c, Some(1), None)?.first().get(1))?) + Ok(Spi::connect(|c| prepared.execute(&c, Some(1), &[][..])?.first().get(1))?) } fn main() {} diff --git a/pgrx/src/spi.rs b/pgrx/src/spi.rs index 1239b89c3..b6984db36 100644 --- a/pgrx/src/spi.rs +++ b/pgrx/src/spi.rs @@ -238,13 +238,13 @@ impl Spi { } pub fn get_one(query: &str) -> Result> { - Spi::connect(|mut client| client.update(query, Some(1), None)?.first().get_one()) + Spi::connect(|mut client| client.update(query, Some(1), &[][..])?.first().get_one()) } pub fn get_two( query: &str, ) -> Result<(Option, Option)> { - Spi::connect(|mut client| client.update(query, Some(1), None)?.first().get_two::()) + Spi::connect(|mut client| client.update(query, Some(1), &[][..])?.first().get_two::()) } pub fn get_three< @@ -255,7 +255,7 @@ impl Spi { query: &str, ) -> Result<(Option, Option, Option)> { Spi::connect(|mut client| { - client.update(query, Some(1), None)?.first().get_three::() + client.update(query, Some(1), &[][..])?.first().get_three::() }) } @@ -263,16 +263,14 @@ impl Spi { query: &str, args: &[(PgOid, Option)], ) -> Result> { - Spi::connect(|mut client| client.update(query, Some(1), Some(args))?.first().get_one()) + Spi::connect(|mut client| client.update(query, Some(1), args)?.first().get_one()) } pub fn get_two_with_args( query: &str, args: &[(PgOid, Option)], ) -> Result<(Option, Option)> { - Spi::connect(|mut client| { - client.update(query, Some(1), Some(args))?.first().get_two::() - }) + Spi::connect(|mut client| client.update(query, Some(1), args)?.first().get_two::()) } pub fn get_three_with_args< @@ -284,7 +282,7 @@ impl Spi { args: &[(PgOid, Option)], ) -> Result<(Option, Option, Option)> { Spi::connect(|mut client| { - client.update(query, Some(1), Some(args))?.first().get_three::() + client.update(query, Some(1), args)?.first().get_three::() }) } @@ -294,7 +292,7 @@ impl Spi { /// /// The statement runs in read/write mode pub fn run(query: &str) -> std::result::Result<(), Error> { - Spi::run_with_args(query, None) + Spi::run_with_args(query, &[][..]) } /// run an arbitrary SQL statement with args. @@ -304,21 +302,18 @@ impl Spi { /// The statement runs in read/write mode pub fn run_with_args( query: &str, - args: Option<&[(PgOid, Option)]>, + args: &[(PgOid, Option)], ) -> std::result::Result<(), Error> { Spi::connect(|mut client| client.update(query, None, args).map(|_| ())) } /// explain a query, returning its result in json form pub fn explain(query: &str) -> Result { - Spi::explain_with_args(query, None) + Spi::explain_with_args(query, &[][..]) } /// explain a query with args, returning its result in json form - pub fn explain_with_args( - query: &str, - args: Option<&[(PgOid, Option)]>, - ) -> Result { + pub fn explain_with_args(query: &str, args: &[(PgOid, Option)]) -> Result { Ok(Spi::connect(|mut client| { client .update(&format!("EXPLAIN (format json) {query}"), None, args)? @@ -343,7 +338,7 @@ impl Spi { /// use pgrx::prelude::*; /// # fn foo() -> spi::Result> { /// let name = Spi::connect(|client| { - /// client.select("SELECT 'Bob'", None, None)?.first().get_one() + /// client.select("SELECT 'Bob'", None, &[][..])?.first().get_one() /// })?; /// assert_eq!(name, Some("Bob")); /// # return Ok(name.map(str::to_string)) diff --git a/pgrx/src/spi/client.rs b/pgrx/src/spi/client.rs index 4a66d3f41..aea2e6010 100644 --- a/pgrx/src/spi/client.rs +++ b/pgrx/src/spi/client.rs @@ -74,7 +74,7 @@ impl<'conn> SpiClient<'conn> { &self, query: Q, limit: Option, - args: Option<&[Q::Argument]>, + args: &[Q::Argument], ) -> SpiResult> { query.execute(self, limit, args) } @@ -84,7 +84,7 @@ impl<'conn> SpiClient<'conn> { &mut self, query: Q, limit: Option, - args: Option<&[Q::Argument]>, + args: &[Q::Argument], ) -> SpiResult> { Spi::mark_mutable(); query.execute(self, limit, args) @@ -123,11 +123,7 @@ impl<'conn> SpiClient<'conn> { /// # Panics /// /// Panics if a cursor wasn't opened. - pub fn open_cursor>( - &self, - query: Q, - args: Option<&[Q::Argument]>, - ) -> SpiCursor<'conn> { + pub fn open_cursor>(&self, query: Q, args: &[Q::Argument]) -> SpiCursor<'conn> { self.try_open_cursor(query, args).unwrap() } @@ -139,7 +135,7 @@ impl<'conn> SpiClient<'conn> { pub fn try_open_cursor>( &self, query: Q, - args: Option<&[Q::Argument]>, + args: &[Q::Argument], ) -> SpiResult> { query.try_open_cursor(self, args) } @@ -158,7 +154,7 @@ impl<'conn> SpiClient<'conn> { pub fn open_cursor_mut>( &mut self, query: Q, - args: Option<&[Q::Argument]>, + args: &[Q::Argument], ) -> SpiCursor<'conn> { Spi::mark_mutable(); self.try_open_cursor_mut(query, args).unwrap() @@ -172,7 +168,7 @@ impl<'conn> SpiClient<'conn> { pub fn try_open_cursor_mut>( &mut self, query: Q, - args: Option<&[Q::Argument]>, + args: &[Q::Argument], ) -> SpiResult> { Spi::mark_mutable(); query.try_open_cursor(self, args) diff --git a/pgrx/src/spi/cursor.rs b/pgrx/src/spi/cursor.rs index f7bb259d3..8de6ce72c 100644 --- a/pgrx/src/spi/cursor.rs +++ b/pgrx/src/spi/cursor.rs @@ -33,7 +33,7 @@ type CursorName = String; /// use pgrx::prelude::*; /// # fn foo() -> spi::Result<()> { /// Spi::connect(|mut client| { -/// let mut cursor = client.open_cursor("SELECT * FROM generate_series(1, 5)", None); +/// let mut cursor = client.open_cursor("SELECT * FROM generate_series(1, 5)", &[][..]); /// assert_eq!(Some(1), cursor.fetch(1)?.get_one::()?); /// assert_eq!(Some(2), cursor.fetch(2)?.get_one::()?); /// assert_eq!(Some(3), cursor.fetch(3)?.get_one::()?); @@ -48,7 +48,7 @@ type CursorName = String; /// use pgrx::prelude::*; /// # fn foo() -> spi::Result<()> { /// let cursor_name = Spi::connect(|mut client| { -/// let mut cursor = client.open_cursor("SELECT * FROM generate_series(1, 5)", None); +/// let mut cursor = client.open_cursor("SELECT * FROM generate_series(1, 5)", &[][..]); /// assert_eq!(Ok(Some(1)), cursor.fetch(1)?.get_one::()); /// Ok::<_, spi::Error>(cursor.detach_into_name()) // <-- cursor gets dropped here /// // <--- first SpiTupleTable gets freed by Spi::connect at this point diff --git a/pgrx/src/spi/query.rs b/pgrx/src/spi/query.rs index 1948e4e6f..61c50b86e 100644 --- a/pgrx/src/spi/query.rs +++ b/pgrx/src/spi/query.rs @@ -21,7 +21,7 @@ pub trait Query<'conn>: Sized { self, client: &SpiClient<'conn>, limit: Option, - args: Option<&[Self::Argument]>, + args: &[Self::Argument], ) -> SpiResult>; /// Open a cursor for the query. @@ -30,11 +30,7 @@ pub trait Query<'conn>: Sized { /// /// Panics if a cursor wasn't opened. #[deprecated(since = "0.12.2", note = "undefined behavior")] - fn open_cursor( - self, - client: &SpiClient<'conn>, - args: Option<&[Self::Argument]>, - ) -> SpiCursor<'conn> { + fn open_cursor(self, client: &SpiClient<'conn>, args: &[Self::Argument]) -> SpiCursor<'conn> { self.try_open_cursor(client, args).unwrap() } @@ -42,7 +38,7 @@ pub trait Query<'conn>: Sized { fn try_open_cursor( self, client: &SpiClient<'conn>, - args: Option<&[Self::Argument]>, + args: &[Self::Argument], ) -> SpiResult>; } @@ -53,7 +49,7 @@ impl<'conn> Query<'conn> for &String { self, client: &SpiClient<'conn>, limit: Option, - args: Option<&[Self::Argument]>, + args: &[Self::Argument], ) -> SpiResult> { self.as_str().execute(client, limit, args) } @@ -61,7 +57,7 @@ impl<'conn> Query<'conn> for &String { fn try_open_cursor( self, client: &SpiClient<'conn>, - args: Option<&[Self::Argument]>, + args: &[Self::Argument], ) -> SpiResult> { self.as_str().try_open_cursor(client, args) } @@ -102,7 +98,7 @@ impl<'conn> Query<'conn> for &str { self, _client: &SpiClient<'conn>, limit: Option, - args: Option<&[Self::Argument]>, + args: &[Self::Argument], ) -> SpiResult> { // SAFETY: no concurrent access unsafe { @@ -110,9 +106,16 @@ impl<'conn> Query<'conn> for &str { } let src = CString::new(self).expect("query contained a null byte"); - let status_code = match args { - Some(args) => { - let nargs = args.len(); + let status_code = match args.len() { + // SAFETY: arguments are prepared above + 0 => unsafe { + pg_sys::SPI_execute( + src.as_ptr(), + Spi::is_xact_still_immutable(), + limit.unwrap_or(0), + ) + }, + nargs => { let (mut argtypes, mut datums, nulls) = args_to_datums(args); // SAFETY: arguments are prepared above @@ -128,14 +131,6 @@ impl<'conn> Query<'conn> for &str { ) } } - // SAFETY: arguments are prepared above - None => unsafe { - pg_sys::SPI_execute( - src.as_ptr(), - Spi::is_xact_still_immutable(), - limit.unwrap_or(0), - ) - }, }; SpiClient::prepare_tuple_table(status_code) @@ -144,10 +139,9 @@ impl<'conn> Query<'conn> for &str { fn try_open_cursor( self, _client: &SpiClient<'conn>, - args: Option<&[Self::Argument]>, + args: &[Self::Argument], ) -> SpiResult> { let src = CString::new(self).expect("query contained a null byte"); - let args = args.unwrap_or_default(); let nargs = args.len(); let (mut argtypes, mut datums, nulls) = args_to_datums(args); @@ -203,7 +197,7 @@ impl<'conn> Query<'conn> for &OwnedPreparedStatement { self, client: &SpiClient<'conn>, limit: Option, - args: Option<&[Self::Argument]>, + args: &[Self::Argument], ) -> SpiResult> { (&self.0).execute(client, limit, args) } @@ -211,7 +205,7 @@ impl<'conn> Query<'conn> for &OwnedPreparedStatement { fn try_open_cursor( self, client: &SpiClient<'conn>, - args: Option<&[Self::Argument]>, + args: &[Self::Argument], ) -> SpiResult> { (&self.0).try_open_cursor(client, args) } @@ -224,7 +218,7 @@ impl<'conn> Query<'conn> for OwnedPreparedStatement { self, client: &SpiClient<'conn>, limit: Option, - args: Option<&[Self::Argument]>, + args: &[Self::Argument], ) -> SpiResult> { (&self.0).execute(client, limit, args) } @@ -232,7 +226,7 @@ impl<'conn> Query<'conn> for OwnedPreparedStatement { fn try_open_cursor( self, client: &SpiClient<'conn>, - args: Option<&[Self::Argument]>, + args: &[Self::Argument], ) -> SpiResult> { (&self.0).try_open_cursor(client, args) } @@ -258,10 +252,8 @@ impl<'conn> PreparedStatement<'conn> { fn args_to_datums( &self, - args: Option<&[>::Argument]>, + args: &[>::Argument], ) -> SpiResult<(Vec, Vec)> { - let args = args.unwrap_or_default(); - let actual = args.len(); let expected = unsafe { pg_sys::SPI_getargcount(self.plan.as_ptr()) } as usize; @@ -280,7 +272,7 @@ impl<'conn: 'stmt, 'stmt> Query<'conn> for &'stmt PreparedStatement<'conn> { self, _client: &SpiClient<'conn>, limit: Option, - args: Option<&[Self::Argument]>, + args: &[Self::Argument], ) -> SpiResult> { // SAFETY: no concurrent access unsafe { @@ -306,7 +298,7 @@ impl<'conn: 'stmt, 'stmt> Query<'conn> for &'stmt PreparedStatement<'conn> { fn try_open_cursor( self, _client: &SpiClient<'conn>, - args: Option<&[Self::Argument]>, + args: &[Self::Argument], ) -> SpiResult> { let (mut datums, nulls) = self.args_to_datums(args)?; @@ -332,7 +324,7 @@ impl<'conn> Query<'conn> for PreparedStatement<'conn> { self, client: &SpiClient<'conn>, limit: Option, - args: Option<&[Self::Argument]>, + args: &[Self::Argument], ) -> SpiResult> { (&self).execute(client, limit, args) } @@ -340,7 +332,7 @@ impl<'conn> Query<'conn> for PreparedStatement<'conn> { fn try_open_cursor( self, client: &SpiClient<'conn>, - args: Option<&[Self::Argument]>, + args: &[Self::Argument], ) -> SpiResult> { (&self).try_open_cursor(client, args) } From 408f33a48ecb0ce8f889c898a392dddfd5a941c6 Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Wed, 11 Sep 2024 17:20:22 +0300 Subject: [PATCH 3/9] Made query arguments type safe --- pgrx-tests/src/tests/aggregate_tests.rs | 20 ++---- pgrx-tests/src/tests/anyelement_tests.rs | 4 +- pgrx-tests/src/tests/anynumeric_tests.rs | 8 +-- pgrx-tests/src/tests/array_tests.rs | 4 +- pgrx-tests/src/tests/bgworker_tests.rs | 19 ++---- pgrx-tests/src/tests/json_tests.rs | 10 +-- pgrx-tests/src/tests/proptests.rs | 6 +- pgrx-tests/src/tests/roundtrip_tests.rs | 2 +- pgrx-tests/src/tests/spi_tests.rs | 33 ++++------ pgrx-tests/tests/todo/roundtrip-tests.rs | 2 +- pgrx-tests/tests/todo/roundtrip-tests.stderr | 6 +- pgrx/src/datum/mod.rs | 29 +++++++++ pgrx/src/spi.rs | 16 ++--- pgrx/src/spi/client.rs | 17 ++++-- pgrx/src/spi/query.rs | 64 ++++++++------------ 15 files changed, 107 insertions(+), 133 deletions(-) diff --git a/pgrx-tests/src/tests/aggregate_tests.rs b/pgrx-tests/src/tests/aggregate_tests.rs index 7b7a4e48b..8d2b7542c 100644 --- a/pgrx-tests/src/tests/aggregate_tests.rs +++ b/pgrx-tests/src/tests/aggregate_tests.rs @@ -264,14 +264,8 @@ mod tests { let retval = Spi::get_one_with_args::( "SELECT FirstJson(value) FROM UNNEST(ARRAY [$1, $2]) as value;", &[ - ( - PgBuiltInOids::JSONOID.oid(), - pgrx::Json(serde_json::json!({ "foo": "one" })).into_datum(), - ), - ( - PgBuiltInOids::JSONOID.oid(), - pgrx::Json(serde_json::json!({ "foo": "two" })).into_datum(), - ), + pgrx::Json(serde_json::json!({ "foo": "one" })).into(), + pgrx::Json(serde_json::json!({ "foo": "two" })).into(), ], )? .map(|json| json.0); @@ -286,14 +280,8 @@ mod tests { let retval = Spi::get_one_with_args::( "SELECT FirstJsonB(value) FROM UNNEST(ARRAY [$1, $2]) as value;", &[ - ( - PgBuiltInOids::JSONBOID.oid(), - pgrx::JsonB(serde_json::json!({ "foo": "one" })).into_datum(), - ), - ( - PgBuiltInOids::JSONBOID.oid(), - pgrx::JsonB(serde_json::json!({ "foo": "two" })).into_datum(), - ), + pgrx::JsonB(serde_json::json!({ "foo": "one" })).into(), + pgrx::JsonB(serde_json::json!({ "foo": "two" })).into(), ], )? .map(|json| json.0); diff --git a/pgrx-tests/src/tests/anyelement_tests.rs b/pgrx-tests/src/tests/anyelement_tests.rs index f4355a30c..2033386c9 100644 --- a/pgrx-tests/src/tests/anyelement_tests.rs +++ b/pgrx-tests/src/tests/anyelement_tests.rs @@ -11,13 +11,13 @@ mod tests { #[allow(unused_imports)] use crate as pgrx_tests; - use pgrx::{prelude::*, AnyElement}; + use pgrx::{datum::DatumWithOid, prelude::*, AnyElement}; #[pg_test] fn test_anyelement_arg() -> Result<(), pgrx::spi::Error> { let element = Spi::get_one_with_args::( "SELECT anyelement_arg($1);", - &[(PgBuiltInOids::ANYELEMENTOID.oid(), 123.into_datum())], + &[DatumWithOid::new(123, AnyElement::type_oid())], )? .map(|e| e.datum()); diff --git a/pgrx-tests/src/tests/anynumeric_tests.rs b/pgrx-tests/src/tests/anynumeric_tests.rs index 5685ab901..7dadb7fb0 100644 --- a/pgrx-tests/src/tests/anynumeric_tests.rs +++ b/pgrx-tests/src/tests/anynumeric_tests.rs @@ -15,11 +15,9 @@ mod tests { #[pg_test] fn test_anynumeric_arg() -> Result<(), pgrx::spi::Error> { - let numeric = Spi::get_one_with_args::( - "SELECT anynumeric_arg($1);", - &[(PgBuiltInOids::INT4OID.oid(), 123.into_datum())], - )? - .map(|n| n.normalize().to_string()); + let numeric = + Spi::get_one_with_args::("SELECT anynumeric_arg($1);", &[123.into()])? + .map(|n| n.normalize().to_string()); assert_eq!(numeric, Some("123".to_string())); diff --git a/pgrx-tests/src/tests/array_tests.rs b/pgrx-tests/src/tests/array_tests.rs index b5bbae76b..49d413007 100644 --- a/pgrx-tests/src/tests/array_tests.rs +++ b/pgrx-tests/src/tests/array_tests.rs @@ -191,7 +191,7 @@ mod tests { use super::ArrayTestEnum; use pgrx::prelude::*; - use pgrx::{IntoDatum, Json}; + use pgrx::Json; use serde_json::json; #[pg_test] @@ -300,7 +300,7 @@ mod tests { .select( "SELECT serde_serialize_array_i32($1)", None, - &[(PgBuiltInOids::INT4ARRAYOID.oid(), owned_vec.as_slice().into_datum())], + &[owned_vec.as_slice().into()], )? .first() .get_one::() diff --git a/pgrx-tests/src/tests/bgworker_tests.rs b/pgrx-tests/src/tests/bgworker_tests.rs index 03509c290..044a560a6 100644 --- a/pgrx-tests/src/tests/bgworker_tests.rs +++ b/pgrx-tests/src/tests/bgworker_tests.rs @@ -27,11 +27,7 @@ pub extern "C" fn bgworker(arg: pg_sys::Datum) { Spi::run("CREATE TABLE tests.bgworker_test (v INTEGER);")?; Spi::connect(|mut client| { client - .update( - "INSERT INTO tests.bgworker_test VALUES ($1);", - None, - &[(PgOid::BuiltIn(PgBuiltInOids::INT4OID), arg.into_datum())], - ) + .update("INSERT INTO tests.bgworker_test VALUES ($1);", None, &[arg.into()]) .map(|_| ()) }) }) @@ -61,10 +57,7 @@ pub extern "C" fn bgworker_return_value(arg: pg_sys::Datum) { let val = if arg > 0 { BackgroundWorker::transaction(|| { Spi::run("CREATE TABLE tests.bgworker_test_return (v INTEGER);")?; - Spi::get_one_with_args::( - "SELECT $1", - &[(PgOid::BuiltIn(PgBuiltInOids::INT4OID), arg.into_datum())], - ) + Spi::get_one_with_args::("SELECT $1", &[arg.into()]) }) .expect("bgworker transaction failed") .unwrap() @@ -74,12 +67,8 @@ pub extern "C" fn bgworker_return_value(arg: pg_sys::Datum) { while BackgroundWorker::wait_latch(Some(Duration::from_millis(100))) {} BackgroundWorker::transaction(|| { Spi::connect(|mut c| { - c.update( - "INSERT INTO tests.bgworker_test_return VALUES ($1)", - None, - &[(PgOid::BuiltIn(PgBuiltInOids::INT4OID), val.into_datum())], - ) - .map(|_| ()) + c.update("INSERT INTO tests.bgworker_test_return VALUES ($1)", None, &[val.into()]) + .map(|_| ()) }) }) .expect("bgworker transaction failed"); diff --git a/pgrx-tests/src/tests/json_tests.rs b/pgrx-tests/src/tests/json_tests.rs index c481a9147..a29b7b6fa 100644 --- a/pgrx-tests/src/tests/json_tests.rs +++ b/pgrx-tests/src/tests/json_tests.rs @@ -79,10 +79,7 @@ mod tests { fn test_json_arg() -> Result<(), pgrx::spi::Error> { let json = Spi::get_one_with_args::( "SELECT json_arg($1);", - &[( - PgBuiltInOids::JSONOID.oid(), - Json(serde_json::json!({ "foo": "bar" })).into_datum(), - )], + &[Json(serde_json::json!({ "foo": "bar" })).into()], )? .expect("json was null"); @@ -95,10 +92,7 @@ mod tests { fn test_jsonb_arg() -> Result<(), pgrx::spi::Error> { let json = Spi::get_one_with_args::( "SELECT jsonb_arg($1);", - &[( - PgBuiltInOids::JSONBOID.oid(), - JsonB(serde_json::json!({ "foo": "bar" })).into_datum(), - )], + &[JsonB(serde_json::json!({ "foo": "bar" })).into()], )? .expect("json was null"); diff --git a/pgrx-tests/src/tests/proptests.rs b/pgrx-tests/src/tests/proptests.rs index fabab034d..97fbf8c9e 100644 --- a/pgrx-tests/src/tests/proptests.rs +++ b/pgrx-tests/src/tests/proptests.rs @@ -1,7 +1,7 @@ use crate::proptest::PgTestRunner; use core::ffi; use paste::paste; -use pgrx::prelude::*; +use pgrx::{datum::DatumWithOid, prelude::*}; use proptest::prelude::*; use TimeWithTimeZone as TimeTz; @@ -31,8 +31,8 @@ pub fn [<$datetime_ty:lower _spi_roundtrip>] () { proptest .run(&strat, |datetime| { let query = concat!("SELECT ", stringify!($nop_fn), "($1)"); - let builtin_oid = PgOid::BuiltIn(pg_sys::BuiltinOid::from_u32(<$datetime_ty as IntoDatum>::type_oid().as_u32()).unwrap()); - let args = &[(builtin_oid, datetime.into_datum())]; + let builtin_oid = <$datetime_ty as IntoDatum>::type_oid(); + let args = &[DatumWithOid::new(datetime, builtin_oid)]; let spi_ret: $datetime_ty = Spi::get_one_with_args(query, args).unwrap().unwrap(); // 5. A condition on which the test is accepted or rejected: // this is easily done via `prop_assert!` and its friends, diff --git a/pgrx-tests/src/tests/roundtrip_tests.rs b/pgrx-tests/src/tests/roundtrip_tests.rs index 935ed16ca..885e18e16 100644 --- a/pgrx-tests/src/tests/roundtrip_tests.rs +++ b/pgrx-tests/src/tests/roundtrip_tests.rs @@ -79,7 +79,7 @@ mod tests { let expected: $rtype = Clone::clone(&value); let result: $rtype = Spi::get_one_with_args( &format!("SELECT {}($1)", stringify!(tests.$fname)), - &[(PgOid::from(<$rtype>::type_oid()), value.into_datum())], + &[value.into()], )? .unwrap(); diff --git a/pgrx-tests/src/tests/spi_tests.rs b/pgrx-tests/src/tests/spi_tests.rs index 8ef08e7d3..190919d7e 100644 --- a/pgrx-tests/src/tests/spi_tests.rs +++ b/pgrx-tests/src/tests/spi_tests.rs @@ -12,7 +12,8 @@ mod tests { #[allow(unused_imports)] use crate as pgrx_tests; - use pgrx::datum::IntoDatum; + use pgrx::datum::DatumWithOid; + use pgrx::Uuid; use std::error::Error; use pgrx::prelude::*; @@ -138,14 +139,7 @@ mod tests { let i = 1 as i32; let j = 2 as i64; - assert!(Spi::run_with_args( - "SELECT $1 + $2 = 3", - &[ - (PgBuiltInOids::INT4OID.oid(), Some(i.into())), - (PgBuiltInOids::INT8OID.oid(), Some(j.into())), - ], - ) - .is_ok()); + assert!(Spi::run_with_args("SELECT $1 + $2 = 3", &[i.into(), j.into(),],).is_ok()); } #[pg_test] @@ -160,13 +154,7 @@ mod tests { let i = 1 as i32; let j = 2 as i64; - let result = Spi::explain_with_args( - "SELECT $1 + $2 = 3", - &[ - (PgBuiltInOids::INT4OID.oid(), Some(i.into())), - (PgBuiltInOids::INT8OID.oid(), Some(j.into())), - ], - )?; + let result = Spi::explain_with_args("SELECT $1 + $2 = 3", &[i.into(), j.into()])?; assert!(result.0.get(0).unwrap().get("Plan").is_some()); Ok(()) @@ -190,7 +178,7 @@ mod tests { assert_eq!( Spi::get_one_with_args::( "INSERT INTO tests.null_test VALUES ($1) RETURNING 1", - &[(PgBuiltInOids::UUIDOID.oid(), None)], + &[DatumWithOid::null::()], )? .unwrap(), 1 @@ -255,11 +243,14 @@ mod tests { #[pg_test] #[should_panic(expected = "PreparedStatementArgumentMismatch { expected: 1, got: 2 }")] fn test_cursor_prepared_statement_panics_more_args() -> Result<(), pgrx::spi::Error> { - test_cursor_prepared_statement_panics_impl(&[None, None]) + test_cursor_prepared_statement_panics_impl(&[ + DatumWithOid::null::(), + DatumWithOid::null::(), + ]) } fn test_cursor_prepared_statement_panics_impl( - args: &[Option], + args: &[DatumWithOid], ) -> Result<(), pgrx::spi::Error> { Spi::connect(|mut client| { client.update("CREATE TABLE tests.cursor_table (id int)", None, &[][..])?; @@ -394,7 +385,7 @@ mod tests { let rc = Spi::connect(|client| { let prepared = client.prepare("SELECT $1", Some(vec![PgOid::BuiltIn(PgBuiltInOids::INT4OID)]))?; - client.select(&prepared, None, &[42.into_datum()])?.first().get::(1) + client.select(&prepared, None, &[42.into()])?.first().get::(1) })?; assert_eq!(42, rc.expect("SPI failed to return proper value")); @@ -426,7 +417,7 @@ mod tests { ) })?; let rc = Spi::connect(|client| { - client.select(&prepared, None, &[42.into_datum()])?.first().get::(1) + client.select(&prepared, None, &[42.into()])?.first().get::(1) })?; assert_eq!(Some(42), rc); diff --git a/pgrx-tests/tests/todo/roundtrip-tests.rs b/pgrx-tests/tests/todo/roundtrip-tests.rs index b0072e6ba..37333ef78 100644 --- a/pgrx-tests/tests/todo/roundtrip-tests.rs +++ b/pgrx-tests/tests/todo/roundtrip-tests.rs @@ -35,7 +35,7 @@ mod tests { let expected: $rtype = Clone::clone(&value); let result: $rtype = Spi::get_one_with_args( &format!("SELECT {}($1)", stringify!(tests.$fname)), - &[(PgOid::from(<$rtype>::type_oid()), value.into_datum())], + &[value.into()], )? .unwrap(); diff --git a/pgrx-tests/tests/todo/roundtrip-tests.stderr b/pgrx-tests/tests/todo/roundtrip-tests.stderr index 71a7a418a..7e7f708f1 100644 --- a/pgrx-tests/tests/todo/roundtrip-tests.stderr +++ b/pgrx-tests/tests/todo/roundtrip-tests.stderr @@ -79,7 +79,7 @@ error[E0277]: the trait bound `Vec>: FromDatum` is not satisfied 36 | let result: $rtype = Spi::get_one_with_args( | ______________________________________^ 37 | | &format!("SELECT {}($1)", stringify!(tests.$fname)), -38 | | &[(PgOid::from(<$rtype>::type_oid()), value.into_datum())], +38 | | &[value.into()], 39 | | )? | |_________________^ the trait `FromDatum` is not implemented for `Vec>` ... @@ -109,7 +109,7 @@ error[E0277]: the trait bound `Vec>: FromDatum` is not satisfied 36 | let result: $rtype = Spi::get_one_with_args( | ______________________________________^ 37 | | &format!("SELECT {}($1)", stringify!(tests.$fname)), -38 | | &[(PgOid::from(<$rtype>::type_oid()), value.into_datum())], +38 | | &[value.into()], 39 | | )? | |_________________^ the trait `FromDatum` is not implemented for `Vec>` ... @@ -164,7 +164,7 @@ error[E0277]: the trait bound `Vec>: FromDatum` is not satisfied 36 | let result: $rtype = Spi::get_one_with_args( | ______________________________________^ 37 | | &format!("SELECT {}($1)", stringify!(tests.$fname)), -38 | | &[(PgOid::from(<$rtype>::type_oid()), value.into_datum())], +38 | | &[value.into()], 39 | | )? | |_________________^ the trait `FromDatum` is not implemented for `Vec>` ... diff --git a/pgrx/src/datum/mod.rs b/pgrx/src/datum/mod.rs index 09851c958..264ac9ae6 100644 --- a/pgrx/src/datum/mod.rs +++ b/pgrx/src/datum/mod.rs @@ -146,6 +146,35 @@ impl<'src> Datum<'src> { } } +pub struct DatumWithOid<'src> { + datum: Option>, + oid: pg_sys::Oid, +} + +impl<'src> DatumWithOid<'src> { + pub fn new(value: T, oid: pg_sys::Oid) -> Self { + Self { datum: value.into_datum().map(|d| Datum(d, PhantomData::default())), oid } + } + + pub fn null() -> Self { + Self { datum: None, oid: T::type_oid() } + } + + pub fn datum(&self) -> Option> { + self.datum.as_ref().map(|d| Datum(d.0, PhantomData::default())) + } + + pub fn oid(&self) -> pg_sys::Oid { + self.oid + } +} + +impl<'src, T: IntoDatum> From for DatumWithOid<'src> { + fn from(value: T) -> Self { + Self::new(value, T::type_oid()) + } +} + /// A tagging trait to indicate a user type is also meant to be used by Postgres /// Implemented automatically by `#[derive(PostgresType)]` pub trait PostgresType {} diff --git a/pgrx/src/spi.rs b/pgrx/src/spi.rs index b6984db36..c92dd55a9 100644 --- a/pgrx/src/spi.rs +++ b/pgrx/src/spi.rs @@ -9,9 +9,8 @@ //LICENSE Use of this source code is governed by the MIT license that can be found in the LICENSE file. //! Safe access to Postgres' *Server Programming Interface* (SPI). -use crate::datum::{FromDatum, IntoDatum, Json, TryFromDatumError}; +use crate::datum::{DatumWithOid, FromDatum, IntoDatum, Json, TryFromDatumError}; use crate::pg_sys; -use crate::PgOid; use core::fmt::Formatter; use std::ffi::{CStr, CString}; use std::fmt::Debug; @@ -261,14 +260,14 @@ impl Spi { pub fn get_one_with_args( query: &str, - args: &[(PgOid, Option)], + args: &[DatumWithOid], ) -> Result> { Spi::connect(|mut client| client.update(query, Some(1), args)?.first().get_one()) } pub fn get_two_with_args( query: &str, - args: &[(PgOid, Option)], + args: &[DatumWithOid], ) -> Result<(Option, Option)> { Spi::connect(|mut client| client.update(query, Some(1), args)?.first().get_two::()) } @@ -279,7 +278,7 @@ impl Spi { C: FromDatum + IntoDatum, >( query: &str, - args: &[(PgOid, Option)], + args: &[DatumWithOid], ) -> Result<(Option, Option, Option)> { Spi::connect(|mut client| { client.update(query, Some(1), args)?.first().get_three::() @@ -300,10 +299,7 @@ impl Spi { /// ## Safety /// /// The statement runs in read/write mode - pub fn run_with_args( - query: &str, - args: &[(PgOid, Option)], - ) -> std::result::Result<(), Error> { + pub fn run_with_args(query: &str, args: &[DatumWithOid]) -> std::result::Result<(), Error> { Spi::connect(|mut client| client.update(query, None, args).map(|_| ())) } @@ -313,7 +309,7 @@ impl Spi { } /// explain a query with args, returning its result in json form - pub fn explain_with_args(query: &str, args: &[(PgOid, Option)]) -> Result { + pub fn explain_with_args(query: &str, args: &[DatumWithOid]) -> Result { Ok(Spi::connect(|mut client| { client .update(&format!("EXPLAIN (format json) {query}"), None, args)? diff --git a/pgrx/src/spi/client.rs b/pgrx/src/spi/client.rs index aea2e6010..7e6042733 100644 --- a/pgrx/src/spi/client.rs +++ b/pgrx/src/spi/client.rs @@ -2,6 +2,7 @@ use std::ffi::CString; use std::marker::PhantomData; use std::ptr::NonNull; +use crate::datum::DatumWithOid; use crate::pg_sys::{self, PgOid}; use crate::spi::{PreparedStatement, Query, Spi, SpiCursor, SpiError, SpiResult, SpiTupleTable}; @@ -74,7 +75,7 @@ impl<'conn> SpiClient<'conn> { &self, query: Q, limit: Option, - args: &[Q::Argument], + args: &[DatumWithOid], ) -> SpiResult> { query.execute(self, limit, args) } @@ -84,7 +85,7 @@ impl<'conn> SpiClient<'conn> { &mut self, query: Q, limit: Option, - args: &[Q::Argument], + args: &[DatumWithOid], ) -> SpiResult> { Spi::mark_mutable(); query.execute(self, limit, args) @@ -123,7 +124,11 @@ impl<'conn> SpiClient<'conn> { /// # Panics /// /// Panics if a cursor wasn't opened. - pub fn open_cursor>(&self, query: Q, args: &[Q::Argument]) -> SpiCursor<'conn> { + pub fn open_cursor>( + &self, + query: Q, + args: &[DatumWithOid], + ) -> SpiCursor<'conn> { self.try_open_cursor(query, args).unwrap() } @@ -135,7 +140,7 @@ impl<'conn> SpiClient<'conn> { pub fn try_open_cursor>( &self, query: Q, - args: &[Q::Argument], + args: &[DatumWithOid], ) -> SpiResult> { query.try_open_cursor(self, args) } @@ -154,7 +159,7 @@ impl<'conn> SpiClient<'conn> { pub fn open_cursor_mut>( &mut self, query: Q, - args: &[Q::Argument], + args: &[DatumWithOid], ) -> SpiCursor<'conn> { Spi::mark_mutable(); self.try_open_cursor_mut(query, args).unwrap() @@ -168,7 +173,7 @@ impl<'conn> SpiClient<'conn> { pub fn try_open_cursor_mut>( &mut self, query: Q, - args: &[Q::Argument], + args: &[DatumWithOid], ) -> SpiResult> { Spi::mark_mutable(); query.try_open_cursor(self, args) diff --git a/pgrx/src/spi/query.rs b/pgrx/src/spi/query.rs index 61c50b86e..a2618d43f 100644 --- a/pgrx/src/spi/query.rs +++ b/pgrx/src/spi/query.rs @@ -6,7 +6,7 @@ use std::ptr::NonNull; use libc::c_char; use super::{Spi, SpiClient, SpiCursor, SpiError, SpiResult, SpiTupleTable}; -use crate::pg_sys::{self, PgOid}; +use crate::{datum::DatumWithOid, pg_sys}; /// A generalized interface to what constitutes a query /// @@ -14,14 +14,12 @@ use crate::pg_sys::{self, PgOid}; /// one-off statements and prepared statements, but it can potentially /// be implemented for other types, provided they can be converted into a query. pub trait Query<'conn>: Sized { - type Argument; - /// Execute a query given a client and other arguments. fn execute( self, client: &SpiClient<'conn>, limit: Option, - args: &[Self::Argument], + args: &[DatumWithOid], ) -> SpiResult>; /// Open a cursor for the query. @@ -30,7 +28,7 @@ pub trait Query<'conn>: Sized { /// /// Panics if a cursor wasn't opened. #[deprecated(since = "0.12.2", note = "undefined behavior")] - fn open_cursor(self, client: &SpiClient<'conn>, args: &[Self::Argument]) -> SpiCursor<'conn> { + fn open_cursor(self, client: &SpiClient<'conn>, args: &[DatumWithOid]) -> SpiCursor<'conn> { self.try_open_cursor(client, args).unwrap() } @@ -38,18 +36,16 @@ pub trait Query<'conn>: Sized { fn try_open_cursor( self, client: &SpiClient<'conn>, - args: &[Self::Argument], + args: &[DatumWithOid], ) -> SpiResult>; } impl<'conn> Query<'conn> for &String { - type Argument = (PgOid, Option); - fn execute( self, client: &SpiClient<'conn>, limit: Option, - args: &[Self::Argument], + args: &[DatumWithOid], ) -> SpiResult> { self.as_str().execute(client, limit, args) } @@ -57,30 +53,28 @@ impl<'conn> Query<'conn> for &String { fn try_open_cursor( self, client: &SpiClient<'conn>, - args: &[Self::Argument], + args: &[DatumWithOid], ) -> SpiResult> { self.as_str().try_open_cursor(client, args) } } -fn prepare_datum(datum: &Option) -> (pg_sys::Datum, std::os::raw::c_char) { - match datum { - Some(datum) => (*datum, ' ' as std::os::raw::c_char), +fn prepare_datum(datum: &DatumWithOid) -> (pg_sys::Datum, std::os::raw::c_char) { + match datum.datum() { + Some(datum) => (datum.sans_lifetime(), ' ' as std::os::raw::c_char), None => (pg_sys::Datum::from(0usize), 'n' as std::os::raw::c_char), } } -fn args_to_datums( - args: &[(PgOid, Option)], -) -> (Vec, Vec, Vec) { +fn args_to_datums(args: &[DatumWithOid]) -> (Vec, Vec, Vec) { let mut argtypes = Vec::with_capacity(args.len()); let mut datums = Vec::with_capacity(args.len()); let mut nulls = Vec::with_capacity(args.len()); - for (types, maybe_datum) in args { - let (datum, null) = prepare_datum(maybe_datum); + for arg in args { + let (datum, null) = prepare_datum(arg); - argtypes.push(types.value()); + argtypes.push(arg.oid()); datums.push(datum); nulls.push(null); } @@ -89,8 +83,6 @@ fn args_to_datums( } impl<'conn> Query<'conn> for &str { - type Argument = (PgOid, Option); - /// # Panics /// /// This function will panic if somehow the specified query contains a null byte. @@ -98,7 +90,7 @@ impl<'conn> Query<'conn> for &str { self, _client: &SpiClient<'conn>, limit: Option, - args: &[Self::Argument], + args: &[DatumWithOid], ) -> SpiResult> { // SAFETY: no concurrent access unsafe { @@ -139,7 +131,7 @@ impl<'conn> Query<'conn> for &str { fn try_open_cursor( self, _client: &SpiClient<'conn>, - args: &[Self::Argument], + args: &[DatumWithOid], ) -> SpiResult> { let src = CString::new(self).expect("query contained a null byte"); @@ -191,13 +183,11 @@ impl Drop for OwnedPreparedStatement { } impl<'conn> Query<'conn> for &OwnedPreparedStatement { - type Argument = <::Target as Query<'static>>::Argument; - fn execute( self, client: &SpiClient<'conn>, limit: Option, - args: &[Self::Argument], + args: &[DatumWithOid], ) -> SpiResult> { (&self.0).execute(client, limit, args) } @@ -205,20 +195,18 @@ impl<'conn> Query<'conn> for &OwnedPreparedStatement { fn try_open_cursor( self, client: &SpiClient<'conn>, - args: &[Self::Argument], + args: &[DatumWithOid], ) -> SpiResult> { (&self.0).try_open_cursor(client, args) } } impl<'conn> Query<'conn> for OwnedPreparedStatement { - type Argument = <::Target as Query<'static>>::Argument; - fn execute( self, client: &SpiClient<'conn>, limit: Option, - args: &[Self::Argument], + args: &[DatumWithOid], ) -> SpiResult> { (&self.0).execute(client, limit, args) } @@ -226,7 +214,7 @@ impl<'conn> Query<'conn> for OwnedPreparedStatement { fn try_open_cursor( self, client: &SpiClient<'conn>, - args: &[Self::Argument], + args: &[DatumWithOid], ) -> SpiResult> { (&self.0).try_open_cursor(client, args) } @@ -252,7 +240,7 @@ impl<'conn> PreparedStatement<'conn> { fn args_to_datums( &self, - args: &[>::Argument], + args: &[DatumWithOid], ) -> SpiResult<(Vec, Vec)> { let actual = args.len(); let expected = unsafe { pg_sys::SPI_getargcount(self.plan.as_ptr()) } as usize; @@ -266,13 +254,11 @@ impl<'conn> PreparedStatement<'conn> { } impl<'conn: 'stmt, 'stmt> Query<'conn> for &'stmt PreparedStatement<'conn> { - type Argument = Option; - fn execute( self, _client: &SpiClient<'conn>, limit: Option, - args: &[Self::Argument], + args: &[DatumWithOid], ) -> SpiResult> { // SAFETY: no concurrent access unsafe { @@ -298,7 +284,7 @@ impl<'conn: 'stmt, 'stmt> Query<'conn> for &'stmt PreparedStatement<'conn> { fn try_open_cursor( self, _client: &SpiClient<'conn>, - args: &[Self::Argument], + args: &[DatumWithOid], ) -> SpiResult> { let (mut datums, nulls) = self.args_to_datums(args)?; @@ -318,13 +304,11 @@ impl<'conn: 'stmt, 'stmt> Query<'conn> for &'stmt PreparedStatement<'conn> { } impl<'conn> Query<'conn> for PreparedStatement<'conn> { - type Argument = Option; - fn execute( self, client: &SpiClient<'conn>, limit: Option, - args: &[Self::Argument], + args: &[DatumWithOid], ) -> SpiResult> { (&self).execute(client, limit, args) } @@ -332,7 +316,7 @@ impl<'conn> Query<'conn> for PreparedStatement<'conn> { fn try_open_cursor( self, client: &SpiClient<'conn>, - args: &[Self::Argument], + args: &[DatumWithOid], ) -> SpiResult> { (&self).try_open_cursor(client, args) } From defa24821af06943c8d34257d38d4fb376ef5bd3 Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Thu, 12 Sep 2024 12:12:29 +0300 Subject: [PATCH 4/9] Explicit lifetimes for datum with oids --- pgrx-tests/tests/todo/roundtrip-tests.stderr | 12 ++-- pgrx/src/spi.rs | 18 +++-- pgrx/src/spi/client.rs | 24 +++---- pgrx/src/spi/query.rs | 72 +++++++++++--------- 4 files changed, 68 insertions(+), 58 deletions(-) diff --git a/pgrx-tests/tests/todo/roundtrip-tests.stderr b/pgrx-tests/tests/todo/roundtrip-tests.stderr index 7e7f708f1..9faaeae97 100644 --- a/pgrx-tests/tests/todo/roundtrip-tests.stderr +++ b/pgrx-tests/tests/todo/roundtrip-tests.stderr @@ -99,8 +99,8 @@ error[E0277]: the trait bound `Vec>: FromDatum` is not satisfied note: required by a bound in `pgrx::Spi::get_one_with_args` --> $WORKSPACE/pgrx/src/spi.rs | - | pub fn get_one_with_args( - | ^^^^^^^^^ required by this bound in `Spi::get_one_with_args` + | pub fn get_one_with_args<'mcx, A: FromDatum + IntoDatum>( + | ^^^^^^^^^ required by this bound in `Spi::get_one_with_args` = note: this error originates in the macro `roundtrip_test` which comes from the expansion of the macro `roundtrip` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Vec>: FromDatum` is not satisfied @@ -128,8 +128,8 @@ error[E0277]: the trait bound `Vec>: FromDatum` is not satisfied note: required by a bound in `pgrx::Spi::get_one_with_args` --> $WORKSPACE/pgrx/src/spi.rs | - | pub fn get_one_with_args( - | ^^^^^^^^^ required by this bound in `Spi::get_one_with_args` + | pub fn get_one_with_args<'mcx, A: FromDatum + IntoDatum>( + | ^^^^^^^^^ required by this bound in `Spi::get_one_with_args` = note: this error originates in the macro `roundtrip_test` which comes from the expansion of the macro `roundtrip` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Vec>: ArgAbi<'_>` is not satisfied @@ -184,6 +184,6 @@ error[E0277]: the trait bound `Vec>: FromDatum` is not satisfied note: required by a bound in `pgrx::Spi::get_one_with_args` --> $WORKSPACE/pgrx/src/spi.rs | - | pub fn get_one_with_args( - | ^^^^^^^^^ required by this bound in `Spi::get_one_with_args` + | pub fn get_one_with_args<'mcx, A: FromDatum + IntoDatum>( + | ^^^^^^^^^ required by this bound in `Spi::get_one_with_args` = note: this error originates in the macro `roundtrip_test` which comes from the expansion of the macro `roundtrip` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/pgrx/src/spi.rs b/pgrx/src/spi.rs index c92dd55a9..df618ef21 100644 --- a/pgrx/src/spi.rs +++ b/pgrx/src/spi.rs @@ -258,27 +258,28 @@ impl Spi { }) } - pub fn get_one_with_args( + pub fn get_one_with_args<'mcx, A: FromDatum + IntoDatum>( query: &str, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> Result> { Spi::connect(|mut client| client.update(query, Some(1), args)?.first().get_one()) } - pub fn get_two_with_args( + pub fn get_two_with_args<'mcx, A: FromDatum + IntoDatum, B: FromDatum + IntoDatum>( query: &str, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> Result<(Option, Option)> { Spi::connect(|mut client| client.update(query, Some(1), args)?.first().get_two::()) } pub fn get_three_with_args< + 'mcx, A: FromDatum + IntoDatum, B: FromDatum + IntoDatum, C: FromDatum + IntoDatum, >( query: &str, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> Result<(Option, Option, Option)> { Spi::connect(|mut client| { client.update(query, Some(1), args)?.first().get_three::() @@ -299,7 +300,10 @@ impl Spi { /// ## Safety /// /// The statement runs in read/write mode - pub fn run_with_args(query: &str, args: &[DatumWithOid]) -> std::result::Result<(), Error> { + pub fn run_with_args<'mcx>( + query: &str, + args: &[DatumWithOid<'mcx>], + ) -> std::result::Result<(), Error> { Spi::connect(|mut client| client.update(query, None, args).map(|_| ())) } @@ -309,7 +313,7 @@ impl Spi { } /// explain a query with args, returning its result in json form - pub fn explain_with_args(query: &str, args: &[DatumWithOid]) -> Result { + pub fn explain_with_args<'mcx>(query: &str, args: &[DatumWithOid<'mcx>]) -> Result { Ok(Spi::connect(|mut client| { client .update(&format!("EXPLAIN (format json) {query}"), None, args)? diff --git a/pgrx/src/spi/client.rs b/pgrx/src/spi/client.rs index 7e6042733..d04956f43 100644 --- a/pgrx/src/spi/client.rs +++ b/pgrx/src/spi/client.rs @@ -71,21 +71,21 @@ impl<'conn> SpiClient<'conn> { } /// perform a SELECT statement - pub fn select>( + pub fn select<'mcx, Q: Query<'conn>>( &self, query: Q, limit: Option, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> SpiResult> { query.execute(self, limit, args) } /// perform any query (including utility statements) that modify the database in some way - pub fn update>( + pub fn update<'mcx, Q: Query<'conn>>( &mut self, query: Q, limit: Option, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> SpiResult> { Spi::mark_mutable(); query.execute(self, limit, args) @@ -124,10 +124,10 @@ impl<'conn> SpiClient<'conn> { /// # Panics /// /// Panics if a cursor wasn't opened. - pub fn open_cursor>( + pub fn open_cursor<'mcx, Q: Query<'conn>>( &self, query: Q, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> SpiCursor<'conn> { self.try_open_cursor(query, args).unwrap() } @@ -137,10 +137,10 @@ impl<'conn> SpiClient<'conn> { /// Rows may be then fetched using [`SpiCursor::fetch`]. /// /// See [`SpiCursor`] docs for usage details. - pub fn try_open_cursor>( + pub fn try_open_cursor<'mcx, Q: Query<'conn>>( &self, query: Q, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> SpiResult> { query.try_open_cursor(self, args) } @@ -156,10 +156,10 @@ impl<'conn> SpiClient<'conn> { /// # Panics /// /// Panics if a cursor wasn't opened. - pub fn open_cursor_mut>( + pub fn open_cursor_mut<'mcx, Q: Query<'conn>>( &mut self, query: Q, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> SpiCursor<'conn> { Spi::mark_mutable(); self.try_open_cursor_mut(query, args).unwrap() @@ -170,10 +170,10 @@ impl<'conn> SpiClient<'conn> { /// Rows may be then fetched using [`SpiCursor::fetch`]. /// /// See [`SpiCursor`] docs for usage details. - pub fn try_open_cursor_mut>( + pub fn try_open_cursor_mut<'mcx, Q: Query<'conn>>( &mut self, query: Q, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> SpiResult> { Spi::mark_mutable(); query.try_open_cursor(self, args) diff --git a/pgrx/src/spi/query.rs b/pgrx/src/spi/query.rs index a2618d43f..3001f4c6d 100644 --- a/pgrx/src/spi/query.rs +++ b/pgrx/src/spi/query.rs @@ -15,11 +15,11 @@ use crate::{datum::DatumWithOid, pg_sys}; /// be implemented for other types, provided they can be converted into a query. pub trait Query<'conn>: Sized { /// Execute a query given a client and other arguments. - fn execute( + fn execute<'mcx>( self, client: &SpiClient<'conn>, limit: Option, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> SpiResult>; /// Open a cursor for the query. @@ -28,45 +28,51 @@ pub trait Query<'conn>: Sized { /// /// Panics if a cursor wasn't opened. #[deprecated(since = "0.12.2", note = "undefined behavior")] - fn open_cursor(self, client: &SpiClient<'conn>, args: &[DatumWithOid]) -> SpiCursor<'conn> { + fn open_cursor<'mcx>( + self, + client: &SpiClient<'conn>, + args: &[DatumWithOid<'mcx>], + ) -> SpiCursor<'conn> { self.try_open_cursor(client, args).unwrap() } /// Tries to open cursor for the query. - fn try_open_cursor( + fn try_open_cursor<'mcx>( self, client: &SpiClient<'conn>, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> SpiResult>; } impl<'conn> Query<'conn> for &String { - fn execute( + fn execute<'mcx>( self, client: &SpiClient<'conn>, limit: Option, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> SpiResult> { self.as_str().execute(client, limit, args) } - fn try_open_cursor( + fn try_open_cursor<'mcx>( self, client: &SpiClient<'conn>, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> SpiResult> { self.as_str().try_open_cursor(client, args) } } -fn prepare_datum(datum: &DatumWithOid) -> (pg_sys::Datum, std::os::raw::c_char) { +fn prepare_datum<'mcx>(datum: &DatumWithOid<'mcx>) -> (pg_sys::Datum, std::os::raw::c_char) { match datum.datum() { Some(datum) => (datum.sans_lifetime(), ' ' as std::os::raw::c_char), None => (pg_sys::Datum::from(0usize), 'n' as std::os::raw::c_char), } } -fn args_to_datums(args: &[DatumWithOid]) -> (Vec, Vec, Vec) { +fn args_to_datums<'mcx>( + args: &[DatumWithOid<'mcx>], +) -> (Vec, Vec, Vec) { let mut argtypes = Vec::with_capacity(args.len()); let mut datums = Vec::with_capacity(args.len()); let mut nulls = Vec::with_capacity(args.len()); @@ -86,11 +92,11 @@ impl<'conn> Query<'conn> for &str { /// # Panics /// /// This function will panic if somehow the specified query contains a null byte. - fn execute( + fn execute<'mcx>( self, _client: &SpiClient<'conn>, limit: Option, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> SpiResult> { // SAFETY: no concurrent access unsafe { @@ -128,10 +134,10 @@ impl<'conn> Query<'conn> for &str { SpiClient::prepare_tuple_table(status_code) } - fn try_open_cursor( + fn try_open_cursor<'mcx>( self, _client: &SpiClient<'conn>, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> SpiResult> { let src = CString::new(self).expect("query contained a null byte"); @@ -183,38 +189,38 @@ impl Drop for OwnedPreparedStatement { } impl<'conn> Query<'conn> for &OwnedPreparedStatement { - fn execute( + fn execute<'mcx>( self, client: &SpiClient<'conn>, limit: Option, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> SpiResult> { (&self.0).execute(client, limit, args) } - fn try_open_cursor( + fn try_open_cursor<'mcx>( self, client: &SpiClient<'conn>, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> SpiResult> { (&self.0).try_open_cursor(client, args) } } impl<'conn> Query<'conn> for OwnedPreparedStatement { - fn execute( + fn execute<'mcx>( self, client: &SpiClient<'conn>, limit: Option, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> SpiResult> { (&self.0).execute(client, limit, args) } - fn try_open_cursor( + fn try_open_cursor<'mcx>( self, client: &SpiClient<'conn>, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> SpiResult> { (&self.0).try_open_cursor(client, args) } @@ -238,9 +244,9 @@ impl<'conn> PreparedStatement<'conn> { }) } - fn args_to_datums( + fn args_to_datums<'mcx>( &self, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> SpiResult<(Vec, Vec)> { let actual = args.len(); let expected = unsafe { pg_sys::SPI_getargcount(self.plan.as_ptr()) } as usize; @@ -254,11 +260,11 @@ impl<'conn> PreparedStatement<'conn> { } impl<'conn: 'stmt, 'stmt> Query<'conn> for &'stmt PreparedStatement<'conn> { - fn execute( + fn execute<'mcx>( self, _client: &SpiClient<'conn>, limit: Option, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> SpiResult> { // SAFETY: no concurrent access unsafe { @@ -281,10 +287,10 @@ impl<'conn: 'stmt, 'stmt> Query<'conn> for &'stmt PreparedStatement<'conn> { SpiClient::prepare_tuple_table(status_code) } - fn try_open_cursor( + fn try_open_cursor<'mcx>( self, _client: &SpiClient<'conn>, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> SpiResult> { let (mut datums, nulls) = self.args_to_datums(args)?; @@ -304,19 +310,19 @@ impl<'conn: 'stmt, 'stmt> Query<'conn> for &'stmt PreparedStatement<'conn> { } impl<'conn> Query<'conn> for PreparedStatement<'conn> { - fn execute( + fn execute<'mcx>( self, client: &SpiClient<'conn>, limit: Option, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> SpiResult> { (&self).execute(client, limit, args) } - fn try_open_cursor( + fn try_open_cursor<'mcx>( self, client: &SpiClient<'conn>, - args: &[DatumWithOid], + args: &[DatumWithOid<'mcx>], ) -> SpiResult> { (&self).try_open_cursor(client, args) } From 3a7ea89e85ee2f0bb7a849d4990537946004d504 Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Thu, 12 Sep 2024 21:16:37 +0300 Subject: [PATCH 5/9] Fixed examples --- pgrx-examples/pgtrybuilder/Cargo.lock | 52 ++++++++++++++++++--------- pgrx-examples/spi/src/lib.rs | 15 +++----- pgrx-examples/spi_srf/src/lib.rs | 2 +- 3 files changed, 40 insertions(+), 29 deletions(-) diff --git a/pgrx-examples/pgtrybuilder/Cargo.lock b/pgrx-examples/pgtrybuilder/Cargo.lock index 69562292b..773ee93f8 100644 --- a/pgrx-examples/pgtrybuilder/Cargo.lock +++ b/pgrx-examples/pgtrybuilder/Cargo.lock @@ -26,6 +26,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "annotate-snippets" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccaf7e9dfbb6ab22c82e473cd1a8a7bd313c19a5b7e40970f3d89ef5a5c9e81e" +dependencies = [ + "unicode-width", + "yansi-term", +] + [[package]] name = "anstyle" version = "1.0.8" @@ -88,16 +98,15 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bindgen" -version = "0.69.4" +version = "0.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" dependencies = [ + "annotate-snippets", "bitflags", "cexpr", "clang-sys", "itertools", - "lazy_static", - "lazycell", "proc-macro2", "quote", "regex", @@ -690,12 +699,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "libc" version = "0.2.158" @@ -904,7 +907,7 @@ dependencies = [ [[package]] name = "pgrx" -version = "0.12.3" +version = "0.12.4" dependencies = [ "atomic-traits", "bitflags", @@ -926,7 +929,7 @@ dependencies = [ [[package]] name = "pgrx-bindgen" -version = "0.12.3" +version = "0.12.4" dependencies = [ "bindgen", "clang-sys", @@ -941,7 +944,7 @@ dependencies = [ [[package]] name = "pgrx-macros" -version = "0.12.3" +version = "0.12.4" dependencies = [ "pgrx-sql-entity-graph", "proc-macro2", @@ -951,7 +954,7 @@ dependencies = [ [[package]] name = "pgrx-pg-config" -version = "0.12.3" +version = "0.12.4" dependencies = [ "cargo_toml", "eyre", @@ -967,7 +970,7 @@ dependencies = [ [[package]] name = "pgrx-pg-sys" -version = "0.12.3" +version = "0.12.4" dependencies = [ "cee-scape", "libc", @@ -980,7 +983,7 @@ dependencies = [ [[package]] name = "pgrx-sql-entity-graph" -version = "0.12.3" +version = "0.12.4" dependencies = [ "convert_case", "eyre", @@ -994,7 +997,7 @@ dependencies = [ [[package]] name = "pgrx-tests" -version = "0.12.3" +version = "0.12.4" dependencies = [ "clap-cargo", "eyre", @@ -1714,6 +1717,12 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +[[package]] +name = "unicode-width" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" + [[package]] name = "url" version = "2.5.2" @@ -1997,6 +2006,15 @@ dependencies = [ "tap", ] +[[package]] +name = "yansi-term" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe5c30ade05e61656247b2e334a031dfd0cc466fadef865bdcdea8d537951bf1" +dependencies = [ + "winapi", +] + [[package]] name = "zerocopy" version = "0.7.35" diff --git a/pgrx-examples/spi/src/lib.rs b/pgrx-examples/spi/src/lib.rs index 8a1b5a08d..65d2956d7 100644 --- a/pgrx-examples/spi/src/lib.rs +++ b/pgrx-examples/spi/src/lib.rs @@ -62,21 +62,14 @@ fn spi_query_random_id() -> Result, pgrx::spi::Error> { #[pg_extern] fn spi_query_title(title: &str) -> Result, pgrx::spi::Error> { - Spi::get_one_with_args( - "SELECT id FROM spi.spi_example WHERE title = $1;", - &[(PgBuiltInOids::TEXTOID.oid(), title.into_datum())], - ) + Spi::get_one_with_args("SELECT id FROM spi.spi_example WHERE title = $1;", &[title.into()]) } #[pg_extern] fn spi_query_by_id(id: i64) -> Result, spi::Error> { let (returned_id, title) = Spi::connect(|client| { let tuptable = client - .select( - "SELECT id, title FROM spi.spi_example WHERE id = $1", - None, - &[(PgBuiltInOids::INT8OID.oid(), id.into_datum())], - )? + .select("SELECT id, title FROM spi.spi_example WHERE id = $1", None, &[id.into()])? .first(); tuptable.get_two::() @@ -90,7 +83,7 @@ fn spi_query_by_id(id: i64) -> Result, spi::Error> { fn spi_insert_title(title: &str) -> Result, spi::Error> { Spi::get_one_with_args( "INSERT INTO spi.spi_example(title) VALUES ($1) RETURNING id", - &[(PgBuiltInOids::TEXTOID.oid(), title.into_datum())], + &[title.into()], ) } @@ -100,7 +93,7 @@ fn spi_insert_title2( ) -> TableIterator<(name!(id, Option), name!(title, Option))> { let tuple = Spi::get_two_with_args( "INSERT INTO spi.spi_example(title) VALUES ($1) RETURNING id, title", - &[(PgBuiltInOids::TEXTOID.oid(), title.into_datum())], + &[title.into()], ) .unwrap(); diff --git a/pgrx-examples/spi_srf/src/lib.rs b/pgrx-examples/spi_srf/src/lib.rs index 125ec0c65..30a306032 100644 --- a/pgrx-examples/spi_srf/src/lib.rs +++ b/pgrx-examples/spi_srf/src/lib.rs @@ -89,7 +89,7 @@ fn filter_by_breed( */ let query = "SELECT * FROM spi_srf.dog_daycare WHERE dog_breed = $1;"; - let args = vec![(PgBuiltInOids::TEXTOID.oid(), breed.into_datum())]; + let args = vec![breed.into()]; Spi::connect(|client| { let tup_table = client.select(query, None, &args)?; From bf62700914a1164174e310a909381771b5bfece8 Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Thu, 12 Sep 2024 21:43:51 +0300 Subject: [PATCH 6/9] Simplified empty slice expressions --- pgrx-examples/bgworker/src/lib.rs | 2 +- pgrx-examples/custom_sql/src/lib.rs | 2 +- pgrx-examples/schemas/src/lib.rs | 4 +- pgrx-examples/spi/src/lib.rs | 5 +- pgrx-examples/spi_srf/src/lib.rs | 2 +- pgrx-tests/src/tests/heap_tuple.rs | 2 +- pgrx-tests/src/tests/pg_cast_tests.rs | 4 +- pgrx-tests/src/tests/spi_tests.rs | 102 ++++++++---------- pgrx-tests/src/tests/srf_tests.rs | 20 ++-- pgrx-tests/src/tests/struct_type_tests.rs | 6 +- .../escaping-spiclient-1209-cursor.rs | 4 +- .../escaping-spiclient-1209-cursor.stderr | 14 +-- .../escaping-spiclient-1209-prep-stmt.rs | 2 +- pgrx/src/spi.rs | 12 +-- pgrx/src/spi/cursor.rs | 4 +- 15 files changed, 88 insertions(+), 97 deletions(-) diff --git a/pgrx-examples/bgworker/src/lib.rs b/pgrx-examples/bgworker/src/lib.rs index 16770ddcf..b71d9accd 100644 --- a/pgrx-examples/bgworker/src/lib.rs +++ b/pgrx-examples/bgworker/src/lib.rs @@ -69,7 +69,7 @@ pub extern "C" fn background_worker_main(arg: pg_sys::Datum) { let tuple_table = client.select( "SELECT 'Hi', id, ''||a FROM (SELECT id, 42 from generate_series(1,10) id) a ", None, - &[][..], + &[], )?; for tuple in tuple_table { let a = tuple.get_datum_by_ordinal(1)?.value::()?; diff --git a/pgrx-examples/custom_sql/src/lib.rs b/pgrx-examples/custom_sql/src/lib.rs index 602f67c6a..251676b3a 100644 --- a/pgrx-examples/custom_sql/src/lib.rs +++ b/pgrx-examples/custom_sql/src/lib.rs @@ -89,7 +89,7 @@ mod tests { let buf = Spi::connect(|client| { Ok::<_, spi::Error>( client - .select("SELECT * FROM extension_sql", None, &[][..])? + .select("SELECT * FROM extension_sql", None, &[])? .flat_map(|tup| { tup.get_datum_by_ordinal(1) .ok() diff --git a/pgrx-examples/schemas/src/lib.rs b/pgrx-examples/schemas/src/lib.rs index 5b83373dc..66064c766 100644 --- a/pgrx-examples/schemas/src/lib.rs +++ b/pgrx-examples/schemas/src/lib.rs @@ -103,10 +103,10 @@ mod tests { fn test_my_some_schema_type() -> Result<(), spi::Error> { Spi::connect(|mut c| { // "MySomeSchemaType" is in 'some_schema', so it needs to be discoverable - c.update("SET search_path TO some_schema,public", None, &[][..])?; + c.update("SET search_path TO some_schema,public", None, &[])?; assert_eq!( String::from("test"), - c.select("SELECT '\"test\"'::MySomeSchemaType", None, &[][..])? + c.select("SELECT '\"test\"'::MySomeSchemaType", None, &[])? .first() .get_one::() .expect("get_one::() failed") diff --git a/pgrx-examples/spi/src/lib.rs b/pgrx-examples/spi/src/lib.rs index 65d2956d7..22b31bed2 100644 --- a/pgrx-examples/spi/src/lib.rs +++ b/pgrx-examples/spi/src/lib.rs @@ -48,7 +48,7 @@ fn spi_return_query() -> Result< Spi::connect(|client| { client - .select(query, None, &[][..])? + .select(query, None, &[])? .map(|row| Ok((row["oid"].value()?, row[2].value()?))) .collect::, _>>() }) @@ -103,8 +103,7 @@ fn spi_insert_title2( #[pg_extern] fn issue1209_fixed() -> Result, Box> { let res = Spi::connect(|c| { - let mut cursor = - c.try_open_cursor("SELECT 'hello' FROM generate_series(1, 10000)", &[][..])?; + let mut cursor = c.try_open_cursor("SELECT 'hello' FROM generate_series(1, 10000)", &[])?; let table = cursor.fetch(10000)?; table.into_iter().map(|row| row.get::<&str>(1)).collect::, _>>() })?; diff --git a/pgrx-examples/spi_srf/src/lib.rs b/pgrx-examples/spi_srf/src/lib.rs index 30a306032..63027fed3 100644 --- a/pgrx-examples/spi_srf/src/lib.rs +++ b/pgrx-examples/spi_srf/src/lib.rs @@ -55,7 +55,7 @@ fn calculate_human_years() -> Result< Spi::connect(|client| { let mut results = Vec::new(); - let tup_table = client.select(query, None, &[][..])?; + let tup_table = client.select(query, None, &[])?; for row in tup_table { let dog_name = row["dog_name"].value::(); diff --git a/pgrx-tests/src/tests/heap_tuple.rs b/pgrx-tests/src/tests/heap_tuple.rs index 17a0db09f..dd8cdc053 100644 --- a/pgrx-tests/src/tests/heap_tuple.rs +++ b/pgrx-tests/src/tests/heap_tuple.rs @@ -881,7 +881,7 @@ mod tests { fn test_tuple_desc_clone() -> Result<(), spi::Error> { let result = Spi::connect(|client| { let query = "select * from generate_lots_of_dogs()"; - client.select(query, None, &[][..]).map(|table| table.len()) + client.select(query, None, &[]).map(|table| table.len()) })?; assert_eq!(result, 10_000); Ok(()) diff --git a/pgrx-tests/src/tests/pg_cast_tests.rs b/pgrx-tests/src/tests/pg_cast_tests.rs index a27f9c5be..503aec338 100644 --- a/pgrx-tests/src/tests/pg_cast_tests.rs +++ b/pgrx-tests/src/tests/pg_cast_tests.rs @@ -48,11 +48,11 @@ mod tests { #[pg_test] fn test_pg_cast_assignment_type_cast() { let _ = Spi::connect(|mut client| { - client.update("CREATE TABLE test_table(value int4);", None, &[][..])?; + client.update("CREATE TABLE test_table(value int4);", None, &[])?; client.update( "INSERT INTO test_table VALUES('{\"a\": 1}'::json->'a');", None, - &[][..], + &[], )?; Ok::<_, spi::Error>(()) diff --git a/pgrx-tests/src/tests/spi_tests.rs b/pgrx-tests/src/tests/spi_tests.rs index 190919d7e..dabb69a98 100644 --- a/pgrx-tests/src/tests/spi_tests.rs +++ b/pgrx-tests/src/tests/spi_tests.rs @@ -22,7 +22,7 @@ mod tests { #[pg_test(error = "syntax error at or near \"THIS\"")] fn test_spi_failure() -> Result<(), spi::Error> { - Spi::connect(|client| client.select("THIS IS NOT A VALID QUERY", None, &[][..]).map(|_| ())) + Spi::connect(|client| client.select("THIS IS NOT A VALID QUERY", None, &[]).map(|_| ())) } #[pg_test] @@ -34,9 +34,8 @@ mod tests { #[pg_test] fn test_spi_returns_primitive() -> Result<(), spi::Error> { - let rc = Spi::connect(|client| { - client.select("SELECT 42", None, &[][..])?.first().get::(1) - })?; + let rc = + Spi::connect(|client| client.select("SELECT 42", None, &[])?.first().get::(1))?; assert_eq!(Some(42), rc); Ok(()) @@ -45,7 +44,7 @@ mod tests { #[pg_test] fn test_spi_returns_str() -> Result<(), spi::Error> { let rc = Spi::connect(|client| { - client.select("SELECT 'this is a test'", None, &[][..])?.first().get::<&str>(1) + client.select("SELECT 'this is a test'", None, &[])?.first().get::<&str>(1) })?; assert_eq!(Some("this is a test"), rc); @@ -55,7 +54,7 @@ mod tests { #[pg_test] fn test_spi_returns_string() -> Result<(), spi::Error> { let rc = Spi::connect(|client| { - client.select("SELECT 'this is a test'", None, &[][..])?.first().get::<&str>(1) + client.select("SELECT 'this is a test'", None, &[])?.first().get::<&str>(1) })?; assert_eq!(Some("this is a test"), rc); @@ -65,7 +64,7 @@ mod tests { #[pg_test] fn test_spi_get_one() -> Result<(), spi::Error> { Spi::connect(|client| { - let i = client.select("SELECT 42::bigint", None, &[][..])?.first().get_one::()?; + let i = client.select("SELECT 42::bigint", None, &[])?.first().get_one::()?; assert_eq!(Some(42), i); Ok(()) }) @@ -74,10 +73,8 @@ mod tests { #[pg_test] fn test_spi_get_two() -> Result<(), spi::Error> { Spi::connect(|client| { - let (i, s) = client - .select("SELECT 42, 'test'", None, &[][..])? - .first() - .get_two::()?; + let (i, s) = + client.select("SELECT 42, 'test'", None, &[])?.first().get_two::()?; assert_eq!(Some(42), i); assert_eq!(Some("test"), s); @@ -89,7 +86,7 @@ mod tests { fn test_spi_get_three() -> Result<(), spi::Error> { Spi::connect(|client| { let (i, s, b) = client - .select("SELECT 42, 'test', true", None, &[][..])? + .select("SELECT 42, 'test', true", None, &[])? .first() .get_three::()?; @@ -103,11 +100,7 @@ mod tests { #[pg_test] fn test_spi_get_two_with_failure() -> Result<(), spi::Error> { Spi::connect(|client| { - assert!(client - .select("SELECT 42", None, &[][..])? - .first() - .get_two::() - .is_err()); + assert!(client.select("SELECT 42", None, &[])?.first().get_two::().is_err()); Ok(()) }) } @@ -116,7 +109,7 @@ mod tests { fn test_spi_get_three_failure() -> Result<(), spi::Error> { Spi::connect(|client| { assert!(client - .select("SELECT 42, 'test'", None, &[][..])? + .select("SELECT 42, 'test'", None, &[])? .first() .get_three::() .is_err()); @@ -173,7 +166,7 @@ mod tests { #[pg_test] fn test_inserting_null() -> Result<(), pgrx::spi::Error> { Spi::connect(|mut client| { - client.update("CREATE TABLE tests.null_test (id uuid)", None, &[][..]).map(|_| ()) + client.update("CREATE TABLE tests.null_test (id uuid)", None, &[]).map(|_| ()) })?; assert_eq!( Spi::get_one_with_args::( @@ -196,14 +189,14 @@ mod tests { #[pg_test] fn test_cursor() -> Result<(), spi::Error> { Spi::connect(|mut client| { - client.update("CREATE TABLE tests.cursor_table (id int)", None, &[][..])?; + client.update("CREATE TABLE tests.cursor_table (id int)", None, &[])?; client.update( "INSERT INTO tests.cursor_table (id) \ SELECT i FROM generate_series(1, 10) AS t(i)", None, - &[][..], + &[], )?; - let mut portal = client.open_cursor("SELECT * FROM tests.cursor_table", &[][..]); + let mut portal = client.open_cursor("SELECT * FROM tests.cursor_table", &[]); assert_eq!(sum_all(portal.fetch(3)?), 1 + 2 + 3); assert_eq!(sum_all(portal.fetch(3)?), 4 + 5 + 6); @@ -216,15 +209,15 @@ mod tests { #[pg_test] fn test_cursor_prepared_statement() -> Result<(), pgrx::spi::Error> { Spi::connect(|mut client| { - client.update("CREATE TABLE tests.cursor_table (id int)", None, &[][..])?; + client.update("CREATE TABLE tests.cursor_table (id int)", None, &[])?; client.update( "INSERT INTO tests.cursor_table (id) \ SELECT i FROM generate_series(1, 10) AS t(i)", None, - &[][..], + &[], )?; let prepared = client.prepare("SELECT * FROM tests.cursor_table", None)?; - let mut portal = client.open_cursor(&prepared, &[][..]); + let mut portal = client.open_cursor(&prepared, &[]); assert_eq!(sum_all(portal.fetch(3)?), 1 + 2 + 3); assert_eq!(sum_all(portal.fetch(3)?), 4 + 5 + 6); @@ -237,7 +230,7 @@ mod tests { #[pg_test] #[should_panic(expected = "PreparedStatementArgumentMismatch { expected: 1, got: 0 }")] fn test_cursor_prepared_statement_panics_less_args() -> Result<(), pgrx::spi::Error> { - test_cursor_prepared_statement_panics_impl(&[][..]) + test_cursor_prepared_statement_panics_impl(&[]) } #[pg_test] @@ -253,12 +246,12 @@ mod tests { args: &[DatumWithOid], ) -> Result<(), pgrx::spi::Error> { Spi::connect(|mut client| { - client.update("CREATE TABLE tests.cursor_table (id int)", None, &[][..])?; + client.update("CREATE TABLE tests.cursor_table (id int)", None, &[])?; client.update( "INSERT INTO tests.cursor_table (id) \ SELECT i FROM generate_series(1, 10) AS t(i)", None, - &[][..], + &[], )?; let prepared = client.prepare( "SELECT * FROM tests.cursor_table WHERE id = $1", @@ -272,14 +265,14 @@ mod tests { #[pg_test] fn test_cursor_by_name() -> Result<(), pgrx::spi::Error> { let cursor_name = Spi::connect(|mut client| { - client.update("CREATE TABLE tests.cursor_table (id int)", None, &[][..])?; + client.update("CREATE TABLE tests.cursor_table (id int)", None, &[])?; client.update( "INSERT INTO tests.cursor_table (id) \ SELECT i FROM generate_series(1, 10) AS t(i)", None, - &[][..], + &[], )?; - let mut cursor = client.open_cursor("SELECT * FROM tests.cursor_table", &[][..]); + let mut cursor = client.open_cursor("SELECT * FROM tests.cursor_table", &[]); assert_eq!(sum_all(cursor.fetch(3)?), 1 + 2 + 3); Ok::<_, spi::Error>(cursor.detach_into_name()) })?; @@ -303,7 +296,7 @@ mod tests { #[pg_test(error = "syntax error at or near \"THIS\"")] fn test_cursor_failure() { Spi::connect(|client| { - client.open_cursor("THIS IS NOT SQL", &[][..]); + client.open_cursor("THIS IS NOT SQL", &[]); }) } @@ -315,7 +308,7 @@ mod tests { #[pg_test] fn test_columns() -> Result<(), spi::Error> { Spi::connect(|client| { - let res = client.select("SELECT 42 AS a, 'test' AS b", None, &[][..])?; + let res = client.select("SELECT 42 AS a, 'test' AS b", None, &[])?; assert_eq!(Ok(2), res.columns()); assert_eq!(res.column_type_oid(1).unwrap(), PgOid::BuiltIn(PgBuiltInOids::INT4OID)); @@ -326,7 +319,7 @@ mod tests { })?; Spi::connect(|mut client| { - let res = client.update("SET TIME ZONE 'PST8PDT'", None, &[][..])?; + let res = client.update("SET TIME ZONE 'PST8PDT'", None, &[])?; assert_eq!(Err(spi::Error::NoTupleTable), res.columns()); Ok(()) @@ -343,8 +336,8 @@ mod tests { fn test_spi_non_mut() -> Result<(), pgrx::spi::Error> { // Ensures update and cursor APIs do not need mutable reference to SpiClient Spi::connect(|mut client| { - client.update("SELECT 1", None, &[][..]).expect("SPI failed"); - let cursor = client.open_cursor("SELECT 1", &[][..]).detach_into_name(); + client.update("SELECT 1", None, &[]).expect("SPI failed"); + let cursor = client.open_cursor("SELECT 1", &[]).detach_into_name(); client.find_cursor(&cursor).map(|_| ()) }) } @@ -354,8 +347,8 @@ mod tests { // Regression test to ensure a new `SpiTupTable` instance does not override the // effective length of an already open one due to misuse of Spi statics Spi::connect(|client| { - let a = client.select("SELECT 1", None, &[][..])?.first(); - let _b = client.select("SELECT 1 WHERE 'f'", None, &[][..])?; + let a = client.select("SELECT 1", None, &[])?.first(); + let _b = client.select("SELECT 1 WHERE 'f'", None, &[])?; assert!(!a.is_empty()); assert_eq!(1, a.len()); assert!(a.get_heap_tuple().is_ok()); @@ -370,8 +363,8 @@ mod tests { // effective length of an already open one. // Same as `test_open_multiple_tuptables`, but with the second tuptable being empty Spi::connect(|client| { - let a = client.select("SELECT 1 WHERE 'f'", None, &[][..])?.first(); - let _b = client.select("SELECT 1", None, &[][..])?; + let a = client.select("SELECT 1 WHERE 'f'", None, &[])?.first(); + let _b = client.select("SELECT 1", None, &[])?; assert!(a.is_empty()); assert_eq!(0, a.len()); assert!(a.get_heap_tuple().is_ok()); @@ -397,7 +390,7 @@ mod tests { let err = Spi::connect(|client| { let prepared = client.prepare("SELECT $1", Some(vec![PgOid::BuiltIn(PgBuiltInOids::INT4OID)]))?; - client.select(&prepared, None, &[][..]).map(|_| ()) + client.select(&prepared, None, &[]).map(|_| ()) }) .unwrap_err(); @@ -432,16 +425,16 @@ mod tests { #[pg_test(error = "CREATE TABLE is not allowed in a non-volatile function")] fn test_readwrite_in_readonly() -> Result<(), spi::Error> { // This is supposed to run in read-only - Spi::connect(|client| client.select("CREATE TABLE a ()", None, &[][..]).map(|_| ())) + Spi::connect(|client| client.select("CREATE TABLE a ()", None, &[]).map(|_| ())) } #[pg_test] fn test_readwrite_in_select_readwrite() -> Result<(), spi::Error> { Spi::connect(|mut client| { // This is supposed to switch connection to read-write and run it there - client.update("CREATE TABLE a (id INT)", None, &[][..])?; + client.update("CREATE TABLE a (id INT)", None, &[])?; // This is supposed to run in read-write - client.select("INSERT INTO a VALUES (1)", None, &[][..])?; + client.select("INSERT INTO a VALUES (1)", None, &[])?; Ok(()) }) } @@ -451,7 +444,7 @@ mod tests { Spi::connect(|client| { let stmt = client.prepare("CREATE TABLE a ()", None)?; // This is supposed to run in read-only - stmt.execute(&client, Some(1), &[][..])?; + stmt.execute(&client, Some(1), &[])?; Ok(()) }) } @@ -461,7 +454,7 @@ mod tests { Spi::connect(|client| { let stmt = client.prepare_mut("CREATE TABLE a ()", None)?; // This is supposed to run in read-write - stmt.execute(&client, Some(1), &[][..])?; + stmt.execute(&client, Some(1), &[])?; Ok(()) }) } @@ -469,9 +462,9 @@ mod tests { #[pg_test] fn test_spi_select_sees_update() -> spi::Result<()> { let with_select = Spi::connect(|mut client| { - client.update("CREATE TABLE asd(id int)", None, &[][..])?; - client.update("INSERT INTO asd(id) VALUES (1)", None, &[][..])?; - client.select("SELECT COUNT(*) FROM asd", None, &[][..])?.first().get_one::() + client.update("CREATE TABLE asd(id int)", None, &[])?; + client.update("INSERT INTO asd(id) VALUES (1)", None, &[])?; + client.select("SELECT COUNT(*) FROM asd", None, &[])?.first().get_one::() })?; let with_get_one = Spi::get_one::("SELECT COUNT(*) FROM asd")?; @@ -484,7 +477,7 @@ mod tests { Spi::run("CREATE TABLE asd(id int)")?; Spi::run("INSERT INTO asd(id) VALUES (1)")?; let with_select = Spi::connect(|client| { - client.select("SELECT COUNT(*) FROM asd", None, &[][..])?.first().get_one::() + client.select("SELECT COUNT(*) FROM asd", None, &[])?.first().get_one::() })?; let with_get_one = Spi::get_one::("SELECT COUNT(*) FROM asd")?; @@ -495,12 +488,12 @@ mod tests { #[pg_test] fn test_spi_select_sees_update_in_other_session() -> spi::Result<()> { Spi::connect::, _>(|mut client| { - client.update("CREATE TABLE asd(id int)", None, &[][..])?; - client.update("INSERT INTO asd(id) VALUES (1)", None, &[][..])?; + client.update("CREATE TABLE asd(id int)", None, &[])?; + client.update("INSERT INTO asd(id) VALUES (1)", None, &[])?; Ok(()) })?; let with_select = Spi::connect(|client| { - client.select("SELECT COUNT(*) FROM asd", None, &[][..])?.first().get_one::() + client.select("SELECT COUNT(*) FROM asd", None, &[])?.first().get_one::() })?; let with_get_one = Spi::get_one::("SELECT COUNT(*) FROM asd")?; @@ -560,8 +553,7 @@ mod tests { #[pg_test] fn can_return_borrowed_str() -> Result<(), Box> { let res = Spi::connect(|c| { - let mut cursor = - c.open_cursor("SELECT 'hello' FROM generate_series(1, 10000)", &[][..]); + let mut cursor = c.open_cursor("SELECT 'hello' FROM generate_series(1, 10000)", &[]); let table = cursor.fetch(10000)?; table.into_iter().map(|row| row.get::<&str>(1)).collect::, _>>() })?; diff --git a/pgrx-tests/src/tests/srf_tests.rs b/pgrx-tests/src/tests/srf_tests.rs index 3f5554fb2..f8b964eba 100644 --- a/pgrx-tests/src/tests/srf_tests.rs +++ b/pgrx-tests/src/tests/srf_tests.rs @@ -154,7 +154,7 @@ mod tests { fn test_generate_series() { let cnt = Spi::connect(|client| { let mut table = - client.select("SELECT * FROM example_generate_series(1, 10)", None, &[][..])?; + client.select("SELECT * FROM example_generate_series(1, 10)", None, &[])?; let mut expect = 0; while table.next().is_some() { @@ -175,7 +175,7 @@ mod tests { fn test_composite_set() { let cnt = Spi::connect(|client| { let mut table = - client.select("SELECT * FROM example_composite_set()", None, &[][..])?; + client.select("SELECT * FROM example_composite_set()", None, &[])?; let mut expect = 0; while table.next().is_some() { @@ -201,7 +201,7 @@ mod tests { #[pg_test] fn test_return_table_iterator() { let cnt = Spi::connect(|client| { - let table = client.select("SELECT * from return_table_iterator();", None, &[][..])?; + let table = client.select("SELECT * from return_table_iterator();", None, &[])?; Ok::<_, spi::Error>(table.len() as i64) }); @@ -212,7 +212,7 @@ mod tests { #[pg_test] fn test_return_empty_iterator() { let cnt = Spi::connect(|client| { - let table = client.select("SELECT * from return_empty_iterator();", None, &[][..])?; + let table = client.select("SELECT * from return_empty_iterator();", None, &[])?; Ok::<_, spi::Error>(table.len() as i64) }); @@ -223,7 +223,7 @@ mod tests { #[pg_test] fn test_return_setof_iterator() { let cnt = Spi::connect(|client| { - let table = client.select("SELECT * from return_setof_iterator();", None, &[][..])?; + let table = client.select("SELECT * from return_setof_iterator();", None, &[])?; Ok::<_, spi::Error>(table.len() as i64) }); @@ -235,7 +235,7 @@ mod tests { fn test_return_empty_setof_iterator() { let cnt = Spi::connect(|client| { let table = - client.select("SELECT * from return_empty_setof_iterator();", None, &[][..])?; + client.select("SELECT * from return_empty_setof_iterator();", None, &[])?; Ok::<_, spi::Error>(table.len() as i64) }); @@ -247,13 +247,13 @@ mod tests { fn test_srf_setof_datum_detoasting_with_borrow() { let cnt = Spi::connect(|mut client| { // build up a table with one large column that Postgres will be forced to TOAST - client.update("CREATE TABLE test_srf_datum_detoasting AS SELECT array_to_string(array_agg(g),' ') s FROM (SELECT 'a' g FROM generate_series(1, 1000)) x;", None, &[][..])?; + client.update("CREATE TABLE test_srf_datum_detoasting AS SELECT array_to_string(array_agg(g),' ') s FROM (SELECT 'a' g FROM generate_series(1, 1000)) x;", None, &[])?; // and make sure we can use the DETOASTED value with our SRF function let table = client.select( "SELECT split_set_with_borrow(s, ' ') FROM test_srf_datum_detoasting", None, - &[][..], + &[], )?; Ok::<_, spi::Error>(table.len() as i64) @@ -265,13 +265,13 @@ mod tests { fn test_srf_table_datum_detoasting_with_borrow() { let cnt = Spi::connect(|mut client| { // build up a table with one large column that Postgres will be forced to TOAST - client.update("CREATE TABLE test_srf_datum_detoasting AS SELECT array_to_string(array_agg(g),' ') s FROM (SELECT 'a' g FROM generate_series(1, 1000)) x;", None, &[][..])?; + client.update("CREATE TABLE test_srf_datum_detoasting AS SELECT array_to_string(array_agg(g),' ') s FROM (SELECT 'a' g FROM generate_series(1, 1000)) x;", None, &[])?; // and make sure we can use the DETOASTED value with our SRF function let table = client.select( "SELECT split_table_with_borrow(s, ' ') FROM test_srf_datum_detoasting", None, - &[][..], + &[], )?; Ok::<_, spi::Error>(table.len() as i64) diff --git a/pgrx-tests/src/tests/struct_type_tests.rs b/pgrx-tests/src/tests/struct_type_tests.rs index 32a90ccbd..5dcf8ce08 100644 --- a/pgrx-tests/src/tests/struct_type_tests.rs +++ b/pgrx-tests/src/tests/struct_type_tests.rs @@ -22,7 +22,7 @@ mod tests { fn test_complex_in() -> Result<(), pgrx::spi::Error> { Spi::connect(|client| { let complex = client - .select("SELECT '1.1,2.2'::complex;", None, &[][..])? + .select("SELECT '1.1,2.2'::complex;", None, &[])? .first() .get_one::>()? .expect("datum was null"); @@ -44,7 +44,7 @@ mod tests { fn test_complex_from_text() -> Result<(), pgrx::spi::Error> { Spi::connect(|client| { let complex = client - .select("SELECT '1.1, 2.2'::complex;", None, &[][..])? + .select("SELECT '1.1, 2.2'::complex;", None, &[])? .first() .get_one::>()? .expect("datum was null"); @@ -60,7 +60,7 @@ mod tests { let complex = Spi::connect(|mut client| { client.update( "CREATE TABLE complex_test AS SELECT s as id, (s || '.0, 2.0' || s)::complex as value FROM generate_series(1, 1000) s;\ - SELECT value FROM complex_test ORDER BY id;", None, &[][..])?.first().get_one::>() + SELECT value FROM complex_test ORDER BY id;", None, &[])?.first().get_one::>() })?.expect("datum was null"); assert_eq!(&complex.r, &1.0); diff --git a/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-cursor.rs b/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-cursor.rs index a1ccd41c6..ea7ebfe29 100644 --- a/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-cursor.rs +++ b/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-cursor.rs @@ -6,14 +6,14 @@ use std::error::Error; fn issue1209() -> Result, Box> { // create the cursor we actually care about let mut res = Spi::connect(|c| { - c.open_cursor("select 'hello world' from generate_series(1, 1000)", &[][..]) + c.open_cursor("select 'hello world' from generate_series(1, 1000)", &[]) .fetch(1000) .unwrap() }); // here we just perform some allocations to make sure that the previous cursor gets invalidated for _ in 0..100 { - Spi::connect(|c| c.open_cursor("select 1", &[][..]).fetch(1).unwrap()); + Spi::connect(|c| c.open_cursor("select 1", &[]).fetch(1).unwrap()); } // later elements are probably more likely to point to deallocated memory diff --git a/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-cursor.stderr b/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-cursor.stderr index fba9f322f..f4ef0709b 100644 --- a/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-cursor.stderr +++ b/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-cursor.stderr @@ -5,7 +5,7 @@ error: lifetime may not live long enough | -- return type of closure is SpiTupleTable<'2> | | | has type `SpiClient<'1>` -9 | / c.open_cursor("select 'hello world' from generate_series(1, 1000)", &[][..]) +9 | / c.open_cursor("select 'hello world' from generate_series(1, 1000)", &[]) 10 | | .fetch(1000) 11 | | .unwrap() | |_____________________^ returning this value requires that `'1` must outlive `'2` @@ -13,8 +13,8 @@ error: lifetime may not live long enough error[E0515]: cannot return value referencing temporary value --> tests/compile-fail/escaping-spiclient-1209-cursor.rs:9:9 | -9 | c.open_cursor("select 'hello world' from generate_series(1, 1000)", &[][..]) - | ^--------------------------------------------------------------------------- +9 | c.open_cursor("select 'hello world' from generate_series(1, 1000)", &[]) + | ^----------------------------------------------------------------------- | | | _________temporary value created here | | @@ -27,8 +27,8 @@ error[E0515]: cannot return value referencing temporary value error: lifetime may not live long enough --> tests/compile-fail/escaping-spiclient-1209-cursor.rs:16:26 | -16 | Spi::connect(|c| c.open_cursor("select 1", &[][..]).fetch(1).unwrap()); - | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2` +16 | Spi::connect(|c| c.open_cursor("select 1", &[]).fetch(1).unwrap()); + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2` | || | |return type of closure is SpiTupleTable<'2> | has type `SpiClient<'1>` @@ -36,8 +36,8 @@ error: lifetime may not live long enough error[E0515]: cannot return value referencing temporary value --> tests/compile-fail/escaping-spiclient-1209-cursor.rs:16:26 | -16 | Spi::connect(|c| c.open_cursor("select 1", &[][..]).fetch(1).unwrap()); - | ----------------------------------^^^^^^^^^^^^^^^^^^ +16 | Spi::connect(|c| c.open_cursor("select 1", &[]).fetch(1).unwrap()); + | ------------------------------^^^^^^^^^^^^^^^^^^ | | | returns a value referencing data owned by the current function | temporary value created here diff --git a/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-prep-stmt.rs b/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-prep-stmt.rs index 07bda1498..bffe369f2 100644 --- a/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-prep-stmt.rs +++ b/pgrx-tests/tests/compile-fail/escaping-spiclient-1209-prep-stmt.rs @@ -7,7 +7,7 @@ fn issue1209_prepared_stmt(q: &str) -> Result, Box> { let prepared = { Spi::connect(|c| c.prepare(q, None))? }; - Ok(Spi::connect(|c| prepared.execute(&c, Some(1), &[][..])?.first().get(1))?) + Ok(Spi::connect(|c| prepared.execute(&c, Some(1), &[])?.first().get(1))?) } fn main() {} diff --git a/pgrx/src/spi.rs b/pgrx/src/spi.rs index df618ef21..cebbde7b4 100644 --- a/pgrx/src/spi.rs +++ b/pgrx/src/spi.rs @@ -237,13 +237,13 @@ impl Spi { } pub fn get_one(query: &str) -> Result> { - Spi::connect(|mut client| client.update(query, Some(1), &[][..])?.first().get_one()) + Spi::connect(|mut client| client.update(query, Some(1), &[])?.first().get_one()) } pub fn get_two( query: &str, ) -> Result<(Option, Option)> { - Spi::connect(|mut client| client.update(query, Some(1), &[][..])?.first().get_two::()) + Spi::connect(|mut client| client.update(query, Some(1), &[])?.first().get_two::()) } pub fn get_three< @@ -254,7 +254,7 @@ impl Spi { query: &str, ) -> Result<(Option, Option, Option)> { Spi::connect(|mut client| { - client.update(query, Some(1), &[][..])?.first().get_three::() + client.update(query, Some(1), &[])?.first().get_three::() }) } @@ -292,7 +292,7 @@ impl Spi { /// /// The statement runs in read/write mode pub fn run(query: &str) -> std::result::Result<(), Error> { - Spi::run_with_args(query, &[][..]) + Spi::run_with_args(query, &[]) } /// run an arbitrary SQL statement with args. @@ -309,7 +309,7 @@ impl Spi { /// explain a query, returning its result in json form pub fn explain(query: &str) -> Result { - Spi::explain_with_args(query, &[][..]) + Spi::explain_with_args(query, &[]) } /// explain a query with args, returning its result in json form @@ -338,7 +338,7 @@ impl Spi { /// use pgrx::prelude::*; /// # fn foo() -> spi::Result> { /// let name = Spi::connect(|client| { - /// client.select("SELECT 'Bob'", None, &[][..])?.first().get_one() + /// client.select("SELECT 'Bob'", None, &[])?.first().get_one() /// })?; /// assert_eq!(name, Some("Bob")); /// # return Ok(name.map(str::to_string)) diff --git a/pgrx/src/spi/cursor.rs b/pgrx/src/spi/cursor.rs index 8de6ce72c..40f13c968 100644 --- a/pgrx/src/spi/cursor.rs +++ b/pgrx/src/spi/cursor.rs @@ -33,7 +33,7 @@ type CursorName = String; /// use pgrx::prelude::*; /// # fn foo() -> spi::Result<()> { /// Spi::connect(|mut client| { -/// let mut cursor = client.open_cursor("SELECT * FROM generate_series(1, 5)", &[][..]); +/// let mut cursor = client.open_cursor("SELECT * FROM generate_series(1, 5)", &[]); /// assert_eq!(Some(1), cursor.fetch(1)?.get_one::()?); /// assert_eq!(Some(2), cursor.fetch(2)?.get_one::()?); /// assert_eq!(Some(3), cursor.fetch(3)?.get_one::()?); @@ -48,7 +48,7 @@ type CursorName = String; /// use pgrx::prelude::*; /// # fn foo() -> spi::Result<()> { /// let cursor_name = Spi::connect(|mut client| { -/// let mut cursor = client.open_cursor("SELECT * FROM generate_series(1, 5)", &[][..]); +/// let mut cursor = client.open_cursor("SELECT * FROM generate_series(1, 5)", &[]); /// assert_eq!(Ok(Some(1)), cursor.fetch(1)?.get_one::()); /// Ok::<_, spi::Error>(cursor.detach_into_name()) // <-- cursor gets dropped here /// // <--- first SpiTupleTable gets freed by Spi::connect at this point From 19748f4eb658f7e8f4a9ece19937204b4be89794 Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Thu, 12 Sep 2024 21:53:38 +0300 Subject: [PATCH 7/9] Fixed formatting --- pgrx-tests/src/tests/pg_cast_tests.rs | 6 +----- pgrx-tests/src/tests/srf_tests.rs | 6 ++---- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/pgrx-tests/src/tests/pg_cast_tests.rs b/pgrx-tests/src/tests/pg_cast_tests.rs index 503aec338..59d53c8b4 100644 --- a/pgrx-tests/src/tests/pg_cast_tests.rs +++ b/pgrx-tests/src/tests/pg_cast_tests.rs @@ -49,11 +49,7 @@ mod tests { fn test_pg_cast_assignment_type_cast() { let _ = Spi::connect(|mut client| { client.update("CREATE TABLE test_table(value int4);", None, &[])?; - client.update( - "INSERT INTO test_table VALUES('{\"a\": 1}'::json->'a');", - None, - &[], - )?; + client.update("INSERT INTO test_table VALUES('{\"a\": 1}'::json->'a');", None, &[])?; Ok::<_, spi::Error>(()) }); diff --git a/pgrx-tests/src/tests/srf_tests.rs b/pgrx-tests/src/tests/srf_tests.rs index f8b964eba..3fc19ea9a 100644 --- a/pgrx-tests/src/tests/srf_tests.rs +++ b/pgrx-tests/src/tests/srf_tests.rs @@ -174,8 +174,7 @@ mod tests { #[pg_test] fn test_composite_set() { let cnt = Spi::connect(|client| { - let mut table = - client.select("SELECT * FROM example_composite_set()", None, &[])?; + let mut table = client.select("SELECT * FROM example_composite_set()", None, &[])?; let mut expect = 0; while table.next().is_some() { @@ -234,8 +233,7 @@ mod tests { #[pg_test] fn test_return_empty_setof_iterator() { let cnt = Spi::connect(|client| { - let table = - client.select("SELECT * from return_empty_setof_iterator();", None, &[])?; + let table = client.select("SELECT * from return_empty_setof_iterator();", None, &[])?; Ok::<_, spi::Error>(table.len() as i64) }); From 92bc2e480dff09aae687c6ac8294b6946952cdb6 Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Sat, 14 Sep 2024 22:41:34 +0300 Subject: [PATCH 8/9] Made unsafe manual construction of DatumWithOid --- pgrx-tests/src/tests/anyelement_tests.rs | 7 +++---- pgrx-tests/src/tests/proptests.rs | 5 ++--- pgrx/src/datum/mod.rs | 7 +++++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/pgrx-tests/src/tests/anyelement_tests.rs b/pgrx-tests/src/tests/anyelement_tests.rs index 2033386c9..283119ddd 100644 --- a/pgrx-tests/src/tests/anyelement_tests.rs +++ b/pgrx-tests/src/tests/anyelement_tests.rs @@ -15,10 +15,9 @@ mod tests { #[pg_test] fn test_anyelement_arg() -> Result<(), pgrx::spi::Error> { - let element = Spi::get_one_with_args::( - "SELECT anyelement_arg($1);", - &[DatumWithOid::new(123, AnyElement::type_oid())], - )? + let element = Spi::get_one_with_args::("SELECT anyelement_arg($1);", unsafe { + &[DatumWithOid::new(123, AnyElement::type_oid())] + })? .map(|e| e.datum()); assert_eq!(element, 123.into_datum()); diff --git a/pgrx-tests/src/tests/proptests.rs b/pgrx-tests/src/tests/proptests.rs index 97fbf8c9e..865da26ee 100644 --- a/pgrx-tests/src/tests/proptests.rs +++ b/pgrx-tests/src/tests/proptests.rs @@ -1,7 +1,7 @@ use crate::proptest::PgTestRunner; use core::ffi; use paste::paste; -use pgrx::{datum::DatumWithOid, prelude::*}; +use pgrx::prelude::*; use proptest::prelude::*; use TimeWithTimeZone as TimeTz; @@ -31,8 +31,7 @@ pub fn [<$datetime_ty:lower _spi_roundtrip>] () { proptest .run(&strat, |datetime| { let query = concat!("SELECT ", stringify!($nop_fn), "($1)"); - let builtin_oid = <$datetime_ty as IntoDatum>::type_oid(); - let args = &[DatumWithOid::new(datetime, builtin_oid)]; + let args = &[datetime.into()]; let spi_ret: $datetime_ty = Spi::get_one_with_args(query, args).unwrap().unwrap(); // 5. A condition on which the test is accepted or rejected: // this is easily done via `prop_assert!` and its friends, diff --git a/pgrx/src/datum/mod.rs b/pgrx/src/datum/mod.rs index 264ac9ae6..af8f60bf5 100644 --- a/pgrx/src/datum/mod.rs +++ b/pgrx/src/datum/mod.rs @@ -152,7 +152,7 @@ pub struct DatumWithOid<'src> { } impl<'src> DatumWithOid<'src> { - pub fn new(value: T, oid: pg_sys::Oid) -> Self { + pub unsafe fn new(value: T, oid: pg_sys::Oid) -> Self { Self { datum: value.into_datum().map(|d| Datum(d, PhantomData::default())), oid } } @@ -171,7 +171,10 @@ impl<'src> DatumWithOid<'src> { impl<'src, T: IntoDatum> From for DatumWithOid<'src> { fn from(value: T) -> Self { - Self::new(value, T::type_oid()) + unsafe { + // SAFETY: The oid is provided by the type. + Self::new(value, T::type_oid()) + } } } From df050ab0a3b41f0487c2a9ba18f95209b43362a0 Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Sat, 14 Sep 2024 22:58:14 +0300 Subject: [PATCH 9/9] Added documentation --- pgrx/src/datum/mod.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pgrx/src/datum/mod.rs b/pgrx/src/datum/mod.rs index af8f60bf5..6cc2ec42e 100644 --- a/pgrx/src/datum/mod.rs +++ b/pgrx/src/datum/mod.rs @@ -140,30 +140,42 @@ impl<'src> Datum<'src> { pub fn sans_lifetime(self) -> pg_sys::Datum { self.0 } + /// Construct a Datum containing only a null pointer. pub fn null() -> Datum<'src> { Self(pg_sys::Datum::from(0), PhantomData) } } +/// Represents a typed value as pair of [`Option`] and [`Oid`]. +/// +/// [`Oid`]: pg_sys::Oid pub struct DatumWithOid<'src> { datum: Option>, oid: pg_sys::Oid, } impl<'src> DatumWithOid<'src> { + /// Construct a `DatumWithOid` containing the provided value and [`Oid`]. + /// + /// [`Oid`]: pg_sys::Oid pub unsafe fn new(value: T, oid: pg_sys::Oid) -> Self { Self { datum: value.into_datum().map(|d| Datum(d, PhantomData::default())), oid } } + /// Construct a `DatumWithOid` containing a null value for type `T`. pub fn null() -> Self { Self { datum: None, oid: T::type_oid() } } + /// Returns an [`Option`]. pub fn datum(&self) -> Option> { self.datum.as_ref().map(|d| Datum(d.0, PhantomData::default())) } + /// Returns an [`Oid`]. + /// + /// [`Oid`]: pg_sys::Oid pub fn oid(&self) -> pg_sys::Oid { self.oid }