我正在尝试将 go 代码编译并运行为 Postgresql 存储过程。 我的动机是因为 postgresql 可以有用 C 编写的扩展,而 golang 可以编译为 c-shared
所以我必须提交文件,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)))
}
CFLAGS 和 LDFLAGS 我是从 pg_config
以及我在其中创建要调用的函数的文件 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")
}
共享库是通过以下方式创建的:go build -buildmode=c-shared -o plgo.so plgo.go pl.go && sudo cp plgo.so/usr/lib/postgresql
postgresql 中的函数是用以下方法创建的:
CREATE OR REPLACE FUNCTION public.plgo_func(integer)
RETURNS text AS
'$libdir/plgo', 'plgo_func'
LANGUAGE c IMMUTABLE STRICT
COST 1;
但是当我运行时:psql -U root -d meh -c "select plgo_func(0)"
服务器崩溃:
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
connection to server was lost
编辑:我已经成功创建了一个 golang“库”,用于在 golang 中创建存储过程和触发器 plgo :)
最佳答案
诀窍是使用版本 0 调用约定,因为这些约定允许调用简单的 C 函数,而无需使用他们添加到版本 1 调用中的所有花哨的宏。
您还需要一个 C 文件来调用 PG_MODULE_MAGIC 宏。
我有一个可以执行所有这些操作的工作示例项目,如果您只是将其复制为起点,这可能是最简单的。
不确定它是否能让您完全按照自己的意愿行事,但它确实适用于某些用例。
https://github.com/dbudworth/gopgfuncs
还将概述 repo 告诉您的相同内容...
用你的函数创建一个 .go 文件,CGO 包含
package main
//#include "postgres.h"
//#include "fmgr.h"
//#include <string.h>
import "C"
import (
"log"
"sync/atomic"
)
// Functions are scoped to the db session
var counter int64
//Inc atomically increments a session local counter by a given delta
//export Inc
func Inc(delta C.int64) C.int64 {
log.Printf("Inc(%v) called", delta)
return C.int64(atomic.AddInt64(&counter, int64(delta)))
}
//AddOne adds one to the given arg and retuns it
//export AddOne
func AddOne(i C.int) C.int {
log.Printf("AddOne(%v) called", i)
return i + 1
}
func main() {
}
在从 postgres.h 调用 PG_MODULE_MAGIC 宏的同一目录中创建一个 .c 文件,这是所有扩展库的要求。 Go 会在编译时自动包含 C 文件,不需要特殊说明。
#include "postgres.h"
#include "fmgr.h"
PG_MODULE_MAGIC;
构建你的so文件,这里的技巧是使用-buildmode=c-shared
go build -buildmode=c-shared -o libMyMod.so
执行 SQL 以注册您的函数。由于注册扩展需要绝对路径,我更喜欢在命令行上传递模块以避免使“install.sql”脚本在其中具有硬编码路径。
PGMOD=`pwd`/libMyMod.so
psql $(DBNAME) --set=MOD=\'$(PGMOD)\' -f install.sql
安装脚本包含您导出的每个函数的这些语句之一。
获得正确的输入/输出类型绝对至关重要,因为系统无法验证它们,您最终可能会占用内存、存储空间等。您可以看到 pg 类型到 c 类型的翻译 here
create or replace function add_one(integer)
returns integer as :MOD,'AddOne'
LANGUAGE C STRICT;
关于postgresql - Postgresql 的 Golang 过程语言,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38590942/
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
几个月前,我读了一篇关于rubygem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:
?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------
嗨~大家好,这里是可莉!今天给大家带来的是7个C语言的经典基础代码~那一起往下看下去把【程序一】打印100到200之间的素数#includeintmain(){ inti; for(i=100;i 【程序二】输出乘法口诀表#includeintmain(){inti;for(i=1;i 【程序三】判断1000年---2000年之间的闰年#includeintmain(){intyear;for(year=1000;year 【程序四】给定两个整形变量的值,将两个值的内容进行交换。这里提供两种方法来进行交换,第一种为创建临时变量来进行交换,第二种是不创建临时变量而直接进行交换。1.创建临时变量来
我已经找到了几个使用datamapper的示例,并且能够让它们正常工作。不过,所有这些示例都是针对sqlite数据库的。我正在尝试将数据映射器与postgresql一起使用。我将datamapper中的调用从sqlite3更改为postgres,并且我已经安装了dm-postgres-adapter。但它仍然不起作用。我还需要做什么? 最佳答案 与SQLite不同,PostgreSQL不将数据库存储在单个文件中。在你拥有createdyourdatabase之后,尝试这样的事情:DataMapper.setup:default,{:
我找到了这样的东西:Rails:Howtolistdatabasetables/objectsusingtheRailsconsole?这一行没问题:ActiveRecord::Base.connection.tables并返回所有表但是ActiveRecord::Base.connection.table_structure("users")产生错误:ActiveRecord::Base.connection.table_structure("projects")我认为table_structure不是Postgres方法。如何列出Postgres数据库的Rails控制台中表中的所有
关闭。这个问题是off-topic.它目前不接受答案。想改进这个问题吗?Updatethequestion所以它是on-topic用于堆栈溢出。关闭11年前。Improvethisquestion我不经常使用ruby-通常它加起来相当于每两个月或更长时间编写一次脚本。我的大部分编程都是使用C++进行的,这与ruby有很大不同。由于我与ruby之间的差距如此之大,我总是忘记语言的基本方面(比如解析文本文件和其他简单的东西)。我想每天练习一些基本的东西,我想知道是否有一些我可以订阅的网站,并且会向我发送当天的Ruby问题或类似的东西。有人知道这样的站点/Internet服务吗?
如果特定语言环境中缺少翻译,如何配置i18n以使用en语言环境翻译?当前已插入翻译缺失消息。我正在使用RoR3.1。 最佳答案 找到相似的question这里是答案:#application.rb#railswillfallbacktoconfig.i18n.default_localetranslationconfig.i18n.fallbacks=true#railswillfallbacktoen,nomatterwhatissetasconfig.i18n.default_localeconfig.i18n.fallback
我想使用PostgreSQL中的point类型。我已经完成了:railsgmodelTestpoint:point最终的迁移是:classCreateTests当我运行时:rakedb:migrate结果是:==CreateTests:migrating====================================================--create_table(:tests)rakeaborted!Anerrorhasoccurred,thisandalllatermigrationscanceled:undefinedmethod`point'for#/hom
我正在使用带有单个“帐户”表的STI模型来保存用户和技术人员的信息(即用户...8)错误:test_the_truth(用户测试):ActiveRecord::StatementInvalid:PGError:ERROR:关系“技术人员”不存在:从“技术人员”中删除...从本质上讲,标准框架不承认Technicians和Users表(或PostgreSQL称它们为“关系”)不存在,事实上,应该别名为Accounts。有什么想法吗?我对RoR比较陌生,不知道如何解决这个问题而又不完全删除STI。 最佳答案 原来问题是由于存在:./te