当前位置: 首页 > news >正文

在duckdb 1.4中编译和使用postgresql协议插件duckdb-pgwire

编译步骤

到https://github.com/euiko/duckdb-pgwire 下载源代码包,并进入pgwire @ 3055550目录下载它和其它第三方组件源代码包, 注意第三方组件的目录务必和存储库保持一致。
将所有源代码解压到/par/duckdb-pgwire-main及相应目录下,先按照https://github.com/euiko/pgwire 提示单独编译测试pgwire组件,

root@6ae32a5ffcde:/par/duckdb-pgwire-main/pgwire# cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=TRUE -B build -DCMAKE_BUILD_TYPE=Release .
-- The C compiler identification is GNU 14.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/local/bin/gcc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Could NOT find QT (missing: QT_DIR)
CMake Warning (dev) at third_party/promise-cpp/CMakeLists.txt:44 (find_package):Policy CMP0084 is not set: The FindQt module does not exist forfind_package().  Run "cmake --help-policy CMP0084" for policy details.  Usethe cmake_policy command to set the policy and suppress this warning.This warning is for project developers.  Use -Wno-dev to suppress it.-- Could NOT find Qt3 (missing: QT_QT_LIBRARY QT_INCLUDE_DIR QT_MOC_EXECUTABLE)
CMake was unable to find desired Qt version: 3. Set advanced values QT_QMAKE_EXECUTABLE and QT3_QGLOBAL_H_FILE.
CMake Warning at third_party/promise-cpp/CMakeLists.txt:46 (message):QT not found, so project qt_timer will not be compiled-- Configuring done
-- Generating done
-- Build files have been written to: /par/duckdb-pgwire-main/pgwire/build
root@6ae32a5ffcde:/par/duckdb-pgwire-main/pgwire# cd build
root@6ae32a5ffcde:/par/duckdb-pgwire-main/pgwire/build# ls
CMakeCache.txt  DartConfiguration.tcl  Testing              compile_commands.json  test
CMakeFiles      Makefile               cmake_install.cmake  src                    third_party
root@6ae32a5ffcde:/par/duckdb-pgwire-main/pgwire/build# make
[  1%] Building CXX object third_party/promise-cpp/CMakeFiles/promise.dir/src/promise.cpp.o
[  2%] Linking CXX static library libpromise.a
[  2%] Built target promise
[  3%] Building CXX object src/pgwire/CMakeFiles/pgwire.dir/buffer.cpp.o
[  4%] Building CXX object src/pgwire/CMakeFiles/pgwire.dir/exception.cpp.o
[  4%] Building CXX object src/pgwire/CMakeFiles/pgwire.dir/io.cpp.o[  3%] Building CXX object src/pgwire/CMakeFiles/pgwire.dir/log.cpp.o
[  4%] Building CXX object src/pgwire/CMakeFiles/pgwire.dir/protocol.cpp.o
[  5%] Building CXX object src/pgwire/CMakeFiles/pgwire.dir/server.cpp.o
[  6%] Building CXX object src/pgwire/CMakeFiles/pgwire.dir/session.cpp.o
[  6%] Building CXX object src/pgwire/CMakeFiles/pgwire.dir/types.cpp.o
[  7%] Building CXX object src/pgwire/CMakeFiles/pgwire.dir/utils.cpp.o
[  8%] Building CXX object src/pgwire/CMakeFiles/pgwire.dir/writer.cpp.o
[  9%] Linking CXX static library libpgwire.a
make[2]: warning:  Clock skew detected.  Your build may be incomplete.
[ 11%] Built target pgwire
[ 12%] Building CXX object src/demo/CMakeFiles/pgwire-demo.dir/main.cpp.o
[ 12%] Linking CXX executable pgwire-demo
[ 12%] Built target pgwire-demo
[ 12%] Building CXX object third_party/catch2/src/CMakeFiles/Catch2.dir/catch2/benchmark/catch_chronometer.cpp.o
...
[ 95%] Building CXX object third_party/catch2/src/CMakeFiles/Catch2.dir/catch2/matchers/catch_matchers_templated.cpp.o
[ 96%] Building CXX object third_party/catch2/src/CMakeFiles/Catch2.dir/catch2/matchers/internal/catch_matchers_impl.cpp.o
[ 96%] Linking CXX static library libCatch2.a
[ 96%] Built target Catch2
[ 97%] Building CXX object third_party/catch2/src/CMakeFiles/Catch2WithMain.dir/catch2/internal/catch_main.cpp.o
[ 98%] Linking CXX static library libCatch2Main.a
[ 98%] Built target Catch2WithMain
[ 99%] Building CXX object test/CMakeFiles/pgwire-test.dir/utils.cpp.o
[100%] Linking CXX executable pgwire-test
[100%] Built target pgwire-test

