Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unreachable code entered when SELECTing nested composite types and DOMAINs #1188

Open
zacknewman opened this issue Nov 18, 2024 · 5 comments · May be fixed by #1189
Open

unreachable code entered when SELECTing nested composite types and DOMAINs #1188

zacknewman opened this issue Nov 18, 2024 · 5 comments · May be fixed by #1189

Comments

@zacknewman
Copy link

zacknewman commented Nov 18, 2024

Execute the following transaction on a PostgreSQL database:

BEGIN;
    CREATE TYPE foo AS (x integer);
    CREATE DOMAIN bar AS foo NOT NULL;
    CREATE TYPE fizz AS (y bar);
    CREATE TABLE buzz(z fizz NOT NULL);
    INSERT INTO buzz VALUES (ROW(ROW(1)));
COMMIT;

Now compile and run the following Rust program:

#![expect(
    clippy::trait_duplication_in_bounds,
    reason = "can't fix since part of ToSql macro"
)]
use core::{
    net::{IpAddr, Ipv6Addr},
    time::Duration,
};
use postgres_types::{FromSql, ToSql};
use tokio::runtime::Builder;
use tokio_postgres::{
    config::{ChannelBinding, Config, LoadBalanceHosts, SslMode, TargetSessionAttrs},
    tls::NoTls,
    IsolationLevel,
};
#[derive(Debug, FromSql, ToSql)]
#[postgres(name = "foo")]
struct Foo {
    x: i32,
}
#[derive(FromSql)]
#[postgres(name = "bar")]
struct Bar(Foo);
#[derive(FromSql)]
#[postgres(name = "fizz")]
struct Fizz {
    y: Bar,
}
fn main() {
    Builder::new_current_thread()
        .enable_all()
        .build()
        .unwrap()
        .block_on(async {
            let mut config = Config::new();
            let c = config
                .application_name("bug")
                .channel_binding(ChannelBinding::Disable)
                .connect_timeout(Duration::from_secs(10))
                .dbname("example")
                .host("")
                .hostaddr(IpAddr::V6(Ipv6Addr::LOCALHOST))
                .keepalives(true)
                .keepalives_idle(Duration::from_secs(300))
                .load_balance_hosts(LoadBalanceHosts::Disable)
                .password(b"password")
                .port(5432)
                .ssl_mode(SslMode::Disable)
                .target_session_attrs(TargetSessionAttrs::Any)
                .user("example");
            let (mut client, con) = c.connect(NoTls).await.unwrap();
            tokio::spawn(async move {
                con.await.unwrap();
            });
            let txn = client
                .build_transaction()
                .isolation_level(IsolationLevel::Serializable)
                .read_only(true)
                .start()
                .await
                .unwrap();
            let stmt = txn
                .prepare_typed("SELECT z FROM buzz;", [].as_slice())
                .await
                .unwrap();
            let row = txn.query_one(&stmt, &[]).await.unwrap();
            // The `panic` occurs on the below line.
            let col1 = row.get::<'_, _, Fizz>(0);
            println!("{}", col1.y.0.x);
            txn.commit().await.unwrap();
        });
}
[zack@laptop bug]$ export RUST_BACKTRACE=full && cargo run
    Updating crates.io index
     Locking 98 packages to latest compatible versions
      Adding fallible-iterator v0.2.0 (latest: v0.3.0)
      Adding generic-array v0.14.7 (latest: v1.1.0)
      Adding hermit-abi v0.3.9 (latest: v0.4.0)
      Adding siphasher v0.3.11 (latest: v1.0.1)
      Adding wasi v0.11.0+wasi-snapshot-preview1 (latest: v0.13.3+wasi-0.2.2)
      Adding windows-sys v0.52.0 (latest: v0.59.0)
      Adding zerocopy v0.7.35 (latest: v0.8.10)
      Adding zerocopy-derive v0.7.35 (latest: v0.8.10)
   Compiling proc-macro2 v1.0.89
   Compiling unicode-ident v1.0.13
   Compiling libc v0.2.164
   Compiling typenum v1.17.0
   Compiling version_check v0.9.5
   Compiling cfg-if v1.0.0
   Compiling autocfg v1.4.0
   Compiling byteorder v1.5.0
   Compiling subtle v2.6.1
   Compiling tinyvec_macros v0.1.1
   Compiling bytes v1.8.0
   Compiling unicode-bidi v0.3.17
   Compiling unicode-properties v0.1.3
   Compiling tinyvec v1.8.0
   Compiling futures-sink v0.3.31
   Compiling pin-project-lite v0.2.15
   Compiling parking_lot_core v0.9.10
   Compiling futures-core v0.3.31
   Compiling cpufeatures v0.2.15
   Compiling memchr v2.7.4
   Compiling base64 v0.22.1
   Compiling smallvec v1.13.2
   Compiling generic-array v0.14.7
   Compiling fallible-iterator v0.2.0
   Compiling siphasher v0.3.11
   Compiling slab v0.4.9
   Compiling lock_api v0.4.12
   Compiling heck v0.5.0
   Compiling scopeguard v1.2.0
   Compiling phf_shared v0.11.2
   Compiling futures-task v0.3.31
   Compiling quote v1.0.37
   Compiling unicode-normalization v0.1.24
   Compiling pin-utils v0.1.0
   Compiling phf v0.11.2
   Compiling futures-channel v0.3.31
   Compiling log v0.4.22
   Compiling whoami v1.5.2
   Compiling getrandom v0.2.15
   Compiling socket2 v0.5.7
   Compiling mio v1.0.2
   Compiling syn v2.0.87
   Compiling rand_core v0.6.4
   Compiling percent-encoding v2.3.1
   Compiling tokio v1.41.1
   Compiling parking_lot v0.12.3
   Compiling stringprep v0.1.5
   Compiling crypto-common v0.1.6
   Compiling block-buffer v0.10.4
   Compiling digest v0.10.7
   Compiling md-5 v0.10.6
   Compiling sha2 v0.10.8
   Compiling hmac v0.12.1
   Compiling zerocopy-derive v0.7.35
   Compiling futures-macro v0.3.31
   Compiling postgres-derive v0.4.6
   Compiling async-trait v0.1.83
   Compiling tokio-util v0.7.12
   Compiling zerocopy v0.7.35
   Compiling futures-util v0.3.31
   Compiling ppv-lite86 v0.2.20
   Compiling rand_chacha v0.3.1
   Compiling rand v0.8.5
   Compiling postgres-protocol v0.6.7
   Compiling postgres-types v0.2.8
   Compiling tokio-postgres v0.7.12
   Compiling bug v0.1.0 (/home/zack/projects/bug)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 6.81s
     Running `target/debug/bug`
