Ich versuche, Go-Code als Postgresql gespeicherte Prozedur kompilieren und ausführen. Meine Motivation ist, weil postgresql excensions geschrieben in C und golang haben kann, kann als c-shared kompiliert werdenGolang Verfahrenssprache für Postgresql
So habe ich auf Dateien, 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)))
}
die CFLAGS
und LDFLAGS
i'we bekam von pg_config
und die Datei, wo ich die Funktion erstellen zu nennen, 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")
}
die gemeinsam genutzte Bibliothek erstellt mit: go build -buildmode=c-shared -o plgo.so plgo.go pl.go && sudo cp plgo.so /usr/lib/postgresql
die Funktion in postgresql mit erstellt:
CREATE OR REPLACE FUNCTION public.plgo_func(integer)
RETURNS text AS
'$libdir/plgo', 'plgo_func'
LANGUAGE c IMMUTABLE STRICT
COST 1;
aber wenn ich laufe: psql -U root -d meh -c "select plgo_func(0)"
der Server abstürzt mit:
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
connection to server was lost
EDIT: Ich habe erfolgreich erstellt eine Golang "Bibliothek" zum Erstellen gespeicherter Prozeduren und Trigger in Golang plgo :)
C hat kein Konzept einer Go 'Schnittstelle {}'. Sie müssen einen C-Typ von Ihrer exportierten Funktion zurückgeben. (Wenn das nicht funktioniert, müssen Sie mehr Debugging-Informationen vom Server bekommen, um zu erfahren, warum es abgestürzt ist) – JimB
Das hat nicht funktioniert, wie kann ich etwas Debugging/Log zu diesem Code hinzufügen? 'import" log "' und dann in Datei zu drucken funktioniert nicht ... – microo8
Ich würde vermuten, dass Sie segfauling in der 'ret' -Funktion sind, da' cstring_to_text' einen '* text' zurückgibt, und Sie palloc nur die Größe des Zeigers, dann kopieren Sie die 'text'-Struktur in diese Position. Ich würde zuerst einen Machbarkeitsnachweis in C machen, um sicherzustellen, dass Sie das schaffen können, bevor Sie auf Go/cgo expandieren. – JimB