Skip to content
Open
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
5 changes: 5 additions & 0 deletions .changeset/pglite-plpgsql-check-exports.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@electric-sql/pglite': patch
---

Export additional core symbols from the main WASM module required by the plpgsql_check extension
5 changes: 5 additions & 0 deletions .changeset/plpgsql-check-initial.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@electric-sql/pglite-plpgsql-check': patch
---

pglite-plpgsql-check: initial deployment
34 changes: 34 additions & 0 deletions .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ jobs:
packages/pglite-postgis/release
packages/pglite-pgvector/release
packages/pglite-pgmq/release
packages/pglite-plpgsql-check/release
key: wasm-build-${{ steps.postgres-pglite-commit-id.outputs.hash }}-pglite-${{ steps.pglite-version.outputs.version }}

- name: Build all if necessary
Expand Down Expand Up @@ -187,6 +188,14 @@ jobs:
path: ./packages/pglite-pgmq/release/**
retention-days: 60

- name: Upload pglite-plpgsql-check build artifacts to Github artifacts
id: upload-pglite-plpgsql-check-release-files
uses: actions/upload-artifact@v7
with:
name: pglite-plpgsql-check-release-files-node-v20.x
path: ./packages/pglite-plpgsql-check/release/**
retention-days: 60

- name: Typecheck pglite
working-directory: ${{ github.workspace }}/packages/pglite
run: pnpm typecheck
Expand Down Expand Up @@ -394,6 +403,12 @@ jobs:
with:
name: pglite-pgmq-release-files-node-v20.x
path: ./packages/pglite-pgmq/release/

- name: Download pglite-plpgsql-check build artifacts
uses: actions/download-artifact@v8
with:
name: pglite-plpgsql-check-release-files-node-v20.x
path: ./packages/pglite-plpgsql-check/release/

- name: Install dependencies
run: pnpm install --frozen-lockfile
Expand Down Expand Up @@ -483,6 +498,13 @@ jobs:
name: pglite-pgmq-dist-node-v${{ matrix.node }}
path: ./packages/pglite-pgmq/dist/*

- name: Upload pglite-plpgsql-check distribution artifact
id: upload-pglite-plpgsql-check-dist
uses: actions/upload-artifact@v7
with:
name: pglite-plpgsql-check-dist-node-v${{ matrix.node }}
path: ./packages/pglite-plpgsql-check/dist/*

publish-website-with-demos:
name: Publish website with demos
runs-on: blacksmith-4vcpu-ubuntu-2204
Expand Down Expand Up @@ -576,6 +598,12 @@ jobs:
name: pglite-pgmq-dist-node-v20.x
path: ./packages/pglite-pgmq/dist/

- name: Download pglite-plpgsql-check dist artifacts
uses: actions/download-artifact@v8
with:
name: pglite-plpgsql-check-dist-node-v20.x
path: ./packages/pglite-plpgsql-check/dist/

- name: Install dependencies
run: pnpm install --frozen-lockfile

Expand Down Expand Up @@ -732,6 +760,12 @@ jobs:
name: pglite-pgmq-release-files-node-v20.x
path: ./packages/pglite-pgmq/release/

- name: Download pglite-plpgsql-check build artifacts
uses: actions/download-artifact@v8
with:
name: pglite-plpgsql-check-release-files-node-v20.x
path: ./packages/pglite-plpgsql-check/release/

- name: Download pglite-age build artifacts
uses: actions/download-artifact@v8
with:
Expand Down
18 changes: 18 additions & 0 deletions docs/extensions/extensions.data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,24 @@ const baseExtensions: Extension[] = [
size: 41908,
npmjsUrl: 'https://www.npmjs.com/package/@electric-sql/pglite-pgmq',
},
{
name: 'plpgsql_check',
description: `
plpgsql_check is a linter, static code analyzer and profiler for PL/pgSQL.
It can detect errors in PL/pgSQL functions - such as references to missing
columns or tables, type mismatches and unused variables - without executing
them.

This is an **external** extension, distributed as a separate package at https://www.npmjs.com/package/@electric-sql/pglite-plpgsql-check
`,
shortDescription: 'Linter and static code analyzer for PL/pgSQL',
docs: 'https://github.com/okbob/plpgsql_check',
tags: ['postgres extension', 'external'],
importPath: '@electric-sql/pglite-plpgsql-check',
importName: 'plpgsql_check',
size: 71993,
npmjsUrl: 'https://www.npmjs.com/package/@electric-sql/pglite-plpgsql-check',
},
]

const tags = [
Expand Down
1 change: 1 addition & 0 deletions docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"@electric-sql/pglite-pg_uuidv7": "workspace:*",
"@electric-sql/pglite-pgtap": "workspace:*",
"@electric-sql/pglite-pgmq": "workspace:*",
"@electric-sql/pglite-plpgsql-check": "workspace:*",
"@uiw/codemirror-theme-github": "^4.23.0",
"dedent": "^1.5.3"
}
Expand Down
1 change: 1 addition & 0 deletions docs/repl/allExtensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export { pg_visibility } from '@electric-sql/pglite/contrib/pg_visibility'
export { pg_walinspect } from '@electric-sql/pglite/contrib/pg_walinspect'
export { pgcrypto } from '@electric-sql/pglite/contrib/pgcrypto'
export { pgtap } from '@electric-sql/pglite-pgtap'
export { plpgsql_check } from '@electric-sql/pglite-plpgsql-check'
export { postgis } from '@electric-sql/pglite-postgis'
export { seg } from '@electric-sql/pglite/contrib/seg'
export { tablefunc } from '@electric-sql/pglite/contrib/tablefunc'
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"ts:build": "pnpm -r --filter \"./packages/**\" build",
"ts:build:debug": "DEBUG=true pnpm ts:build",
"wasm:copy-pgmq": "mkdir -p ./packages/pglite-pgmq/release && cp ./postgres-pglite/dist/extensions/other/pgmq-extension.tar.gz ./packages/pglite-pgmq/release/pgmq.tar.gz",
"wasm:copy-plpgsql-check": "mkdir -p ./packages/pglite-plpgsql-check/release && cp ./postgres-pglite/dist/extensions/other/plpgsql_check.tar.gz ./packages/pglite-plpgsql-check/release",
"wasm:copy-pgvector": "mkdir -p ./packages/pglite-pgvector/release && cp ./postgres-pglite/dist/extensions/other/vector.tar.gz ./packages/pglite-pgvector/release",
"wasm:copy-pg_uuidv7": "mkdir -p ./packages/pglite-pg_uuidv7/release && cp ./postgres-pglite/dist/extensions/other/pg_uuidv7.tar.gz ./packages/pglite-pg_uuidv7/release",
"wasm:copy-pgtap": "mkdir -p ./packages/pglite-pgtap/release && cp ./postgres-pglite/dist/extensions/other/pgtap.tar.gz ./packages/pglite-pgtap/release",
Expand All @@ -21,7 +22,7 @@
"wasm:copy-age": "mkdir -p ./packages/pglite-age/release && cp ./postgres-pglite/dist/extensions/other/age.tar.gz ./packages/pglite-age/release",
"wasm:copy-pg_textsearch": "mkdir -p ./packages/pglite-pg_textsearch/release && cp ./postgres-pglite/dist/extensions/other/pg_textsearch.tar.gz ./packages/pglite-pg_textsearch/release",
"wasm:copy-postgis": "mkdir -p ./packages/pglite-postgis/release && cp ./postgres-pglite/dist/extensions/other/postgis.tar.gz ./packages/pglite-postgis/release",
"wasm:copy-other_extensions": "pnpm wasm:copy-postgis; pnpm wasm:copy-pg_textsearch; pnpm wasm:copy-age; pnpm wasm:copy-pg_hashids; pnpm wasm:copy-pg_ivm; pnpm wasm:copy-pgtap; pnpm wasm:copy-pg_uuidv7; pnpm wasm:copy-pgvector; pnpm wasm:copy-pgmq",
"wasm:copy-other_extensions": "pnpm wasm:copy-postgis; pnpm wasm:copy-pg_textsearch; pnpm wasm:copy-age; pnpm wasm:copy-pg_hashids; pnpm wasm:copy-pg_ivm; pnpm wasm:copy-pgtap; pnpm wasm:copy-pg_uuidv7; pnpm wasm:copy-pgvector; pnpm wasm:copy-pgmq; pnpm wasm:copy-plpgsql-check",
"wasm:copy-initdb": "mkdir -p ./packages/pglite/release && cp ./postgres-pglite/dist/bin/initdb.* ./packages/pglite/release",
"wasm:copy-pgdump": "mkdir -p ./packages/pglite-tools/release && cp ./postgres-pglite/dist/bin/pg_dump.* ./packages/pglite-tools/release",
"wasm:copy-pglite": "mkdir -p ./packages/pglite/release/ && cp ./postgres-pglite/dist/bin/pglite.* ./packages/pglite/release/ && cp ./postgres-pglite/dist/extensions/*.tar.gz ./packages/pglite/release/",
Expand Down
2 changes: 2 additions & 0 deletions packages/pglite-plpgsql-check/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
release/*
dist
63 changes: 63 additions & 0 deletions packages/pglite-plpgsql-check/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# @electric-sql/pglite-plpgsql-check

[plpgsql_check](https://github.com/okbob/plpgsql_check) extension for [PGlite](https://pglite.dev).

plpgsql_check is a linter, static code analyzer and profiler for PL/pgSQL. It can detect errors in PL/pgSQL functions - such as references to missing columns or tables, type mismatches and unused variables - without executing them.

## Installation

```bash
npm install @electric-sql/pglite-plpgsql-check
```

## Usage

```typescript
import { PGlite } from '@electric-sql/pglite'
import { plpgsql_check } from '@electric-sql/pglite-plpgsql-check'

const pg = new PGlite({
extensions: {
plpgsql_check,
},
})

await pg.exec('CREATE EXTENSION IF NOT EXISTS plpgsql_check;')

await pg.exec(`
CREATE TABLE t1(a integer, b integer);

CREATE OR REPLACE FUNCTION public.my_function()
RETURNS void
LANGUAGE plpgsql
AS $$
DECLARE
r record;
BEGIN
FOR r IN SELECT * FROM t1 LOOP
RAISE NOTICE '%', r.missing_column;
END LOOP;
END;
$$;
`)

// Check the function for errors without executing it
const res = await pg.query(`
SELECT * FROM plpgsql_check_function_tb('public.my_function()');
`)
// [
// {
// functionid: 'my_function',
// lineno: 6,
// statement: 'RAISE',
// sqlstate: '42703',
// message: 'record "r" has no field "missing_column"',
// level: 'error',
// ...
// }
// ]
```

## License

Apache-2.0
21 changes: 21 additions & 0 deletions packages/pglite-plpgsql-check/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import globals from 'globals'
import rootConfig from '../../eslint.config.js'

export default [
...rootConfig,
{
ignores: ['release/**/*', 'dist/**/*'],
},
{
languageOptions: {
globals: {
...globals.browser,
...globals.node,
},
},
rules: {
...rootConfig.rules,
'@typescript-eslint/no-explicit-any': 'off',
},
},
]
65 changes: 65 additions & 0 deletions packages/pglite-plpgsql-check/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"name": "@electric-sql/pglite-plpgsql-check",
"version": "0.0.1",
"description": "plpgsql_check extension for PGlite",
"author": "Electric DB Limited",
"homepage": "https://pglite.dev",
"license": "Apache-2.0",
"keywords": [
"postgres",
"sql",
"database",
"wasm",
"pglite",
"plpgsql",
"plpgsql_check"
],
"private": false,
"publishConfig": {
"access": "public"
},
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
}
},
"files": [
"dist"
],
"repository": {
"type": "git",
"url": "git+https://github.com/electric-sql/pglite.git",
"directory": "packages/pglite-plpgsql-check"
},
"scripts": {
"build": "tsup && tsx scripts/bundle-wasm.ts",
"check:exports": "attw . --pack --profile node16",
"lint": "eslint ./src ./tests --report-unused-disable-directives --max-warnings 0",
"format": "prettier --write ./src ./tests",
"typecheck": "tsc",
"stylecheck": "pnpm lint && prettier --check ./src ./tests",
"test": "vitest",
"prepublishOnly": "pnpm check:exports"
},
"devDependencies": {
"@arethetypeswrong/cli": "^0.18.1",
"@electric-sql/pglite": "workspace:*",
"@electric-sql/pglite-utils": "workspace:*",
"@types/node": "^20.16.11",
"vitest": "^2.1.2"
},
"peerDependencies": {
"@electric-sql/pglite": "workspace:*"
}
}
8 changes: 8 additions & 0 deletions packages/pglite-plpgsql-check/scripts/bundle-wasm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { copyFiles, findAndReplaceInDir } from '@electric-sql/pglite-utils/scripts/fileUtils'

async function main() {
await copyFiles('./release', './dist')
await findAndReplaceInDir('./dist', /\.\.\/release\//g, './', ['.js', '.cjs'])
}

await main()
17 changes: 17 additions & 0 deletions packages/pglite-plpgsql-check/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type {
Extension,
ExtensionSetupResult,
PGliteInterface,
} from '@electric-sql/pglite'

const setup = async (_pg: PGliteInterface, emscriptenOpts: any) => {
return {
emscriptenOpts,
bundlePath: new URL('../release/plpgsql_check.tar.gz', import.meta.url),
} satisfies ExtensionSetupResult
}

export const plpgsql_check = {
name: 'plpgsql_check',
setup,
} satisfies Extension
Loading