Skip to content

Commit c770101

Browse files
Merge pull request #231 from theseus-rs/add-unix-socket-support
feat: add unix socket support
2 parents 26612ba + b9e51bf commit c770101

32 files changed

+1206
-72
lines changed

Cargo.lock

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,14 @@ In either case, PostgreSQL will run in a separate process space.
2323

2424
- installing and running PostgreSQL
2525
- running PostgreSQL on ephemeral ports
26+
- Unix socket support
2627
- async and blocking API
2728
- bundling the PostgreSQL archive in an executable
2829
- semantic version resolution
29-
- support for custom PostgreSQL archives / binaries
3030
- ability to configure PostgreSQL startup options
31+
- settings builder for fluent configuration
3132
- URL based configuration
32-
- choice of native-tls vs rustls
33+
- choice of native-tls or rustls
3334
- support for installing PostgreSQL extensions
3435

3536
## Getting Started

examples/unix_socket/Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
edition.workspace = true
3+
name = "unix_socket"
4+
publish = false
5+
license.workspace = true
6+
version.workspace = true
7+
8+
[dependencies]
9+
postgresql_embedded = { path = "../../postgresql_embedded" }
10+
tempfile = { workspace = true }
11+
tokio = { workspace = true, features = ["full"] }

examples/unix_socket/src/main.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use postgresql_embedded::{PostgreSQL, Result, SettingsBuilder};
2+
3+
#[cfg(unix)]
4+
#[tokio::main]
5+
async fn main() -> Result<()> {
6+
let socket_dir = tempfile::tempdir().expect("failed to create temp dir for socket");
7+
8+
let settings = SettingsBuilder::new()
9+
.socket_dir(socket_dir.path().to_path_buf())
10+
.build();
11+
12+
let mut postgresql = PostgreSQL::new(settings);
13+
postgresql.setup().await?;
14+
postgresql.start().await?;
15+
16+
let port = postgresql.settings().port;
17+
let socket_file = socket_dir.path().join(format!(".s.PGSQL.{port}"));
18+
println!("PostgreSQL is listening on Unix socket: {socket_file:?}");
19+
20+
let database_name = "test";
21+
postgresql.create_database(database_name).await?;
22+
println!("Created database '{database_name}'");
23+
24+
let exists = postgresql.database_exists(database_name).await?;
25+
println!("Database '{database_name}' exists: {exists}");
26+
27+
postgresql.drop_database(database_name).await?;
28+
println!("Dropped database '{database_name}'");
29+
30+
postgresql.stop().await?;
31+
println!("PostgreSQL stopped");
32+
33+
Ok(())
34+
}
35+
36+
#[cfg(not(unix))]
37+
fn main() {
38+
eprintln!("Unix socket support is only available on Unix platforms");
39+
}
40+
41+
#[cfg(test)]
42+
#[cfg(unix)]
43+
mod test {
44+
use super::*;
45+
46+
#[test]
47+
fn test_unix_socket_main() -> Result<()> {
48+
main()
49+
}
50+
}

postgresql_archive/src/hasher/registry.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::hasher::md5;
88
use crate::hasher::sha1;
99
#[cfg(feature = "sha2")]
1010
use crate::hasher::sha2_256;
11-
#[cfg(feature = "sha2")]
11+
#[cfg(all(feature = "sha2", feature = "maven"))]
1212
use crate::hasher::sha2_512;
1313
#[cfg(feature = "maven")]
1414
use crate::repository::maven;

