Actually, by default we just use the server certificate as a public key container. libpq pretty much ignores the rest of the certificate's ASN.1 data (or rather, doesn't ask OpenSSL to care about it). It doesn't do any trust chain checking to find a path to a root cert. It doesn't check the host name/IP. It doesn't remember the key for later connections, SSH known-hosts style.
You can freely MITM a sslmode=require libpq connection with your own self signed cert based proxy and nobody will be the wiser. It provides only transport encryption. Or just have your MITM not offer SSL; libpq silently degrades to unencrypted in its default sslmode=prefer mode :(
If you use sslmode=verify-full then you get the behaviour you'd normally expect - validation of server key against local trusted cert, and ip/hostname check.
Even then we don't do any sort of smart cert trust path finding like libnss or Java's JSSE do. We just look at the cert file and expect it to have signed the server's cert. But at least we can do some kind of validation. It's painful if you talk to multiple different servers with different certs, but it works.
I'm not taking a position on the urgency of channel binding by pointing this out. Just trying to set out current behaviour and limitations.