PostgreSQL支持多种语言编写用户自定义函数(UDF)、触发器。今天介绍的plgo可以方便地使用go语言编写PostgreSQL扩展。
环境准备
Mac OSX
PostgreSQL 12.2(安装方法参考6行代码在Jupyter里搞定PostgreSQL从安装到查询)
postgresql-server-dev-12.2(已经随上面的方法一并安装)
Go 1.14.5
安装
go get -u gitlab.com/microo8/plgo/plgo
编译插件
以plgo提供的example为例,记录下Mac OS下编译遇到的问题,及解决办法。
plgo .
报错
Package gitlab.com/microo8/plgo not installedplease install it with: go get -u gitlab.com/microo8/plgo/plgo
查看源代码后发现,而且是到$GOPATH/src/gitlab.com/microo8/plgo/pl.go
func readPlGoSource() ([]byte, error) {goPath := os.Getenv("GOPATH")if goPath == "" {goPath = build.Default.GOPATH // Go 1.8 and later have a default GOPATH}for _, goPathElement := range filepath.SplitList(goPath) {path:=filepath.Join(goPathElement, "src", "gitlab.com", "microo8", "plgo", "pl.go")fmt.Println(path)rv, err := ioutil.ReadFile(filepath.Join(goPathElement, "src", "gitlab.com", "microo8", "plgo", "pl.go"))if err == nil {return rv, nil} else if os.IsNotExist(err) {continue // try the next} else {return nil, fmt.Errorf("Cannot read plgo package: %w", err)}}return nil, fmt.Errorf("Package gitlab.com/microo8/plgo not installed\nplease install it with: go get -u gitlab.com/microo8/plgo/plgo")}
解决办法
把安装好的包copy一份到$GOPATH/src/gitlab.com/microo8/plgo/
或者使用如下方法安装,
GO111MODULE='off' go get -u gitlab.com/microo8/plgo/plgo
再次编译
plgo .
报错
2020/08/11 11:19:40 var/folders/3p/yypfkyxj0wv1hr9dwxrx613c0000gn/T/plgo645118958runtime/cgocommand-line-arguments# command-line-argumentsUndefined symbols for architecture x86_64:"_DirectFunctionCall1Coll", referenced from:_jsonb_to_datum in _x003.o__cgo_b7e4853c1065_Cfunc_jsonb_to_datum in _x003.o"_JsonbToCString", referenced from:_datum_to_jsonb_cstring in _x003.o__cgo_b7e4853c1065_Cfunc_datum_to_jsonb_cstring in _x003.o"_SPI_connect", referenced from:__cgo_b7e4853c1065_Cfunc_SPI_connect in _x003.o(maybe you meant: __cgo_b7e4853c1065_Cfunc_SPI_connect)"_SPI_execute_plan", referenced from:__cgo_b7e4853c1065_Cfunc_SPI_execute_plan in _x003.o(maybe you meant: __cgo_b7e4853c1065_Cfunc_SPI_execute_plan)"_SPI_finish", referenced from:__cgo_b7e4853c1065_Cfunc_SPI_finish in _x003.o(maybe you meant: __cgo_b7e4853c1065_Cfunc_SPI_finish)"_SPI_fname", referenced from:__cgo_b7e4853c1065_Cfunc_SPI_fname in _x003.o(maybe you meant: __cgo_b7e4853c1065_Cfunc_SPI_fname)"_SPI_getbinval", referenced from:_get_col_as_datum in _x003.o__cgo_b7e4853c1065_Cfunc_get_col_as_datum in _x003.o"_SPI_gettype", referenced from:__cgo_b7e4853c1065_Cfunc_SPI_gettype in _x003.o(maybe you meant: __cgo_b7e4853c1065_Cfunc_SPI_gettypeid, __cgo_b7e4853c1065_Cfunc_SPI_gettype )"_SPI_gettypeid", referenced from:__cgo_b7e4853c1065_Cfunc_SPI_gettypeid in _x003.o(maybe you meant: __cgo_b7e4853c1065_Cfunc_SPI_gettypeid)"_SPI_prepare", referenced from:__cgo_b7e4853c1065_Cfunc_SPI_prepare in _x003.o(maybe you meant: __cgo_b7e4853c1065_Cfunc_SPI_prepare)"_SPI_processed", referenced from:__cgohack_SPI_processed in _cgo_main.o(maybe you meant: __cgohack_SPI_processed)"_SPI_result", referenced from:__cgohack_SPI_result in _cgo_main.o(maybe you meant: __cgo_b7e4853c1065_Cfunc_SPI_result_code_string, __cgohack_SPI_result )"_SPI_result_code_string", referenced from:__cgo_b7e4853c1065_Cfunc_SPI_result_code_string in _x003.o(maybe you meant: __cgo_b7e4853c1065_Cfunc_SPI_result_code_string)"_SPI_tuptable", referenced from:__cgohack_SPI_tuptable in _cgo_main.o(maybe you meant: __cgohack_SPI_tuptable)"_construct_md_array", referenced from:_array_to_datum in _x003.o__cgo_b7e4853c1065_Cfunc_array_to_datum in _x003.o"_cstring_to_text", referenced from:_cstring_to_datum in _x003.o__cgo_b7e4853c1065_Cfunc_cstring_to_datum in _x003.o"_deconstruct_array", referenced from:_datum_to_array in _x003.o__cgo_b7e4853c1065_Cfunc_datum_to_array in _x003.o"_elog_finish", referenced from:_elog_notice in _x003.o__cgo_b7e4853c1065_Cfunc_elog_notice in _x003.o_elog_error.cold.1 in _x003.o"_elog_start", referenced from:_elog_notice in _x003.o__cgo_b7e4853c1065_Cfunc_elog_notice in _x003.o_elog_error.cold.1 in _x003.o"_get_call_expr_argtype", referenced from:__cgo_b7e4853c1065_Cfunc_get_call_expr_argtype in _x003.o(maybe you meant: __cgo_b7e4853c1065_Cfunc_get_call_expr_argtype)"_get_typlenbyvalalign", referenced from:_array_to_datum in _x003.o_datum_to_array in _x003.o__cgo_b7e4853c1065_Cfunc_array_to_datum in _x003.o__cgo_b7e4853c1065_Cfunc_datum_to_array in _x003.o"_getmissingattr", referenced from:_get_heap_getattr in _x003.o"_heap_form_tuple", referenced from:__cgo_b7e4853c1065_Cfunc_heap_form_tuple in _x003.o(maybe you meant: __cgo_b7e4853c1065_Cfunc_heap_form_tuple)"_heap_getsysattr", referenced from:_get_heap_getattr in _x003.o"_jsonb_in", referenced from:_jsonb_to_datum in _x003.o__cgo_b7e4853c1065_Cfunc_jsonb_to_datum in _x003.o"_nocachegetattr", referenced from:_get_heap_getattr in _x003.o"_palloc", referenced from:_bytes_to_datum in _x003.o__cgo_b7e4853c1065_Cfunc_bytes_to_datum in _x003.o"_palloc0", referenced from:_array_to_datum in _x003.o__cgo_b7e4853c1065_Cfunc_array_to_datum in _x003.o"_parseTypeString", referenced from:__cgo_b7e4853c1065_Cfunc_parseTypeString in _x003.o(maybe you meant: __cgo_b7e4853c1065_Cfunc_parseTypeString)"_pg_detoast_datum", referenced from:_jsonb_to_datum in _x003.o_datum_to_array in _x003.o_datum_to_jsonb_cstring in _x003.o__cgo_b7e4853c1065_Cfunc_datum_to_array in _x003.o__cgo_b7e4853c1065_Cfunc_datum_to_jsonb_cstring in _x003.o__cgo_b7e4853c1065_Cfunc_jsonb_to_datum in _x003.o"_pg_detoast_datum_packed", referenced from:_datum_to_byteap in _x003.o__cgo_b7e4853c1065_Cfunc_datum_to_byteap in _x003.o"_text_to_cstring", referenced from:_datum_to_cstring in _x003.o__cgo_b7e4853c1065_Cfunc_datum_to_cstring in _x003.old: symbol(s) not found for architecture x86_64clang: error: linker command failed with exit code 1 (use -v to see invocation)Cannot build package: exit status 2
解决办法
CGO_LDFLAGS="-Wl,-undefined,dynamic_lookup" plgo .
解释
clang use ld command to make the final link, I checked the manual and found -U
and -undefined
can ignore undefined symbols.
-U symbol_name
Specified that it is ok for symbol_name to have no definition. With two_levelnamespace, the resulting symbol will be marked dynamic_lookup which means dyld will search all loaded images.
-undefined treatment
Specifies how undefined symbols are to be treated. Options are: error, warning, suppress, or dynamic_lookup. The default is error.
So the final solution is set -Wl,-undefined,dynamic_lookup
to OTHER_LDFLAGS
, also make sure search path set correctly. It works.
安装插件
cd buildmake install with_llvm=no>>返回信息/bin/sh Users/steven/anaconda3/envs/new/lib/pgxs/src/makefiles/../../config/install-sh -c -d '/Users/steven/anaconda3/envs/new/share/extension'/bin/sh Users/steven/anaconda3/envs/new/lib/pgxs/src/makefiles/../../config/install-sh -c -d '/Users/steven/anaconda3/envs/new/share/extension'/bin/sh Users/steven/anaconda3/envs/new/lib/pgxs/src/makefiles/../../config/install-sh -c -d '/Users/steven/anaconda3/envs/new/lib'/usr/bin/install -c -m 644 .//ex1.control '/Users/steven/anaconda3/envs/new/share/extension/'/usr/bin/install -c -m 644 .//ex1--0.1.sql '/Users/steven/anaconda3/envs/new/share/extension/'/usr/bin/install -c -m 755 ex1.so '/Users/steven/anaconda3/envs/new/lib/'
测试插件
CREATE EXTENSION ex1;select concatarray(array['foo','bar']);select concatarray(array_agg(DISTINCT "Species")) from iris;select Meh();

代码汇总
GO111MODULE='off' go get -u gitlab.com/microo8/plgo/plgoCGO_LDFLAGS="-Wl,-undefined,dynamic_lookup" plgo .cd buildmake install with_llvm=no
参考
https://gitlab.com/microo8/plgo
https://stackoverflow.com/questions/17281901/ignoring-an-undefined-symbol-in-a-dynamic-library-from-xcode
6行代码在Jupyter里搞定PostgreSQL从安装到查询
macOS下安装PostgreSQL的方法汇总