postgresql_commands/src/clusterdb.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,16 @@ impl ClusterDbBuilder {
3535

3636
/// Create a new [`ClusterDbBuilder`] from [Settings]
3737
pub fn from(settings: &dyn Settings) -> Self {
38-
Self::new()
38+
let mut builder = Self::new()
3939
.program_dir(settings.get_binary_dir())
4040
.host(settings.get_host())
4141
.port(settings.get_port())
4242
.username(settings.get_username())
43-
.pg_password(settings.get_password())
43+
.pg_password(settings.get_password());
44+
if let Some(socket_dir) = settings.get_socket_dir() {
45+
builder = builder.host(socket_dir.to_string_lossy().to_string());
46+
}
47+
builder
4448
}
4549

4650
/// Location of the program binary
@@ -259,6 +263,7 @@ impl CommandBuilder for ClusterDbBuilder {
259263
mod tests {
260264
use super::*;
261265
use crate::TestSettings;
266+
use crate::TestSocketSettings;
262267
use crate::traits::CommandToString;
263268
use test_log::test;
264269

@@ -319,4 +324,20 @@ mod tests {
319324
command.to_command_string()
320325
);
321326
}
327+
328+
#[test]
329+
fn test_builder_from_socket() {
330+
let command = ClusterDbBuilder::from(&TestSocketSettings).build();
331+
#[cfg(not(target_os = "windows"))]
332+
let command_prefix = r#"PGPASSWORD="password" "./clusterdb" "#;
333+
#[cfg(target_os = "windows")]
334+
let command_prefix = r#"".\\clusterdb" "#;
335+
336+
assert_eq!(
337+
format!(
338+
r#"{command_prefix}"--host" "/tmp/pg_socket" "--port" "5432" "--username" "postgres""#
339+
),
340+
command.to_command_string()
341+
);
342+
}
322343
}

postgresql_commands/src/createdb.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,16 @@ impl CreateDbBuilder {
4343

4444
/// Create a new [`CreateDbBuilder`] from [Settings]
4545
pub fn from(settings: &dyn Settings) -> Self {
46-
Self::new()
46+
let mut builder = Self::new()
4747
.program_dir(settings.get_binary_dir())
4848
.host(settings.get_host())
4949
.port(settings.get_port())
5050
.username(settings.get_username())
51-
.pg_password(settings.get_password())
51+
.pg_password(settings.get_password());
52+
if let Some(socket_dir) = settings.get_socket_dir() {
53+
builder = builder.host(socket_dir.to_string_lossy().to_string());
54+
}
55+
builder
5256
}
5357

5458
/// Location of the program binary
@@ -364,6 +368,7 @@ impl CommandBuilder for CreateDbBuilder {
364368
mod tests {
365369
use super::*;
366370
use crate::TestSettings;
371+
use crate::TestSocketSettings;
367372
use crate::traits::CommandToString;
368373
use test_log::test;
369374

@@ -432,4 +437,20 @@ mod tests {
432437
command.to_command_string()
433438
);
434439
}
440+
441+
#[test]
442+
fn test_builder_from_socket() {
443+
let command = CreateDbBuilder::from(&TestSocketSettings).build();
444+
#[cfg(not(target_os = "windows"))]
445+
let command_prefix = r#"PGPASSWORD="password" "./createdb" "#;
446+
#[cfg(target_os = "windows")]
447+
let command_prefix = r#"".\\createdb" "#;
448+
449+
assert_eq!(
450+
format!(
451+
r#"{command_prefix}"--host" "/tmp/pg_socket" "--port" "5432" "--username" "postgres""#
452+
),
453+
command.to_command_string()
454+
);
455+
}
435456
}

postgresql_commands/src/createuser.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,16 @@ impl CreateUserBuilder {
5050

5151
/// Create a new [`CreateUserBuilder`] from [Settings]
5252
pub fn from(settings: &dyn Settings) -> Self {
53-
Self::new()
53+
let mut builder = Self::new()
5454
.program_dir(settings.get_binary_dir())
5555
.host(settings.get_host())
5656
.port(settings.get_port())
5757
.username(settings.get_username())
58-
.pg_password(settings.get_password())
58+
.pg_password(settings.get_password());
59+
if let Some(socket_dir) = settings.get_socket_dir() {
60+
builder = builder.host(socket_dir.to_string_lossy().to_string());
61+
}
62+
builder
5963
}
6064

6165
/// Location of the program binary
@@ -441,6 +445,7 @@ impl CommandBuilder for CreateUserBuilder {
441445
mod tests {
442446
use super::*;
443447
use crate::TestSettings;
448+
use crate::TestSocketSettings;
444449
use crate::traits::CommandToString;
445450
use test_log::test;
446451

@@ -516,4 +521,20 @@ mod tests {
516521
command.to_command_string()
517522
);
518523
}
524+
525+
#[test]
526+
fn test_builder_from_socket() {
527+
let command = CreateUserBuilder::from(&TestSocketSettings).build();
528+
#[cfg(not(target_os = "windows"))]
529+
let command_prefix = r#"PGPASSWORD="password" "./createuser" "#;
530+
#[cfg(target_os = "windows")]
531+
let command_prefix = r#"".\\createuser" "#;
532+
533+
assert_eq!(
534+
format!(
535+
r#"{command_prefix}"--host" "/tmp/pg_socket" "--port" "5432" "--username" "postgres""#
536+
),
537+
command.to_command_string()
538+
);
539+
}
519540
}

postgresql_commands/src/dropdb.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,16 @@ impl DropDbBuilder {
3333

3434
/// Create a new [`DropDbBuilder`] from [Settings]
3535
pub fn from(settings: &dyn Settings) -> Self {
36-
Self::new()
36+
let mut builder = Self::new()
3737
.program_dir(settings.get_binary_dir())
3838
.host(settings.get_host())
3939
.port(settings.get_port())
4040
.username(settings.get_username())
41-
.pg_password(settings.get_password())
41+
.pg_password(settings.get_password());
42+
if let Some(socket_dir) = settings.get_socket_dir() {
43+
builder = builder.host(socket_dir.to_string_lossy().to_string());
44+
}
45+
builder
4246
}
4347

4448
/// Location of the program binary
@@ -244,6 +248,7 @@ impl CommandBuilder for DropDbBuilder {
244248
mod tests {
245249
use super::*;
246250
use crate::TestSettings;
251+
use crate::TestSocketSettings;
247252
use crate::traits::CommandToString;
248253
use test_log::test;
249254

@@ -303,4 +308,20 @@ mod tests {
303308
command.to_command_string()
304309
);
305310
}
311+
312+
#[test]
313+
fn test_builder_from_socket() {
314+
let command = DropDbBuilder::from(&TestSocketSettings).build();
315+
#[cfg(not(target_os = "windows"))]
316+
let command_prefix = r#"PGPASSWORD="password" "./dropdb" "#;
317+
#[cfg(target_os = "windows")]
318+
let command_prefix = r#"".\\dropdb" "#;
319+
320+
assert_eq!(
321+
format!(
322+
r#"{command_prefix}"--host" "/tmp/pg_socket" "--port" "5432" "--username" "postgres""#
323+
),
324+
command.to_command_string()
325+
);
326+
}
306327
}

postgresql_commands/src/dropuser.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,16 @@ impl DropUserBuilder {
3131

3232
/// Create a new [`DropUserBuilder`] from [Settings]
3333
pub fn from(settings: &dyn Settings) -> Self {
34-
Self::new()
34+
let mut builder = Self::new()
3535
.program_dir(settings.get_binary_dir())
3636
.host(settings.get_host())
3737
.port(settings.get_port())
3838
.username(settings.get_username())
39-
.pg_password(settings.get_password())
39+
.pg_password(settings.get_password());
40+
if let Some(socket_dir) = settings.get_socket_dir() {
41+
builder = builder.host(socket_dir.to_string_lossy().to_string());
42+
}
43+
builder
4044
}
4145

4246
/// Location of the program binary
@@ -208,6 +212,7 @@ impl CommandBuilder for DropUserBuilder {
208212
mod tests {
209213
use super::*;
210214
use crate::TestSettings;
215+
use crate::TestSocketSettings;
211216
use crate::traits::CommandToString;
212217
use test_log::test;
213218

@@ -264,4 +269,20 @@ mod tests {
264269
command.to_command_string()
265270
);
266271
}
272+
273+
#[test]
274+
fn test_builder_from_socket() {
275+
let command = DropUserBuilder::from(&TestSocketSettings).build();
276+
#[cfg(not(target_os = "windows"))]
277+
let command_prefix = r#"PGPASSWORD="password" "./dropuser" "#;
278+
#[cfg(target_os = "windows")]
279+
let command_prefix = r#"".\\dropuser" "#;
280+
281+
assert_eq!(
282+
format!(
283+
r#"{command_prefix}"--host" "/tmp/pg_socket" "--port" "5432" "--username" "postgres""#
284+
),
285+
command.to_command_string()
286+
);
287+
}
267288
}

0 commit comments

Comments
 (0)