diff --git a/.github/workflows/fmt.yml b/.github/workflows/fmt.yml index f198ebdbd..18d8f7fe4 100644 --- a/.github/workflows/fmt.yml +++ b/.github/workflows/fmt.yml @@ -16,4 +16,4 @@ jobs: - name: Format run: cargo fmt --all -- --check - name: Clippy - run: cargo clippy --all-targets + run: cargo clippy --all-targets -- -D warnings diff --git a/pgdog-postgres-types/src/array.rs b/pgdog-postgres-types/src/array.rs index 6c50d5573..1214b4b43 100644 --- a/pgdog-postgres-types/src/array.rs +++ b/pgdog-postgres-types/src/array.rs @@ -431,79 +431,160 @@ mod tests { // ── Text decode ────────────────────────────────────────────────── + struct TextDecodeCase { + name: &'static str, + input: &'static str, + oid: i32, + expected_elements: Vec>, + expected_lb: i32, + } + #[test] fn test_text_decode_table() { - let cases: Vec<(&str, &str, i32, Vec>, i32)> = vec![ - ("empty", "{}", 23, vec![], 1), - ("single int", "{1}", 23, vec![Some("1")], 1), - ( - "three ints", - "{1,2,3}", - 23, - vec![Some("1"), Some("2"), Some("3")], - 1, - ), - ("negative int", "{-1}", 23, vec![Some("-1")], 1), - ("single NULL", "{NULL}", 23, vec![None], 1), - ("NULL mixed case", "{null}", 23, vec![None], 1), - ( - "NULL start", - "{NULL,1,2}", - 23, - vec![None, Some("1"), Some("2")], - 1, - ), - ("all NULLs", "{NULL,NULL}", 23, vec![None, None], 1), - ( - "text elements", - "{hello,world}", - 25, - vec![Some("hello"), Some("world")], - 1, - ), - ("quoted comma", r#"{"a,b"}"#, 25, vec![Some("a,b")], 1), - ("quoted quote", r#"{"a\"b"}"#, 25, vec![Some("a\"b")], 1), - ("quoted backslash", r#"{"a\\b"}"#, 25, vec![Some("a\\b")], 1), - ("empty string", r#"{""}"#, 25, vec![Some("")], 1), - ( - "quoted NULL literal", - r#"{"NULL"}"#, - 25, - vec![Some("NULL")], - 1, - ), - ( - "whitespace around", - "{ 1 , 2 }", - 23, - vec![Some("1"), Some("2")], - 1, - ), - ("escaped comma", r#"{a\,b}"#, 25, vec![Some("a,b")], 1), - ( - "escaped trailing space", - r#"{a\ }"#, - 25, - vec![Some("a ")], - 1, - ), - ( - "escaped null literal", - r#"{\N\U\L\L}"#, - 25, - vec![Some("NULL")], - 1, - ), - ( - "custom lower bound", - "[0:2]={1,2,3}", - 23, - vec![Some("1"), Some("2"), Some("3")], - 0, - ), + let cases = vec![ + TextDecodeCase { + name: "empty", + input: "{}", + oid: 23, + expected_elements: vec![], + expected_lb: 1, + }, + TextDecodeCase { + name: "single int", + input: "{1}", + oid: 23, + expected_elements: vec![Some("1")], + expected_lb: 1, + }, + TextDecodeCase { + name: "three ints", + input: "{1,2,3}", + oid: 23, + expected_elements: vec![Some("1"), Some("2"), Some("3")], + expected_lb: 1, + }, + TextDecodeCase { + name: "negative int", + input: "{-1}", + oid: 23, + expected_elements: vec![Some("-1")], + expected_lb: 1, + }, + TextDecodeCase { + name: "single NULL", + input: "{NULL}", + oid: 23, + expected_elements: vec![None], + expected_lb: 1, + }, + TextDecodeCase { + name: "NULL mixed case", + input: "{null}", + oid: 23, + expected_elements: vec![None], + expected_lb: 1, + }, + TextDecodeCase { + name: "NULL start", + input: "{NULL,1,2}", + oid: 23, + expected_elements: vec![None, Some("1"), Some("2")], + expected_lb: 1, + }, + TextDecodeCase { + name: "all NULLs", + input: "{NULL,NULL}", + oid: 23, + expected_elements: vec![None, None], + expected_lb: 1, + }, + TextDecodeCase { + name: "text elements", + input: "{hello,world}", + oid: 25, + expected_elements: vec![Some("hello"), Some("world")], + expected_lb: 1, + }, + TextDecodeCase { + name: "quoted comma", + input: r#"{"a,b"}"#, + oid: 25, + expected_elements: vec![Some("a,b")], + expected_lb: 1, + }, + TextDecodeCase { + name: "quoted quote", + input: r#"{"a\"b"}"#, + oid: 25, + expected_elements: vec![Some("a\"b")], + expected_lb: 1, + }, + TextDecodeCase { + name: "quoted backslash", + input: r#"{"a\\b"}"#, + oid: 25, + expected_elements: vec![Some("a\\b")], + expected_lb: 1, + }, + TextDecodeCase { + name: "empty string", + input: r#"{""}"#, + oid: 25, + expected_elements: vec![Some("")], + expected_lb: 1, + }, + TextDecodeCase { + name: "quoted NULL literal", + input: r#"{"NULL"}"#, + oid: 25, + expected_elements: vec![Some("NULL")], + expected_lb: 1, + }, + TextDecodeCase { + name: "whitespace around", + input: "{ 1 , 2 }", + oid: 23, + expected_elements: vec![Some("1"), Some("2")], + expected_lb: 1, + }, + TextDecodeCase { + name: "escaped comma", + input: r#"{a\,b}"#, + oid: 25, + expected_elements: vec![Some("a,b")], + expected_lb: 1, + }, + TextDecodeCase { + name: "escaped trailing space", + input: r#"{a\ }"#, + oid: 25, + expected_elements: vec![Some("a ")], + expected_lb: 1, + }, + TextDecodeCase { + name: "escaped null literal", + input: r#"{\N\U\L\L}"#, + oid: 25, + expected_elements: vec![Some("NULL")], + expected_lb: 1, + }, + TextDecodeCase { + name: "custom lower bound", + input: "[0:2]={1,2,3}", + oid: 23, + expected_elements: vec![Some("1"), Some("2"), Some("3")], + expected_lb: 0, + }, ]; - for (name, input, oid, expected_elements, expected_lb) in cases { + for TextDecodeCase { + name, + input, + oid, + expected_elements, + expected_lb, + } in cases + { let array = Array::decode_typed(input.as_bytes(), Format::Text, oid).expect(name); assert_eq!(array.dim.lower_bound, expected_lb, "lower_bound: {name}"); assert_eq!( diff --git a/pgdog/src/admin/show_servers.rs b/pgdog/src/admin/show_servers.rs index d2c77fab8..5393648b6 100644 --- a/pgdog/src/admin/show_servers.rs +++ b/pgdog/src/admin/show_servers.rs @@ -101,7 +101,11 @@ impl Command for ShowServers { .add("remote_pid", server.stats.id.pid as i64) .add( "client_id", - server.stats.client_id.map(|client| client.pid as i64), + server + .stats + .client_id + .as_ref() + .map(|client| client.pid as i64), ) .add("transactions", server.stats.total.transactions) .add("queries", server.stats.total.queries) diff --git a/pgdog/src/backend/pool/cluster.rs b/pgdog/src/backend/pool/cluster.rs index d8421212a..b80fb17a0 100644 --- a/pgdog/src/backend/pool/cluster.rs +++ b/pgdog/src/backend/pool/cluster.rs @@ -1097,7 +1097,7 @@ mod test { // Trigger schema_not_needed on each shard after a short delay so the // waiter wakes up via the per-shard schema_waiter notification. - let shards: Vec<_> = cluster.shards.iter().cloned().collect(); + let shards = cluster.shards.to_vec(); tokio::spawn(async move { tokio::time::sleep(Duration::from_millis(10)).await; for shard in &shards { diff --git a/pgdog/src/backend/pool/connection/multi_shard/test.rs b/pgdog/src/backend/pool/connection/multi_shard/test.rs index 98b4532ff..e9fcd248d 100644 --- a/pgdog/src/backend/pool/connection/multi_shard/test.rs +++ b/pgdog/src/backend/pool/connection/multi_shard/test.rs @@ -102,7 +102,7 @@ fn test_rd_before_dr() { let result = multi_shard.message(); let id = BackendKeyData::default(); assert_eq!( - result.map(|m| m.backend(id)), + result.map(|m| m.backend(id.clone())), Some(dr.message().unwrap().backend(id)) ); } @@ -236,10 +236,10 @@ fn test_omni_data_rows_only_from_first_server() { // Setup: send RowDescription from both shards let rd = RowDescription::new(&[Field::bigint("id")]); multi_shard - .forward(rd.message().unwrap().backend(backend1)) + .forward(rd.message().unwrap().backend(backend1.clone())) .unwrap(); let rd_result = multi_shard - .forward(rd.message().unwrap().backend(backend2)) + .forward(rd.message().unwrap().backend(backend2.clone())) .unwrap(); assert!(rd_result.is_some()); // RowDescription forwarded after all shards @@ -247,7 +247,7 @@ fn test_omni_data_rows_only_from_first_server() { let mut dr1 = DataRow::new(); dr1.add(100_i64); let result = multi_shard - .forward(dr1.message().unwrap().backend(backend1)) + .forward(dr1.message().unwrap().backend(backend1.clone())) .unwrap(); assert!(result.is_some()); // Should be forwarded diff --git a/pgdog/src/backend/pool/error.rs b/pgdog/src/backend/pool/error.rs index 27e32ba8b..dcdc56a55 100644 --- a/pgdog/src/backend/pool/error.rs +++ b/pgdog/src/backend/pool/error.rs @@ -1,8 +1,6 @@ //! Connection pool errors. use thiserror::Error; -use crate::net::BackendKeyData; - #[derive(Debug, Error, PartialEq, Clone, Copy)] pub enum Error { #[error("checkout timeout")] @@ -68,8 +66,8 @@ pub enum Error { #[error("pool is not healthy")] PoolUnhealthy, - #[error("checked in untracked connection: {0}")] - UntrackedConnCheckin(BackendKeyData), + #[error("checked in untracked connection: pid={0}")] + UntrackedConnCheckin(i32), #[error("mapping missing: {0}")] MappingMissing(usize), diff --git a/pgdog/src/backend/pool/inner.rs b/pgdog/src/backend/pool/inner.rs index 7e822f530..0f3d69a0a 100644 --- a/pgdog/src/backend/pool/inner.rs +++ b/pgdog/src/backend/pool/inner.rs @@ -239,8 +239,8 @@ impl Inner { pub(super) fn take(&mut self, request: &Request) -> Result>, Error> { if let Some(conn) = self.idle_connections.pop() { self.taken.take(&Mapping { - client: request.id, - server: *(conn.id()), + client: request.id.clone(), + server: conn.id().clone(), })?; Ok(Some(conn)) @@ -254,13 +254,13 @@ impl Inner { #[inline] pub(super) fn put(&mut self, mut conn: Box, now: Instant) -> Result<(), Error> { // Try to give it to a client that's been waiting, if any. - let id = *conn.id(); + let id = conn.id().clone(); while let Some(waiter) = self.waiting.pop_front() { if let Err(conn_ret) = waiter.tx.send(Ok(conn)) { conn = conn_ret.unwrap(); // SAFETY: We sent Ok(conn), we'll get back Ok(conn) if channel is closed. } else { self.taken.take(&Mapping { - server: id, + server: id.clone(), client: waiter.request.id, })?; self.stats.counts.server_assignment_count += 1; @@ -496,7 +496,7 @@ mod test { let mut inner = Inner::default(); let server = Box::new(Server::default()); - let server_id = *server.id(); + let server_id = server.id().clone(); inner .taken .take(&Mapping { @@ -523,7 +523,7 @@ mod test { }; let server = Box::new(Server::default()); - let server_id = *server.id(); + let server_id = server.id().clone(); inner .taken .take(&Mapping { @@ -548,7 +548,7 @@ mod test { }; let server = Box::new(Server::default()); - let server_id = *server.id(); + let server_id = server.id().clone(); inner .taken .take(&Mapping { @@ -574,7 +574,7 @@ mod test { }; let server = Box::new(Server::new_error()); - let server_id = *server.id(); + let server_id = server.id().clone(); // Simulate server being checked out inner @@ -714,7 +714,7 @@ mod test { // Add a connection let server = Box::new(Server::default()); - let server_id = *server.id(); + let server_id = server.id().clone(); inner .taken .take(&Mapping { @@ -763,7 +763,7 @@ mod test { inner.config.max_age = Duration::from_millis(60_000); let server = Box::new(Server::default()); - let server_id = *server.id(); + let server_id = server.id().clone(); inner .taken .take(&Mapping { @@ -795,8 +795,8 @@ mod test { inner .taken .take(&Mapping { - client: client_id, - server: server_id, + client: client_id.clone(), + server: server_id.clone(), }) .unwrap(); @@ -815,8 +815,8 @@ mod test { // Add mapping taken .take(&Mapping { - client: client_id, - server: server_id, + client: client_id.clone(), + server: server_id.clone(), }) .unwrap(); @@ -915,7 +915,7 @@ mod test { let req1 = Request::default(); let req2 = Request::default(); let req3 = Request::default(); - let target_id = req2.id; + let target_id = req2.id.clone(); inner.waiting.push_back(Waiter { request: req1, @@ -1125,9 +1125,9 @@ mod test { // Add two idle connections to the pool let server1 = Box::new(Server::default()); - let server1_id = *server1.id(); + let server1_id = server1.id().clone(); let server2 = Box::new(Server::default()); - let server2_id = *server2.id(); + let server2_id = server2.id().clone(); inner.idle_connections.push(server1); inner.idle_connections.push(server2); @@ -1177,7 +1177,7 @@ mod test { assert_eq!(inner.total(), 2); // Verify the specific servers are back in the idle pool - let idle_ids: Vec<_> = inner.idle_conns().iter().map(|s| *s.id()).collect(); + let idle_ids: Vec<_> = inner.idle_conns().iter().map(|s| s.id().clone()).collect(); assert!(idle_ids.contains(&server1_id)); assert!(idle_ids.contains(&server2_id)); } diff --git a/pgdog/src/backend/pool/lb/mod.rs b/pgdog/src/backend/pool/lb/mod.rs index 340f3258e..75a657f5c 100644 --- a/pgdog/src/backend/pool/lb/mod.rs +++ b/pgdog/src/backend/pool/lb/mod.rs @@ -310,7 +310,7 @@ impl LoadBalancer { match timeout(self.checkout_timeout, self.get_primary_internal(request)).await { Ok(Ok(guard)) => Ok(guard), Err(_) => Err(Error::CheckoutTimeout), - Ok(Err(err)) => Err(err.into()), + Ok(Err(err)) => Err(err), } } diff --git a/pgdog/src/backend/pool/mapping.rs b/pgdog/src/backend/pool/mapping.rs index 377c93325..c12480ca4 100644 --- a/pgdog/src/backend/pool/mapping.rs +++ b/pgdog/src/backend/pool/mapping.rs @@ -1,7 +1,7 @@ use crate::net::messages::BackendKeyData; /// Mapping between a client and a server. -#[derive(Debug, Copy, Clone, PartialEq, Default)] +#[derive(Debug, Clone, PartialEq, Default)] pub(super) struct Mapping { /// Client ID. pub(super) client: BackendKeyData, diff --git a/pgdog/src/backend/pool/request.rs b/pgdog/src/backend/pool/request.rs index 22267ddba..f1b16e5fb 100644 --- a/pgdog/src/backend/pool/request.rs +++ b/pgdog/src/backend/pool/request.rs @@ -3,7 +3,7 @@ use tokio::time::Instant; use crate::net::messages::BackendKeyData; /// Connection request. -#[derive(Clone, Debug, Copy)] +#[derive(Clone, Debug)] pub struct Request { pub id: BackendKeyData, pub created_at: Instant, diff --git a/pgdog/src/backend/pool/taken.rs b/pgdog/src/backend/pool/taken.rs index c660c5ea9..edfaba539 100644 --- a/pgdog/src/backend/pool/taken.rs +++ b/pgdog/src/backend/pool/taken.rs @@ -21,9 +21,11 @@ pub(super) struct Taken { impl Taken { #[inline] pub(super) fn take(&mut self, mapping: &Mapping) -> Result<(), Error> { - self.taken.insert(self.counter, *mapping); - self.server_client.insert(mapping.server, self.counter); - self.client_server.insert(mapping.client, mapping.server); + self.taken.insert(self.counter, mapping.clone()); + self.server_client + .insert(mapping.server.clone(), self.counter); + self.client_server + .insert(mapping.client.clone(), mapping.server.clone()); self.counter = self.counter.wrapping_add(1); Ok(()) } @@ -33,7 +35,7 @@ impl Taken { let counter = self .server_client .remove(server) - .ok_or(Error::UntrackedConnCheckin(*server))?; + .ok_or(Error::UntrackedConnCheckin(server.pid))?; let mapping = self .taken .remove(&counter) @@ -55,11 +57,11 @@ impl Taken { #[inline] pub(super) fn server(&self, client: &BackendKeyData) -> Option { - self.client_server.get(client).copied() + self.client_server.get(client).cloned() } pub(super) fn servers(&self) -> Vec { - self.client_server.values().copied().collect() + self.client_server.values().cloned().collect() } #[cfg(test)] diff --git a/pgdog/src/backend/pool/test/mod.rs b/pgdog/src/backend/pool/test/mod.rs index 8c2a76bb5..c03b53613 100644 --- a/pgdog/src/backend/pool/test/mod.rs +++ b/pgdog/src/backend/pool/test/mod.rs @@ -74,7 +74,7 @@ async fn test_pool_checkout() { let pool = pool(); let conn = pool.get(&Request::default()).await.unwrap(); - let id = *(conn.id()); + let id = conn.id().clone(); assert!(conn.done()); assert!(conn.done()); @@ -255,6 +255,7 @@ async fn test_benchmark_pool() { for _ in 0..workers { let pool = pool.clone(); + let request = request.clone(); let handle = tokio::spawn(async move { for _ in 0..counts { let conn = pool.get(&request).await.unwrap(); @@ -279,7 +280,7 @@ async fn test_incomplete_request_recovery() { for query in ["SELECT 1", "BEGIN"] { let mut conn = pool.get(&Request::default()).await.unwrap(); - let conn_id = *(conn.id()); + let conn_id = conn.id().clone(); conn.send(&vec![ProtocolMessage::from(Query::new(query))].into()) .await diff --git a/pgdog/src/backend/pool/waiting.rs b/pgdog/src/backend/pool/waiting.rs index 741aec70a..2f39deae9 100644 --- a/pgdog/src/backend/pool/waiting.rs +++ b/pgdog/src/backend/pool/waiting.rs @@ -24,7 +24,7 @@ impl Waiting { /// N.B. You must call and await `Waiting::wait`, otherwise you'll leak waiters. /// pub(super) fn new(pool: Pool, request: &Request) -> Result { - let request = *request; + let request = request.clone(); let (tx, rx) = channel(); let full = { @@ -37,7 +37,10 @@ impl Waiting { } else { guard.stats.counts.writes += 1; } - guard.waiting.push_back(Waiter { request, tx }); + guard.waiting.push_back(Waiter { + request: request.clone(), + tx, + }); guard.full() }; diff --git a/pgdog/src/backend/replication/logical/error.rs b/pgdog/src/backend/replication/logical/error.rs index 59a9a1995..d05c554aa 100644 --- a/pgdog/src/backend/replication/logical/error.rs +++ b/pgdog/src/backend/replication/logical/error.rs @@ -212,7 +212,7 @@ pub enum Error { "FULL identity {op} on {table} (oid {oid}): missing OLD pre-image; source replica identity changed mid-stream" )] FullIdentityMissingOld { - table: PublicationTable, + table: Box, oid: pgdog_postgres_types::Oid, op: &'static str, }, @@ -352,7 +352,7 @@ mod tests { }) .is_retryable()); assert!(!Error::FullIdentityMissingOld { - table: PublicationTable::default(), + table: Box::new(PublicationTable::default()), oid: pgdog_postgres_types::Oid::from(1234u32), op: "UPDATE", } diff --git a/pgdog/src/backend/replication/logical/orchestrator.rs b/pgdog/src/backend/replication/logical/orchestrator.rs index 0630bad35..98f6ef9ce 100644 --- a/pgdog/src/backend/replication/logical/orchestrator.rs +++ b/pgdog/src/backend/replication/logical/orchestrator.rs @@ -301,7 +301,7 @@ impl ReplicationWaiter { let lag = self.orchestrator.replication_lag().await; cutover_state(CutoverState::WaitingForReplication { lag }); - info!("[cutover] replication lag: {}", format_bytes(lag as u64)); + info!("[cutover] replication lag: {}", format_bytes(lag)); // Time to go. if lag <= traffic_stop { diff --git a/pgdog/src/backend/replication/logical/publisher/queries.rs b/pgdog/src/backend/replication/logical/publisher/queries.rs index f1b341bbf..e6807faba 100644 --- a/pgdog/src/backend/replication/logical/publisher/queries.rs +++ b/pgdog/src/backend/replication/logical/publisher/queries.rs @@ -197,6 +197,7 @@ impl From for PublicationTableColumn { /// unique constraint) or every indexed attribute has `attnotnull = true` (NULLs impossible). /// A plain nullable unique index allows two NULL-keyed rows to coexist during the copy–stream /// overlap window, leaving the destination with more rows than the source. +/// /// Requires PostgreSQL 15+ when an `indnullsnotdistinct` index is present; the column does /// not exist on older servers and the query will return an error rather than silently accept. /// diff --git a/pgdog/src/backend/replication/logical/publisher/table.rs b/pgdog/src/backend/replication/logical/publisher/table.rs index ec4dfe544..a8b6d8f70 100644 --- a/pgdog/src/backend/replication/logical/publisher/table.rs +++ b/pgdog/src/backend/replication/logical/publisher/table.rs @@ -129,7 +129,7 @@ where } /// `"col" IS NOT DISTINCT FROM $pos` predicates joined by ` AND `. - fn is_not_distinct_from_predicates(self) -> String { + fn not_distinct_from_predicates(self) -> String { self.inner .map(|(i, c)| { format!( @@ -399,7 +399,7 @@ impl Table { "(SELECT tableoid, ctid FROM \"{}\".\"{}\" WHERE {} LIMIT 1)", escape_identifier(self.table.destination_schema()), escape_identifier(self.table.destination_name()), - self.all_columns().is_not_distinct_from_predicates(), + self.all_columns().not_distinct_from_predicates(), ) } diff --git a/pgdog/src/backend/replication/logical/status.rs b/pgdog/src/backend/replication/logical/status.rs index f9560aee2..a06f70279 100644 --- a/pgdog/src/backend/replication/logical/status.rs +++ b/pgdog/src/backend/replication/logical/status.rs @@ -243,7 +243,7 @@ impl SchemaStatement { let stmt = match stmt { Statement::Index { table, sql, .. } => pgdog_stats::SchemaStatement { id, - user: user.into(), + user, shard, sql: sql.clone(), kind: StatementKind::Index, @@ -254,7 +254,7 @@ impl SchemaStatement { }, Statement::Table { table, sql } => pgdog_stats::SchemaStatement { id, - user: user.into(), + user, shard, sql: sql.clone(), kind: StatementKind::Table, @@ -265,7 +265,7 @@ impl SchemaStatement { }, Statement::Other { sql, .. } => pgdog_stats::SchemaStatement { id, - user: user.into(), + user, shard, sql: sql.clone(), kind: StatementKind::Statement, @@ -276,7 +276,7 @@ impl SchemaStatement { }, Statement::SequenceOwner { sql, .. } => pgdog_stats::SchemaStatement { id, - user: user.into(), + user, shard, sql: sql.to_string(), kind: StatementKind::Statement, @@ -287,7 +287,7 @@ impl SchemaStatement { }, Statement::SequenceSetMax { sql, .. } => pgdog_stats::SchemaStatement { id, - user: user.into(), + user, shard, sql: sql.clone(), kind: StatementKind::Statement, diff --git a/pgdog/src/backend/replication/logical/subscriber/stream.rs b/pgdog/src/backend/replication/logical/subscriber/stream.rs index b8f4dd1f4..6829962df 100644 --- a/pgdog/src/backend/replication/logical/subscriber/stream.rs +++ b/pgdog/src/backend/replication/logical/subscriber/stream.rs @@ -310,7 +310,7 @@ impl StreamSubscriber { } else { statements.insert.parse() }; - let ctx = StreamContext::new(&self.cluster, &insert.tuple_data, &parse)?; + let ctx = StreamContext::new(&self.cluster, &insert.tuple_data, parse)?; self.send(ctx.shard(), ctx.bind()).await?; } @@ -553,7 +553,7 @@ impl StreamSubscriber { UpdateIdentity::Old(old) => old, _ => { return Err(Error::FullIdentityMissingOld { - table: table.table, + table: Box::new(table.table), oid, op: "UPDATE", }); @@ -573,9 +573,9 @@ impl StreamSubscriber { // FULL identity guarantees old_full is fully materialised; 'u' columns in // update.new carry the same value as the corresponding column in old_full. // Routing from a raw 'u' column yields empty bytes → wrong shard. - let complete_new = update.new.fill_toasted_from(&old_full)?; + let complete_new = update.new.fill_toasted_from(old_full)?; let new_shard = self.shard_for(&complete_new, &update_parse)?; - let old_shard = self.shard_for(&old_full, &update_parse)?; + let old_shard = self.shard_for(old_full, &update_parse)?; if new_shard != old_shard { // Shard key changed: DELETE on old shard, INSERT on new shard. @@ -637,7 +637,7 @@ impl StreamSubscriber { let Some(old) = delete.old else { let table = self.get_table(oid)?; return Err(Error::FullIdentityMissingOld { - table: table.table.clone(), + table: Box::new(table.table.clone()), oid, op: "DELETE", }); diff --git a/pgdog/src/backend/server.rs b/pgdog/src/backend/server.rs index 306fcda7e..4e1d871d0 100644 --- a/pgdog/src/backend/server.rs +++ b/pgdog/src/backend/server.rs @@ -314,7 +314,11 @@ impl Server { // so they don't send BackendKeyData. // Generating a random one is fine, it just won't work when we try to // cancel a query with this secret. - let id = key_data.unwrap_or(BackendKeyData::new()); + let id = if let Some(key_data) = key_data { + key_data + } else { + BackendKeyData::new() + }; let params: Parameters = params.into(); info!( @@ -329,7 +333,7 @@ impl Server { let mut server = Server { addr: addr.clone(), stream: Some(stream), - id, + id: id.clone(), stats: Stats::connect(id, addr, ¶ms, &options, &config.config.memory), replication_mode: options.replication_mode(), params, @@ -360,7 +364,7 @@ impl Server { pub async fn cancel(addr: &Address, id: &BackendKeyData) -> Result<(), Error> { let mut stream = TcpStream::connect(addr.addr().await?).await?; stream - .write_all(&Startup::Cancel { id: *id }.to_bytes()?) + .write_all(&Startup::Cancel { id: id.clone() }.to_bytes()?) .await?; stream.flush().await?; @@ -464,11 +468,11 @@ impl Server { pub async fn read(&mut self) -> Result { let message = loop { if let Some(message) = self.prepared_statements.state_mut().get_simulated() { - return Ok(message.backend(self.id)); + return Ok(message.backend(self.id.clone())); } match self.stream_buffer.read(self.stream.as_mut().unwrap()).await { Ok(message) => { - let message = message.stream(self.streaming).backend(self.id); + let message = message.stream(self.streaming).backend(self.id.clone()); match self.prepared_statements.forward(&message) { Ok(forward) => { if forward { @@ -1211,7 +1215,7 @@ pub mod test { let addr = Address::default(); Self { stream: None, - id, + id: id.clone(), params: Parameters::default(), changed_params: Parameters::default(), client_params: Parameters::default(), diff --git a/pgdog/src/backend/stats.rs b/pgdog/src/backend/stats.rs index ceb7018fe..d0ec04c49 100644 --- a/pgdog/src/backend/stats.rs +++ b/pgdog/src/backend/stats.rs @@ -26,7 +26,7 @@ pub fn stats() -> HashMap { STATS .read() .iter() - .map(|(k, v)| (*k, v.lock().clone())) + .map(|(k, v)| (k.clone(), v.lock().clone())) .collect() } @@ -43,7 +43,7 @@ pub fn idle_in_transaction(pool: &Pool) -> usize { } /// Core server statistics (shared between local and global). -#[derive(Clone, Debug, Copy)] +#[derive(Clone, Debug)] pub struct ServerStats { pub inner: pgdog_stats::server::Stats, pub id: BackendKeyData, @@ -122,10 +122,10 @@ impl Stats { options: &ServerOptions, config: &Memory, ) -> Self { - let local = ServerStats::new(id, options, config); + let local = ServerStats::new(id.clone(), options, config); let server = ConnectedServer { - stats: local, + stats: local.clone(), addr: addr.clone(), application_name: params.get_default("application_name", "PgDog").to_owned(), client: None, @@ -140,7 +140,7 @@ impl Stats { /// Sync local stats to shared (called on I/O operations). #[inline] fn sync_to_shared(&self) { - self.shared.lock().stats = self.local; + self.shared.lock().stats = self.local.clone(); } fn transaction_state(&mut self, now: Instant, state: State) { @@ -157,10 +157,10 @@ impl Stats { } pub fn link_client(&mut self, client_name: &str, server_name: &str, id: &BackendKeyData) { - self.local.client_id = Some(*id); + self.local.client_id = Some(id.clone()); if client_name != server_name { let mut guard = self.shared.lock(); - guard.stats.client_id = self.local.client_id; + guard.stats.client_id = self.local.client_id.clone(); guard.application_name.clear(); guard.application_name.push_str(client_name); } diff --git a/pgdog/src/frontend/client/mod.rs b/pgdog/src/frontend/client/mod.rs index 92a8e3ab5..4aa035d10 100644 --- a/pgdog/src/frontend/client/mod.rs +++ b/pgdog/src/frontend/client/mod.rs @@ -312,7 +312,7 @@ impl Client { // Get connection parameters. These will be most likely cached, // unless the pool was just created. - let server_params = match conn.parameters(&Request::unrouted(id)).await { + let server_params = match conn.parameters(&Request::unrouted(id.clone())).await { Ok(params) => params, Err(err) => { if err.no_server() { @@ -392,7 +392,7 @@ impl Client { Self { stream, addr: SocketAddr::from(([127, 0, 0, 1], 1234)), - id, + id: id.clone(), comms: ClientComms::new(&id), streaming: false, prepared_statements, @@ -409,7 +409,7 @@ impl Client { /// Get client's identifier. pub fn id(&self) -> BackendKeyData { - self.id + self.id.clone() } /// Run the client and log disconnect. diff --git a/pgdog/src/frontend/client/query_engine/connect.rs b/pgdog/src/frontend/client/query_engine/connect.rs index 57bcc6026..1fce521e9 100644 --- a/pgdog/src/frontend/client/query_engine/connect.rs +++ b/pgdog/src/frontend/client/query_engine/connect.rs @@ -30,7 +30,7 @@ impl QueryEngine { let connect_route = connect_route.unwrap_or(context.client_request.route()); - let request = Request::new(*context.id, connect_route.is_read()); + let request = Request::new(context.id.clone(), connect_route.is_read()); self.stats.waiting(request.created_at); self.comms.update_stats(self.stats); diff --git a/pgdog/src/frontend/client/query_engine/two_pc/test.rs b/pgdog/src/frontend/client/query_engine/two_pc/test.rs index dcf52346f..30be3cd6f 100644 --- a/pgdog/src/frontend/client/query_engine/two_pc/test.rs +++ b/pgdog/src/frontend/client/query_engine/two_pc/test.rs @@ -47,7 +47,7 @@ async fn test_cleanup_transaction_phase_one() { .await .unwrap(); // We have two-pc transactions. - assert!(two_pc.iter().find(|p| p.code() == 'D').is_some()); + assert!(two_pc.iter().any(|p| p.code() == 'D')); // Simulate client disconnecting abruptly. conn.disconnect(); @@ -71,7 +71,7 @@ async fn test_cleanup_transaction_phase_one() { .await .unwrap(); // No transactions. - assert!(two_pc.iter().find(|p| p.code() == 'D').is_none()); + assert!(!two_pc.iter().any(|p| p.code() == 'D')); // Table wasn't committed. let table = conn .execute("SELECT * FROM test_cleanup_transaction_phase_one") @@ -117,7 +117,7 @@ async fn test_cleanup_transaction_phase_two() { .await .unwrap(); // We have two-pc transactions. - assert!(txns.iter().find(|p| p.code() == 'D').is_some()); + assert!(txns.iter().any(|p| p.code() == 'D')); let guard_2 = two_pc.phase_two(&cluster.identifier()).await.unwrap(); let info = Manager::get().transaction(&transaction).unwrap(); @@ -146,7 +146,7 @@ async fn test_cleanup_transaction_phase_two() { .await .unwrap(); // No transactions. - assert!(two_pc.iter().find(|p| p.code() == 'D').is_none()); + assert!(!two_pc.iter().any(|p| p.code() == 'D')); // Table was committed. let _table = conn .execute("SELECT * FROM test_cleanup_transaction_phase_two") diff --git a/pgdog/src/frontend/comms.rs b/pgdog/src/frontend/comms.rs index 2887e2d16..14b029dd3 100644 --- a/pgdog/src/frontend/comms.rs +++ b/pgdog/src/frontend/comms.rs @@ -91,7 +91,7 @@ impl Comms { self.global .clients .lock() - .insert(*id, ConnectedClient::new(id, addr, params)); + .insert(id.clone(), ConnectedClient::new(id, addr, params)); } /// Update client parameters. @@ -158,7 +158,7 @@ impl ClientComms { pub fn new(id: &BackendKeyData) -> Self { Self { - id: *id, + id: id.clone(), comms: comms(), } } diff --git a/pgdog/src/frontend/connected_client.rs b/pgdog/src/frontend/connected_client.rs index dd7318e32..56f8d784f 100644 --- a/pgdog/src/frontend/connected_client.rs +++ b/pgdog/src/frontend/connected_client.rs @@ -24,7 +24,7 @@ impl ConnectedClient { /// New connected client. pub fn new(id: &BackendKeyData, addr: SocketAddr, params: &Parameters) -> Self { Self { - id: *id, + id: id.clone(), stats: Stats::new(), addr, connected_at: Local::now(), diff --git a/pgdog/src/frontend/router/parser/cache/ast.rs b/pgdog/src/frontend/router/parser/cache/ast.rs index 3af1c3768..1458b8fde 100644 --- a/pgdog/src/frontend/router/parser/cache/ast.rs +++ b/pgdog/src/frontend/router/parser/cache/ast.rs @@ -201,13 +201,11 @@ impl Ast { } } - NodeRef::DropStmt(stmt) => { - if stmt.remove_type() == ObjectType::ObjectTable { - for object in &stmt.objects { - if let Some(NodeEnum::List(ref list)) = object.node { - if let Ok(table) = Table::try_from(list) { - tables.insert(table); - } + NodeRef::DropStmt(stmt) if stmt.remove_type() == ObjectType::ObjectTable => { + for object in &stmt.objects { + if let Some(NodeEnum::List(ref list)) = object.node { + if let Ok(table) = Table::try_from(list) { + tables.insert(table); } } } diff --git a/pgdog/src/frontend/router/parser/cache/test.rs b/pgdog/src/frontend/router/parser/cache/test.rs index 68abd33cb..2810e0d3e 100644 --- a/pgdog/src/frontend/router/parser/cache/test.rs +++ b/pgdog/src/frontend/router/parser/cache/test.rs @@ -278,7 +278,7 @@ fn test_cache_key_strips_leading_comment() { // The LRU map key must also be the stripped query. let queries = Cache::queries(); assert!( - queries.contains_key(&"SELECT 1 FROM cache_key_leading".to_string()), + queries.contains_key(&String::from("SELECT 1 FROM cache_key_leading")), "cache map key must be the comment-stripped query" ); } diff --git a/pgdog/src/frontend/router/parser/comment/strip.rs b/pgdog/src/frontend/router/parser/comment/strip.rs index fd562b4b6..6a71b15af 100644 --- a/pgdog/src/frontend/router/parser/comment/strip.rs +++ b/pgdog/src/frontend/router/parser/comment/strip.rs @@ -63,7 +63,7 @@ pub(super) fn trailing_block_comment(q: &str) -> Option<(&str, &str)> { }; // If the body contains `*/`, the trailing `*/` pairs with an earlier // `/*` we can't see from here — stop. - if memmem::find(inner[s + start.len()..].as_bytes(), end.as_bytes()).is_some() { + if memmem::find(&inner.as_bytes()[s + start.len()..], end.as_bytes()).is_some() { break; } first_start = Some(s); diff --git a/pgdog/src/frontend/router/parser/query/test/test_select.rs b/pgdog/src/frontend/router/parser/query/test/test_select.rs index 084df0d7b..647952731 100644 --- a/pgdog/src/frontend/router/parser/query/test/test_select.rs +++ b/pgdog/src/frontend/router/parser/query/test/test_select.rs @@ -89,7 +89,7 @@ fn test_limit_offset_with_bad_params() { Sync.into(), ]); - let err = command.err().expect("limit should fail"); + let err = command.expect_err("limit should fail"); assert_eq!( err.to_string(), "expected parameter $1 to be an integer, got 'apples' instead" @@ -106,7 +106,7 @@ fn test_limit_offset_with_bad_params() { Sync.into(), ]); - let err = command.err().expect("offset should fail"); + let err = command.expect_err("offset should fail"); assert_eq!( err.to_string(), "expected parameter $2 to be an integer, got 'oranges' instead" diff --git a/pgdog/src/frontend/router/parser/query/test/test_set.rs b/pgdog/src/frontend/router/parser/query/test/test_set.rs index acbd521b4..7fd47168d 100644 --- a/pgdog/src/frontend/router/parser/query/test/test_set.rs +++ b/pgdog/src/frontend/router/parser/query/test/test_set.rs @@ -167,14 +167,14 @@ fn test_reset() { #[test] fn test_set_single_primary() { let mut test = QueryParserTest::new_single_primary(&config()); - let command = test.execute(vec![Query::new("SET statement_timeout TO 1").into()].into()); + let command = test.execute(vec![Query::new("SET statement_timeout TO 1").into()]); assert!(matches!(command, Command::Set { .. })); let mut config = (*config()).clone(); config.config.general.query_parser = pgdog_config::QueryParserLevel::Off; let mut test = QueryParserTest::new_single_primary(&config); - let command = test.execute(vec![Query::new("SET statement_timeout TO 1").into()].into()); + let command = test.execute(vec![Query::new("SET statement_timeout TO 1").into()]); match command { Command::Query(query) => assert_eq!( query.shard_with_priority().source(), @@ -187,7 +187,7 @@ fn test_set_single_primary() { #[test] fn test_single_shard_set() { let mut test = QueryParserTest::new_single_shard(&config()); - let command = test.execute(vec![Query::new("SET lock_timeout TO '1s'").into()].into()); + let command = test.execute(vec![Query::new("SET lock_timeout TO '1s'").into()]); match command { Command::Set { route, .. } => assert!(!route.is_cross_shard()), diff --git a/pgdog/src/frontend/router/parser/query/transaction.rs b/pgdog/src/frontend/router/parser/query/transaction.rs index 3639174b9..7c7f8197c 100644 --- a/pgdog/src/frontend/router/parser/query/transaction.rs +++ b/pgdog/src/frontend/router/parser/query/transaction.rs @@ -42,10 +42,10 @@ impl QueryParser { TransactionStmtKind::TransStmtRollbackTo => rollback_savepoint = true, TransactionStmtKind::TransStmtPrepare | TransactionStmtKind::TransStmtCommitPrepared - | TransactionStmtKind::TransStmtRollbackPrepared => { - if context.router_context.two_pc { - return Err(Error::NoTwoPc); - } + | TransactionStmtKind::TransStmtRollbackPrepared + if context.router_context.two_pc => + { + return Err(Error::NoTwoPc); } _ => (), } diff --git a/pgdog/src/frontend/router/parser/rewrite/statement/aggregate/mod.rs b/pgdog/src/frontend/router/parser/rewrite/statement/aggregate/mod.rs index 0dca2c6ee..c3c73b644 100644 --- a/pgdog/src/frontend/router/parser/rewrite/statement/aggregate/mod.rs +++ b/pgdog/src/frontend/router/parser/rewrite/statement/aggregate/mod.rs @@ -27,7 +27,7 @@ impl StatementRewrite<'_> { return Ok(()); }; - let aggregate = Aggregate::parse(&select); + let aggregate = Aggregate::parse(select); if aggregate.is_empty() { return Ok(()); } diff --git a/pgdog/src/frontend/router/parser/rewrite/statement/insert.rs b/pgdog/src/frontend/router/parser/rewrite/statement/insert.rs index 803ef10c6..ab16949c6 100644 --- a/pgdog/src/frontend/router/parser/rewrite/statement/insert.rs +++ b/pgdog/src/frontend/router/parser/rewrite/statement/insert.rs @@ -267,10 +267,8 @@ impl StatementRewrite<'_> { fn collect_params(node: &Node, params: &mut Vec) { if let Some(node_enum) = &node.node { match node_enum { - NodeEnum::ParamRef(param) => { - if param.number > 0 { - params.push((param.number - 1) as u16); - } + NodeEnum::ParamRef(param) if param.number > 0 => { + params.push((param.number - 1) as u16); } NodeEnum::List(list) => { for item in &list.items { @@ -291,12 +289,10 @@ impl StatementRewrite<'_> { fn renumber_params(node: &mut Node, params: &[u16]) { if let Some(node_enum) = &mut node.node { match node_enum { - NodeEnum::ParamRef(param) => { - if param.number > 0 { - let old_pos = (param.number - 1) as u16; - if let Some(new_pos) = params.iter().position(|&p| p == old_pos) { - param.number = (new_pos + 1) as i32; - } + NodeEnum::ParamRef(param) if param.number > 0 => { + let old_pos = (param.number - 1) as u16; + if let Some(new_pos) = params.iter().position(|&p| p == old_pos) { + param.number = (new_pos + 1) as i32; } } NodeEnum::List(list) => { diff --git a/pgdog/src/frontend/router/parser/rewrite/statement/update.rs b/pgdog/src/frontend/router/parser/rewrite/statement/update.rs index 96f5ad441..0a03a25ae 100644 --- a/pgdog/src/frontend/router/parser/rewrite/statement/update.rs +++ b/pgdog/src/frontend/router/parser/rewrite/statement/update.rs @@ -403,7 +403,7 @@ fn rewrite_params(parse_result: &mut ParseResult) -> Result, Error> { })?; let mut params: Vec<(i32, i32)> = params.into_iter().collect(); - params.sort_by(|a, b| a.1.cmp(&b.1)); + params.sort_by_key(|a| a.1); Ok(params .into_iter() diff --git a/pgdog/src/frontend/router/parser/where_clause.rs b/pgdog/src/frontend/router/parser/where_clause.rs index 970ce3a8e..be84f007a 100644 --- a/pgdog/src/frontend/router/parser/where_clause.rs +++ b/pgdog/src/frontend/router/parser/where_clause.rs @@ -204,9 +204,9 @@ impl<'a> WhereClause<'a> { let mut keys = vec![]; match node.node { - Some(NodeEnum::NullTest(ref null_test)) => { + Some(NodeEnum::NullTest(ref null_test)) // Only check for IS NULL, IS NOT NULL definitely doesn't help. - if NullTestType::try_from(null_test.nulltesttype) == Ok(NullTestType::IsNull) { + if NullTestType::try_from(null_test.nulltesttype) == Ok(NullTestType::IsNull) => { let left = null_test .arg .as_ref() @@ -216,7 +216,6 @@ impl<'a> WhereClause<'a> { keys.push(Output::NullCheck(c)); } } - } Some(NodeEnum::BoolExpr(ref expr)) => { // Only AND expressions can really be asserted. diff --git a/pgdog/src/frontend/router/sharding/range.rs b/pgdog/src/frontend/router/sharding/range.rs index db419232a..0211709b3 100644 --- a/pgdog/src/frontend/router/sharding/range.rs +++ b/pgdog/src/frontend/router/sharding/range.rs @@ -37,15 +37,11 @@ impl<'a> Ranges<'a> { let mut matches = 0; for value in &bound { match value { - Some(FlexibleType::String(s)) => { - if range.varchar(s) { - matches += 1; - } + Some(FlexibleType::String(s)) if range.varchar(s) => { + matches += 1; } - Some(FlexibleType::Integer(i)) => { - if range.integer(i) { - matches += 1; - } + Some(FlexibleType::Integer(i)) if range.integer(i) => { + matches += 1; } _ => (), } diff --git a/pgdog/src/net/messages/backend_key.rs b/pgdog/src/net/messages/backend_key.rs index 9e9e4bc70..2784716e7 100644 --- a/pgdog/src/net/messages/backend_key.rs +++ b/pgdog/src/net/messages/backend_key.rs @@ -22,10 +22,17 @@ fn next_counter() -> i32 { } /// Variable-length cancel secret. -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] -pub struct SecretKey { - len: u16, - bytes: [u8; MAX_SECRET_LEN], +/// +/// The legacy 3.0 secret is a 4-byte integer stored inline, while the 3.2 +/// protocol allows a variable-length secret kept on the heap. Keeping the +/// extended secret in a `Vec` rather than a fixed buffer keeps this type small +/// (the legacy case, which dominates, never allocates). +#[derive(Clone, Debug, Hash, PartialEq, Eq)] +pub enum SecretKey { + /// 3.0-compatible 4-byte secret. + Legacy([u8; LEGACY_SECRET_LEN]), + /// 3.2 variable-length secret. + Extended(Vec), } impl Default for SecretKey { @@ -37,12 +44,7 @@ impl Default for SecretKey { impl SecretKey { /// Create a 3.0-compatible secret key from a 4-byte integer. pub fn legacy(secret: i32) -> Self { - let mut bytes = [0; MAX_SECRET_LEN]; - bytes[..LEGACY_SECRET_LEN].copy_from_slice(&secret.to_be_bytes()); - Self { - len: LEGACY_SECRET_LEN as u16, - bytes, - } + Self::Legacy(secret.to_be_bytes()) } /// Create a random secret key of the requested length. @@ -52,11 +54,14 @@ impl SecretKey { "cancel secret must be between 1 and {MAX_SECRET_LEN} bytes" ); - let mut bytes = [0; MAX_SECRET_LEN]; - rand::rng().fill(&mut bytes[..len]); - Self { - len: len as u16, - bytes, + if len == LEGACY_SECRET_LEN { + let mut bytes = [0; LEGACY_SECRET_LEN]; + rand::rng().fill(&mut bytes[..]); + Self::Legacy(bytes) + } else { + let mut bytes = vec![0; len]; + rand::rng().fill(&mut bytes[..]); + Self::Extended(bytes) } } @@ -66,41 +71,45 @@ impl SecretKey { return Err(crate::net::Error::UnexpectedPayload); } - let mut bytes = [0; MAX_SECRET_LEN]; - bytes[..secret.len()].copy_from_slice(secret); - Ok(Self { - len: secret.len() as u16, - bytes, + Ok(if secret.len() == LEGACY_SECRET_LEN { + let mut bytes = [0; LEGACY_SECRET_LEN]; + bytes.copy_from_slice(secret); + Self::Legacy(bytes) + } else { + Self::Extended(secret.to_vec()) }) } /// Secret bytes as they appear on the wire. pub fn as_slice(&self) -> &[u8] { - &self.bytes[..self.len()] + match self { + Self::Legacy(bytes) => bytes, + Self::Extended(bytes) => bytes, + } } /// Secret length in bytes. pub fn len(&self) -> usize { - self.len as usize + self.as_slice().len() } } impl Display for SecretKey { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if self.len() == LEGACY_SECRET_LEN { - let legacy = i32::from_be_bytes(self.as_slice().try_into().expect("4-byte secret")); - write!(f, "{legacy}") - } else { - for byte in self.as_slice() { - write!(f, "{byte:02x}")?; + match self { + Self::Legacy(bytes) => write!(f, "{}", i32::from_be_bytes(*bytes)), + Self::Extended(bytes) => { + for byte in bytes { + write!(f, "{byte:02x}")?; + } + Ok(()) } - Ok(()) } } } /// BackendKeyData (B) -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Default)] +#[derive(Clone, Debug, Hash, PartialEq, Eq, Default)] pub struct BackendKeyData { /// Process ID. pub pid: i32, diff --git a/pgdog/src/net/messages/mod.rs b/pgdog/src/net/messages/mod.rs index 1f726bca9..8d4a103a4 100644 --- a/pgdog/src/net/messages/mod.rs +++ b/pgdog/src/net/messages/mod.rs @@ -107,7 +107,7 @@ pub trait Protocol: ToBytes + FromBytes + std::fmt::Debug { } } -#[derive(Clone, PartialEq, Default, Copy, Debug)] +#[derive(Clone, PartialEq, Default, Debug)] pub enum Source { Backend(BackendKeyData), #[default] @@ -117,7 +117,7 @@ pub enum Source { impl Source { pub fn backend_id(&self) -> Option { if let Self::Backend(id) = self { - Some(*id) + Some(id.clone()) } else { None } @@ -255,7 +255,7 @@ impl Message { /// Where is this message coming from? pub fn source(&self) -> Source { - self.source + self.source.clone() } pub fn in_transaction(&self) -> bool { diff --git a/pgdog/src/util.rs b/pgdog/src/util.rs index 51d5d0ffe..bc208de4a 100644 --- a/pgdog/src/util.rs +++ b/pgdog/src/util.rs @@ -232,12 +232,12 @@ pub fn raise_nofile_limit() -> u64 { "failed to raise NOFILE soft limit from {} to {}", prev, rlim.rlim_max ); - return prev as u64; + return prev; } } } - rlim.rlim_cur as u64 + rlim.rlim_cur } #[cfg(not(unix))]