编译完成后执行测试,这个演示程序允许指定IP和端口,默认是127.0.0.1:15432

root@6ae32a5ffcde:/par/duckdb-pgwire-main/pgwire/build# cd test
root@6ae32a5ffcde:/par/duckdb-pgwire-main/pgwire/build/test# ./pgwire-test
Randomness seeded to: 773044056
===============================================================================
All tests passed (3 assertions in 1 test case)root@6ae32a5ffcde:/par/duckdb-pgwire-main/pgwire/build/test#root@6ae32a5ffcde:/par/duckdb-pgwire-main/pgwire/build/test# cd ..
root@6ae32a5ffcde:/par/duckdb-pgwire-main/pgwire/build# cd ..
root@6ae32a5ffcde:/par/duckdb-pgwire-main/pgwire# ./build/src/demo/pgwire-demo --help
pgwire-demo is a demo program to showcase the usage of pgwire library
Usage: ./build/src/demo/pgwire-demo [OPTIONS]Available options:--host (-H)        Host to listen on (default: 127.0.0.1)--port (-P)        Port to listen on (default: 15432)--help (-h)        To show this usage
root@6ae32a5ffcde:/par/duckdb-pgwire-main/pgwire# ./build/src/demo/pgwire-demo
2025-10-02T02:44:27+00:00 [INFO] Starting server on 127.0.0.1:15432
2025-10-02T02:45:13+00:00 [INFO] [session #1] started
2025-10-02T02:45:13+00:00 [INFO] [session #1] [query #1] executing query "SELECT * FROM dummy_query"
2025-10-02T02:45:13+00:00 [INFO] [session #1] [query #1] query done, elapsed = 0.61ms
2025-10-02T02:45:20+00:00 [INFO] [session #1] done

另开一个终端,输入命令行,可返回结果,并且服务端有相应提示

root@6ae32a5ffcde:/# psql 'postgresql://localhost:15432/main' -c 'SELECT * FROM dummy_query'name   |  address  | age
----------+-----------+------kharista | indonesia |    1kharista | indonesia |    2kharista | indonesia |    3kharista | indonesia |    4kharista | indonesia |    5kharista | indonesia |    6kharista | indonesia |    7kharista | indonesia |    8

可见pgwire组件工作正常。

接下来编译duckdb_pgwire插件,先将各个组件的头文件目录全都加入查找路径,才能让g++识别。

root@6ae32a5ffcde:/par/duckdb-pgwire-main/src# g++ -fPIC -shared -o libtest2.so duckdb_pgwire_extension.cpp -I /par/extension-template/duckdb/src/include -I include -I ../pgwire/include  -I ../pgwire/third_party/promise-cpp/include -I ../pgwire/third_party/asio/asio/include  -I ../pgwire/third_party/endian/src -lduckdb -L /par/libduckdb
In file included from ../pgwire/include/pgwire/server.hpp:3,from duckdb_pgwire_extension.cpp:17:
../pgwire/include/pgwire/session.hpp:11:10: fatal error: function2/function2.hpp: No such file or directory11 | #include <function2/function2.hpp>|          ^~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
root@6ae32a5ffcde:/par/duckdb-pgwire-main/src# g++ -fPIC -shared -o libtest2.so duckdb_pgwire_extension.cpp -I /par/extension-template/duckdb/src/include -I include -I ../pgwire/include  -I ../pgwire/third_party/promise-cpp/include -I ../pgwire/third_party/asio/asio/include  -I ../pgwire/third_party/endian/src -I ../pgwire/third_party/function2/include -lduckdb -L /par/libduckdb
In file included from duckdb_pgwire_extension.cpp:5:
include/duckdb_pgwire_extension.hpp:9:10: error: 'void duckdb::DuckdbPgwireExtension::Load(duckdb::DuckDB&)' marked 'override', but does not override9 |     void Load(DuckDB &db) override;|          ^~~~
In file included from duckdb_pgwire_extension.cpp:10:
/par/extension-template/duckdb/src/include/duckdb/main/extension_util.hpp:7:15: error: static assertion failed: The DuckDB 'ExtensionUtil' class has been removed, see this PR for more details: https://github.com/duckdb/duckdb/pull/177727 | static_assert(false, "The DuckDB 'ExtensionUtil' class has been removed, see this PR for more details: "|               ^~~~~
duckdb_pgwire_extension.cpp: In function 'void duckdb::LoadInternal(DatabaseInstance&)':
duckdb_pgwire_extension.cpp:208:5: error: 'ExtensionUtil' has not been declared208 |     ExtensionUtil::RegisterFunction(instance,|     ^~~~~~~~~~~~~
duckdb_pgwire_extension.cpp:212:5: error: 'ExtensionUtil' has not been declared212 |     ExtensionUtil::RegisterFunction(instance, duckdb_pgwire_scalar_function);|     ^~~~~~~~~~~~~
duckdb_pgwire_extension.cpp: In function 'void duckdb_pgwire_init(duckdb::DatabaseInstance&)':
duckdb_pgwire_extension.cpp:226:16: error: 'class duckdb::DuckDB' has no member named 'LoadExtension'; did you mean 'LoadStaticExtension'?226 |     db_wrapper.LoadExtension<duckdb::DuckdbPgwireExtension>();|                ^~~~~~~~~~~~~|                LoadStaticExtension
duckdb_pgwire_extension.cpp:226:59: error: expected primary-expression before '>' token226 |     db_wrapper.LoadExtension<duckdb::DuckdbPgwireExtension>();|                                                           ^
duckdb_pgwire_extension.cpp:226:61: error: expected primary-expression before ')' token226 |     db_wrapper.LoadExtension<duckdb::DuckdbPgwireExtension>();|                                                             ^

因为duckdb_pgwire插件基于旧版DuckDB设计,很多函数在1.4版中都找不到了,需要对源代码修改。我参考1.4版的quack_extension修改duckdb_pgwire_extension.cpp如下

#include "duckdb/common/types.hpp"
#include <unordered_map>
#define DUCKDB_EXTENSION_MAIN#include <duckdb_pgwire_extension.hpp>#include <duckdb/common/exception.hpp>
#include <duckdb/common/string_util.hpp>
#include <duckdb/function/scalar_function.hpp>
//#include <duckdb/main/extension_util.hpp>
#include <duckdb/main/extension/extension_loader.hpp>
#include <duckdb/parser/parsed_data/create_scalar_function_info.hpp>#include <atomic>
#include <optional>
#include <pgwire/exception.hpp>
#include <pgwire/log.hpp>
#include <pgwire/server.hpp>
#include <pgwire/types.hpp>
#include <stdexcept>namespace duckdb {static std::atomic<bool> g_started;static std::unordered_map<LogicalTypeId, pgwire::Oid> g_typemap = {{LogicalTypeId::FLOAT, pgwire::Oid::Float4},{LogicalTypeId::DOUBLE, pgwire::Oid::Float8},// {LogicalTypeId::TINYINT, pgwire::Oid::Char},{LogicalTypeId::SMALLINT, pgwire::Oid::Int2},{LogicalTypeId::INTEGER, pgwire::Oid::Int4},{LogicalTypeId::BIGINT, pgwire::Oid::Int8},// uses string{LogicalTypeId::VARCHAR, pgwire::Oid::Varchar},{LogicalTypeId::DATE, pgwire::Oid::Date},{LogicalTypeId::TIME, pgwire::Oid::Time},{LogicalTypeId::TIMESTAMP, pgwire::Oid::Timestamp},{LogicalTypeId::TIMESTAMP, pgwire::Oid::TimestampTz},
};static pgwire::ParseHandler duckdb_handler(DatabaseInstance &db) {return [&db](std::string const &query) mutable {Connection conn(db);pgwire::PreparedStatement stmt;std::unique_ptr<PreparedStatement> prepared;std::optional<pgwire::SqlException> error;std::vector<std::string> column_names;std::vector<LogicalType> column_types;std::size_t column_total;try {prepared = conn.Prepare(query);if (!prepared) {throw std::runtime_error("failed prepare query with unknown error");}if (prepared->HasError()) {throw std::runtime_error(prepared->GetError());}column_names = prepared->GetNames();column_types = prepared->GetTypes();column_total = prepared->ColumnCount();} catch (std::exception &e) {error =pgwire::SqlException{e.what(), pgwire::SqlState::DataException};}// rethrow errorif (error) {throw *error;}stmt.fields.reserve(column_total);for (std::size_t i = 0; i < column_total; i++) {auto &name = column_names[i];auto &type = column_types[i];auto it = g_typemap.find(type.id());if (it == g_typemap.end()) {continue;}auto oid = it->second;// can't uses emplace_back for POD struct in C++17stmt.fields.push_back({name, oid});}stmt.handler = [column_total, p = std::move(prepared)](pgwire::Writer &writer,pgwire::Values const &parameters) mutable {std::unique_ptr<QueryResult> result;std::optional<pgwire::SqlException> error;try {result = p->Execute();if (!result) {throw std::runtime_error("failed to execute query with unknown error");}if (result->HasError()) {throw std::runtime_error(result->GetError());}} catch (std::exception &e) {// std::cout << "error occured during execute:" << std::endl;error = pgwire::SqlException{e.what(),pgwire::SqlState::DataException};}if (error) {throw *error;}auto &column_types = p->GetTypes();for (auto &chunk : *result) {auto row = writer.add_row();for (std::size_t i = 0; i < column_total; i++) {auto &type = column_types[i];auto it = g_typemap.find(type.id());if (it == g_typemap.end()) {continue;}auto value = chunk.iterator.chunk->GetValue(i, chunk.row);if (value.IsNull()) {row.write_null();continue;}switch (type.id()) {case LogicalTypeId::FLOAT:row.write_float4(chunk.GetValue<float>(i));break;case LogicalTypeId::DOUBLE:row.write_float8(chunk.GetValue<double>(i));break;case LogicalTypeId::SMALLINT:row.write_int2(chunk.GetValue<int16_t>(i));break;case LogicalTypeId::INTEGER:row.write_int4(chunk.GetValue<int32_t>(i));break;case LogicalTypeId::BIGINT:row.write_int8(chunk.GetValue<int64_t>(i));break;case LogicalTypeId::BOOLEAN:row.write_bool(chunk.GetValue<bool>(i));break;case LogicalTypeId::VARCHAR:case LogicalTypeId::DATE:case LogicalTypeId::TIME:case LogicalTypeId::TIMESTAMP:case LogicalTypeId::TIMESTAMP_TZ:row.write_string(chunk.GetValue<std::string>(i));break;default:break;}}}};return stmt;};
}static void start_server(DatabaseInstance &db) {using namespace asio;if (g_started)return;g_started = true;io_context io_context;ip::tcp::endpoint endpoint(ip::tcp::v4(), 15432);pgwire::log::initialize(io_context, "duckdb_pgwire.log");pgwire::Server server(io_context, endpoint,[&db](pgwire::Session &sess) mutable { return duckdb_handler(db); });server.start();
}inline void PgIsInRecovery(DataChunk &args, ExpressionState &state,Vector &result) {result.SetValue(0, false);
}inline void DuckdbPgwireScalarFun(DataChunk &args, ExpressionState &state, Vector &result) {auto &name_vector = args.data[0];UnaryExecutor::Execute<string_t, string_t>(name_vector, result, args.size(),[&](string_t name) {return StringVector::AddString(result, "DuckdbPgwire "+name.GetString()+" 🐥");;});
}
/*
static void LoadInternal(DatabaseInstance &instance) {// Register a scalar functionauto pg_is_in_recovery_scalar_function = ScalarFunction("pg_is_in_recovery", {}, LogicalType::BOOLEAN, PgIsInRecovery);ExtensionUtil::RegisterFunction(instance,pg_is_in_recovery_scalar_function);auto duckdb_pgwire_scalar_function = ScalarFunction("duckdb_pgwire", {LogicalType::VARCHAR}, LogicalType::VARCHAR, DuckdbPgwireScalarFun);ExtensionUtil::RegisterFunction(instance, duckdb_pgwire_scalar_function);std::thread([&instance]() mutable { start_server(instance); }).detach();
}void DuckdbPgwireExtension::Load(DuckDB &db) { LoadInternal(*db.instance); }
std::string DuckdbPgwireExtension::Name() { return "duckdb_pgwire"; }
*/static void LoadInternal(ExtensionLoader &loader) {// Register a scalar functionauto pg_is_in_recovery_scalar_function = ScalarFunction("pg_is_in_recovery", {}, LogicalType::BOOLEAN, PgIsInRecovery);loader.RegisterFunction(pg_is_in_recovery_scalar_function);// Register another scalar functionauto duckdb_pgwire_scalar_function = ScalarFunction("duckdb_pgwire", {LogicalType::VARCHAR}, LogicalType::VARCHAR, DuckdbPgwireScalarFun);loader.RegisterFunction(duckdb_pgwire_scalar_function);DatabaseInstance & instance=loader.GetDatabaseInstance();std::thread([&instance]() mutable { start_server(instance); }).detach();
}void DuckdbPgwireExtension::Load(ExtensionLoader &loader) {LoadInternal(loader);
}
std::string DuckdbPgwireExtension::Name() {return "duckdb_pgwire";
}
std::string DuckdbPgwireExtension::Version() const {
#ifdef EXT_VERSION_QUACKreturn EXT_VERSION_QUACK;
#elsereturn "";
#endif
}} // namespace duckdbextern "C" {
/*
DUCKDB_EXTENSION_API void duckdb_pgwire_init(duckdb::DatabaseInstance &db) {duckdb::DuckDB db_wrapper(db);db_wrapper.LoadExtension<duckdb::DuckdbPgwireExtension>();
}DUCKDB_EXTENSION_API const char *duckdb_pgwire_version() {return duckdb::DuckDB::LibraryVersion();
}
*/
DUCKDB_CPP_EXTENSION_ENTRY(duckdb_pgwire, loader) {duckdb::LoadInternal(loader);
}
}#ifndef DUCKDB_EXTENSION_MAIN
#error DUCKDB_EXTENSION_MAIN not defined
#endif

同时修改include/duckdb_pgwire_extension.hpp如下

#pragma once#include <duckdb.hpp>namespace duckdb {class DuckdbPgwireExtension : public Extension {public://void Load(DuckDB &db) override;void Load(ExtensionLoader &db);std::string Name() override;std::string Version() const override;    
};} // namespace duckdb 

编译完成后用python脚本添加元数据

python3 /par/appendmetadata.py -l libtest2.so -n duckdb_pgwire -dv v1.4.0   --duckdb-platform linux_amd64 --extension-version 0.1 --abi-type ""

加载出错,有未定义的符号,想要静态链接libpgwire.a,也出错了

root@6ae32a5ffcde:/par/duckdb-pgwire-main/src# export LD_LIBRARY_PATH=/par/libduckdb
root@6ae32a5ffcde:/par/duckdb-pgwire-main/src# /par/duckdb140 -unsigned
DuckDB v1.4.0 (Andium) b8a06e4a22
Enter ".help" for usage hints.
D load '/par/duckdb-pgwire-main/src/duckdb_pgwire.duckdb_extension';
IO Error:
Extension "/par/duckdb-pgwire-main/src/duckdb_pgwire.duckdb_extension" could not be loaded: /par/duckdb-pgwire-main/src/duckdb_pgwire.duckdb_extension: undefined symbol: _ZTIN6pgwire12SqlExceptionE
D .exit
root@6ae32a5ffcde:/par/duckdb-pgwire-main/src# g++ -fPIC -shared -o libtest2.so duckdb_pgwire_extension.cpp -I /par/extension-template/duckdb/src/include -I include -I ../pgwire/include  -I ../pgwire/third_party/promise-cpp/include -I ../pgwire/third_party/asio/asio/include  -I ../pgwire/third_party/endian/src -I ../pgwire/third_party/function2/include -lduckdb -L /par/libduckdb ../pgwire/build/src/pgwire/libpgwire.a
/usr/bin/ld: ../pgwire/build/src/pgwire/libpgwire.a(exception.cpp.o): relocation R_X86_64_32S against symbol `_ZTVN6pgwire12SqlExceptionE' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: failed to set dynamic section sizes: bad value
collect2: error: ld returned 1 exit status

干脆把pgwire编成动态库libpgwire.so, 然后让duckdb-pgwire插件再动态链接它

root@6ae32a5ffcde:/par/duckdb-pgwire-main/src# g++ -fPIC -shared -o libpgwire.so ../pgwire/src/pgwire/*.cpp -I /par/extension-template/duckdb/src/include -I include -I ../pgwire/include  -I ../pgwire/third_party/promise-cpp/include -I ../pg
wire/third_party/asio/asio/include  -I ../pgwire/third_party/endian/src -I ../pgwire/third_party/function2/include
root@6ae32a5ffcde:/par/duckdb-pgwire-main/src# g++ -fPIC -shared -o libtest2.so duckdb_pgwire_extension.cpp -I /par/extension-template/duckdb/src/include -I include -I ../pgwire/include  -I ../pgwire/third_party/promise-cpp/include -I ../pgwire/third_party/asio/asio/include  -I ../pgwire/third_party/endian/src -I ../pgwire/third_party/function2/include -lduckdb -L /par/libduckdb -lpgwire -L .
root@6ae32a5ffcde:/par/duckdb-pgwire-main/src# python3 /par/appendmetadata.py -l libtest2.so -n duckdb_pgwire -dv v1.4.0  --duckdb-platform linux_amd64 --extension-version 0.1 --abi-type ""

插件可以加载了

root@6ae32a5ffcde:/par/duckdb-pgwire-main/src# /par/duckdb140 -unsigned
DuckDB v1.4.0 (Andium) b8a06e4a22
Enter ".help" for usage hints.
D load '/par/duckdb-pgwire-main/src/duckdb_pgwire.duckdb_extension';D select duckdb_pgwire('asdf');
┌───────────────────────┐
│ duckdb_pgwire('asdf') │
│        varchar        │
├───────────────────────┤
│ DuckdbPgwire asdf 🐥  │
└───────────────────────┘
D select pg_is_in_recovery();
┌─────────────────────┐
│ pg_is_in_recovery() │
│       boolean       │
├─────────────────────┤
│ false               │
└─────────────────────┘
D .exitroot@6ae32a5ffcde:/par/duckdb-pgwire-main/src# /par/duckdb140 -unsigned -cmd "load '/par/duckdb-pgwire-main/src/duckdb_pgwire.duckdb_extension'"
DuckDB v1.4.0 (Andium) b8a06e4a22
Enter ".help" for usage hints.
D select duckdb_pgwire('asdf');
┌───────────────────────┐
│ duckdb_pgwire('asdf') │
│        varchar        │
├───────────────────────┤
│ DuckdbPgwire asdf 🐥  │
└───────────────────────┘

但是再开一个客户端,用psql访问不行,

root@6ae32a5ffcde:/# psql 'postgresql://localhost:15432/main' -c 'select * from generate_series(0, 4)'
psql: error: connection to server at "localhost" (127.0.0.1), port 15432 failed: Connection refusedIs the server running on that host and accepting TCP/IP connections?

仔细比对修改前后源代码,发现我遗漏了一句

    std::thread([&instance]() mutable { start_server(instance); }).detach();

而这里需要的instance, 在函数参数里没有,怎么获取,查看duckdb/main/extension/extension_loader.cpp中定义

namespace duckdb {ExtensionLoader::ExtensionLoader(ExtensionActiveLoad &load_info): db(load_info.db), extension_name(load_info.extension_name), extension_info(load_info.info) {
}ExtensionLoader::ExtensionLoader(DatabaseInstance &db, const string &name) : db(db), extension_name(name) {
}DatabaseInstance &ExtensionLoader::GetDatabaseInstance() {return db;
}

所以把上述语句改为

	DatabaseInstance & instance=loader.GetDatabaseInstance();std::thread([&instance]() mutable { start_server(instance); }).detach();

重新编译,处理,加载,这次再用psql就能访问了。

root@6ae32a5ffcde:/# psql 'postgresql://localhost:15432/main' -c 'select * from generate_series(0, 4)'generate_series
-----------------01234
(5 rows)

至此,我们可以通过插件duckdb-pgwire为duckdb添加postgresql协议,用支持这个协议的工具来访问了。

root@6ae32a5ffcde:/# psql 'postgresql://localhost:15432/main'
psql (15.13 (Debian 15.13-0+deb12u1), server 14)
Type "help" for help.main=> select version();"version"()
-------------v1.4.0
(1 row)main=> select * from duckdb_functions() where function_name like '%pgwire%';database_name | database_oid | schema_name | function_name | alias_of | function_type | description | comment | return_
type | varargs | macro_definition | function_oid | stability
---------------+--------------+-------------+---------------+----------+---------------+-------------+---------+--------
-----+---------+------------------+--------------+------------system        | 0            | main        | duckdb_pgwire |          | scalar        |             |         | VARCHAR|         |                  |         1998 | CONSISTENT
(1 row)
http://www.dtcms.com/a/434920.html

相关文章:

  • 鸿蒙开发2--常用UI组件与@State状态管理入门
  • Spring Boot 配置属性松散绑定
  • 重庆网站产品推广浙江省建设厅证书查询
  • 【代码随想录day 32】 力扣 509.斐波那契数列
  • 工信部网站备案怎么登录青岛公司做网站的价格
  • C语言中的scanf函数(头文件、格式控制、取地址符号分析)
  • 洛谷——P2437 蜜蜂路线
  • 网页制作网站花店水头网站建设
  • 在网站上做承诺书厦门在线制作网站
  • 国家认可的赚钱平台东莞seo网络推广专
  • 安装网站wordpress加个微信登录
  • 在线音频三选一强制选择测试(3-AFC)
  • 高斯消元矩阵
  • 吉林网站优化路得威网站谁做的
  • 神经网络之理解温度对Softmax的影响
  • 做视频怎么去除网站个人网站代做
  • Linux中信号量semaphore的实现
  • 广州网站推广公司建筑工程公司是干嘛的
  • ESP32驱动DHT11温湿度传感器详解
  • flask做的网站 网址做网站推广有什么升职空间
  • 网站上线过程做美团网站多少钱
  • 微信分享网站短链接怎么做公司的介绍怎么写
  • 算法分析:时间和空间复杂度
  • 第6章串数组:稀疏矩阵的十字链表表示
  • 【STM32项目开源】基于STM32的工地环境监测系统
  • 手机登录网站怎么建设如何做一个网站代码
  • 解决django.db.utils.OperationalError: attempt to write a readonly database错误
  • CAN-超时计数器(Timeout Counter)
  • 网站建设策划有哪些建设网站用英文怎么说
  • 报告派研读:2025年光学光电子深度报告