thread 'main' panicked at src/main.rs:16:17:
internal error: entered unreachable code
stack backtrace:
   0:     0x5b8541de129a - std::backtrace_rs::backtrace::libunwind::trace::h99efb0985cae5d78
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/../../backtrace/src/backtrace/libunwind.rs:116:5
   1:     0x5b8541de129a - std::backtrace_rs::backtrace::trace_unsynchronized::he2c1aa63b3f7fad8
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
   2:     0x5b8541de129a - std::sys::backtrace::_print_fmt::h8a221d40f5e0f88b
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/sys/backtrace.rs:66:9
   3:     0x5b8541de129a - <std::sys::backtrace::BacktraceLock::print::DisplayBacktrace as core::fmt::Display>::fmt::h304520fd6a30aa07
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/sys/backtrace.rs:39:26
   4:     0x5b8541e00cfb - core::fmt::rt::Argument::fmt::h5da9c218ec984eaf
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/fmt/rt.rs:177:76
   5:     0x5b8541e00cfb - core::fmt::write::hf5713710ce10ff22
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/fmt/mod.rs:1178:21
   6:     0x5b8541dde1f3 - std::io::Write::write_fmt::hda708db57927dacf
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/io/mod.rs:1823:15
   7:     0x5b8541de2442 - std::sys::backtrace::BacktraceLock::print::hbcdbec4d97c91528
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/sys/backtrace.rs:42:9
   8:     0x5b8541de2442 - std::panicking::default_hook::{{closure}}::he1ad87607d0c11c5
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/panicking.rs:266:22
   9:     0x5b8541de20ae - std::panicking::default_hook::h81c8cd2e7c59ee33
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/panicking.rs:293:9
  10:     0x5b8541de2ccf - std::panicking::rust_panic_with_hook::had2118629c312a4a
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/panicking.rs:797:13
  11:     0x5b8541de2983 - std::panicking::begin_panic_handler::{{closure}}::h7fa5985d111bafa2
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/panicking.rs:664:13
  12:     0x5b8541de1779 - std::sys::backtrace::__rust_end_short_backtrace::h704d151dbefa09c5
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/sys/backtrace.rs:170:18
  13:     0x5b8541de2644 - rust_begin_unwind
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/panicking.rs:662:5
  14:     0x5b8541c24ba3 - core::panicking::panic_fmt::h3eea515d05f7a35e
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/panicking.rs:74:14
  15:     0x5b8541c24c2c - core::panicking::panic::h102d65dbfa674afe
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/panicking.rs:148:5
  16:     0x5b8541c65f92 - <bug::Foo as postgres_types::FromSql>::from_sql::h43e1abeab9a3c013
                               at /home/zack/projects/bug/src/main.rs:16:17
  17:     0x5b8541c66626 - <bug::Bar as postgres_types::FromSql>::from_sql::h3bf354d1b63b138d
                               at /home/zack/projects/bug/src/main.rs:21:17
  18:     0x5b8541c49be0 - postgres_types::FromSql::from_sql_nullable::heb890c98a7575749
                               at /home/zack/.cargo/registry/src/index.crates.io-6f17d22bba15001f/postgres-types-0.2.8/src/lib.rs:553:26
  19:     0x5b8541c3a5b6 - postgres_types::private::read_value::h60ed5086d229f1fd
                               at /home/zack/.cargo/registry/src/index.crates.io-6f17d22bba15001f/postgres-types-0.2.8/src/private.rs:33:5
  20:     0x5b8541c66c04 - <bug::Fizz as postgres_types::FromSql>::from_sql::hd1e47626297d0f67
                               at /home/zack/projects/bug/src/main.rs:24:17
  21:     0x5b8541c49b60 - postgres_types::FromSql::from_sql_nullable::h8b6560ee4998bc3c
                               at /home/zack/.cargo/registry/src/index.crates.io-6f17d22bba15001f/postgres-types-0.2.8/src/lib.rs:553:26
  22:     0x5b8541c3ff59 - tokio_postgres::row::Row::get_inner::hbdb55d077f4a2675
                               at /home/zack/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-postgres-0.7.12/src/row.rs:184:9
  23:     0x5b8541c3fb8e - tokio_postgres::row::Row::get::h51f09083614dfe15
                               at /home/zack/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-postgres-0.7.12/src/row.rs:151:15
  24:     0x5b8541c4ac65 - bug::main::{{closure}}::hec6cf66abc2b37c0
                               at /home/zack/projects/bug/src/main.rs:67:24
  25:     0x5b8541c3a1fd - <core::pin::Pin<P> as core::future::future::Future>::poll::h5b0901c32bd73ba6
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/future/future.rs:123:9
  26:     0x5b8541c3a2bd - <core::pin::Pin<P> as core::future::future::Future>::poll::hcf178ea35cd368f9
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/future/future.rs:123:9
  27:     0x5b8541c34bff - tokio::runtime::scheduler::current_thread::CoreGuard::block_on::{{closure}}::{{closure}}::{{closure}}::h5c8ff6977dfd5361
                               at /home/zack/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/scheduler/current_thread/mod.rs:729:57
  28:     0x5b8541c34b25 - tokio::runtime::coop::with_budget::h79f7fee45e1fa95c
                               at /home/zack/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/coop.rs:107:5
  29:     0x5b8541c34b25 - tokio::runtime::coop::budget::ha98b8bca93bacaa2
                               at /home/zack/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/coop.rs:73:5
  30:     0x5b8541c34b25 - tokio::runtime::scheduler::current_thread::CoreGuard::block_on::{{closure}}::{{closure}}::h1c41bed8d6c2e705
                               at /home/zack/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/scheduler/current_thread/mod.rs:729:25
  31:     0x5b8541c324b0 - tokio::runtime::scheduler::current_thread::Context::enter::h75f2cabd0440a202
                               at /home/zack/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/scheduler/current_thread/mod.rs:428:19
  32:     0x5b8541c3420b - tokio::runtime::scheduler::current_thread::CoreGuard::block_on::{{closure}}::hd312ed3b2fc5c4b0
                               at /home/zack/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/scheduler/current_thread/mod.rs:728:36
  33:     0x5b8541c336a4 - tokio::runtime::scheduler::current_thread::CoreGuard::enter::{{closure}}::hfcbec99e2427c975
                               at /home/zack/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/scheduler/current_thread/mod.rs:807:68
  34:     0x5b8541c66f9b - tokio::runtime::context::scoped::Scoped<T>::set::hfd7dc621c1a86dd6
                               at /home/zack/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/context/scoped.rs:40:9
  35:     0x5b8541c3e469 - tokio::runtime::context::set_scheduler::{{closure}}::he0284573d5eb0ca5
                               at /home/zack/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/context.rs:180:26
  36:     0x5b8541c5c65a - std::thread::local::LocalKey<T>::try_with::h705fa3e9e86b8046
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/thread/local.rs:283:12
  37:     0x5b8541c5bc2a - std::thread::local::LocalKey<T>::with::hcbecfc679dd67832
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/thread/local.rs:260:9
  38:     0x5b8541c3e3dd - tokio::runtime::context::set_scheduler::hac0d58a5dc54ad36
                               at /home/zack/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/context.rs:180:9
  39:     0x5b8541c33430 - tokio::runtime::scheduler::current_thread::CoreGuard::enter::h1e18d6ebd2188d54
                               at /home/zack/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/scheduler/current_thread/mod.rs:807:27
  40:     0x5b8541c33723 - tokio::runtime::scheduler::current_thread::CoreGuard::block_on::hf8078cbf5b28f26c
                               at /home/zack/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/scheduler/current_thread/mod.rs:716:19
  41:     0x5b8541c30efd - tokio::runtime::scheduler::current_thread::CurrentThread::block_on::{{closure}}::ha66859ddb7d9bad0
                               at /home/zack/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/scheduler/current_thread/mod.rs:196:28
  42:     0x5b8541c2a527 - tokio::runtime::context::runtime::enter_runtime::hae321f8f5ba61d93
                               at /home/zack/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/context/runtime.rs:65:16
  43:     0x5b8541c30bd3 - tokio::runtime::scheduler::current_thread::CurrentThread::block_on::h14c83c76c10473e3
                               at /home/zack/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/scheduler/current_thread/mod.rs:184:9
  44:     0x5b8541c2ab10 - tokio::runtime::runtime::Runtime::block_on_inner::h28918626ddecdeee
                               at /home/zack/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/runtime.rs:368:47
  45:     0x5b8541c2aefe - tokio::runtime::runtime::Runtime::block_on::h751fbbf92aa61924
                               at /home/zack/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.41.1/src/runtime/runtime.rs:340:13
  46:     0x5b8541c65e4c - bug::main::ha7253ccdcb8d6d35
                               at /home/zack/projects/bug/src/main.rs:30:5
  47:     0x5b8541c25b4b - core::ops::function::FnOnce::call_once::h9f3bb0ebd6d37fd7
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/ops/function.rs:250:5
  48:     0x5b8541c5cd7e - std::sys::backtrace::__rust_begin_short_backtrace::h0b49c9502cd6f287
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/sys/backtrace.rs:154:18
  49:     0x5b8541c2a081 - std::rt::lang_start::{{closure}}::hc1d9acf0009135ce
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/rt.rs:164:18
  50:     0x5b8541ddae40 - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::h08ecba131ab90ec4
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/ops/function.rs:284:13
  51:     0x5b8541ddae40 - std::panicking::try::do_call::hf33a59fd8ce953f4
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/panicking.rs:554:40
  52:     0x5b8541ddae40 - std::panicking::try::h5005ce80ce949fd8
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/panicking.rs:518:19
  53:     0x5b8541ddae40 - std::panic::catch_unwind::hfbae19e2e2c5b7ed
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/panic.rs:345:14
  54:     0x5b8541ddae40 - std::rt::lang_start_internal::{{closure}}::ha0331c3690741813
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/rt.rs:143:48
  55:     0x5b8541ddae40 - std::panicking::try::do_call::hcdcbdb616b4d0295
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/panicking.rs:554:40
  56:     0x5b8541ddae40 - std::panicking::try::h3f2f1725a07d2256
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/panicking.rs:518:19
  57:     0x5b8541ddae40 - std::panic::catch_unwind::h51869e04b56b2dc3
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/panic.rs:345:14
  58:     0x5b8541ddae40 - std::rt::lang_start_internal::h4d90db0530245041
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/rt.rs:143:20
  59:     0x5b8541c2a05a - std::rt::lang_start::h0c5b3abe1e928f3c
                               at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/rt.rs:163:17
  60:     0x5b8541c66d8e - main
  61:     0x747cf2318e08 - <unknown>
  62:     0x747cf2318ecc - __libc_start_main
  63:     0x5b8541c255f5 - _start
  64:                0x0 - <unknown>

