[PostgreSQL] PL/Rust
PostgreSQL์์๋ Rust๋ ํ์ฅ์ ํํ๋ก ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค. ๊ธฐ๋ณธ์ ์๋๊ณ ์๋ํํฐ๋ค.
๊ตณ์ด ์ด๋ ๊ฒ๊น์ง ์ธ ์ผ์ด ์ ์์ผ๋ ค๋ ์ถ๊ธด ํ๋ฐ...
ํ ์์ ์์๋ ์์ง PG17๊น์ง๋ง ์ง์๋๋ ๊ฒ ๊ฐ๋ค.
rust๋ก ๊ณ ์ฑ๋ฅ ํด์ ์ฒ๋ฆฌ, JSON ์ฒ๋ฆฌ, ์ ๊ท์, ๋น ๋๋ฒ ์ฐ์ฐ ๋ฑ์ ์ต์ ํํ ์ผ์ด ์๋ค๋ฉด ์ธ๋ง์ ํ๋ค.
๊ทผ๋ฐ ๋จ์ ๋ ๋ง๋ค. ๋ชจ๋ crate์ ์ฌ์ฉํ๊ธฐ๋ ์ด๋ ต๊ณ , Rust ๋ฒ์ ์ง์๋ ๋ฎ๋ค. ์ต์ ๋ฒ์ ์ ์ฐ๊ธฐ๋ ์ด๋ ต๋ค.
์๋ฐ ๋ค ๋ฌถ์ธ ์ฑ๋ก ์ฐ๋๊ฑฐ๋ผ Rust์ ์ฅ์ ์ ์ ๋๋ก ๋์ด๋ด๊ธฐ๋ ์์ํ๋ค.
์ฌ์ฉ ๊ฐ๋ฅ ์ฌ๋ถ ํ์ธ
ํ์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ชฉ๋ก์ ์๋์ง๋ถํฐ ํ์ธํด์ผ ํ๋ค. ์ฌ๊ธฐ ์๋ค๋ฉด ๋ฐ๋ก ์ธ ์ ์๊ณ , ์๋ค๋ฉด ์ค์น๋ฅผ ํด์ค์ผ ํ๋ค.
SHOW shared_preload_libraries;
์ด๋ฌ๋ฉด ์๋๊ฑฐ๊ณ
์ด๋ฌ๋ฉด ์๋๊ฑฐ๋ค.
์ค์น (Self Hosted)
๋ค๋ฅธ ํ์ฅ๋ค๊ณผ ๋น๊ตํด์๋ ์ค์น๊ฐ ๋งค์ฐ ๋ฒ๊ฑฐ๋ก์ด ํธ์ด๋ค.
๊ถํ์ค์ ๊ฐ์๊ฑฐ ํด์ฃผ๊ณ , Rust๋ ๊น๊ณ ์ด๊ฒ์ ๊ฒ ์
์
์ ํด์ค์ผ ํ๋ค.
Rust ์ ๋๋ ๊น๋ ค์๋ค๊ณ ๊ฐ์ ํ๋ค.
sudo chown postgres -R $(pg_config --sharedir)/extension/
sudo chown postgres -R $(pg_config --sharedir)/lib/
sudo su - postgres
source ~/.cargo/env
rustup default stable

Rust ์ปดํฌ๋ํธ์ ํ๊ฒ์ ์ถ๊ฐํ๊ณ
rustup component add rustc-dev llvm-tools-preview
rustup target install x86_64-unknown-linux-gnu

Postgres ๋ฒ์ ์ ํ์ธํ ๋ค์
pg_config --version
๋ฒ์ ์ ๋ง๋ ํ๋๊ทธ๋ฅผ ์ถ๊ณ init์ ๋๋ฆฌ๋ฉด ๋๋ค.
git clone https://github.com/pgcentralfoundation/plrust.git
cd ~/plrust/plrustc
./build.sh
mv ~/plrust/build/bin/plrustc ~/.cargo/bin/
cd ~/plrust/plrust
PG_VER=17 STD_TARGETS="x86_64-postgres-linux-gnu " ./build
mkdir -p ~/.pgrx
export PGRX_HOME=~/.pgrx
cargo pgrx init --pg17 $(which pg_config)
cd ~/plrust/plrust
cargo pgrx install --release --features trusted -c $(which pg_config)
๊ทธ๋ฆฌ๊ณ ์ค๋ฅ ์์ด ๋ค ํต๊ณผ๋๋ฉด ์ฌ์ฉ์ด ๊ฐ๋ฅํด์ง ๊ฒ์ด๋ค.
AWS RDS์์
๋คํํ, ์์ฉ ํด๋ผ์ฐ๋๋ค์์๋ ๊ธฐ๋ณธ ํ์ฅ ์ธํธ์ ํฌํจ๋๋ ๊ฒฝ์ฐ๊ฐ ํํ๋ค.
13๋ฒ์ ๊ณผ 17๋ฒ์ ๊น์ง๋ shared_preload_libraries์ plrust๋ฅผ ์ถ๊ฐํ๊ณ ๋ฆฌ๋ก๋๋ง ํ๋ฉด ์๋์ผ๋ก ์ค์น๋๋ค.
๋ค๋ง, Aurora ๊ณ์ด์๋ ์๋ ๋ฒ์ ์ด ๋ ๋ง์ ๊ฒ ๊ฐ๋ค.

