{"id":13581573,"url":"https://github.com/xataio/pgzx","last_synced_at":"2025-04-06T10:11:52.589Z","repository":{"id":224564878,"uuid":"756488872","full_name":"xataio/pgzx","owner":"xataio","description":"Create PostgreSQL extensions using Zig.","archived":false,"fork":false,"pushed_at":"2024-04-14T14:23:08.000Z","size":7057,"stargazers_count":309,"open_issues_count":3,"forks_count":5,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-04-15T14:29:14.983Z","etag":null,"topics":["extens","extensions","pgrx","postgres","postgresql","zig","ziglang"],"latest_commit_sha":null,"homepage":"https://xata.io","language":"Zig","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xataio.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2024-02-12T19:03:32.000Z","updated_at":"2024-04-23T11:58:04.724Z","dependencies_parsed_at":"2024-04-14T15:35:11.860Z","dependency_job_id":null,"html_url":"https://github.com/xataio/pgzx","commit_stats":null,"previous_names":["xataio/pgzx"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xataio%2Fpgzx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xataio%2Fpgzx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xataio%2Fpgzx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xataio%2Fpgzx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xataio","download_url":"https://codeload.github.com/xataio/pgzx/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247464222,"owners_count":20942970,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["extens","extensions","pgrx","postgres","postgresql","zig","ziglang"],"created_at":"2024-08-01T15:02:06.099Z","updated_at":"2025-04-06T10:11:52.561Z","avatar_url":"https://github.com/xataio.png","language":"Zig","readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"brand-kit/banner/pgzx-banner-github@2x.png\" alt=\"pgzx logo\" /\u003e\n\u003c/div\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/xataio/pgzx/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/License-Apache_2.0-green\" alt=\"License - Apache 2.0\"\u003e\u003c/a\u003e\u0026nbsp;\n  \u003ca href=\"https://github.com/xataio/pgzx/actions?query=branch%3Amain\"\u003e\u003cimg src=\"https://github.com/xataio/pgzx/actions/workflows/check.yaml/badge.svg\" alt=\"CI Build\"\u003e\u003c/a\u003e \u0026nbsp;\n  \u003ca href=\"https://xata.io/discord\"\u003e\u003cimg src=\"https://img.shields.io/discord/996791218879086662?label=Discord\" alt=\"Discord\"\u003e\u003c/a\u003e \u0026nbsp;\n  \u003ca href=\"https://twitter.com/xata\"\u003e\u003cimg src=\"https://img.shields.io/twitter/follow/xata?style=flat\" alt=\"X (formerly Twitter) Follow\" /\u003e \u003c/a\u003e\n\u003c/p\u003e\n\n\n# pgzx - Create Postgres Extensions with Zig!\n\n`pgzx` is a library for developing PostgreSQL extensions written in Zig. It provides a set of utilities (e.g. error handling, memory allocators, wrappers) as well as a development environment that simplifies integrating with the Postgres code base.\n\n## Why Zig?\n\n[Zig](https://ziglang.org/) is a small and simple language that aims to be a \"modern C\" and make system-level code bases easier to maintain. It provides safe memory management, compilation time code execution (comptime), and a rich standard library.\n\nZig can interact with C code quite naturally: it supports the C ABI, can work with C pointers and types directly, it can import header files and even translate C code to Zig code. Thanks to this interoperability, a Postgres extension written in Zig can, theoretically, accomplish anything that a C extension can. This means you get full power AND a modern language and standard library to write your extension.\n\nWhile in theory you can write any extension in Zig that you could in C, in practice you will need to make sense of a lot of Postgres internals in order to know how to correctly use them from Zig. Also, Postgres makes extensive use of macros, and not all of them can be translated automatically. This is where pgzx comes in: it provides a set of Zig modules that make the development of Postgres Extensions in Zig much simpler.\n\n## Examples\n\nThe following sample extensions (ordered from simple to complex) show how to use pgzx:\n\n| Extension                                  | Description |\n|--------------------------------------------|-------------|\n| [char_count_zig](examples/char_count_zig/) | Adds a function that counts how many times a particular character shows up in a string. Shows how to register a function and how to interpret the parameters. |\n| [pghostname_zig](examples/pghostname_zig/) | Adds a function that returns the database server's host name. |\n| [pg_audit_zig](examples/pgaudit_zig/)      | Inspired by the pgaudit C extension, this one registers callbacks to multiple hooks and uses more advanced error handling and memory allocation patterns. |\n\n## Docs\n\n\nThe reference documentation is available at [here](https://xataio.github.io/pgzx/#docs.pgzx).\n\nWe recommend checking the examples in the section above to understand how to use pgzx. The next sections contain a high-level walkthrough of the most important utilities and how they relate to the Postgres internals.\n\n### Getting Started\n\nThis project uses [Nix flakes](https://nixos.wiki/wiki/Flakes) to manage build dependencies and provide a development shell. We provide a template for you to initialize a new Zig based Postgres extension project which allows you to reuse some of the utilities we're using.\n\nBefore getting started we would recommend you familiarize yourself with the projects setup first. To do so, please start with the [Contributing](#contributing) section.   \n\nWe will create a new project folder for our new extension and initialize the folder using the projects template:\n\n```\n$ mkdir my_extension\n$ cd my_extension\n$ nix flake init -t github:xataio/pgzx\n```\n\nThis step will create a working extension named 'my_extension'. The extension exports a hello world function named `hello()`.\n\nThe templates [README.md](./nix/templates/init/README.md) file already contains instructions on how to enter the development shell, build, and test the extension. You can follow the instructions and verify that your setup is functioning. Do not forget to use `pgstop` before quitting the development shell.\n\nThe development shell declares a few environment variables used by the project (see [devshell.nix](./devshell.nix)):\n- `PRJ_ROOT`: folder of the current project. If not set some shell scripts will\n  ask `git` to find the projects folder. Some scripts use this environment variable to ensure that you can run the script from within any folder within your project.\n- `PG_HOME`: Installation path of your postgres instance. When building postgres from scratch this matches the \npath prefix used by `make install`. When using the development shell we will relocate/build the postgres extension into the `./out` folder and create a symlink `./out/default` to the local version. If you plan to build and install the extension with another PostgreSQL installation set `PG_HOME=$(dirname $(pg_config --bindir))`.\n\n\nNext we want to rename the project to match our extension name. To do so, update the file names in the `extension` folder, and replace `my_extension` with your project name in the `README.md`, `build.zig`, `build.zig.zon`, and extensions SQL file.\n\n### Logging and error handling\n\nPostgres [error reporting functions](https://www.postgresql.org/docs/current/error-message-reporting.html) are used to report errors and log messages. They have typical logging functionality like log levels and formatting, but also Postgres specific functionality, like error reports that can be thrown and caught like exceptions. `pgzx` provides a wrapper around these functions that makes it easier to use from Zig.\n\nSimple logging can be done with functions like [Log][docs_Log], [Info][docs_Info], [Notice][docs_Notice], [Warning][docs_Warning], for example:\n\n```zig\n    elog.Info(@src(), \"input_text: {s}\\n\", .{input_text});\n```\n\nNote the `@src()` built-in which provides the file location. This will be stored in the error report.\n\nTo report errors during execution, use the [Error][docs_Error] or [ErrorThrow][docs_ErrorThrow] functions. The latter will throw an error report, which can be caught by the Postgres error handling system (explained below). Example with `Error`:\n\n```zig\n    if (target_char.len \u003e 1) {\n        return elog.Error(@src(), \"Target char is more than one byte\", .{});\n    }\n```\n\nThe elog module also exports functions that resemble the C API including functions like `ereport`, `errcode`, or `errmsg`.\n\nIf you browse through the Postgres source code, you'll see the [PG_TRY / PG_CATCH / PG_FINALLY](https://github.com/postgres/postgres/blob/master/src/include/utils/elog.h#L318) macros used as a form of \"exception handling\" in C, catching errors raised by the [ereport](https://www.postgresql.org/docs/current/error-message-reporting.html) family of functions. These macros make use of long jumps (i.e. jumps across function boundaries) to the \"catch/finally\" destination. This means we need to be careful when calling Postgres functions from Zig. For example, if the called C function raises an `ereport` error, the long jump might skip the Zig code that would have cleaned up resources (e.g. `errdefer`).\n\npgzx offers an alternative Zig implementation for the PG_TRY family of macros. This typically looks in code something like this:\n\n```zig\n    var errctx = pgzx.err.Context.init();\n    defer errctx.deinit();\n    if (errctx.pg_try()) {\n        // zig code that calls several Postgres C functions.\n    } else {\n        return errctx.errorValue();\n    }\n```\n\nThe above code pattern makes sure that we catch any errors raised by Postgres functions and return them as Zig errors. This way, we make sure that all the `defer` and `errdefer` code in the caller(s) are executed as expected. For more details, see the documentation for the [pgzx.err.Context][docs_Context] struct.\n\nThe above code pattern is implemented in a [wrap][docs_wrap] convenience function which takes a function and its arguments, and executes it in a block like the above. For example:\n\n```zig\n    try pgzx.err.wrap(myFunction, .{arg1, arg2});\n```\n\n### Memory context allocators\n\nPostgres uses a [memory context system](https://github.com/postgres/postgres/blob/master/src/backend/utils/mmgr/README) to manage memory. Memory allocated in a context can be freed all at once (for example, when a query execution is finished), which simplifies memory management significantly, because you only need to track contexts, not individual allocations. Contexts are also hierarchical, so you can create a context that is a child of another context, and when the parent context is freed, all children are freed as well.\n\npgzx offers custom wrapper Zig allocators that use Postgres' memory context system. The [pgzx.mem.createAllocSetContext][docs_createAllocSetContext] function creates an [pgzx.mem.MemoryContextAllocator][docs_MemoryContextAllocator] that you can use as a Zig allocator. For example:\n\n```zig\n    var memctx = try pgzx.mem.createAllocSetContext(\"zig_context\", .{ .parent = pg.CurrentMemoryContext });\n    const allocator = memctx.allocator();\n```\n\nIn the above, note the use of `pg.CurrentMemoryContext` as the parent context. This is the context of the current query execution, and it will be freed when the query is finished. This means that the memory allocated with `allocator` will be freed at the same time.\n\nIt's also possible to register a callback for when the memory context is destroyed or reset. This is useful to free or close resources that are tied to the context (e.g. sockets). pgzx provides an utility to register a callback:\n\n```zig\n    try memctx.registerAllocResetCallback(\n        queryDesc.*.estate.*.es_query_cxt,\n        pgaudit_zig_MemoryContextCallback,\n    );\n```\n\n### Function manager\n\npgzx has utilities for registering functions, written in Zig, that are then available to call over SQL. This is done, for example, via the [PG_FUNCTION_V1][docs_PG_FUNCTION_V1] function:\n\n```\ncomptime {\n    pgzx.PG_FUNCTION_V1(\"my_function\", myFunction);\n}\n```\n\nThe parameters are received from Postgres serialized, but pgzx automatically deserializes them into Zig types.\n\n### Testing your extension\n\npgzx provides two types of automatic tests: pg_regress tests and unit tests. The [pg_regress tests](https://www.postgresql.org/docs/current/regress.html) work similar with the way they work for C extensions. You provide inputs in a `sql` folder and expected outputs in the `expected` folder, and then you can run them like this:\n\n```sh\nzig build pg_regress\n```\n\nUnder the hood, this calls the `pg_regress` tool from the Postgres build.\n\nFor unit tests, we would like to run tests in a Postgres instance, so that the unit tests compile in the same environment as the tested code, and so that the tests can call Postgres APIs. In order to do this, pgzx registers a custom `run_tests` function via the Function manager. This function can be called from SQL (`SELECT run_tests();`) and it will run the unit tests.\n\nA test suite is a Zig struct for which each function whose name starts with `test` is a unit test. To register a test suite, you would typically do something like this:\n\n```zig\ncomptime {\n    pgzx.testing.registerTests(@import(\"build_options\").testfn, .{Tests});\n}\n``` \n\nThe `build_options.testfn` options should be defined via `build.zig`. For an example on how to do that, check out the `char_count_zig` or the `pgaudit_zig` sample extensions.\n\nNote that you can only call the `pgzx.testing.registerTests` function once per extension. If your extension has multiple modules/files, you should call it like this:\n\n```zig\n comptime {\n    pgzx.testing.registerTests(@import(\"build_options\").testfn, .{\n         @import(\"module1.zig\").Tests,\n         @import(\"module2.zig\").Tests,\n         @import(\"module2.zig\").Tests,\n    });\n}\n```\n\nTo run the unit tests, provided that you are using our sample `build.zig`, you can run:\n\n```sh\nzig build unit -p $PG_HOME\n```\n\nBehind the scenes, this builds the extension with the `testfn` build option set to `true`, deploys it in the Postgres instance, and then calls `SELECT run_tests();` to run the tests.\n\n## Status/Roadmap\n\npgzx is currently under heavy development by the [Xata](https://xata.io) team. If you want to try Zig for writing PostgreSQL extensions, it is easier with pgzx than without, but expect breaking changes and potential instability. If you need help, join us on the [Xata discord](https://xata.io/discord).\n\n* Utilities\n  * [ ] Postgres versions (compile and test)\n    * [ ] Postgres 14\n    * [ ] Postgres 15\n    * [ ] Postgres 16\n    * [x] Postgres 17\n  * [x] Logging\n  * [x] Error handling\n  * [x] Memory context allocators\n  * [x] Function manager\n  * [x] Background worker process\n  * [x] LWLocks\n  * [x] Signals and interrupts\n  * [x] String formatting\n  * [ ] Shared memory\n  * [ ] SPI\n  * Postgres data structures wrappers:\n    * Array based list (List)\n        * [x] Pointer list\n        * [ ] int list\n        * [ ] oid list\n        * ...\n    * [ ] Single list\n    * [ ] Double list\n    * [x] Hash tables\n* Development environment\n  * [ ] Download and vendor Postgres source code\n  * [x] Compile example extensions against the Postgres source code\n  * [x] Build target to run Postgres regression tests\n  * [x] Run unit tests in the Postgres environment\n  * [ ] Provide a standard way to test extensions from separate repos\n* Packaging\n  * [x] Add support for Zig packaging\n\n\n\n## Contributing\n\n### Develpment shell and local installation\n\nWe use Nix to provide a local development shell.\nThis ensures that we have a stable environment with all dependencies available\nin the expected versions. This is especially important with Zig, which is still\nin active development.\n\nFor this purpose it is possible to use this project as input in downstream\nflake files as well.\n\nThe tools we use also require some environment variables set, which are already\npre-configured in the develpment shell.\n\nWe would recommend the [nix-installer from DeterminateSystems](https://github.com/DeterminateSystems/nix-installer). The\ninstaller enables Nix Flakes (used by this project) out of the box and also\nprovides an uninstaller.\n\nIf you want to try out the project without having to install Nix on your\nsystem, you can do so using Docker. You can build the docker image by running\nthe `dev/docker/build.sh` script. The docker image is named `pgzx:latest`.\n\nTo enter the develpment shell run:\n\n```\n$ nix develop\n```\n\nIf you want to use docker instead, run:\n\n```\n$ ./dev/docker/run.sh\n```\n\n\nNOTE:\nWe also provide a `.envrc` file to automatically enter the development shell when entering\nthe projects folder. If you use direnv you can enable the environment via `direnv allow`.\n\nThe nix configuration already installs PostgreSQL, but for testing we want to\nhave a local postgres installation where we can install our test extensions in.\n\nWe use `pglocal` to relocate the existing installation into our development environment:\n\n```\n$ pglocal\n...\n\n$ ls out\n16  default\n```\n\nThe `out/default` folder is a symlink to the postgres installation currently in use.\n\nHaving a local installation we want to create a local database and user:\n\n```\n$ pginit\n...\n```\n\nThis creates a local database named `postgres`. The script allows us to configure an alternative name for the cluster, database, or user. This allows us to create multiple clusters within our current installation.\n\nWe can start and stop the database using `pgstart` and `pgstop`. Let's test our current setup:\n\n```\n$ pgstart\n$ psql  -U postgres -c 'select version()'\n                                         version\n-----------------------------------------------------------------------------------------\n PostgreSQL 16.1 on aarch64-apple-darwin22.6.0, compiled by clang version 16.0.6, 64-bit\n(1 row)\n```\n\nThis project has a few example extensions. We will install and test the `char_count_zig` extension next:\n\n```sh\n$ cd examples/char_count_zig\n$ zig build -freference-trace -p $PG_HOME\n$ psql  -U postgres -c 'CREATE EXTENSION char_count_zig;'\nCREATE EXTENSION\n$ psql  -U postgres -c \"SELECT char_count_zig('aaabc', 'a');\"\nINFO:  input_text: aaabc\n\nINFO:  target_char: a\n\nINFO:  Target char len: 1\n\n char_count_zig\n----------------\n              3\n(1 row)\n```\n\nThe sample extension also supports pg_regress bases testing:\n\n```\n$ zig build pg_regress --verbose\n# using postmaster on Unix socket, port 5432\nok 1         - char_count_test                            10 ms\n1..1\n# All 1 tests passed.\n```\n\n### Debugging the unit tests\n\nBecause Postgres manages the actual processes and starts a new process for each client we must attach our debugger to an existing session.\n\nTo debug an extension that exposes a function, like the unit tests, first start a SQL session:\n\n```\n$ psql -U postgres\n```\n\nIn order to attach our debugger to the session we need the PID for your current process:\n\n```\npostgres=# select pg_backend_pid();\n pg_backend_pid\n----------------\n          14985\n(1 row)\n```\n\nIf we want to set breakpoints we must also ensure that our extensions library has been loaded. You might have to drop and re-create an the test function in case you can't set a breakpoint (this will force Postgres to load the library):\n\n```\npostgres=# DROP FUNCTION run_tests;\nCREATE FUNCTION run_tests() RETURNS INTEGER AS '$libdir/pgzx_unit' LANGUAGE C IMMUTABLE;\n```\n\nNow we can attach our debugger and set a breakpoint (See your debuggers documentation on how to attach):\n\n```\n$ lldb -p 14985\n(lldb) b hsearch.zig:117\n...\n(lldb) c\n```\n\nYou can set breakpoints in your Zig based extension in C sources given you have all debug symbols available.\n\nWith our breakpoints set we want to start the testsuite:\n\n```\npostgres=# SELECT run_tests();\n```\n\n\n### Postgres debug build\n\nThe default development shell and scripts relocated the Nix postgres installation into the `out` folder only. When debugging an extension in isolation this is normally all you need. But in case you need to debug and step into the Postgres sources as well it is helpful to have a debug build available.\n\nThis project provides a second development shell type that provides tooling to fetch and build Postgres in debug mode.\n\nSelect the `debug` shell to start a shell with required development tools:\n\n```\nnix develop '.#debug'\n```\n\nThe `pgbuild` script will fetch the Postgres sources and build a local debug build that you can use for development, testing, and debugging:\n\n```\n$ pgbuild\n```\n\nThis will checkout Postgres into the `out/postgresql_src` directory. The build files will be stored in `out/postgresql_src/build`. We use [meson](https://mesonbuild.com/) and [Ninja](https://ninja-build.org/) to build Postgres. Ninja speeds up the compilation by parallelizing compilation tasks as much as possible. Compilation via Ninja also emits a `compile_commands.json` file that you can use with your editors LSP to improve navigating the Postgres source code if you wish to do so.\n\nOptionally symlink the `compile_commands.json` file:\n\n```\n$ ln -s ./out/postgresql_src/build/compile_commands.json ./out/postgresql_src/compile_commands.json\n```\n\nThe local build will be installed in `out/local`. To switch to the local Postgres build and ensure that your extension builds against it use:\n\n```\n$ pguse local\n\n```\n\nNote: Delete the `zig-cache` folder when switching to another Postgres installation to ensure that you extension is rebuilt properly against the new version.\n\n\n### Debugging Zig standard library and build script support\n\nTo debug Zig build scripts or the standard library all you need is the original sources. No additional build step is required. Anyways, it is recommended to use the same library version as the zig compiler ships with. You can query the current version or Git commit of a nightly build using the `zig` tool:\n\n```\n$ zig version\n0.13.0-dev.28+3c5e84073\n```\n\nThe version shown here for example indicates that we use a nightly build. The commit ID of that build is `0b744da84`.\n\nYou can clone and checkout the repository by yourself. We also have a small script `ziglocal` to checkout and even build the compiler. You can use the script to just checkout the correct version into your development environment:\n\n```\n$ ziglocal clone --commit 0b744da84\n```\n\nThis command clones the master branch only into the `./out/zig` directory.\n\nNow when building the test extensions you can use the `--zig-lib-dir` CLI flag to tell the compiler to use an alternative library:\n\n```\n$ zig build unit -p $PG_HOME --zig-lib-dir $PRJ_ROOT/out/zig/lib\n```\n\nThe zig compiler will now use the local checkout to build the `build.zig` file and your project.\n\n\n### Debugging Zig compiler/linker\n\nAs Zig is still in development, you might have the need to build the Zig toolchain yourself, maybe in debug mode.\n\nThe `debug` shell installs the additional dependencies that you need to build Postgres or the Zig compiler yourself.\n\n```\nnix develop '.#debug'\n```\n\nOptionally we might want to debug the actual version that we normally use:\n\n```\n$ zig version\n0.12.0-dev.3154+0b744da84\n```\n\nNext we checkout and compile the toolchain (Note: the `--commit` option is optional):\n\n```\n$ ziglocal --commit 0b744da84\n```\n\nThis step will take a while. You will find the compiler and library of your local debug build in the `out/zig/build/stage3` directory.\n\n## Q\u0026A\n\n### Which Zig version do you support?\n\nThe Zig toolchain, including the compiler, build system, and standard library, is still in development and breaking changes do happen every now and then. For this reason this project follows the [Zig master branch](https://github.com/ziglang/zig).\n\nThe Nix based development shell uses [zig-overlay](https://github.com/mitchellh/zig-overlay) in conjunction with the `flake.lock` file to pin the zig toolchain version to a recent commit ID.\n\nThe dependency is updated by us every so often and we try to test and fix breaking changes when updating the toolchain version. We highly recommend to use the projects develoment shell when testing the example extensions provided, otherwise you might have problems compiling the extensions at all.\n\nWe understand not everyone is keen to install Nix locally. For getting to know the environment you can build and run a development shell in a local docker container. Use `./dev/docker/build.sh` to build the container and `./dev/docker/run.sh` to start the dockerized development shell.\n\nThe current stable release is verion 0.12. As the build system APIs and package management system are undergoing heavy development recently we chose to stick with the `master` branch for now.\n\n\n### Where is my extension installed?\n\nBy default the zig build system installs all artifacts into the local `zig-out` folder.\n\nFor example we can see that behavior when building the `char_count_zig` extension:\n\n```\n$ cd examples/char_count_zig\n$ zig build\n$ find zig-out\nzig-out\nzig-out/lib\nzig-out/lib/char_count_zig.dylib\nzig-out/share\nzig-out/share/postgresql\nzig-out/share/postgresql/extension\nzig-out/share/postgresql/extension/char_count_zig.control\nzig-out/share/postgresql/extension/char_count_zig--0.1.sql\n```\n\nIf you are not sure whether the build system puts all files into the correct location or in case you generate code it can be helpful to debug your build scripts to install into `zig-out`.\n\nTo install the extension with your local Postgres instance you need to pass the path prefix where postgres was installed to using the `-p` flag:\n\n```\n$ zig build -p \u003cpath/to/postgres\u003e\n```\n\nYou can run `dirname $(pg_config --bindir)` from your shell to find the installation prefix. We set `PG_HOME` to the expected path in the development shell, assuming you use the `pglocal` or `pgbuild` scripts to prepare a local postgres installation for development.\n\n## See also\n\n* [pgrx](https://github.com/pgcentralfoundation/pgrx) - Similar project but for Rust, it served as an inspiration for this project. \n* [pg_tle](https://github.com/aws/pg_tle) - Trusted Language Extensions for PostgreSQL.\n\n## License\n\nThis project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.\n\n## Support\n\nIf you have any questions, encounter issues, or need assistance, open an issue in this repository or join our [Discord](https://xata.io/discord), and our community will be happy to help.\n\n\n\u003cbr\u003e\n\u003cp align=\"right\"\u003eMade with :heart: by \u003ca href=\"https://xata.io\"\u003eXata 🦋\u003c/a\u003e\u003c/p\u003e\n\n\n[docs_Log]: https://xataio.github.io/pgzx/#A;pgzx:elog.Log\n[docs_Info]: https://xataio.github.io/pgzx/#A;pgzx:elog.Info\n[docs_Notice]: https://xataio.github.io/pgzx/#A;pgzx:elog.Notice\n[docs_Warning]: https://xataio.github.io/pgzx/#A;pgzx:elog.Warning\n[docs_Error]: https://xataio.github.io/pgzx/#A;pgzx:elog.Error\n[docs_ErrorThrow]: https://xataio.github.io/pgzx/#A;pgzx:elog.ErrorThrow\n[docs_Context]: https://xataio.github.io/pgzx/#A;pgzx:err.Context\n[docs_wrap]: https://xataio.github.io/pgzx/#A;pgzx:err.wrap\n[docs_createAllocSetContext]: https://xataio.github.io/pgzx/#A;pgzx:mem.createAllocSetContext\n[docs_MemoryContextAllocator]: https://xataio.github.io/pgzx/#A;pgzx:mem.MemoryContextAllocator\n[docs_PG_FUNCTION_V1]: https://xataio.github.io/pgzx/#A;pgzx:PG_FUNCTION_V1\n","funding_links":[],"categories":["Zig","Extension Hacking","\u003ca name=\"Zig\"\u003e\u003c/a\u003eZig"],"sub_categories":["Tools"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxataio%2Fpgzx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxataio%2Fpgzx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxataio%2Fpgzx/lists"}