I'm trying to compile and run go code as Postgresql stored procedure. My motivation is because postgresql can have excensions written in C and golang can be compiled as c-shared
So I have to files, pl.go:
package main
/*
#cgo CFLAGS: -Wall -Wpointer-arith -Wno-declaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong -fpic -I. -I./ -I/usr/include/postgresql/server -I/usr/include/postgresql/internal -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2
#cgo LDFLAGS: -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong -fpic -L/usr/lib -Wl,-O1,--sort-common,--as-needed,-z,relro -Wl,--as-needed -Wl,-rpath,'/usr/lib',--enable-new-dtags -shared
#include "postgres.h"
#include "fmgr.h"
#include "utils/builtins.h"
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
//the return value must be allocated trough palloc
void* ret(void *val, uint64 *size) {
void *retDatum = palloc(*size);
memcpy(retDatum, val, *size);
return retDatum;
}
PG_FUNCTION_INFO_V1(plgo_func);
*/
import "C"
import "unsafe"
func main() {}
//PGVal returns the Postgresql C type from Golang type (currently implements just stringtotext)
func PGVal(val interface{}) (ret interface{}) {
var size uintptr
switch v := val.(type) {
case string:
ret = C.cstring_to_text(C.CString(v))
size = unsafe.Sizeof(ret)
default:
ret = val
size = unsafe.Sizeof(ret)
}
return C.ret(ret, (*C.uint64)(unsafe.Pointer(size)))
}
the CFLAGS and LDFLAGS i'we got from pg_config
and the file where I create the function to call, plgo.go:
package main
/*
#include "postgres.h"
#include "fmgr.h"
#include "utils/builtins.h"
*/
import "C"
//export plgo_func
func plgo_func(fcinfo *C.FunctionCallInfoData) interface{} {
return PGVal("meh")
}
the shared library is created with: go build -buildmode=c-shared -o plgo.so plgo.go pl.go && sudo cp plgo.so /usr/lib/postgresql
the function in postgresql is created with:
CREATE OR REPLACE FUNCTION public.plgo_func(integer)
RETURNS text AS
'$libdir/plgo', 'plgo_func'
LANGUAGE c IMMUTABLE STRICT
COST 1;
but when I run: psql -U root -d meh -c "select plgo_func(0)"
the server crashes with:
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
connection to server was lost
EDIT: I've successfully created an golang "library" for creating stored procedures and triggers in golang plgo :)
interface{}. You need to return a C type from your exported function. (If that doesn't work, you need to get dome more debugging info from the server as to why it crashed)import "log"and than printing to file doesn't work ...retfunction, sincecstring_to_textreturns a*text, and you palloc only the size of that pointer, then copy thetextstruct into that location. I would make a proof of concept in C first to ensure you can get that working before expanding to Go/cgo.