์๋ค๋ฉด ์ถ๊ฐํ๊ณ ์ฌ๋ถํ
๊น์ง ํด์ผ ํ๋ค. ๋ค์ดํ์์ด ํ์์ ์ด๋ค.
์ดํ์ CREATE EXTENTION๋ง ํ๋ฉด ๋๋ค.
ํ์ฅ ์ฌ์ฉํ๊ธฐ
์ค์น๊ฐ ์ ๋์ด์๋ค๋ฉด, CREATE EXTENSION ๋ช ๋ น ํ๋๋ก ์ฆ์ ํ์ฑํ๊ฐ ๊ฐ๋ฅํ๋ค.
CREATE EXTENSION plrust;

CREATE FUNCTION hello()
RETURNS text
LANGUAGE plrust
AS $$
Ok(Some("hello".to_string()))
$$;
SELECT hello();

๊ทธ๋ฆฌ๊ณ ๋ญ ๊ผฌ์ด๋ฉด rustyํ ์ค๋ฅ๊ฐ ๋๋ค.
์ค์ ๋ก ์ปดํ์ผ๋ฌ๋ฅผ ๊ทธ๋๋ก ๋๋ฆฌ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทธ๋ฆฌ๊ณ ํ๋ผ๋ฏธํฐ๋ ๋ฐํ๊ฐ ์ฒ๋ฆฌ๋ ๋๋ค.
๋ค๋ง ์ฌ๊ธฐ์๋ ์์์ ์ธ ๊ท์น์ด ๋ช๊ฐ์ง ์๋๋ฐ
SQL ํ์
์ด ์์์ ์ผ๋ก ๋ณํ๋๋ค๋ ๊ฒ (์: int => i32)
๋ชจ๋ ๋ฐํ๊ฐ์ Result๋ก ๊ฐ์ธ์ ธ์ผ ํ๋ค๋ ๊ฒ (Ok ๋ฐํ)
Nullable์ Option์ผ๋ก ํํ๋๋ค๋ ๊ฒ ์ ๋๋ค.
์๋ฌดํผ ์ฐ๋๋ฐ๋ ๋ณ๋ฐ ๋ฌธ์ ๊ฐ ์๋ค.
์ค๋ฅ ์ฒ๋ฆฌ
Err์ ๋ฌธ์์ด ์ ๋นํ ๋ฃ์ด์ ์๋ฉด ํ์ค Postgres ํ์๋๋ก ์ค๋ฅ๊ฐ ๋๊ฐ๋ค.
๋น์ฐํ ์ด๊ฑด try catch๊ฐ์๊ฒ ์์ผ๋ฏ๋ก ์ฆ์ ์ค๋ฅ๋ก ๋ฐ์ฌ๋๋ค.

crate ์ฌ์ฉ
์ธ๋ถ crate๋ ์ ํ์ ์ด์ง๋ง ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
๋ณด์ ๋ฌธ์ ๋๋ฌธ์ RDS ๊ฐ์ ๊ฒฝ์ฐ์๋ ์ผ๋ถ ์ ๋ขฐ์ฑ ์๋ crate์ ํํด์๋ง ์ฌ์ฉ์ด ํ์ฉ๋๋ค.
url, regex, serde, serde_json, num-bigint ๊ฐ์ ๊ฒ๋ค์ด ๊ทธ๊ฒ์ด๋ค. tokio ๊ฐ์๊ฑด ์๋๋ค.
์ด๊ฑด ๊ฐ์ ๋ฌธ์๋ฅผ ํ์ธํ๋ ํธ์ด ์ข๋ค.
https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/PostgreSQL.Concepts.General.Using.PL_Rust.html?utm_source=chatgpt.com
๊ทธ๋ฆฌ๊ณ ์ด๊ฑด PL/Rust๋ง๋ค ๋ฌธ๋ฒ๋ ๋ง์ด ๋ค๋ฅด๋ค.
์ผ๋จ 1.1 ๊ธฐ์ค์ผ๋ก ์ ์ด๋ณด์๋ฉด, ์ด๋ ๋ค.
๋ํ๋์๋ฅผ ํจ์ ๋ด์ ๋๋ ค๋ฐ์์ผ ํ๋ค.
CREATE OR REPLACE FUNCTION is_email(input text)
RETURNS bool
LANGUAGE plrust
AS $$
[dependencies]
regex = "1"
[code]
use regex::Regex;
let s = input.unwrap_or_default();
let re = Regex::new(
r"^[A-Za-z0-9._%+\-]+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,}$"
)?;
Ok(Some(re.is_match(&s)))
$$;
์ข ๋ชป์๊ธฐ๊ธด ํ์ง๋ง ๋์์ ํ๋ค.
์ฐธ์กฐ
https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/PostgreSQL.Concepts.General.Using.PL_Rust.html
https://plrust.io/config-pg.html
https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/PostgreSQL.Concepts.General.Using.PL_Rust.html?utm_source=chatgpt.com