Additional information:

[zack@laptop bug]$ cat Cargo.toml
[package]
name = "bug"
version = "0.1.0"
edition = "2021"

[dependencies]
postgres-types = { version = "0.2.8", default-features = false, features = ["derive"] }
tokio = { version = "1.41.1", default-features = false, features = ["rt"] }
tokio-postgres = { version = "0.7.12", default-features = false, features = ["runtime"] }
[zack@laptop bug]$ rustc --version
rustc 1.82.0 (f6e511eec 2024-10-15)
[zack@laptop bug]$ postgres --version
postgres (PostgreSQL) 16.3
[zack@laptop bug]$ uname -a
Linux laptop 6.11.7-arch1-1 #1 SMP PREEMPT_DYNAMIC Fri, 08 Nov 2024 17:57:56 +0000 x86_64 GNU/Linux
@zacknewman zacknewman changed the title unreachable code entered when using nested composite types and DOMAINs unreachable code entered when SELECTing nested composite types and DOMAINs Nov 18, 2024
@zacknewman
Copy link
Author

Some extra information. The ToSql macro works fine (i.e., I can INSERT a Fizz into buzz). FromSql works fine for Bar (i.e., SELECT (z).y FROM buzz; successfully grabs a Bar). The &[u8] that is passed to Fizz::from_sql is the following:

