Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: rewrite to run on plv8 and add support for pg_tle #3

Merged
merged 10 commits into from
Jun 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .cargo/config.toml

This file was deleted.

32 changes: 32 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: JS CI

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:

build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
rust:
- stable

steps:
- uses: actions/checkout@v3

- name: Setup Node.js environment
uses: actions/setup-node@v3.8.1

- name: NPM install with caching
run: npm install

- name: Build
run: npm run build

- name: Node Test
run: npm run test
138 changes: 127 additions & 11 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,14 +1,130 @@
# Generated by Cargo
# will have compiled files and executables
debug/
target/
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# These are backup files generated by rustfmt
**/*.rs.bk
# Runtime data
pids
*.pid
*.seed
*.pid.lock

# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional stylelint cache
.stylelintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# vuepress v2.x temp and cache directory
.temp
.cache

# Docusaurus cache and generated files
.docusaurus

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
5 changes: 5 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"printWidth": 120,
"trailingComma": "all",
"singleQuote": true
}
9 changes: 7 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
{
"rust-analyzer.linkedProjects": [

"deno.enable": true,
"deno.lint": true,
"deno.unstable": true,
"deno.enablePaths": [
"./src/deno/mod.ts",
"./examples/deno.ts",
"./tests/mod.test.ts"
]
}
36 changes: 0 additions & 36 deletions Cargo.toml

This file was deleted.

13 changes: 0 additions & 13 deletions Dockerfile

This file was deleted.

32 changes: 32 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
.PHONY: test

prepare:
npm install

build:
npm run build

test: prepare
npm run test
deno test -A .\tests\mod.test.ts

clean:
echo "No clean implemented"

publish: clean prepare build
npm publish

format:
npx prettier --write src

lint:
npx prettier --check src

docs:
npx typedoc --out doc src

show-docs: docs
open doc/index.html

update-kernel:
node update-kernel.js
74 changes: 71 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,74 @@
# pg_extism
An Extism sample showing how you can run Extism plugins from PostgreSQl using pgrx!

**Note**: This is an experimental SDK.

## Getting started
Make sure [`plv8`](https://github.com/plv8/plv8) is installed on your server. Then enable it for your database:
```sql
create extension plv8;
```

Now run the script in [dist/index.sql](./dist/index.sql) and you'll get two SQL functions: `extism_create_plugin` and `extism_call`.

## Use pg_extism

Assume you have a table called `plugins`:
```sql
CREATE TABLE public.plugins (
id int4 GENERATED ALWAYS AS IDENTITY( INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START 1 CACHE 1 NO CYCLE) NOT NULL,
"data" bytea NULL,
"name" varchar NULL,
CONSTRAINT plugins_pk PRIMARY KEY (id)
);
```

Insert a few plugins into the table. And then call:

```sql
select extism_call(data, 'count_vowels', 'Hello World!') from plugins where id = 2;
```

**Note:** this assumes the plugin with id `2` has a function called `count_vowels`. You can find the plugin [here](https://github.com/extism/plugins/releases).

If you want more control over your plugin, you can use `extism_create_plugin`:

```sql
-- DROP FUNCTION public.count_vowels_kv(varchar);

CREATE OR REPLACE FUNCTION public.count_vowels_kv(input character varying)
RETURNS character varying
LANGUAGE plv8
AS $function$
const createPlugin = plv8.find_function("extism_create_plugin");
const wasm = plv8.execute("select data from plugins where id = 3")[0];
const opts = {
useWasi: true,

functions: {
"extism:host/user": {
kv_read(cp, offs) {
const key = cp.read(offs).text();
let result = plv8.execute("SELECT value FROM kv WHERE key = $1", [key]);
let value = result.length > 0 ? result[0].value : new Uint8Array([0, 0, 0, 0]);
return cp.store(value);
},
kv_write(cp, kOffs, vOffs) {
const key = cp.read(kOffs).text();
const value = cp.read(vOffs).bytes();
let result = plv8.execute("SELECT value FROM kv WHERE key = $1", [key]);
if (result.length > 0) {
plv8.execute("UPDATE kv SET value = $1 WHERE key = $2", [value, key]);
} else {
plv8.execute("INSERT INTO kv (key, value) VALUES ($1, $2)", [key, value]);
}
}
}
}
};

const plugin = createPlugin(wasm, opts);
return plugin.call("count_vowels", input).text()
$function$
;
```
cargo pgx run pg14
```
The above example shows how you can use `extism_create_plugin` to supply your own host functions to the plugin. You can find th source code for the plugin [here](https://github.com/extism/plugins/tree/main/count_vowels_kvstore).
Loading
Loading