如何将已编译的 PL/Java 代码直接从应用程序部署到 Postgres 数据库?

How to deploy compiled PL/Java code straight to Postgres database from application?

我已经安装了 PL/Java 二进制文件的 Postgres 数据库服务器。

我观察了获取示例 PL/Java 代码并在数据库上安装 运行 的过程,因为它首先将已编译的 .jar 文件从应用程序服务器移动到数据库服务器,通过文件传输,然后调用 sqlj.install_jar('file::<path>', 'name', true);.jar 加载到数据库服务器。

我正在寻找一种不同的方式来加载已编译的 PL/Java 代码,而无需诉诸上述文件传输方法。我正在查看 PL/Java 文档,其中提到 sqlj.install_jar 函数还支持从网络中提取 .jar。理论上,我可以让应用程序服务器短暂地启动一个 HTTP 文件服务器来为 .jar 文件提供服务,并调用 sqlj.install_jar 从临时网络服务器中提取 .jar。但是,如果不知道应用程序服务器的主机名(即不是本地主机或在 firewall/private 网络之后),这可能会很困难。

但是我想知道是否有更好的方法来做到这一点。我正在寻找一种方法,允许应用程序服务器使用与 Postgres 服务器的现有连接直接在 .jar 内推送实现,而无需求助于上面解释的 "hacks"。

PL/Java 中是否已经存在类似的内容?

很遗憾,简短的回答是“否”。此 PL/Java 未格式化或写入控制文件和 .sql 文件,需要将其部署为扩展。尽管无论我在他们的 official site 上读到什么 网站说它是 PG 的扩展。

但是要以 PG(postgres) 的方式安装扩展,你需要有它的控制文件,因为它是用 java 编写的,并且没有任何控制文件,它必须在它的编译中自己的方式。

通常 PGXS 是在 PG_CONFIG 文件的帮助下帮助编译 postgres 扩展的东西。

注意:在他们的网站上明确提到 "PL/Java can be downloaded, then built using Maven"

只是想分享一点我所知道的 :),希望对您有所帮助。

如果您在 psql 中这样做:

\df sqlj.install_jar

您将看到该函数有两个版本:

 Schema |    Name     | Result data type |                          Argument data types                           | Type 
--------+-------------+------------------+------------------------------------------------------------------------+------
 sqlj   | install_jar | void             | image bytea, jarname character varying, deploy boolean                 | func
 sqlj   | install_jar | void             | urlstring character varying, jarname character varying, deploy boolean | func

urlstring的是SQL/JRT标准规定的。采用 bytea 的扩展名是 PL/Java 非标准扩展名,但它对这种情况很有用。如果 jar 文件在您 运行 psql 所在的客户端计算机上可用,您可以执行以下操作:

postgres=$ \lo_import foo.jar
lo_import 16725
postgres=$ select sqlj.install_jar(lo_get(16725), 'foo', true);
 install_jar
-------------

(1 row)
postgres=$ \lo_unlink 16725
lo_unlink 16725

也就是说,你可以使用psql\lo_import命令,它会打开一个本地文件并将其另存为"large object" 在服务器上,并给你一个 Oid 号码来引用它(我的例子中的 16725 对你来说可能是一个不同的号码)。

一旦大对象存在,SQL 函数 lo_get(16725) returns 其内容作为 bytea,因此您可以将其传递给 bytea install_jar 的味道。完成后,您只需使用 \lo_unlink 从服务器中删除大对象。

如果您使用 JDBC 或其他一些编程方式 API 连接到服务器,您可以将本地 jar 文件绑定为 select sqlj.install_jar(?::bytea,?,?); 中的第一个参数。