[0, 0, 0, 1, 0, 0, 74, 174, 0, 0, 0, 16, 0, 0, 0, 1, 0, 0, 0, 23, 0, 0, 0, 4, 0, 0, 0, 1].

@zacknewman
Copy link
Author

zacknewman commented Nov 19, 2024

OK, I looked at the code that is generated; and I believe I found the issue. Bar::from_sql ends up passing its own type to the contained type's from_sql (i.e., Foo::from_sql is passed the type for Bar instead of itself).

Generated code:

#[postgres(name = "bar")]
struct Bar(Foo);
impl<'a> postgres_types::FromSql<'a> for Bar {
    fn from_sql(_type: &postgres_types::Type, buf: &'a [u8])
        ->
            std::result::Result<Bar,
            std::boxed::Box<dyn std::error::Error + std::marker::Sync +
            std::marker::Send>> {
        <Foo as postgres_types::FromSql>::from_sql(_type, buf).map(Bar)
    }
    fn accepts(type_: &postgres_types::Type) -> bool {
        if <Foo as postgres_types::FromSql>::accepts(type_) { return true; }
        if type_.name() != "bar" { return false; }
        match *type_.kind() {
            ::postgres_types::Kind::Domain(ref type_) => {
                <Foo as ::postgres_types::ToSql>::accepts(type_)
            }
            _ => false,
        }
    }
}

from_sql should instead look similar to below:

