Skip to content

Instantly share code, notes, and snippets.

@Florents-Tselai
Created October 30, 2025 09:02
Show Gist options
  • Select an option

  • Save Florents-Tselai/bc7a9aec6f27c294454ea11d06009e67 to your computer and use it in GitHub Desktop.

Select an option

Save Florents-Tselai/bc7a9aec6f27c294454ea11d06009e67 to your computer and use it in GitHub Desktop.
base64url encoding in PostgreSQL using CPython
## `base64url` encoding in PostgreSQL using CPython
```c
/* File: pyb64url.c
* Build idea (PGXS):
* CFLAGS += $(shell python3-config --includes)
* SHLIB_LINK += $(shell python3-config --ldflags)
* MODULE_big = pyb64url
* OBJS = pyb64url.o
*/
#include "postgres.h"
#include "fmgr.h"
#include "utils/builtins.h"
#include <Python.h>
PG_MODULE_MAGIC;
static bool py_ready = false;
/* Initialize CPython once per backend */
void _PG_init(void)
{
if (!py_ready) {
Py_Initialize();
/* Optional but good practice if extensions might use threads */
PyEval_InitThreads();
py_ready = true;
}
}
PG_FUNCTION_INFO_V1(py_base64url_encode);
/* SQL: CREATE FUNCTION py_base64url_encode(bytea) RETURNS text
* AS 'pyb64url', 'py_base64url_encode' LANGUAGE C STRICT;
*/
Datum
py_base64url_encode(PG_FUNCTION_ARGS)
{
bytea *arg = PG_GETARG_BYTEA_PP(0);
const char *buf = VARDATA_ANY(arg);
Py_ssize_t len = (Py_ssize_t) VARSIZE_ANY_EXHDR(arg);
text *result_text = NULL;
/* Acquire the GIL before touching Python */
PyGILState_STATE gstate = PyGILState_Ensure();
PyObject *py_bytes = NULL, *mod_b64 = NULL, *fn_enc = NULL;
PyObject *out_bytes = NULL, *eq = NULL, *trimmed = NULL;
py_bytes = PyBytes_FromStringAndSize(buf, len);
if (!py_bytes) goto fail;
mod_b64 = PyImport_ImportModule("base64");
if (!mod_b64) goto fail;
fn_enc = PyObject_GetAttrString(mod_b64, "urlsafe_b64encode");
if (!fn_enc || !PyCallable_Check(fn_enc)) goto fail;
out_bytes = PyObject_CallFunctionObjArgs(fn_enc, py_bytes, NULL);
if (!out_bytes) goto fail;
/* Optional: strip '=' padding to match common base64url usage */
eq = PyBytes_FromString("=");
if (!eq) goto fail;
trimmed = PyObject_CallMethod(out_bytes, "rstrip", "O", eq);
if (!trimmed) goto fail;
Py_DECREF(out_bytes);
out_bytes = trimmed; /* use trimmed as final bytes */
/* Convert Python bytes -> PostgreSQL text */
char *cstr = PyBytes_AsString(out_bytes);
if (!cstr) goto fail;
Py_ssize_t out_len = PyBytes_GET_SIZE(out_bytes);
result_text = cstring_to_text_with_len(cstr, (int) out_len);
/* Cleanup Python refs */
Py_DECREF(py_bytes);
Py_DECREF(mod_b64);
Py_DECREF(fn_enc);
Py_DECREF(out_bytes);
Py_DECREF(eq);
PyGILState_Release(gstate);
PG_RETURN_TEXT_P(result_text);
fail:
/* Fetch Python error (if any) and surface a PG error */
if (PyErr_Occurred()) {
PyObject *ptype, *pval, *ptrace;
PyErr_Fetch(&ptype, &pval, &ptrace);
PyErr_NormalizeException(&ptype, &pval, &ptrace);
const char *msg = "CPython error";
if (pval) {
PyObject *py_msg = PyObject_Str(pval);
if (py_msg) {
msg = PyUnicode_AsUTF8(py_msg);
/* Don't DECREF msg; it's owned by py_msg */
}
Py_XDECREF(py_msg);
}
/* Best effort cleanup */
Py_XDECREF(ptype);
Py_XDECREF(pval);
Py_XDECREF(ptrace);
PyGILState_Release(gstate);
ereport(ERROR, (errmsg("base64url encode via CPython failed: %s", msg ? msg : "unknown")));
} else {
PyGILState_Release(gstate);
ereport(ERROR, (errmsg("base64url encode via CPython failed")));
}
PG_RETURN_NULL(); /* not reached */
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment