PostgreSQL extension for generating Xata-style xata_id unique identifiers (rec_<20_chars>) using Rust and pgrx.

Initial Commit

+134
+3
.cargo/config.toml
··· 1 + [target.'cfg(target_os="macos")'] 2 + # Postgres symbols won't be available until runtime 3 + rustflags = ["-Clink-arg=-Wl,-undefined,dynamic_lookup"]
+9
.gitignore
··· 1 + .DS_Store 2 + .idea/ 3 + /target 4 + *.iml 5 + **/*.rs.bk 6 + Cargo.lock 7 + pg_regress/results 8 + pg_regress/regression.diffs 9 + pg_regress/regression.out
+37
Cargo.toml
··· 1 + [package] 2 + name = "xata_id_extension" 3 + version = "0.0.0" 4 + edition = "2021" 5 + 6 + [lib] 7 + crate-type = ["cdylib", "lib"] 8 + 9 + [[bin]] 10 + name = "pgrx_embed_xata_id_extension" 11 + path = "./src/bin/pgrx_embed.rs" 12 + 13 + [features] 14 + default = ["pg13"] 15 + pg13 = ["pgrx/pg13", "pgrx-tests/pg13" ] 16 + pg14 = ["pgrx/pg14", "pgrx-tests/pg14" ] 17 + pg15 = ["pgrx/pg15", "pgrx-tests/pg15" ] 18 + pg16 = ["pgrx/pg16", "pgrx-tests/pg16" ] 19 + pg17 = ["pgrx/pg17", "pgrx-tests/pg17" ] 20 + pg18 = ["pgrx/pg18", "pgrx-tests/pg18" ] 21 + pg_test = [] 22 + 23 + [dependencies] 24 + pgrx = "=0.15.0" 25 + xid = "1.1.1" 26 + 27 + [dev-dependencies] 28 + pgrx-tests = "=0.15.0" 29 + 30 + [profile.dev] 31 + panic = "unwind" 32 + 33 + [profile.release] 34 + panic = "unwind" 35 + opt-level = 3 36 + lto = "fat" 37 + codegen-units = 1
+3
pg_regress/expected/setup.out
··· 1 + -- this setup file is run immediately after the regression database is (re)created 2 + -- the file is optional but you likely want to create the extension 3 + CREATE EXTENSION xata_id_extension;
+3
pg_regress/sql/setup.sql
··· 1 + -- this setup file is run immediately after the regression database is (re)created 2 + -- the file is optional but you likely want to create the extension 3 + CREATE EXTENSION xata_id_extension;
+1
src/bin/pgrx_embed.rs
··· 1 + ::pgrx::pgrx_embed!();
+72
src/lib.rs
··· 1 + use pgrx::prelude::*; 2 + 3 + ::pgrx::pg_module_magic!(name, version); 4 + 5 + fn generate_xata_id() -> String { 6 + format!("rec_{}", xid::new()) 7 + } 8 + 9 + #[pg_extern] 10 + fn xata_id() -> String { 11 + generate_xata_id() 12 + } 13 + 14 + #[cfg(any(test, feature = "pg_test"))] 15 + #[pg_schema] 16 + mod tests { 17 + use pgrx::prelude::*; 18 + 19 + #[pg_test] 20 + fn test_xata_id_length_and_prefix() { 21 + let id = crate::generate_xata_id(); 22 + assert_eq!(id.len(), 24, "ID length should be 24"); 23 + assert!(id.starts_with("rec_"), "ID should start with 'rec_'"); 24 + } 25 + 26 + #[pg_test] 27 + fn test_xata_id_valid_characters() { 28 + let id = crate::generate_xata_id(); 29 + let random_part = &id[4..]; 30 + for c in random_part.chars() { 31 + assert!( 32 + c.is_ascii_lowercase() || c.is_ascii_digit(), 33 + "Invalid character in random part: {}", 34 + c 35 + ); 36 + } 37 + } 38 + 39 + #[pg_test] 40 + fn test_xata_id_uniqueness() { 41 + let id1 = crate::generate_xata_id(); 42 + let id2 = crate::generate_xata_id(); 43 + assert_ne!(id1, id2, "IDs should be unique"); 44 + } 45 + 46 + #[pg_test] 47 + fn test_xata_id_multiple() { 48 + for _ in 0..100 { 49 + let id = crate::generate_xata_id(); 50 + assert_eq!(id.len(), 24, "ID length should be 24"); 51 + assert!(id.starts_with("rec_"), "ID should start with 'rec_'"); 52 + for c in id[4..].chars() { 53 + assert!( 54 + c.is_ascii_lowercase() || c.is_ascii_digit(), 55 + "Invalid character: {}", 56 + c 57 + ); 58 + } 59 + } 60 + } 61 + } 62 + 63 + #[cfg(test)] 64 + pub mod pg_test { 65 + pub fn setup(_options: Vec<&str>) { 66 + // No initialization needed 67 + } 68 + 69 + pub fn postgresql_conf_options() -> Vec<&'static str> { 70 + vec![] 71 + } 72 + }
+6
xata_id_extension.control
··· 1 + comment = 'xata_id_extension: Created by pgrx' 2 + default_version = '@CARGO_VERSION@' 3 + module_pathname = 'xata_id_extension' 4 + relocatable = false 5 + superuser = true 6 + trusted = false