From 54f00c73099510a6477194f89c3ecfce57d4dedd Mon Sep 17 00:00:00 2001 From: Paolo Barbolini Date: Wed, 29 Dec 2021 12:01:26 +0100 Subject: [PATCH 1/8] postgres: use Oid type instead of u32 --- sqlx-core/src/postgres/arguments.rs | 2 +- sqlx-core/src/postgres/connection/describe.rs | 36 +-- .../src/postgres/connection/establish.rs | 3 +- sqlx-core/src/postgres/connection/executor.rs | 7 +- sqlx-core/src/postgres/connection/mod.rs | 9 +- sqlx-core/src/postgres/io/buf_mut.rs | 14 +- sqlx-core/src/postgres/message/bind.rs | 5 +- sqlx-core/src/postgres/message/close.rs | 5 +- sqlx-core/src/postgres/message/describe.rs | 5 +- sqlx-core/src/postgres/message/execute.rs | 3 +- .../postgres/message/parameter_description.rs | 5 +- sqlx-core/src/postgres/message/parse.rs | 7 +- .../src/postgres/message/row_description.rs | 5 +- sqlx-core/src/postgres/type_info.rs | 206 +++++++++--------- sqlx-core/src/postgres/types/array.rs | 5 +- sqlx-core/src/postgres/types/int.rs | 29 --- sqlx-core/src/postgres/types/mod.rs | 2 + sqlx-core/src/postgres/types/oid.rs | 57 +++++ sqlx-core/src/postgres/types/record.rs | 7 +- sqlx-macros/src/database/postgres.rs | 4 +- 20 files changed, 234 insertions(+), 182 deletions(-) create mode 100644 sqlx-core/src/postgres/types/oid.rs diff --git a/sqlx-core/src/postgres/arguments.rs b/sqlx-core/src/postgres/arguments.rs index 9bd60dbbbd..7ce2e298cb 100644 --- a/sqlx-core/src/postgres/arguments.rs +++ b/sqlx-core/src/postgres/arguments.rs @@ -95,7 +95,7 @@ impl PgArguments { for (offset, name) in type_holes { let oid = conn.fetch_type_id_by_name(&*name).await?; - buffer[*offset..(*offset + 4)].copy_from_slice(&oid.to_be_bytes()); + buffer[*offset..(*offset + 4)].copy_from_slice(&oid.as_u32().to_be_bytes()); } Ok(()) diff --git a/sqlx-core/src/postgres/connection/describe.rs b/sqlx-core/src/postgres/connection/describe.rs index 6d7a3f7dc0..181d04fa14 100644 --- a/sqlx-core/src/postgres/connection/describe.rs +++ b/sqlx-core/src/postgres/connection/describe.rs @@ -3,6 +3,7 @@ use crate::ext::ustr::UStr; use crate::postgres::message::{ParameterDescription, RowDescription}; use crate::postgres::statement::PgStatementMetadata; use crate::postgres::type_info::{PgCustomType, PgType, PgTypeKind}; +use crate::postgres::types::Oid; use crate::postgres::{PgArguments, PgColumn, PgConnection, PgTypeInfo}; use crate::query_as::query_as; use crate::query_scalar::{query_scalar, query_scalar_with}; @@ -145,7 +146,7 @@ impl PgConnection { async fn maybe_fetch_type_info_by_oid( &mut self, - oid: u32, + oid: Oid, should_fetch: bool, ) -> Result { // first we check if this is a built-in type @@ -181,9 +182,9 @@ impl PgConnection { } } - fn fetch_type_by_oid(&mut self, oid: u32) -> BoxFuture<'_, Result> { + fn fetch_type_by_oid(&mut self, oid: Oid) -> BoxFuture<'_, Result> { Box::pin(async move { - let (name, typ_type, category, relation_id, element, base_type): (String, i8, i8, u32, u32, u32) = query_as( + let (name, typ_type, category, relation_id, element, base_type): (String, i8, i8, Oid, Oid, Oid) = query_as( "SELECT typname, typtype, typcategory, typrelid, typelem, typbasetype FROM pg_catalog.pg_type WHERE oid = $1", ) .bind(oid) @@ -233,7 +234,7 @@ impl PgConnection { }) } - async fn fetch_enum_by_oid(&mut self, oid: u32, name: String) -> Result { + async fn fetch_enum_by_oid(&mut self, oid: Oid, name: String) -> Result { let variants: Vec = query_scalar( r#" SELECT enumlabel @@ -255,12 +256,12 @@ ORDER BY enumsortorder fn fetch_composite_by_oid( &mut self, - oid: u32, - relation_id: u32, + oid: Oid, + relation_id: Oid, name: String, ) -> BoxFuture<'_, Result> { Box::pin(async move { - let raw_fields: Vec<(String, u32)> = query_as( + let raw_fields: Vec<(String, Oid)> = query_as( r#" SELECT attname, atttypid FROM pg_catalog.pg_attribute @@ -292,8 +293,8 @@ ORDER BY attnum fn fetch_domain_by_oid( &mut self, - oid: u32, - base_type: u32, + oid: Oid, + base_type: Oid, name: String, ) -> BoxFuture<'_, Result> { Box::pin(async move { @@ -309,11 +310,11 @@ ORDER BY attnum fn fetch_range_by_oid( &mut self, - oid: u32, + oid: Oid, name: String, ) -> BoxFuture<'_, Result> { Box::pin(async move { - let element_oid: u32 = query_scalar( + let element_oid: Oid = query_scalar( r#" SELECT rngsubtype FROM pg_catalog.pg_range @@ -334,13 +335,13 @@ WHERE rngtypid = $1 }) } - pub(crate) async fn fetch_type_id_by_name(&mut self, name: &str) -> Result { + pub(crate) async fn fetch_type_id_by_name(&mut self, name: &str) -> Result { if let Some(oid) = self.cache_type_oid.get(name) { return Ok(*oid); } // language=SQL - let (oid,): (u32,) = query_as( + let (oid,): (Oid,) = query_as( " SELECT oid FROM pg_catalog.pg_type WHERE typname ILIKE $1 ", @@ -358,7 +359,7 @@ SELECT oid FROM pg_catalog.pg_type WHERE typname ILIKE $1 pub(crate) async fn get_nullable_for_columns( &mut self, - stmt_id: u32, + stmt_id: Oid, meta: &PgStatementMetadata, ) -> Result>, Error> { if meta.columns.is_empty() { @@ -420,10 +421,13 @@ SELECT oid FROM pg_catalog.pg_type WHERE typname ILIKE $1 /// and returns `None` for all others. async fn nullables_from_explain( &mut self, - stmt_id: u32, + stmt_id: Oid, params_len: usize, ) -> Result>, Error> { - let mut explain = format!("EXPLAIN (VERBOSE, FORMAT JSON) EXECUTE sqlx_s_{}", stmt_id); + let mut explain = format!( + "EXPLAIN (VERBOSE, FORMAT JSON) EXECUTE sqlx_s_{}", + stmt_id.as_u32() + ); let mut comma = false; if params_len > 0 { diff --git a/sqlx-core/src/postgres/connection/establish.rs b/sqlx-core/src/postgres/connection/establish.rs index 59e3727c24..5bde516f0b 100644 --- a/sqlx-core/src/postgres/connection/establish.rs +++ b/sqlx-core/src/postgres/connection/establish.rs @@ -7,6 +7,7 @@ use crate::postgres::connection::{sasl, stream::PgStream, tls}; use crate::postgres::message::{ Authentication, BackendKeyData, MessageFormat, Password, ReadyForQuery, Startup, }; +use crate::postgres::types::Oid; use crate::postgres::{PgConnectOptions, PgConnection}; // https://www.postgresql.org/docs/current/protocol-flow.html#id-1.10.5.7.3 @@ -138,7 +139,7 @@ impl PgConnection { transaction_status, transaction_depth: 0, pending_ready_for_query_count: 0, - next_statement_id: 1, + next_statement_id: Oid::new(1), cache_statement: StatementCache::new(options.statement_cache_capacity), cache_type_oid: HashMap::new(), cache_type_info: HashMap::new(), diff --git a/sqlx-core/src/postgres/connection/executor.rs b/sqlx-core/src/postgres/connection/executor.rs index a1e27a6a8b..01c1cc0074 100644 --- a/sqlx-core/src/postgres/connection/executor.rs +++ b/sqlx-core/src/postgres/connection/executor.rs @@ -8,6 +8,7 @@ use crate::postgres::message::{ }; use crate::postgres::statement::PgStatementMetadata; use crate::postgres::type_info::PgType; +use crate::postgres::types::Oid; use crate::postgres::{ statement::PgStatement, PgArguments, PgConnection, PgQueryResult, PgRow, PgTypeInfo, PgValueFormat, Postgres, @@ -24,9 +25,9 @@ async fn prepare( sql: &str, parameters: &[PgTypeInfo], metadata: Option>, -) -> Result<(u32, Arc), Error> { +) -> Result<(Oid, Arc), Error> { let id = conn.next_statement_id; - conn.next_statement_id = conn.next_statement_id.wrapping_add(1); + conn.next_statement_id.incr_one(); // build a list of type OIDs to send to the database in the PARSE command // we have not yet started the query sequence, so we are *safe* to cleanly make @@ -169,7 +170,7 @@ impl PgConnection { // optional metadata that was provided by the user, this means they are reusing // a statement object metadata: Option>, - ) -> Result<(u32, Arc), Error> { + ) -> Result<(Oid, Arc), Error> { if let Some(statement) = self.cache_statement.get_mut(sql) { return Ok((*statement).clone()); } diff --git a/sqlx-core/src/postgres/connection/mod.rs b/sqlx-core/src/postgres/connection/mod.rs index 5241af0210..332de05ed3 100644 --- a/sqlx-core/src/postgres/connection/mod.rs +++ b/sqlx-core/src/postgres/connection/mod.rs @@ -15,6 +15,7 @@ use crate::postgres::message::{ Close, Message, MessageFormat, ReadyForQuery, Terminate, TransactionStatus, }; use crate::postgres::statement::PgStatementMetadata; +use crate::postgres::types::Oid; use crate::postgres::{PgConnectOptions, PgTypeInfo, Postgres}; use crate::transaction::Transaction; @@ -46,14 +47,14 @@ pub struct PgConnection { // sequence of statement IDs for use in preparing statements // in PostgreSQL, the statement is prepared to a user-supplied identifier - next_statement_id: u32, + next_statement_id: Oid, // cache statement by query string to the id and columns - cache_statement: StatementCache<(u32, Arc)>, + cache_statement: StatementCache<(Oid, Arc)>, // cache user-defined types by id <-> info - cache_type_info: HashMap, - cache_type_oid: HashMap, + cache_type_info: HashMap, + cache_type_oid: HashMap, // number of ReadyForQuery messages that we are currently expecting pub(crate) pending_ready_for_query_count: usize, diff --git a/sqlx-core/src/postgres/io/buf_mut.rs b/sqlx-core/src/postgres/io/buf_mut.rs index d9366302de..c67b1c05eb 100644 --- a/sqlx-core/src/postgres/io/buf_mut.rs +++ b/sqlx-core/src/postgres/io/buf_mut.rs @@ -1,11 +1,13 @@ +use crate::postgres::types::Oid; + pub trait PgBufMutExt { fn put_length_prefixed(&mut self, f: F) where F: FnOnce(&mut Vec); - fn put_statement_name(&mut self, id: u32); + fn put_statement_name(&mut self, id: Oid); - fn put_portal_name(&mut self, id: Option); + fn put_portal_name(&mut self, id: Option); } impl PgBufMutExt for Vec { @@ -29,22 +31,22 @@ impl PgBufMutExt for Vec { // writes a statement name by ID #[inline] - fn put_statement_name(&mut self, id: u32) { + fn put_statement_name(&mut self, id: Oid) { // N.B. if you change this don't forget to update it in ../describe.rs self.extend(b"sqlx_s_"); - itoa::write(&mut *self, id).unwrap(); + itoa::write(&mut *self, id.as_u32()).unwrap(); self.push(0); } // writes a portal name by ID #[inline] - fn put_portal_name(&mut self, id: Option) { + fn put_portal_name(&mut self, id: Option) { if let Some(id) = id { self.extend(b"sqlx_p_"); - itoa::write(&mut *self, id).unwrap(); + itoa::write(&mut *self, id.as_u32()).unwrap(); } self.push(0); diff --git a/sqlx-core/src/postgres/message/bind.rs b/sqlx-core/src/postgres/message/bind.rs index 84d665e907..6c5dcf78c8 100644 --- a/sqlx-core/src/postgres/message/bind.rs +++ b/sqlx-core/src/postgres/message/bind.rs @@ -1,14 +1,15 @@ use crate::io::Encode; use crate::postgres::io::PgBufMutExt; +use crate::postgres::types::Oid; use crate::postgres::PgValueFormat; #[derive(Debug)] pub struct Bind<'a> { /// The ID of the destination portal (`None` selects the unnamed portal). - pub portal: Option, + pub portal: Option, /// The id of the source prepared statement. - pub statement: u32, + pub statement: Oid, /// The parameter format codes. Each must presently be zero (text) or one (binary). /// diff --git a/sqlx-core/src/postgres/message/close.rs b/sqlx-core/src/postgres/message/close.rs index 07e7795008..a073979063 100644 --- a/sqlx-core/src/postgres/message/close.rs +++ b/sqlx-core/src/postgres/message/close.rs @@ -1,5 +1,6 @@ use crate::io::Encode; use crate::postgres::io::PgBufMutExt; +use crate::postgres::types::Oid; const CLOSE_PORTAL: u8 = b'P'; const CLOSE_STATEMENT: u8 = b'S'; @@ -7,8 +8,8 @@ const CLOSE_STATEMENT: u8 = b'S'; #[derive(Debug)] #[allow(dead_code)] pub enum Close { - Statement(u32), - Portal(u32), + Statement(Oid), + Portal(Oid), } impl Encode<'_> for Close { diff --git a/sqlx-core/src/postgres/message/describe.rs b/sqlx-core/src/postgres/message/describe.rs index 08b4c408eb..63fb724a74 100644 --- a/sqlx-core/src/postgres/message/describe.rs +++ b/sqlx-core/src/postgres/message/describe.rs @@ -1,5 +1,6 @@ use crate::io::Encode; use crate::postgres::io::PgBufMutExt; +use crate::postgres::types::Oid; const DESCRIBE_PORTAL: u8 = b'P'; const DESCRIBE_STATEMENT: u8 = b'S'; @@ -10,10 +11,10 @@ const DESCRIBE_STATEMENT: u8 = b'S'; #[allow(dead_code)] pub enum Describe { UnnamedStatement, - Statement(u32), + Statement(Oid), UnnamedPortal, - Portal(u32), + Portal(Oid), } impl Encode<'_> for Describe { diff --git a/sqlx-core/src/postgres/message/execute.rs b/sqlx-core/src/postgres/message/execute.rs index 9465750368..82ce4a286a 100644 --- a/sqlx-core/src/postgres/message/execute.rs +++ b/sqlx-core/src/postgres/message/execute.rs @@ -1,9 +1,10 @@ use crate::io::Encode; use crate::postgres::io::PgBufMutExt; +use crate::postgres::types::Oid; pub struct Execute { /// The id of the portal to execute (`None` selects the unnamed portal). - pub portal: Option, + pub portal: Option, /// Maximum number of rows to return, if portal contains a query /// that returns rows (ignored otherwise). Zero denotes “no limit”. diff --git a/sqlx-core/src/postgres/message/parameter_description.rs b/sqlx-core/src/postgres/message/parameter_description.rs index c0cbf2fc6d..6a20aafcdf 100644 --- a/sqlx-core/src/postgres/message/parameter_description.rs +++ b/sqlx-core/src/postgres/message/parameter_description.rs @@ -3,10 +3,11 @@ use smallvec::SmallVec; use crate::error::Error; use crate::io::Decode; +use crate::postgres::types::Oid; #[derive(Debug)] pub struct ParameterDescription { - pub types: SmallVec<[u32; 6]>, + pub types: SmallVec<[Oid; 6]>, } impl Decode<'_> for ParameterDescription { @@ -15,7 +16,7 @@ impl Decode<'_> for ParameterDescription { let mut types = SmallVec::with_capacity(cnt as usize); for _ in 0..cnt { - types.push(buf.get_u32()); + types.push(Oid::new(buf.get_u32())); } Ok(Self { types }) diff --git a/sqlx-core/src/postgres/message/parse.rs b/sqlx-core/src/postgres/message/parse.rs index 2e3576de91..1305dd0ad1 100644 --- a/sqlx-core/src/postgres/message/parse.rs +++ b/sqlx-core/src/postgres/message/parse.rs @@ -2,11 +2,12 @@ use std::i16; use crate::io::{BufMutExt, Encode}; use crate::postgres::io::PgBufMutExt; +use crate::postgres::types::Oid; #[derive(Debug)] pub struct Parse<'a> { /// The ID of the destination prepared statement. - pub statement: u32, + pub statement: Oid, /// The query string to be parsed. pub query: &'a str, @@ -14,7 +15,7 @@ pub struct Parse<'a> { /// The parameter data types specified (could be zero). Note that this is not an /// indication of the number of parameters that might appear in the query string, /// only the number that the frontend wants to pre-specify types for. - pub param_types: &'a [u32], + pub param_types: &'a [Oid], } impl Encode<'_> for Parse<'_> { @@ -32,7 +33,7 @@ impl Encode<'_> for Parse<'_> { buf.extend(&(self.param_types.len() as i16).to_be_bytes()); for &oid in self.param_types { - buf.extend(&oid.to_be_bytes()); + buf.extend(&oid.as_u32().to_be_bytes()); } }) } diff --git a/sqlx-core/src/postgres/message/row_description.rs b/sqlx-core/src/postgres/message/row_description.rs index d6fa0ac22f..8b85484d92 100644 --- a/sqlx-core/src/postgres/message/row_description.rs +++ b/sqlx-core/src/postgres/message/row_description.rs @@ -2,6 +2,7 @@ use bytes::{Buf, Bytes}; use crate::error::Error; use crate::io::{BufExt, Decode}; +use crate::postgres::types::Oid; #[derive(Debug)] pub struct RowDescription { @@ -22,7 +23,7 @@ pub struct Field { pub relation_attribute_no: Option, /// The object ID of the field's data type. - pub data_type_id: u32, + pub data_type_id: Oid, /// The data type size (see pg_type.typlen). Note that negative values denote /// variable-width types. @@ -45,7 +46,7 @@ impl Decode<'_> for RowDescription { let name = buf.get_str_nul()?.to_owned(); let relation_id = buf.get_i32(); let relation_attribute_no = buf.get_i16(); - let data_type_id = buf.get_u32(); + let data_type_id = Oid::new(buf.get_u32()); let data_type_size = buf.get_i16(); let type_modifier = buf.get_i32(); let format = buf.get_i16(); diff --git a/sqlx-core/src/postgres/type_info.rs b/sqlx-core/src/postgres/type_info.rs index 37c018f798..1addae37a5 100644 --- a/sqlx-core/src/postgres/type_info.rs +++ b/sqlx-core/src/postgres/type_info.rs @@ -5,6 +5,7 @@ use std::ops::Deref; use std::sync::Arc; use crate::ext::ustr::UStr; +use crate::postgres::types::Oid; use crate::type_info::TypeInfo; /// Type information for a PostgreSQL type. @@ -128,14 +129,14 @@ pub enum PgType { // NOTE: Do we want to bring back type declaration by ID? It's notoriously fragile but // someone may have a user for it - DeclareWithOid(u32), + DeclareWithOid(Oid), } #[derive(Debug, Clone)] #[cfg_attr(feature = "offline", derive(serde::Serialize, serde::Deserialize))] pub struct PgCustomType { #[cfg_attr(feature = "offline", serde(skip))] - pub(crate) oid: u32, + pub(crate) oid: Oid, pub(crate) name: UStr, pub(crate) kind: PgTypeKind, } @@ -154,7 +155,7 @@ pub enum PgTypeKind { impl PgTypeInfo { /// Returns the corresponding `PgTypeInfo` if the OID is a built-in type and recognized by SQLx. - pub(crate) fn try_from_oid(oid: u32) -> Option { + pub(crate) fn try_from_oid(oid: Oid) -> Option { PgType::try_from_oid(oid).map(Self) } @@ -220,7 +221,7 @@ impl PgTypeInfo { /// Note that the OID for a type is very dependent on the environment. If you only ever use /// one database or if this is an unhandled build-in type, you should be fine. Otherwise, /// you will be better served using [`with_name`](Self::with_name). - pub const fn with_oid(oid: u32) -> Self { + pub const fn with_oid(oid: Oid) -> Self { Self(PgType::DeclareWithOid(oid)) } } @@ -233,8 +234,8 @@ impl PgTypeInfo { impl PgType { /// Returns the corresponding `PgType` if the OID is a built-in type and recognized by SQLx. - pub(crate) fn try_from_oid(oid: u32) -> Option { - Some(match oid { + pub(crate) fn try_from_oid(oid: Oid) -> Option { + Some(match oid.as_u32() { 16 => PgType::Bool, 17 => PgType::Bytea, 18 => PgType::Char, @@ -334,107 +335,107 @@ impl PgType { }) } - pub(crate) fn oid(&self) -> u32 { + pub(crate) fn oid(&self) -> Oid { match self.try_oid() { Some(oid) => oid, None => unreachable!("(bug) use of unresolved type declaration [oid]"), } } - pub(crate) fn try_oid(&self) -> Option { + pub(crate) fn try_oid(&self) -> Option { Some(match self { - PgType::Bool => 16, - PgType::Bytea => 17, - PgType::Char => 18, - PgType::Name => 19, - PgType::Int8 => 20, - PgType::Int2 => 21, - PgType::Int4 => 23, - PgType::Text => 25, - PgType::Oid => 26, - PgType::Json => 114, - PgType::JsonArray => 199, - PgType::Point => 600, - PgType::Lseg => 601, - PgType::Path => 602, - PgType::Box => 603, - PgType::Polygon => 604, - PgType::Line => 628, - PgType::LineArray => 629, - PgType::Cidr => 650, - PgType::CidrArray => 651, - PgType::Float4 => 700, - PgType::Float8 => 701, - PgType::Unknown => 705, - PgType::Circle => 718, - PgType::CircleArray => 719, - PgType::Macaddr8 => 774, - PgType::Macaddr8Array => 775, - PgType::Money => 790, - PgType::MoneyArray => 791, - PgType::Macaddr => 829, - PgType::Inet => 869, - PgType::BoolArray => 1000, - PgType::ByteaArray => 1001, - PgType::CharArray => 1002, - PgType::NameArray => 1003, - PgType::Int2Array => 1005, - PgType::Int4Array => 1007, - PgType::TextArray => 1009, - PgType::BpcharArray => 1014, - PgType::VarcharArray => 1015, - PgType::Int8Array => 1016, - PgType::PointArray => 1017, - PgType::LsegArray => 1018, - PgType::PathArray => 1019, - PgType::BoxArray => 1020, - PgType::Float4Array => 1021, - PgType::Float8Array => 1022, - PgType::PolygonArray => 1027, - PgType::OidArray => 1028, - PgType::MacaddrArray => 1040, - PgType::InetArray => 1041, - PgType::Bpchar => 1042, - PgType::Varchar => 1043, - PgType::Date => 1082, - PgType::Time => 1083, - PgType::Timestamp => 1114, - PgType::TimestampArray => 1115, - PgType::DateArray => 1182, - PgType::TimeArray => 1183, - PgType::Timestamptz => 1184, - PgType::TimestamptzArray => 1185, - PgType::Interval => 1186, - PgType::IntervalArray => 1187, - PgType::NumericArray => 1231, - PgType::Timetz => 1266, - PgType::TimetzArray => 1270, - PgType::Bit => 1560, - PgType::BitArray => 1561, - PgType::Varbit => 1562, - PgType::VarbitArray => 1563, - PgType::Numeric => 1700, - PgType::Void => 2278, - PgType::Record => 2249, - PgType::RecordArray => 2287, - PgType::Uuid => 2950, - PgType::UuidArray => 2951, - PgType::Jsonb => 3802, - PgType::JsonbArray => 3807, - PgType::Int4Range => 3904, - PgType::Int4RangeArray => 3905, - PgType::NumRange => 3906, - PgType::NumRangeArray => 3907, - PgType::TsRange => 3908, - PgType::TsRangeArray => 3909, - PgType::TstzRange => 3910, - PgType::TstzRangeArray => 3911, - PgType::DateRange => 3912, - PgType::DateRangeArray => 3913, - PgType::Int8Range => 3926, - PgType::Int8RangeArray => 3927, - PgType::Jsonpath => 4072, - PgType::JsonpathArray => 4073, + PgType::Bool => Oid::new(16), + PgType::Bytea => Oid::new(17), + PgType::Char => Oid::new(18), + PgType::Name => Oid::new(19), + PgType::Int8 => Oid::new(20), + PgType::Int2 => Oid::new(21), + PgType::Int4 => Oid::new(23), + PgType::Text => Oid::new(25), + PgType::Oid => Oid::new(26), + PgType::Json => Oid::new(114), + PgType::JsonArray => Oid::new(199), + PgType::Point => Oid::new(600), + PgType::Lseg => Oid::new(601), + PgType::Path => Oid::new(602), + PgType::Box => Oid::new(603), + PgType::Polygon => Oid::new(604), + PgType::Line => Oid::new(628), + PgType::LineArray => Oid::new(629), + PgType::Cidr => Oid::new(650), + PgType::CidrArray => Oid::new(651), + PgType::Float4 => Oid::new(700), + PgType::Float8 => Oid::new(701), + PgType::Unknown => Oid::new(705), + PgType::Circle => Oid::new(718), + PgType::CircleArray => Oid::new(719), + PgType::Macaddr8 => Oid::new(774), + PgType::Macaddr8Array => Oid::new(775), + PgType::Money => Oid::new(790), + PgType::MoneyArray => Oid::new(791), + PgType::Macaddr => Oid::new(829), + PgType::Inet => Oid::new(869), + PgType::BoolArray => Oid::new(1000), + PgType::ByteaArray => Oid::new(1001), + PgType::CharArray => Oid::new(1002), + PgType::NameArray => Oid::new(1003), + PgType::Int2Array => Oid::new(1005), + PgType::Int4Array => Oid::new(1007), + PgType::TextArray => Oid::new(1009), + PgType::BpcharArray => Oid::new(1014), + PgType::VarcharArray => Oid::new(1015), + PgType::Int8Array => Oid::new(1016), + PgType::PointArray => Oid::new(1017), + PgType::LsegArray => Oid::new(1018), + PgType::PathArray => Oid::new(1019), + PgType::BoxArray => Oid::new(1020), + PgType::Float4Array => Oid::new(1021), + PgType::Float8Array => Oid::new(1022), + PgType::PolygonArray => Oid::new(1027), + PgType::OidArray => Oid::new(1028), + PgType::MacaddrArray => Oid::new(1040), + PgType::InetArray => Oid::new(1041), + PgType::Bpchar => Oid::new(1042), + PgType::Varchar => Oid::new(1043), + PgType::Date => Oid::new(1082), + PgType::Time => Oid::new(1083), + PgType::Timestamp => Oid::new(1114), + PgType::TimestampArray => Oid::new(1115), + PgType::DateArray => Oid::new(1182), + PgType::TimeArray => Oid::new(1183), + PgType::Timestamptz => Oid::new(1184), + PgType::TimestamptzArray => Oid::new(1185), + PgType::Interval => Oid::new(1186), + PgType::IntervalArray => Oid::new(1187), + PgType::NumericArray => Oid::new(1231), + PgType::Timetz => Oid::new(1266), + PgType::TimetzArray => Oid::new(1270), + PgType::Bit => Oid::new(1560), + PgType::BitArray => Oid::new(1561), + PgType::Varbit => Oid::new(1562), + PgType::VarbitArray => Oid::new(1563), + PgType::Numeric => Oid::new(1700), + PgType::Void => Oid::new(2278), + PgType::Record => Oid::new(2249), + PgType::RecordArray => Oid::new(2287), + PgType::Uuid => Oid::new(2950), + PgType::UuidArray => Oid::new(2951), + PgType::Jsonb => Oid::new(3802), + PgType::JsonbArray => Oid::new(3807), + PgType::Int4Range => Oid::new(3904), + PgType::Int4RangeArray => Oid::new(3905), + PgType::NumRange => Oid::new(3906), + PgType::NumRangeArray => Oid::new(3907), + PgType::TsRange => Oid::new(3908), + PgType::TsRangeArray => Oid::new(3909), + PgType::TstzRange => Oid::new(3910), + PgType::TstzRangeArray => Oid::new(3911), + PgType::DateRange => Oid::new(3912), + PgType::DateRangeArray => Oid::new(3913), + PgType::Int8Range => Oid::new(3926), + PgType::Int8RangeArray => Oid::new(3927), + PgType::Jsonpath => Oid::new(4072), + PgType::JsonpathArray => Oid::new(4073), PgType::Custom(ty) => ty.oid, PgType::DeclareWithOid(oid) => *oid, @@ -743,7 +744,10 @@ impl PgType { PgType::Custom(ty) => &ty.kind, PgType::DeclareWithOid(oid) => { - unreachable!("(bug) use of unresolved type declaration [oid={}]", oid); + unreachable!( + "(bug) use of unresolved type declaration [oid={}]", + oid.as_u32() + ); } PgType::DeclareWithName(name) => { unreachable!("(bug) use of unresolved type declaration [name={}]", name); diff --git a/sqlx-core/src/postgres/types/array.rs b/sqlx-core/src/postgres/types/array.rs index a478e11d05..cb974f4335 100644 --- a/sqlx-core/src/postgres/types/array.rs +++ b/sqlx-core/src/postgres/types/array.rs @@ -4,6 +4,7 @@ use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; use crate::postgres::type_info::PgType; +use crate::postgres::types::Oid; use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}; use crate::types::Type; @@ -77,7 +78,7 @@ where PgType::DeclareWithName(name) => buf.patch_type_by_name(&name), ty => { - buf.extend(&ty.oid().to_be_bytes()); + buf.extend(&ty.oid().as_u32().to_be_bytes()); } } @@ -124,7 +125,7 @@ where let _flags = buf.get_i32(); // the OID of the element - let element_type_oid = buf.get_u32(); + let element_type_oid = Oid::new(buf.get_u32()); element_type_info = PgTypeInfo::try_from_oid(element_type_oid) .unwrap_or_else(|| PgTypeInfo(PgType::DeclareWithOid(element_type_oid))); diff --git a/sqlx-core/src/postgres/types/int.rs b/sqlx-core/src/postgres/types/int.rs index 63b7d3dfee..e721bab143 100644 --- a/sqlx-core/src/postgres/types/int.rs +++ b/sqlx-core/src/postgres/types/int.rs @@ -64,35 +64,6 @@ impl Decode<'_, Postgres> for i16 { } } -impl Type for u32 { - fn type_info() -> PgTypeInfo { - PgTypeInfo::OID - } -} - -impl PgHasArrayType for u32 { - fn array_type_info() -> PgTypeInfo { - PgTypeInfo::OID_ARRAY - } -} - -impl Encode<'_, Postgres> for u32 { - fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { - buf.extend(&self.to_be_bytes()); - - IsNull::No - } -} - -impl Decode<'_, Postgres> for u32 { - fn decode(value: PgValueRef<'_>) -> Result { - Ok(match value.format() { - PgValueFormat::Binary => BigEndian::read_u32(value.as_bytes()?), - PgValueFormat::Text => value.as_str()?.parse()?, - }) - } -} - impl Type for i32 { fn type_info() -> PgTypeInfo { PgTypeInfo::INT4 diff --git a/sqlx-core/src/postgres/types/mod.rs b/sqlx-core/src/postgres/types/mod.rs index eaf11f1093..776c78f651 100644 --- a/sqlx-core/src/postgres/types/mod.rs +++ b/sqlx-core/src/postgres/types/mod.rs @@ -169,6 +169,7 @@ mod float; mod int; mod interval; mod money; +mod oid; mod range; mod record; mod str; @@ -211,6 +212,7 @@ mod bit_vec; pub use array::PgHasArrayType; pub use interval::PgInterval; pub use money::PgMoney; +pub use oid::Oid; pub use range::PgRange; #[cfg(any(feature = "chrono", feature = "time"))] diff --git a/sqlx-core/src/postgres/types/oid.rs b/sqlx-core/src/postgres/types/oid.rs new file mode 100644 index 0000000000..48275cd253 --- /dev/null +++ b/sqlx-core/src/postgres/types/oid.rs @@ -0,0 +1,57 @@ +use byteorder::{BigEndian, ByteOrder}; + +use crate::decode::Decode; +use crate::encode::{Encode, IsNull}; +use crate::error::BoxDynError; +use crate::postgres::{ + PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueFormat, PgValueRef, Postgres, +}; +use crate::types::Type; + +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Oid(u32); + +impl Oid { + #[inline(always)] + pub const fn new(oid: u32) -> Self { + Self(oid) + } + + #[inline(always)] + pub const fn as_u32(self) -> u32 { + self.0 + } + + pub(crate) fn incr_one(&mut self) { + self.0 = self.0.wrapping_add(1); + } +} + +impl Type for Oid { + fn type_info() -> PgTypeInfo { + PgTypeInfo::OID + } +} + +impl PgHasArrayType for Oid { + fn array_type_info() -> PgTypeInfo { + PgTypeInfo::OID_ARRAY + } +} + +impl Encode<'_, Postgres> for Oid { + fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { + buf.extend(&self.0.to_be_bytes()); + + IsNull::No + } +} + +impl Decode<'_, Postgres> for Oid { + fn decode(value: PgValueRef<'_>) -> Result { + Ok(Self(match value.format() { + PgValueFormat::Binary => BigEndian::read_u32(value.as_bytes()?), + PgValueFormat::Text => value.as_str()?.parse()?, + })) + } +} diff --git a/sqlx-core/src/postgres/types/record.rs b/sqlx-core/src/postgres/types/record.rs index 8ae55c2c0a..c713ca6f29 100644 --- a/sqlx-core/src/postgres/types/record.rs +++ b/sqlx-core/src/postgres/types/record.rs @@ -4,6 +4,7 @@ use crate::decode::Decode; use crate::encode::Encode; use crate::error::{mismatched_types, BoxDynError}; use crate::postgres::type_info::{PgType, PgTypeKind}; +use crate::postgres::types::Oid; use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}; use crate::type_info::TypeInfo; use crate::types::Type; @@ -46,7 +47,7 @@ impl<'a> PgRecordEncoder<'a> { self.buf.patch_type_by_name(&name); } else { // write type id - self.buf.extend(&ty.0.oid().to_be_bytes()); + self.buf.extend(&ty.0.oid().as_u32().to_be_bytes()); } self.buf.encode(value); @@ -101,7 +102,7 @@ impl<'r> PgRecordDecoder<'r> { match self.fmt { PgValueFormat::Binary => { - let element_type_oid = self.buf.get_u32(); + let element_type_oid = Oid::new(self.buf.get_u32()); let element_type_opt = match self.typ.0.kind() { PgTypeKind::Simple if self.typ.0 == PgType::Record => { PgTypeInfo::try_from_oid(element_type_oid) @@ -192,7 +193,7 @@ impl<'r> PgRecordDecoder<'r> { T::decode(PgValueRef { // NOTE: We pass `0` as the type ID because we don't have a reasonable value // we could use. - type_info: PgTypeInfo::with_oid(0), + type_info: PgTypeInfo::with_oid(Oid::new(0)), format: self.fmt, value: buf, row: None, diff --git a/sqlx-macros/src/database/postgres.rs b/sqlx-macros/src/database/postgres.rs index 5330bb3cd9..634a6ac4fb 100644 --- a/sqlx-macros/src/database/postgres.rs +++ b/sqlx-macros/src/database/postgres.rs @@ -8,7 +8,7 @@ impl_database_ext! { i8, i16, i32, - u32, + sqlx::postgres::types::Oid, i64, f32, f64, @@ -77,7 +77,7 @@ impl_database_ext! { Vec | &[i8], Vec | &[i16], Vec | &[i32], - Vec | &[u32], + Vec | &[sqlx::postgres::types::Oid], Vec | &[i64], Vec | &[f32], Vec | &[f64], From 24ca5c007aa5442ec60bfb499c2677a38d4b366e Mon Sep 17 00:00:00 2001 From: Paolo Barbolini Date: Wed, 29 Dec 2021 12:14:32 +0100 Subject: [PATCH 2/8] Make serde happy --- sqlx-core/src/postgres/types/oid.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/sqlx-core/src/postgres/types/oid.rs b/sqlx-core/src/postgres/types/oid.rs index 48275cd253..08f1417a33 100644 --- a/sqlx-core/src/postgres/types/oid.rs +++ b/sqlx-core/src/postgres/types/oid.rs @@ -1,4 +1,6 @@ use byteorder::{BigEndian, ByteOrder}; +#[cfg(feature = "serde")] +use serde::{de::Deserializer, ser::Serializer, Deserialize, Serialize}; use crate::decode::Decode; use crate::encode::{Encode, IsNull}; @@ -8,7 +10,7 @@ use crate::postgres::{ }; use crate::types::Type; -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Default)] pub struct Oid(u32); impl Oid { @@ -55,3 +57,23 @@ impl Decode<'_, Postgres> for Oid { })) } } + +#[cfg(feature = "serde")] +impl Serialize for Oid { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.0.serialize(serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for Oid { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + u32::deserialize(deserializer).map(Self) + } +} From 3f882891c9052955b25c07c53a0483ed5b398832 Mon Sep 17 00:00:00 2001 From: Paolo Barbolini Date: Wed, 29 Dec 2021 12:41:44 +0100 Subject: [PATCH 3/8] Expose the inner u32 --- sqlx-core/src/postgres/arguments.rs | 2 +- sqlx-core/src/postgres/connection/describe.rs | 2 +- .../src/postgres/connection/establish.rs | 2 +- sqlx-core/src/postgres/io/buf_mut.rs | 4 +- .../postgres/message/parameter_description.rs | 2 +- sqlx-core/src/postgres/message/parse.rs | 2 +- .../src/postgres/message/row_description.rs | 2 +- sqlx-core/src/postgres/type_info.rs | 191 +++++++++--------- sqlx-core/src/postgres/types/array.rs | 4 +- sqlx-core/src/postgres/types/oid.rs | 12 +- sqlx-core/src/postgres/types/record.rs | 6 +- 11 files changed, 108 insertions(+), 121 deletions(-) diff --git a/sqlx-core/src/postgres/arguments.rs b/sqlx-core/src/postgres/arguments.rs index 7ce2e298cb..e961d8ee74 100644 --- a/sqlx-core/src/postgres/arguments.rs +++ b/sqlx-core/src/postgres/arguments.rs @@ -95,7 +95,7 @@ impl PgArguments { for (offset, name) in type_holes { let oid = conn.fetch_type_id_by_name(&*name).await?; - buffer[*offset..(*offset + 4)].copy_from_slice(&oid.as_u32().to_be_bytes()); + buffer[*offset..(*offset + 4)].copy_from_slice(&oid.0.to_be_bytes()); } Ok(()) diff --git a/sqlx-core/src/postgres/connection/describe.rs b/sqlx-core/src/postgres/connection/describe.rs index 181d04fa14..dd789d3b14 100644 --- a/sqlx-core/src/postgres/connection/describe.rs +++ b/sqlx-core/src/postgres/connection/describe.rs @@ -426,7 +426,7 @@ SELECT oid FROM pg_catalog.pg_type WHERE typname ILIKE $1 ) -> Result>, Error> { let mut explain = format!( "EXPLAIN (VERBOSE, FORMAT JSON) EXECUTE sqlx_s_{}", - stmt_id.as_u32() + stmt_id.0 ); let mut comma = false; diff --git a/sqlx-core/src/postgres/connection/establish.rs b/sqlx-core/src/postgres/connection/establish.rs index 5bde516f0b..52d79a31a2 100644 --- a/sqlx-core/src/postgres/connection/establish.rs +++ b/sqlx-core/src/postgres/connection/establish.rs @@ -139,7 +139,7 @@ impl PgConnection { transaction_status, transaction_depth: 0, pending_ready_for_query_count: 0, - next_statement_id: Oid::new(1), + next_statement_id: Oid(1), cache_statement: StatementCache::new(options.statement_cache_capacity), cache_type_oid: HashMap::new(), cache_type_info: HashMap::new(), diff --git a/sqlx-core/src/postgres/io/buf_mut.rs b/sqlx-core/src/postgres/io/buf_mut.rs index c67b1c05eb..6d8d3906f9 100644 --- a/sqlx-core/src/postgres/io/buf_mut.rs +++ b/sqlx-core/src/postgres/io/buf_mut.rs @@ -35,7 +35,7 @@ impl PgBufMutExt for Vec { // N.B. if you change this don't forget to update it in ../describe.rs self.extend(b"sqlx_s_"); - itoa::write(&mut *self, id.as_u32()).unwrap(); + itoa::write(&mut *self, id.0).unwrap(); self.push(0); } @@ -46,7 +46,7 @@ impl PgBufMutExt for Vec { if let Some(id) = id { self.extend(b"sqlx_p_"); - itoa::write(&mut *self, id.as_u32()).unwrap(); + itoa::write(&mut *self, id.0).unwrap(); } self.push(0); diff --git a/sqlx-core/src/postgres/message/parameter_description.rs b/sqlx-core/src/postgres/message/parameter_description.rs index 6a20aafcdf..49d0b98b0e 100644 --- a/sqlx-core/src/postgres/message/parameter_description.rs +++ b/sqlx-core/src/postgres/message/parameter_description.rs @@ -16,7 +16,7 @@ impl Decode<'_> for ParameterDescription { let mut types = SmallVec::with_capacity(cnt as usize); for _ in 0..cnt { - types.push(Oid::new(buf.get_u32())); + types.push(Oid(buf.get_u32())); } Ok(Self { types }) diff --git a/sqlx-core/src/postgres/message/parse.rs b/sqlx-core/src/postgres/message/parse.rs index 1305dd0ad1..4efbaefea6 100644 --- a/sqlx-core/src/postgres/message/parse.rs +++ b/sqlx-core/src/postgres/message/parse.rs @@ -33,7 +33,7 @@ impl Encode<'_> for Parse<'_> { buf.extend(&(self.param_types.len() as i16).to_be_bytes()); for &oid in self.param_types { - buf.extend(&oid.as_u32().to_be_bytes()); + buf.extend(&oid.0.to_be_bytes()); } }) } diff --git a/sqlx-core/src/postgres/message/row_description.rs b/sqlx-core/src/postgres/message/row_description.rs index 8b85484d92..ff25ea9373 100644 --- a/sqlx-core/src/postgres/message/row_description.rs +++ b/sqlx-core/src/postgres/message/row_description.rs @@ -46,7 +46,7 @@ impl Decode<'_> for RowDescription { let name = buf.get_str_nul()?.to_owned(); let relation_id = buf.get_i32(); let relation_attribute_no = buf.get_i16(); - let data_type_id = Oid::new(buf.get_u32()); + let data_type_id = Oid(buf.get_u32()); let data_type_size = buf.get_i16(); let type_modifier = buf.get_i32(); let format = buf.get_i16(); diff --git a/sqlx-core/src/postgres/type_info.rs b/sqlx-core/src/postgres/type_info.rs index 1addae37a5..36e820e711 100644 --- a/sqlx-core/src/postgres/type_info.rs +++ b/sqlx-core/src/postgres/type_info.rs @@ -235,7 +235,7 @@ impl PgTypeInfo { impl PgType { /// Returns the corresponding `PgType` if the OID is a built-in type and recognized by SQLx. pub(crate) fn try_from_oid(oid: Oid) -> Option { - Some(match oid.as_u32() { + Some(match oid.0 { 16 => PgType::Bool, 17 => PgType::Bytea, 18 => PgType::Char, @@ -344,98 +344,98 @@ impl PgType { pub(crate) fn try_oid(&self) -> Option { Some(match self { - PgType::Bool => Oid::new(16), - PgType::Bytea => Oid::new(17), - PgType::Char => Oid::new(18), - PgType::Name => Oid::new(19), - PgType::Int8 => Oid::new(20), - PgType::Int2 => Oid::new(21), - PgType::Int4 => Oid::new(23), - PgType::Text => Oid::new(25), - PgType::Oid => Oid::new(26), - PgType::Json => Oid::new(114), - PgType::JsonArray => Oid::new(199), - PgType::Point => Oid::new(600), - PgType::Lseg => Oid::new(601), - PgType::Path => Oid::new(602), - PgType::Box => Oid::new(603), - PgType::Polygon => Oid::new(604), - PgType::Line => Oid::new(628), - PgType::LineArray => Oid::new(629), - PgType::Cidr => Oid::new(650), - PgType::CidrArray => Oid::new(651), - PgType::Float4 => Oid::new(700), - PgType::Float8 => Oid::new(701), - PgType::Unknown => Oid::new(705), - PgType::Circle => Oid::new(718), - PgType::CircleArray => Oid::new(719), - PgType::Macaddr8 => Oid::new(774), - PgType::Macaddr8Array => Oid::new(775), - PgType::Money => Oid::new(790), - PgType::MoneyArray => Oid::new(791), - PgType::Macaddr => Oid::new(829), - PgType::Inet => Oid::new(869), - PgType::BoolArray => Oid::new(1000), - PgType::ByteaArray => Oid::new(1001), - PgType::CharArray => Oid::new(1002), - PgType::NameArray => Oid::new(1003), - PgType::Int2Array => Oid::new(1005), - PgType::Int4Array => Oid::new(1007), - PgType::TextArray => Oid::new(1009), - PgType::BpcharArray => Oid::new(1014), - PgType::VarcharArray => Oid::new(1015), - PgType::Int8Array => Oid::new(1016), - PgType::PointArray => Oid::new(1017), - PgType::LsegArray => Oid::new(1018), - PgType::PathArray => Oid::new(1019), - PgType::BoxArray => Oid::new(1020), - PgType::Float4Array => Oid::new(1021), - PgType::Float8Array => Oid::new(1022), - PgType::PolygonArray => Oid::new(1027), - PgType::OidArray => Oid::new(1028), - PgType::MacaddrArray => Oid::new(1040), - PgType::InetArray => Oid::new(1041), - PgType::Bpchar => Oid::new(1042), - PgType::Varchar => Oid::new(1043), - PgType::Date => Oid::new(1082), - PgType::Time => Oid::new(1083), - PgType::Timestamp => Oid::new(1114), - PgType::TimestampArray => Oid::new(1115), - PgType::DateArray => Oid::new(1182), - PgType::TimeArray => Oid::new(1183), - PgType::Timestamptz => Oid::new(1184), - PgType::TimestamptzArray => Oid::new(1185), - PgType::Interval => Oid::new(1186), - PgType::IntervalArray => Oid::new(1187), - PgType::NumericArray => Oid::new(1231), - PgType::Timetz => Oid::new(1266), - PgType::TimetzArray => Oid::new(1270), - PgType::Bit => Oid::new(1560), - PgType::BitArray => Oid::new(1561), - PgType::Varbit => Oid::new(1562), - PgType::VarbitArray => Oid::new(1563), - PgType::Numeric => Oid::new(1700), - PgType::Void => Oid::new(2278), - PgType::Record => Oid::new(2249), - PgType::RecordArray => Oid::new(2287), - PgType::Uuid => Oid::new(2950), - PgType::UuidArray => Oid::new(2951), - PgType::Jsonb => Oid::new(3802), - PgType::JsonbArray => Oid::new(3807), - PgType::Int4Range => Oid::new(3904), - PgType::Int4RangeArray => Oid::new(3905), - PgType::NumRange => Oid::new(3906), - PgType::NumRangeArray => Oid::new(3907), - PgType::TsRange => Oid::new(3908), - PgType::TsRangeArray => Oid::new(3909), - PgType::TstzRange => Oid::new(3910), - PgType::TstzRangeArray => Oid::new(3911), - PgType::DateRange => Oid::new(3912), - PgType::DateRangeArray => Oid::new(3913), - PgType::Int8Range => Oid::new(3926), - PgType::Int8RangeArray => Oid::new(3927), - PgType::Jsonpath => Oid::new(4072), - PgType::JsonpathArray => Oid::new(4073), + PgType::Bool => Oid(16), + PgType::Bytea => Oid(17), + PgType::Char => Oid(18), + PgType::Name => Oid(19), + PgType::Int8 => Oid(20), + PgType::Int2 => Oid(21), + PgType::Int4 => Oid(23), + PgType::Text => Oid(25), + PgType::Oid => Oid(26), + PgType::Json => Oid(114), + PgType::JsonArray => Oid(199), + PgType::Point => Oid(600), + PgType::Lseg => Oid(601), + PgType::Path => Oid(602), + PgType::Box => Oid(603), + PgType::Polygon => Oid(604), + PgType::Line => Oid(628), + PgType::LineArray => Oid(629), + PgType::Cidr => Oid(650), + PgType::CidrArray => Oid(651), + PgType::Float4 => Oid(700), + PgType::Float8 => Oid(701), + PgType::Unknown => Oid(705), + PgType::Circle => Oid(718), + PgType::CircleArray => Oid(719), + PgType::Macaddr8 => Oid(774), + PgType::Macaddr8Array => Oid(775), + PgType::Money => Oid(790), + PgType::MoneyArray => Oid(791), + PgType::Macaddr => Oid(829), + PgType::Inet => Oid(869), + PgType::BoolArray => Oid(1000), + PgType::ByteaArray => Oid(1001), + PgType::CharArray => Oid(1002), + PgType::NameArray => Oid(1003), + PgType::Int2Array => Oid(1005), + PgType::Int4Array => Oid(1007), + PgType::TextArray => Oid(1009), + PgType::BpcharArray => Oid(1014), + PgType::VarcharArray => Oid(1015), + PgType::Int8Array => Oid(1016), + PgType::PointArray => Oid(1017), + PgType::LsegArray => Oid(1018), + PgType::PathArray => Oid(1019), + PgType::BoxArray => Oid(1020), + PgType::Float4Array => Oid(1021), + PgType::Float8Array => Oid(1022), + PgType::PolygonArray => Oid(1027), + PgType::OidArray => Oid(1028), + PgType::MacaddrArray => Oid(1040), + PgType::InetArray => Oid(1041), + PgType::Bpchar => Oid(1042), + PgType::Varchar => Oid(1043), + PgType::Date => Oid(1082), + PgType::Time => Oid(1083), + PgType::Timestamp => Oid(1114), + PgType::TimestampArray => Oid(1115), + PgType::DateArray => Oid(1182), + PgType::TimeArray => Oid(1183), + PgType::Timestamptz => Oid(1184), + PgType::TimestamptzArray => Oid(1185), + PgType::Interval => Oid(1186), + PgType::IntervalArray => Oid(1187), + PgType::NumericArray => Oid(1231), + PgType::Timetz => Oid(1266), + PgType::TimetzArray => Oid(1270), + PgType::Bit => Oid(1560), + PgType::BitArray => Oid(1561), + PgType::Varbit => Oid(1562), + PgType::VarbitArray => Oid(1563), + PgType::Numeric => Oid(1700), + PgType::Void => Oid(2278), + PgType::Record => Oid(2249), + PgType::RecordArray => Oid(2287), + PgType::Uuid => Oid(2950), + PgType::UuidArray => Oid(2951), + PgType::Jsonb => Oid(3802), + PgType::JsonbArray => Oid(3807), + PgType::Int4Range => Oid(3904), + PgType::Int4RangeArray => Oid(3905), + PgType::NumRange => Oid(3906), + PgType::NumRangeArray => Oid(3907), + PgType::TsRange => Oid(3908), + PgType::TsRangeArray => Oid(3909), + PgType::TstzRange => Oid(3910), + PgType::TstzRangeArray => Oid(3911), + PgType::DateRange => Oid(3912), + PgType::DateRangeArray => Oid(3913), + PgType::Int8Range => Oid(3926), + PgType::Int8RangeArray => Oid(3927), + PgType::Jsonpath => Oid(4072), + PgType::JsonpathArray => Oid(4073), PgType::Custom(ty) => ty.oid, PgType::DeclareWithOid(oid) => *oid, @@ -744,10 +744,7 @@ impl PgType { PgType::Custom(ty) => &ty.kind, PgType::DeclareWithOid(oid) => { - unreachable!( - "(bug) use of unresolved type declaration [oid={}]", - oid.as_u32() - ); + unreachable!("(bug) use of unresolved type declaration [oid={}]", oid.0); } PgType::DeclareWithName(name) => { unreachable!("(bug) use of unresolved type declaration [name={}]", name); diff --git a/sqlx-core/src/postgres/types/array.rs b/sqlx-core/src/postgres/types/array.rs index cb974f4335..8784587b7c 100644 --- a/sqlx-core/src/postgres/types/array.rs +++ b/sqlx-core/src/postgres/types/array.rs @@ -78,7 +78,7 @@ where PgType::DeclareWithName(name) => buf.patch_type_by_name(&name), ty => { - buf.extend(&ty.oid().as_u32().to_be_bytes()); + buf.extend(&ty.oid().0.to_be_bytes()); } } @@ -125,7 +125,7 @@ where let _flags = buf.get_i32(); // the OID of the element - let element_type_oid = Oid::new(buf.get_u32()); + let element_type_oid = Oid(buf.get_u32()); element_type_info = PgTypeInfo::try_from_oid(element_type_oid) .unwrap_or_else(|| PgTypeInfo(PgType::DeclareWithOid(element_type_oid))); diff --git a/sqlx-core/src/postgres/types/oid.rs b/sqlx-core/src/postgres/types/oid.rs index 08f1417a33..62448be095 100644 --- a/sqlx-core/src/postgres/types/oid.rs +++ b/sqlx-core/src/postgres/types/oid.rs @@ -11,19 +11,9 @@ use crate::postgres::{ use crate::types::Type; #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Default)] -pub struct Oid(u32); +pub struct Oid(pub u32); impl Oid { - #[inline(always)] - pub const fn new(oid: u32) -> Self { - Self(oid) - } - - #[inline(always)] - pub const fn as_u32(self) -> u32 { - self.0 - } - pub(crate) fn incr_one(&mut self) { self.0 = self.0.wrapping_add(1); } diff --git a/sqlx-core/src/postgres/types/record.rs b/sqlx-core/src/postgres/types/record.rs index c713ca6f29..bf2c31b8fe 100644 --- a/sqlx-core/src/postgres/types/record.rs +++ b/sqlx-core/src/postgres/types/record.rs @@ -47,7 +47,7 @@ impl<'a> PgRecordEncoder<'a> { self.buf.patch_type_by_name(&name); } else { // write type id - self.buf.extend(&ty.0.oid().as_u32().to_be_bytes()); + self.buf.extend(&ty.0.oid().0.to_be_bytes()); } self.buf.encode(value); @@ -102,7 +102,7 @@ impl<'r> PgRecordDecoder<'r> { match self.fmt { PgValueFormat::Binary => { - let element_type_oid = Oid::new(self.buf.get_u32()); + let element_type_oid = Oid(self.buf.get_u32()); let element_type_opt = match self.typ.0.kind() { PgTypeKind::Simple if self.typ.0 == PgType::Record => { PgTypeInfo::try_from_oid(element_type_oid) @@ -193,7 +193,7 @@ impl<'r> PgRecordDecoder<'r> { T::decode(PgValueRef { // NOTE: We pass `0` as the type ID because we don't have a reasonable value // we could use. - type_info: PgTypeInfo::with_oid(Oid::new(0)), + type_info: PgTypeInfo::with_oid(Oid(0)), format: self.fmt, value: buf, row: None, From 7fd65fd2af885e368e52052eda972a6ea9376911 Mon Sep 17 00:00:00 2001 From: Paolo Barbolini Date: Wed, 29 Dec 2021 12:46:53 +0100 Subject: [PATCH 4/8] docs --- sqlx-core/src/postgres/types/oid.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sqlx-core/src/postgres/types/oid.rs b/sqlx-core/src/postgres/types/oid.rs index 62448be095..74d8e3b68b 100644 --- a/sqlx-core/src/postgres/types/oid.rs +++ b/sqlx-core/src/postgres/types/oid.rs @@ -10,8 +10,15 @@ use crate::postgres::{ }; use crate::types::Type; +/// The PostgreSQL [`OID`] type stores an object identifier, +/// used internally by PostgreSQL as primary keys for various system tables. +/// +/// [`OID`]: https://www.postgresql.org/docs/current/datatype-oid.html #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Default)] -pub struct Oid(pub u32); +pub struct Oid( + /// The raw unsigned integer value sent over the wire + pub u32, +); impl Oid { pub(crate) fn incr_one(&mut self) { From f0a5dba05215f744cf0bb74926b9c766aa435a7f Mon Sep 17 00:00:00 2001 From: Paolo Barbolini Date: Wed, 29 Dec 2021 12:50:56 +0100 Subject: [PATCH 5/8] Try to fix tests --- tests/postgres/postgres.rs | 17 +++++++++-------- tests/postgres/types.rs | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/tests/postgres/postgres.rs b/tests/postgres/postgres.rs index 51dfbc6d37..5b59e0c8c2 100644 --- a/tests/postgres/postgres.rs +++ b/tests/postgres/postgres.rs @@ -1,8 +1,9 @@ use futures::{StreamExt, TryStreamExt}; +use sqlx::postgres::types::Oid; use sqlx::postgres::{ - PgConnectOptions, PgConnection, PgDatabaseError, PgErrorPosition, PgSeverity, + PgConnectOptions, PgConnection, PgConnectionInfo, PgDatabaseError, PgErrorPosition, + PgPoolOptions, PgRow, PgSeverity, Postgres, }; -use sqlx::postgres::{PgConnectionInfo, PgPoolOptions, PgRow, Postgres}; use sqlx::{Column, Connection, Executor, Row, Statement, TypeInfo}; use sqlx_test::{new, setup_if_needed}; use std::env; @@ -660,14 +661,14 @@ async fn it_caches_statements() -> anyhow::Result<()> { for i in 0..2 { let row = sqlx::query("SELECT $1 AS val") - .bind(i) + .bind(Oid(i)) .persistent(true) .fetch_one(&mut conn) .await?; - let val: u32 = row.get("val"); + let val: Oid = row.get("val"); - assert_eq!(i, val); + assert_eq!(Oid(i), val); } assert_eq!(1, conn.cached_statements_size()); @@ -676,14 +677,14 @@ async fn it_caches_statements() -> anyhow::Result<()> { for i in 0..2 { let row = sqlx::query("SELECT $1 AS val") - .bind(i) + .bind(Oid(i)) .persistent(false) .fetch_one(&mut conn) .await?; - let val: u32 = row.get("val"); + let val: Oid = row.get("val"); - assert_eq!(i, val); + assert_eq!(Oid(i), val); } assert_eq!(0, conn.cached_statements_size()); diff --git a/tests/postgres/types.rs b/tests/postgres/types.rs index 7b39de8596..99077dfbf1 100644 --- a/tests/postgres/types.rs +++ b/tests/postgres/types.rs @@ -4,7 +4,7 @@ use std::ops::Bound; #[cfg(feature = "decimal")] use std::str::FromStr; -use sqlx::postgres::types::{PgInterval, PgMoney, PgRange}; +use sqlx::postgres::types::{Oid, PgInterval, PgMoney, PgRange}; use sqlx::postgres::Postgres; use sqlx_test::{test_decode_type, test_prepared_type, test_type}; @@ -71,7 +71,7 @@ test_type!(i8( "120::\"char\"" == 120_i8, )); -test_type!(u32(Postgres, "325235::oid" == 325235_u32,)); +test_type!(Oid(Postgres, "325235::oid" == Oid(325235),)); test_type!(i16( Postgres, From 685a25c0aa7e640ce4022c0e156df683c6645153 Mon Sep 17 00:00:00 2001 From: Paolo Barbolini Date: Wed, 29 Dec 2021 12:54:54 +0100 Subject: [PATCH 6/8] Fix unit tests --- sqlx-core/src/postgres/message/describe.rs | 4 ++-- sqlx-core/src/postgres/message/execute.rs | 2 +- sqlx-core/src/postgres/message/parameter_description.rs | 4 ++-- sqlx-core/src/postgres/message/parse.rs | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sqlx-core/src/postgres/message/describe.rs b/sqlx-core/src/postgres/message/describe.rs index 63fb724a74..ea919d5021 100644 --- a/sqlx-core/src/postgres/message/describe.rs +++ b/sqlx-core/src/postgres/message/describe.rs @@ -55,7 +55,7 @@ fn test_encode_describe_portal() { const EXPECTED: &[u8] = b"D\0\0\0\x0EPsqlx_p_5\0"; let mut buf = Vec::new(); - let m = Describe::Portal(5); + let m = Describe::Portal(Oid(5)); m.encode(&mut buf); @@ -79,7 +79,7 @@ fn test_encode_describe_statement() { const EXPECTED: &[u8] = b"D\0\0\0\x0ESsqlx_s_5\0"; let mut buf = Vec::new(); - let m = Describe::Statement(5); + let m = Describe::Statement(Oid(5)); m.encode(&mut buf); diff --git a/sqlx-core/src/postgres/message/execute.rs b/sqlx-core/src/postgres/message/execute.rs index 82ce4a286a..dc70ced914 100644 --- a/sqlx-core/src/postgres/message/execute.rs +++ b/sqlx-core/src/postgres/message/execute.rs @@ -29,7 +29,7 @@ fn test_encode_execute() { let mut buf = Vec::new(); let m = Execute { - portal: Some(5), + portal: Some(Oid(5)), limit: 2, }; diff --git a/sqlx-core/src/postgres/message/parameter_description.rs b/sqlx-core/src/postgres/message/parameter_description.rs index 49d0b98b0e..e6640a73bd 100644 --- a/sqlx-core/src/postgres/message/parameter_description.rs +++ b/sqlx-core/src/postgres/message/parameter_description.rs @@ -30,8 +30,8 @@ fn test_decode_parameter_description() { let m = ParameterDescription::decode(DATA.into()).unwrap(); assert_eq!(m.types.len(), 2); - assert_eq!(m.types[0], 0x0000_0000); - assert_eq!(m.types[1], 0x0000_0500); + assert_eq!(m.types[0], Oid(0x0000_0000)); + assert_eq!(m.types[1], Oid(0x0000_0500)); } #[test] diff --git a/sqlx-core/src/postgres/message/parse.rs b/sqlx-core/src/postgres/message/parse.rs index 4efbaefea6..5734ae4120 100644 --- a/sqlx-core/src/postgres/message/parse.rs +++ b/sqlx-core/src/postgres/message/parse.rs @@ -45,9 +45,9 @@ fn test_encode_parse() { let mut buf = Vec::new(); let m = Parse { - statement: 1, + statement: Oid(1), query: "SELECT $1", - param_types: &[25], + param_types: &[Oid(25)], }; m.encode(&mut buf); From 8a2644bf07f56d2e836640e0fd3cb147fd01627b Mon Sep 17 00:00:00 2001 From: Paolo Barbolini Date: Wed, 29 Dec 2021 22:06:07 +0100 Subject: [PATCH 7/8] Fix order --- sqlx-macros/src/database/postgres.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sqlx-macros/src/database/postgres.rs b/sqlx-macros/src/database/postgres.rs index 634a6ac4fb..557a8119ff 100644 --- a/sqlx-macros/src/database/postgres.rs +++ b/sqlx-macros/src/database/postgres.rs @@ -8,12 +8,13 @@ impl_database_ext! { i8, i16, i32, - sqlx::postgres::types::Oid, i64, f32, f64, Vec | &[u8], + sqlx::postgres::types::Oid, + sqlx::postgres::types::PgInterval, sqlx::postgres::types::PgMoney, @@ -77,10 +78,10 @@ impl_database_ext! { Vec | &[i8], Vec | &[i16], Vec | &[i32], - Vec | &[sqlx::postgres::types::Oid], Vec | &[i64], Vec | &[f32], Vec | &[f64], + Vec | &[sqlx::postgres::types::Oid], Vec | &[sqlx::postgres::types::PgMoney], #[cfg(feature = "uuid")] From 037a2d068111f45eec35cfb588f00912baa47c08 Mon Sep 17 00:00:00 2001 From: Paolo Barbolini Date: Wed, 29 Dec 2021 22:14:05 +0100 Subject: [PATCH 8/8] Not sure what happened here --- sqlx-core/src/postgres/type_info.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sqlx-core/src/postgres/type_info.rs b/sqlx-core/src/postgres/type_info.rs index 831b014def..dbc5a4b7db 100644 --- a/sqlx-core/src/postgres/type_info.rs +++ b/sqlx-core/src/postgres/type_info.rs @@ -864,7 +864,7 @@ impl PgType { PgTypeKind::Range(_) => None, }, PgType::DeclareWithOid(oid) => { - unreachable!("(bug) use of unresolved type declaration [oid={}]", oid); + unreachable!("(bug) use of unresolved type declaration [oid={}]", oid.0); } PgType::DeclareWithName(name) => { unreachable!("(bug) use of unresolved type declaration [name={}]", name);