    fn from_sql(_type: &postgres_types::Type, buf: &'a [u8])
        ->
            std::result::Result<Bar,
            std::boxed::Box<dyn std::error::Error + std::marker::Sync +
            std::marker::Send>> {
       match *_type.kind() {
            postgres_types::Kind::Domain(ref type_) => {
                <Foo as postgres_types::FromSql>::from_sql(type_, buf).map(Bar)
            }
            ref bad => unreachable!("Bar::from_sql was passed a type whose kind was {bad:?}, but it must be passed a type whose kind is Kind::Domain"),
        }
    }

When I make that fix, the code works; however it now breaks when Bar is fetched directly (e.g., SELECT (z).y FROM buzz;). I'm pretty sure the Type that is passed to FromSql::from_sql is supposed to be the same as the implementing type, so my "fix" seems correct. There appears to be another bug in addition to postgres_derive::fromsql::domain_body that calls FromSql::from_sql "specially" for DOMAIN types where it passes the contained type instead of the DOMAIN type when the "root" type is a DOMAIN presumably to work around this bug.

It makes me suspicious how FromSql::accepts is derived too. Why does it first redirect to the contained type and not verify the name matches unless the contained type's accept fails? Presumably it is due to the unnamed bug(s) that is/are calling FromSql::from_sql for DOMAINs by passing in the contained type. This also makes manual implementations very fragile.

@sfackler
Copy link
Owner

I remember there being some funkiness around domains where postgres uses the underlying type directly in some cases instead of the domain type. The logic might just need to handle both cases?

@zacknewman
Copy link
Author

zacknewman commented Nov 20, 2024

Hm, I'd be interested to see such an example. While I realize most people should just derive FromSql and ToSql, it should be possible to manually implement them. This seems very fragile to expect manual implementations to somehow assume calling code will intentionally pass the wrong Type. I almost feel like the warning for ToSql::to_sql_checked should be applied for the entire traits (i.e., All implementations of these traits should be generated by the fromsql!()/tosql!() macros).

@zacknewman zacknewman linked a pull request Nov 20, 2024 that will close this issue
@zacknewman
Copy link
Author

zacknewman commented Nov 20, 2024

OK, I submitted a fix that allows DOMAINs to work when they both contain a composite type and are also not the "root" type. I tested the diff on my local example, and it works for Fizz and Bar.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants