Coder Social home page Coder Social logo

alitrack / duckdb_fdw Goto Github PK

View Code? Open in Web Editor NEW
285.0 5.0 18.0 1.47 MB

DuckDB Foreign Data Wrapper for PostgreSQL

License: MIT License

Makefile 0.05% C 23.94% PLpgSQL 47.31% Shell 0.02% C++ 28.63% Dockerfile 0.04%
duckdb foreign-data-wrapper postgresql duckdb-fdw fdw

duckdb_fdw's Introduction

DuckDB Foreign Data Wrapper for PostgreSQL

This is a foreign data wrapper (FDW) to connect PostgreSQL to DuckDB database file. This FDW works with PostgreSQL 9.6 ... 16 and works with exact same version of libduckdb.

PostgreSQL + DuckDB

Contents

  1. Features
  2. Supported platforms
  3. Installation
  4. Usage
  5. Functions
  6. Identifier case handling
  7. Generated columns
  8. Character set handling
  9. Examples
  10. Limitations
  11. Tests
  12. Contributing
  13. Useful links
  14. License

Features

Common features

  • Transactions
  • Support TRUNCATE by deparsing into DELETE statement without WHERE clause
  • Allow control over whether foreign servers keep connections open after transaction completion. This is controlled by keep_connections and defaults to on
  • Support list cached connections to foreign servers by using function duckdb_fdw_get_connections()
  • Support discard cached connections to foreign servers by using function duckdb_fdw_disconnect(), duckdb_fdw_disconnect_all().
  • Support Bulk INSERT by using batch_size option
  • Support INSERT/UPDATE with generated column

Pushdowning

  • not described

Notes about pushdowning

  • not described

Notes about features

Also see Limitations

Supported platforms

duckdb_fdw was developed on macOS and tested on Linux, so it should run on any reasonably POSIX-compliant system.

Installation

Package installation

There's a duckdb_fdw rpm available on Pigsty's PGSQL yum repository for el8 and el9

Source installation

Prerequisites:

  • postgresql-server-{version}-dev
  • gcc
  • make

1. Download source

git clone https://github.com/alitrack/duckdb_fdw
cd duckdb_fdw

2. Download DuckDB library

For example, we want to compile under Linux AMD64 with DuckDB v1.0.0, just download libduckdb-linux-amd64.zip

wget -c https://github.com/duckdb/duckdb/releases/download/v1.0.0/libduckdb-linux-amd64.zip
unzip -d . libduckdb-linux-amd64.zip

# you can also put the libduckdb.so to a directory in LD_LIBRARY_PATH, such as /usr/lib64
cp libduckdb.so $(pg_config --libdir)

Beware that this libduckdb.so is build on ubuntu with higher glibc version, to use duckdb_fdw on el8 / el9, you have to compile [libduckdb-src.zip](https://github.com/duckdb/duckdb/releases/download/v1.0.0/libduckdb-src.zip) from source

3. Build and install duckdb_fdw

Add a directory of pg_config to PATH and build and install duckdb_fdw.

make USE_PGXS=1
make install USE_PGXS=1

If you want to build duckdb_fdw in a source tree of PostgreSQL, use

make
make install

Usage

CREATE SERVER options

duckdb_fdw accepts the following options via the CREATE SERVER command:

  • database as string, required

    DuckDB database path.

  • truncatable as boolean, optional, default false

    Allows foreign tables to be truncated using the TRUNCATE command.

  • keep_connections as boolean, optional, default false

    Allows to keep connections to DuckDB while there is no SQL operations between PostgreSQL and DuckDB.

  • batch_size as integer, optional, default 1

    Specifies the number of rows which should be inserted in a single INSERT operation. This setting can be overridden for individual tables.

  • temp_directory as string, optional, default NULL

    Specifies the directory to which to write temp files.

CREATE USER MAPPING options

There is no user or password conceptions in DuckDB, hence duckdb_fdw no need any CREATE USER MAPPING command.

In OS duckdb_fdw works as executed code with permissions of user of PostgreSQL server. Usually it is postgres OS user. For interacting with DuckDB database without access errors ensure this user have permissions on DuckDB file and, sometimes, directory of the file.

  • read permission on all directories by path to the DuckDB database file;
  • read permission on DuckDB database file;

CREATE FOREIGN TABLE options

duckdb_fdw accepts the following table-level options via the CREATE FOREIGN TABLE command:

  • table as string, optional, no default

    DuckDB table name. Use if not equal to name of foreign table in PostgreSQL. Also see about identifier case handling.

  • truncatable as boolean, optional, default from the same CREATE SERVER option

    See CREATE SERVER options section for details.

  • batch_size as integer, optional, default from the same CREATE SERVER option

    See CREATE SERVER options section for details.

duckdb_fdw accepts the following column-level options via the CREATE FOREIGN TABLE command:

  • column_name as string, optional, no default

    This option gives the column name to use for the column on the remote server. Also see about identifier case handling.

  • column_type as string, optional, no default

    Option to convert INT DuckDB column (epoch Unix Time) to be treated/visualized as TIMESTAMP in PostgreSQL.

  • key as boolean, optional, default false

    Indicates a column as a part of primary key or unique key of DuckDB table.

IMPORT FOREIGN SCHEMA options

duckdb_fdw supports IMPORT FOREIGN SCHEMA (PostgreSQL 9.5+) and accepts no custom options for this command.

TRUNCATE support

duckdb_fdw implements the foreign data wrapper TRUNCATE API, available from PostgreSQL 14.

As SQlite does not provide a TRUNCATE command, it is simulated with a simple unqualified DELETE operation.

TRUNCATE ... CASCADE support not described.

Functions

As well as the standard duckdb_fdw_handler() and duckdb_fdw_validator() functions, duckdb_fdw provides the following user-callable utility functions:

  • SETOF record duckdb_fdw_get_connections(server_name text, valid bool)

  • bool duckdb_fdw_disconnect(text)

    Closes connection from PostgreSQL to DuckDB in the current session.

  • bool duckdb_fdw_disconnect_all()

  • duckdb_fdw_version();

    Returns standard "version integer" as major version * 10000 + minor version * 100 + bugfix.

duckdb_fdw_version
--------------------
              10000  

DuckDB_execute

FUNCTION duckdb_execute(server name, stmt text) RETURNS void

This function can be used to execute arbitrary SQL statements on the remote DuckDB server. That will only work with statements that do not return results (typically DDL statements).

Be careful when using this function, since it might disturb the transaction management of duckdb_fdw. Remember that running a DDL statement in DuckDB will issue an implicit COMMIT. You are best advised to use this function outside multi-statement transactions.

It is very useful to use command that duckdb_fdw does not support, for example,

  • add more table or view to DuckDB directly.
SELECT duckdb_execute('duckdb_server'
,'create or replace view iris_parquet  as select * from parquet_scan(''temp/iris.parquet'');');

create foreign TABLE duckdb.iris_parquet(
"Sepal.Length" float,  
"Sepal.Width" float,
"Petal.Length" float,
"Petal.Width" float,  
"Species" text)
      SERVER duckdb_server OPTIONS (table 'iris_parquet');

-- or an easy way

IMPORT FOREIGN SCHEMA public limit to (iris_parquet) FROM SERVER  
duckdb_server INTO duckdb;
  • run Copy command on Foreign table
SELECT duckdb_execute('duckdb_server'
,'CREATE TABLE test (a INTEGER, b INTEGER, c VARCHAR(10));
');
SELECT duckdb_execute('duckdb_server'  
,'COPY test FROM ''/tmp/test.csv'';');

Identifier case handling

PostgreSQL folds identifiers to lower case by default. DuckDB behaviour not described. It's important to be aware of potential issues with table and column names.

Generated columns

DuckDB provides support for generated columns. Behaviour of duckdb_fdw with these columns isn't yet described.

Note that while duckdb_fdw will INSERT or UPDATE the generated column value in DuckDB, there is nothing to stop the value being modified within DuckDB, and hence no guarantee that in subsequent SELECT operations the column will still contain the expected generated value. This limitation also applies to postgres_fdw.

For more details on generated columns see:

Character set handling

Yet not described

Examples

Install the extension

Once for a database you need, as PostgreSQL superuser.

CREATE EXTENSION duckdb_fdw;

Create a foreign server with appropriate configuration:

Once for a foreign datasource you need, as PostgreSQL superuser. Please specify DuckDB database path using database option.

CREATE SERVER duckdb_server
FOREIGN DATA WRAPPER duckdb_fdw
OPTIONS (
    database '/path/to/database'
);

Grant usage on foreign server to normal user in PostgreSQL:

Once for a normal user (non-superuser) in PostgreSQL, as PostgreSQL superuser. It is a good idea to use a superuser only where really necessary, so let's allow a normal user to use the foreign server (this is not required for the example to work, but it's secirity recomedation).

GRANT USAGE ON FOREIGN SERVER duckdb_server TO pguser;

Where pguser is a sample user for works with foreign server (and foreign tables).

User mapping

There is no user or password conceptions in DuckDB, hence duckdb_fdw no need any CREATE USER MAPPING command. About access problems see in CREATE USER MAPPING options.

Create foreign table

All CREATE FOREIGN TABLE SQL commands can be executed as a normal PostgreSQL user if there were correct GRANT USAGE ON FOREIGN SERVER. No need PostgreSQL supersuer for secirity reasons but also works with PostgreSQL supersuer.

Please specify table option if DuckDB table name is different from foreign table name.

	CREATE FOREIGN TABLE t1 (
	  a integer,
	  b text
	)
	SERVER duckdb_server
	OPTIONS (
	  table 't1_duckdb'
	);

If you want to update tables, please add OPTIONS (key 'true') to a primary key or unique key like the following:

	CREATE FOREIGN TABLE t1(
	  a integer OPTIONS (key 'true'),
	  b text
	)
	SERVER duckdb_server 
	OPTIONS (
	  table 't1_duckdb'
	);

If you need to convert INT DuckDB column (epoch Unix Time) to be treated/visualized as TIMESTAMP in PostgreSQL, please add OPTIONS (column_type 'INT') when defining FOREIGN table at PostgreSQL like the following:

	CREATE FOREIGN TABLE t1(
	  a integer,
	  b text,
	  c timestamp without time zone OPTIONS (column_type 'INT')
	)
	SERVER duckdb_server
	OPTIONS (
	  table 't1_duckdb'
	);

As above, but with aliased column names:

	CREATE FOREIGN TABLE t1(
	  a integer,
	  b text OPTIONS (column_name 'test_id'),
	  c timestamp without time zone OPTIONS (column_type 'INT', column_name 'unixtime')
	)
	SERVER duckdb_server
	OPTIONS (
	  table 't1_duckdb'
	);

Import a DuckDB database as schema to PostgreSQL:

	IMPORT FOREIGN SCHEMA someschema
	FROM SERVER duckdb_server
	INTO public;

Note: someschema has no particular meaning and can be set to an arbitrary value.

Access foreign table

For the table from previous examples

	SELECT * FROM t1;

Limitations

  • INSERT into a partitioned table which has foreign partitions is not supported. Error Not support partition insert will display.
  • TRUNCATE in duckdb_fdw always delete data of both parent and child tables (no matter user inputs TRUNCATE table CASCADE or TRUNCATE table RESTRICT) if there are foreign-keys references with ON DELETE CASCADE clause.
  • RETURNING is not supported.

Tests

All tests are based on make check, main testing script see in test.sh file. We don't profess a specific environment. You can use any POSIX-compliant system. Testing scripts from PosgreSQL-side is multi-versioned. Hence, you need install PostgreSQL packages in versions listed in sql directory. PostgreSQL server locale for messages in tests must be english. About base testing mechanism see in PostgreSQL documentation.

Testing directory have structure as following:

+---sql
    +---11.7
    |       filename1.sql
    |       filename2.sql
    | 
    +---12.12
    |       filename1.sql
    |       filename2.sql
    | 
.................  
    \---15.0
           filename1.sql
           filename2.sql

The test cases for each version are based on the test of corresponding version of PostgreSQL. You can execute test by test.sh directly. The version of PostgreSQL is detected automatically by $(VERSION) variable in Makefile.

Contributing

Opening issues and pull requests on GitHub are welcome.

You don't need to squash small commits to one big in pull requests.

For pull request, please make sure these items below for testing:

  • Create test cases (if needed) for the latest version of PostgreSQL supported by duckdb_fdw.
  • Execute test cases and update expectations for the latest version of PostgreSQL
  • Test creation and execution for other PostgreSQL versions are welcome but not required.

Useful links

Source

Reference FDW realisation, postgres_fdw

General FDW Documentation

Other FDWs

Special thanks

Authors of https://github.com/pgspider/sqlite_fdw

License

MIT License

duckdb_fdw's People

Contributors

ahuarte47 avatar alex-monahan avatar alitrack avatar eydunn avatar mkgrgis avatar vonng avatar wearpants avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

duckdb_fdw's Issues

failed to open sqlite db error

pg15
duckdb 0.10.1

create server ds foreign data wrapper duckdb_fdw options (database '/home/postgres/duckdb');

select duckdb_execute('ds','create table t1(a integer ,b integer ,c varchar(10));');
ERROR: failed to open SQLite DB. rc=1 path=/home/postgres/duckdb

select duckdb_execute('ds','create or replace view myv select now();');
ERROR: failed to open SQLite DB. rc=1 path=/home/postgres/duckdb

the fdw just worked with precreated database with duckdb cli,I want to know if it can work without duckdb cli,just use duckdb with fdw and duckdb_execute to create table and using it? thanks

ERROR on PolarDB 11.9

./duckdb /home/postgres/db    
  
COPY (select generate_series as id, md5(random()::text) as info,   
now()::timestamp+(generate_series||' second')::interval as crt_time   
from generate_series(1,100)) TO '/home/postgres/t1.parquet' (FORMAT 'PARQUET');    
    
COPY (select generate_series as cid, md5(random()::text) as info,   
now()::timestamp+(generate_series||' second')::interval as crt_time   
from generate_series(1,100)) TO '/home/postgres/t2.parquet' (FORMAT 'PARQUET');    
    
COPY (select (floor(random()*100)+1)::int as gid, (floor(random()*100)+1)::int as cid,   
(random()*10)::int as c1, (random()*100)::int as c2, (random()*1000)::int as c3,   
(random()*10000)::int as c4, (random()*100000)::int as c5 from generate_series(1,1000000))   
TO '/home/postgres/t3.parquet' (FORMAT 'PARQUET');    
    
create view t1 as select * from read_parquet('/home/postgres/t1.parquet');    
create view t2 as select * from read_parquet('/home/postgres/t2.parquet');    
create view t3 as select * from read_parquet('/home/postgres/t3.parquet');    
    
checkpoint;    
  
postgres=# \set VERBOSITY verbose
postgres=# set client_min_messages =DEBUG3;

postgres=# create extension duckdb_fdw;   
CREATE EXTENSION
postgres=# CREATE SERVER DuckDB_server FOREIGN DATA WRAPPER duckdb_fdw OPTIONS   
postgres-#   (database '/home/postgres/db');    
CREATE SERVER
postgres=# IMPORT FOREIGN SCHEMA public FROM SERVER DuckDB_server INTO public;  
DEBUG:  00000: duckdb_fdw : duckdb_fdw_handler
LOCATION:  duckdb_fdw_handler, duckdb_fdw.c:428
DEBUG:  00000: duckdb_fdw : sqliteImportForeignSchema
LOCATION:  sqliteImportForeignSchema, duckdb_fdw.c:2964
DEBUG:  00000: duckdb_fdw xact_callback 2
LOCATION:  sqlitefdw_xact_callback, connection.c:394
ERROR:  HV00L: SQL error during prepare: bad parameter or other API misuse SELECT current_catalog() as remote_catalog
LOCATION:  sqlite_prepare_wrapper, duckdb_fdw.c:503

postgres=# 
postgres=# create foreign table t1 (id int8, info text, crt_time timestamp) server duckdb_server OPTIONS (table 't1');
CREATE FOREIGN TABLE
postgres=# select * from t1;
DEBUG:  00000: PX Failed: param polar_enable_px is off
LOCATION:  should_px_planner, planner.c:7859
DEBUG:  00000: duckdb_fdw : sqliteGetForeignRelSize
LOCATION:  sqliteGetForeignRelSize, duckdb_fdw.c:524
DEBUG:  00000: duckdb_fdw : sqliteGetForeignPaths
LOCATION:  sqliteGetForeignPaths, duckdb_fdw.c:871
DEBUG:  00000: duckdb_fdw : sqliteGetForeignUpperPaths
LOCATION:  sqliteGetForeignUpperPaths, duckdb_fdw.c:3923
DEBUG:  00000: duckdb_fdw : sqliteGetForeignPlan
LOCATION:  sqliteGetForeignPlan, duckdb_fdw.c:1111
DEBUG:  00000: duckdb_fdw : sqliteBeginForeignScan
LOCATION:  sqliteBeginForeignScan, duckdb_fdw.c:1413
DEBUG:  00000: starting remote transaction on connection 0x55ee4b994518
LOCATION:  sqlite_begin_remote_xact, connection.c:326
DEBUG:  00000: duckdb_fdw do_sql_command BEGIN 0x55ee4b994518
LOCATION:  sqlite_do_sql_command, connection.c:285
DEBUG:  00000: duckdb_fdw xact_callback 2
LOCATION:  sqlitefdw_xact_callback, connection.c:394
ERROR:  HV000: SQLite failed to execute sql: BEGIN
LOCATION:  sqlite_do_sql_command, connection.c:306

detail info: https://github.com/digoal/blog/blob/master/202401/20240126_03.md

Failing to open DuckDB database

Hello @alitrack , thanks for the connector !
I can't open my duckdb inside psql (and neither using Postgres connection), it failed to open it.

My duckdb table:

root@server:/# ./duckdb test.db
0.2.4-dev0 436f6455f
Enter ".help" for usage hints.
D CREATE TABLE helloworld (phrase TEXT);
D INSERT INTO helloworld (phrase) VALUES ('Hello, World!');

My Error:

psql (13.1 (Debian 13.1-1.pgdg100+1))
Type "help" for help.

postgres=# CREATE SERVER testsrv FOREIGN DATA WRAPPER duckdb_fdw OPTIONS (database '/test.db');
CREATE SERVER
postgres=# IMPORT FOREIGN SCHEMA public FROM SERVER testsrv INTO public;
ERROR:  failed to open SQLite DB. rc=1 path=/test.db

My Env:

FROM postgres

RUN apt-get update && apt-get install -y \
  git \
  build-essential \
  cmake

RUN git clone https://github.com/cwida/duckdb.git \
  && cd duckdb \
  && make

RUN apt-get install -y postgresql-server-dev-13 postgresql-client-13

RUN git clone https://github.com/alitrack/duckdb_fdw.git  \
   && cd duckdb_fdw \
   && cp /duckdb/build/release/tools/sqlite3_api_wrapper/libsqlite3_api_wrapper.so $(pg_config --libdir)  \
   && cp /duckdb/tools/sqlite3_api_wrapper/include/sqlite3.h .  \
   && make USE_PGXS=1 \
   && make install USE_PGXS=1

ENV POSTGRES_HOST_AUTH_METHOD='trust'

Read only foreign server support

Please allow read-only connections again.

The latest versions of duckdb_fdw do not support read-only accesses and there are problems when querying from more than one session, or when querying foreign tables via Power BI.

I have managed to compile in read-only mode with this code modification, but it is somewhat static.

--- a/connection.c
+++ b/connection.c
@@ -210,7 +210,7 @@ sqlite_make_new_connection(ConnCacheEntry *entry, ForeignServer *server)
                // }
        }

-       rc = sqlite3_open_v2(dbpath, &entry->conn, DUCKDB_UNSIGNED_EXTENSIONS, NULL);
+       rc = sqlite3_open_v2(dbpath, &entry->conn, DUCKDB_UNSIGNED_EXTENSIONS  | SQLITE_OPEN_READONLY  , NULL);
        // rc = sqlite3_open_v2(dbpath, &entry->conn,flags, NULL);

Please consider including a foreign server option to enable it, as it was last year.

Thank you for writing this software.

Best regards.

Does duckdb v0.10.2 is supported?

I've succesfully built docker image for postgres 16.2 with duckdb_fdw and duckdb lib v0.10.2. Mapped duckdb database file with 777 "allow-all" permissions for files and all the directories into the container.

Attempt to read from foreign table or import foreign schema results into postgres server crash

server closed the connection unexpectedly
        This probably means the server terminated abnormally
        before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.
The connection to the server was lost. Attempting reset: Failed.

Connect to the same duckdb database file with the same jdbc jar lib version v0.10.2 from DBEaver works fine.

Support postgresql 16

Hello, please do you plan to support also postgresql 16?

I'm using duckdb_fdw in postgresql 15.5 (with 0.9.2 duckdb version) and work like a charm for my pipeline. I would like to upgrade to postgresql 16.1.

I tried to build for postgresql 16, but seem there too many changes in the permission area in postgresql 16
postgres/postgres@a61b1f74
https://www.postgresql.org/message-id/CA+HiwqGjJDmUhDSfv-U2qhKJjt9ST7Xh9JXC_irsAQ1TAUsJYg@mail.gmail.com

I got this error:

duckdb_fdw.c: In function ‘sqliteGetForeignRelSize’:
duckdb_fdw.c:552:53: error: ‘RangeTblEntry’ has no member named ‘checkAsUser’
  552 |                 Oid                     userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
      |                                                     ^~
duckdb_fdw.c:552:72: error: ‘RangeTblEntry’ has no member named ‘checkAsUser’
  552 |                 Oid                     userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
      |                                                                        ^~
duckdb_fdw.c: In function ‘sqlitePlanForeignModify’:
duckdb_fdw.c:1829:39: error: ‘RangeTblEntry’ has no member named ‘updatedCols’
 1829 |                 tmpset = bms_union(rte->updatedCols, rte->extraUpdatedCols);
      |                                       ^~
duckdb_fdw.c:1829:57: error: ‘RangeTblEntry’ has no member named ‘extraUpdatedCols’
 1829 |                 tmpset = bms_union(rte->updatedCols, rte->extraUpdatedCols);
      |                                                         ^~

Thank you for make this postgresql extension

Can't trunk install

Hi,
trunk install duckdb+fdw produces this output for me:

Failed to fetch Trunk archive from v1 API: Failed to find an archive for duckdb_fdw vlatest built for PostgreSQL 16

error: Cannot install extension for Postgres version 16 through the legacy endpoint

trunk -V: pg-trunk 0.12.26

Error when loading extension with duckdb 0.6.x: undefined symbol: sqlite3_bind_int64

Hello,

When I build duckdb_fdw with duckdb version 0.6.0 or 0.6.1, everything is fine. But when I try to load the extension, with create extension duckdb_fdw, I get the following error:

ERROR: could not load library "/usr/pgsql-14/lib/duckdb_fdw.so":
 /usr/pgsql-14/lib/duckdb_fdw.so: undefined symbol: sqlite3_bind_int64

I am using fedora 37, postgresql 14.6.

When I use it with the duckdb v0.5.1 tag, everything comes out OK.

I have noticed that when I do ldd duckdb_fdw.so, is not linked with the duckdb libraries:

This is the output I get for vesion 0.6.1:

        linux-vdso.so.1 (0x00007ffcd909e000)
	libc.so.6 => /lib64/libc.so.6 (0x00007fca80144000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fca80357000)

And this one for version 0.5.1:

        linux-vdso.so.1 (0x00007fff74edf000)
	libsqlite3_api_wrapper.so => /lib64/libsqlite3_api_wrapper.so (0x00007f81f3478000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f81f329b000)
	libduckdb.so => /root/duckdb6/duckdb/build/release/src/libduckdb.so (0x00007f81f1c00000)
	libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f81f1800000)
	libm.so.6 => /lib64/libm.so.6 (0x00007f81f1b20000)
	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f81f3279000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f81f34ca000)

Thank you for your work

IMPORT FOREIGN SCHEMA fails with "Ambiguous reference to catalog or schema"

When a duckdb database has both a catalog and a schema with the same name, the IMPORT FOREIGN SCHEMA command fails. Seems to be originating here

sprintf(query, "PRAGMA table_info(%s.%s)", quote_identifier(remote_schema), quote_identifier(table));

For example, I have a file called main.db with a schema called main

postgres=# IMPORT FOREIGN SCHEMA main from server duckdb_server into public; ERROR: SQL error during prepare: Binder Error: Ambiguous reference to catalog or schema "main" - use a fully qualified path like "temp.main" PRAGMA table_info(main.fhv_bases)

information_schema looks like:

 table_catalog | table_schema |      table_name      | table_type | self_referencing_column_name | reference_generation | user_defined_type_catalog | user_defined_type_schema | user_defined_type_name | is_insertable_into | is_typed | commit_action 
---------------+--------------+----------------------+------------+------------------------------+----------------------+---------------------------+--------------------------+------------------------+--------------------+----------+---------------
 main          | main         | fhv_bases            | BASE TABLE |                              |                      |                           |                          |                        | YES                | NO       | 
 main          | main         | central_park_weather | BASE TABLE |                              |                      |                           |                          |                        | YES                | NO       | 
 main          | main         | yellow_tripdata      | BASE TABLE |                              |                      |                           |                          |                        | YES                | NO       | 
 main          | main         | green_tripdata       | BASE TABLE |                              |                      |                           |                          |                        | YES                | NO       | 
 main          | main         | fhvhv_tripdata       | BASE TABLE |                              |                      |                           |                          |                        | YES                | NO       | 
 main          | main         | fhv_tripdata         | BASE TABLE |                              |                      |                           |                          |                        | YES                | NO       | 
 main          | main         | bike_data            | BASE TABLE |                              |                      |                           |                          |                        | YES                | NO       | 
 main          | myschema     | mytables_duckdb      | VIEW       |                              |                      |                           |                          |                        | NO                 | NO       | 
(8 rows)

compile duckdb_fdw error use libduckdb 0.10.0

g++ -Wall -Wpointer-arith -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -moutline-atomics -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -std=c++11 -D_GLIBCXX_USE_CXX11_ABI=0 -fPIC -I. -I./ -I/usr/include/postgresql/14/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o sqlite3_api_wrapper.o sqlite3_api_wrapper.cpp
sqlite3_api_wrapper.cpp:55:2: error: ‘PreservedError’ does not name a type
   55 |  PreservedError last_error;
      |  ^~~~~~~~~~~~~~
sqlite3_api_wrapper.cpp: In function ‘int sqlite3_open_v2(const char*, sqlite3**, int, const char*)’:
sqlite3_api_wrapper.cpp:185:9: error: ‘sqlite3’ {aka ‘struct sqlite3’} has no member named ‘last_error’
  185 |    pDb->last_error = PreservedError(ex);
      |         ^~~~~~~~~~
sqlite3_api_wrapper.cpp:185:22: error: ‘PreservedError’ was not declared in this scope
  185 |    pDb->last_error = PreservedError(ex);
      |                      ^~~~~~~~~~~~~~
sqlite3_api_wrapper.cpp:191:9: error: ‘sqlite3’ {aka ‘struct sqlite3’} has no member named ‘last_error’
  191 |    pDb->last_error = PreservedError(ex);
      |         ^~~~~~~~~~
sqlite3_api_wrapper.cpp:191:22: error: ‘PreservedError’ was not declared in this scope
  191 |    pDb->last_error = PreservedError(ex);
      |                      ^~~~~~~~~~~~~~
sqlite3_api_wrapper.cpp: In function ‘int sqlite3_prepare_v2(sqlite3*, const char*, int, sqlite3_stmt**, const char**)’:
sqlite3_api_wrapper.cpp:256:9: error: ‘sqlite3’ {aka ‘struct sqlite3’} has no member named ‘last_error’
  256 |     db->last_error = res->GetErrorObject();
      |         ^~~~~~~~~~
sqlite3_api_wrapper.cpp:265:8: error: ‘sqlite3’ {aka ‘struct sqlite3’} has no member named ‘last_error’
  265 |    db->last_error = prepared->error;
      |        ^~~~~~~~~~
sqlite3_api_wrapper.cpp:288:7: error: ‘sqlite3’ {aka ‘struct sqlite3’} has no member named ‘last_error’
  288 |   db->last_error = PreservedError(ex);
      |       ^~~~~~~~~~
sqlite3_api_wrapper.cpp:288:20: error: ‘PreservedError’ was not declared in this scope
  288 |   db->last_error = PreservedError(ex);
      |                    ^~~~~~~~~~~~~~
sqlite3_api_wrapper.cpp:291:7: error: ‘sqlite3’ {aka ‘struct sqlite3’} has no member named ‘last_error’
  291 |   db->last_error = PreservedError(ex);
      |       ^~~~~~~~~~
sqlite3_api_wrapper.cpp:291:20: error: ‘PreservedError’ was not declared in this scope
  291 |   db->last_error = PreservedError(ex);
      |                    ^~~~~~~~~~~~~~
sqlite3_api_wrapper.cpp: In function ‘int sqlite3_step(sqlite3_stmt*)’:
sqlite3_api_wrapper.cpp:348:14: error: ‘sqlite3’ {aka ‘struct sqlite3’} has no member named ‘last_error’
  348 |   pStmt->db->last_error = PreservedError("Attempting sqlite3_step() on a non-successfully prepared statement");
      |              ^~~~~~~~~~
sqlite3_api_wrapper.cpp:348:27: error: ‘PreservedError’ was not declared in this scope
  348 |   pStmt->db->last_error = PreservedError("Attempting sqlite3_step() on a non-successfully prepared statement");
      |                           ^~~~~~~~~~~~~~
sqlite3_api_wrapper.cpp:357:15: error: ‘sqlite3’ {aka ‘struct sqlite3’} has no member named ‘last_error’
  357 |    pStmt->db->last_error = pStmt->result->GetErrorObject();
      |               ^~~~~~~~~~
sqlite3_api_wrapper.cpp:362:65: error: ‘sqlite3’ {aka ‘struct sqlite3’} has no member named ‘last_error’
  362 |   if (!pStmt->result->TryFetch(pStmt->current_chunk, pStmt->db->last_error)) {
      |                                                                 ^~~~~~~~~~
sqlite3_api_wrapper.cpp:391:65: error: ‘sqlite3’ {aka ‘struct sqlite3’} has no member named ‘last_error’
  391 |   if (!pStmt->result->TryFetch(pStmt->current_chunk, pStmt->db->last_error)) {
      |                                                                 ^~~~~~~~~~
sqlite3_api_wrapper.cpp: In function ‘int sqlite3_finalize(sqlite3_stmt*)’:
sqlite3_api_wrapper.cpp:926:15: error: ‘sqlite3’ {aka ‘struct sqlite3’} has no member named ‘last_error’
  926 |    pStmt->db->last_error = pStmt->result->GetErrorObject();
      |               ^~~~~~~~~~
sqlite3_api_wrapper.cpp: In function ‘const char* sqlite3_errmsg(sqlite3*)’:
sqlite3_api_wrapper.cpp:1048:13: error: ‘sqlite3’ {aka ‘struct sqlite3’} has no member named ‘last_error’
 1048 |  return db->last_error.Message().c_str();
      |             ^~~~~~~~~~
make: *** [<builtin>: sqlite3_api_wrapper.o] Error 1

duckdb_fdw.so: undefined symbol: sqlite3_limit

I create a docker image.
When I run this image , it show this message:
unable load "/usr/lib/postgresql/15/lib/duckdb_fdw.so": /usr/lib/postgresql/15/lib/duckdb_fdw.so: undefined symbol: sqlite3_limit

this is my Dockerfile:
`FROM myaniu/duckdb-build:0.6.0 as duckdb

RUN set -x
&& cd /
&& git clone https://github.com/alitrack/duckdb_fdw.git

FROM myaniu/postgres:15.1

ARG PG_DEV_VERSION=15

COPY --from=duckdb /duckdb_fdw /duckdb_fdw
COPY --from=duckdb /duckdb/build/release/tools/sqlite3_api_wrapper/libsqlite3_api_wrapper.so /usr/lib/postgresql/15/lib/libsqlite3_api_wrapper.so
COPY --from=duckdb /duckdb/build/release/tools/sqlite3_api_wrapper/libsqlite3_api_wrapper.so /usr/lib/x86_64-linux-gnu/libsqlite3_api_wrapper.so
COPY --from=duckdb /duckdb/build/release/src/libduckdb.so /usr/lib/postgresql/15/lib/libduckdb.so
COPY --from=duckdb /duckdb/tools/sqlite3_api_wrapper/include/sqlite3.h /duckdb_fdw/sqlite3.h

RUN set -x
&& apt-get update && apt-get install -y --no-install-recommends ca-certificates make postgresql-server-dev-$PG_DEV_VERSION postgresql-client-$PG_DEV_VERSION gcc libsqlite3-dev libsqlite3-0 libc6-dev
&& cd /duckdb_fdw
&& make USE_PGXS=1
&& make install USE_PGXS=1
&& rm -rf /var/lib/apt/lists/*
&& apt-get purge -y --auto-remove make postgresql-server-dev-$PG_DEV_VERSION gcc libc6-dev libsqlite3-dev
&& rm -rf /duckdb_fdw

ENV POSTGRES_HOST_AUTH_METHOD='md5'

COPY docker-entrypoint-initdb.d/duckdb_fdw_enable.sql /docker-entrypoint-initdb.d/duckdb_fdw_enable.sql`

Thank you for writing this software.

在duckdb_fdw中调用'postgres_scan'时遇到一个libpq报错, 但是在duckdb cli中调用正常.

在duckdb_fdw中调用'postgres_scan'时遇到一个错误:

postgres=# 
SELECT duckdb_execute('duckdb_server',   
$$  
COPY (
select * from POSTGRES_SCAN('dbname=postgres user=postgres hostaddr=127.0.0.1 port=1921 password=123456', 'public', 't1')
) 
TO 's3://adc-oss-1872hd2/ECSOSS/u-ijr7vhba/test_import_from_pg1.parquet'; 
$$);  
ERROR:  HV00L: SQL error during prepare: IO Error: Unable to connect to Postgres at dbname=postgres user=postgres hostaddr=127.0.0.1 port=1921 password=123456: libpq is incorrectly linked to backend functions
   
COPY (
select * from POSTGRES_SCAN('dbname=postgres user=postgres hostaddr=127.0.0.1 port=1921 password=123456', 'public', 't1')
) 
TO 's3://adc-oss-1872hd2/ECSOSS/u-ijr7vhba/test_import_from_pg1.parquet'; 

LOCATION:  sqlite_prepare_wrapper, duckdb_fdw.c:504

这条调用在duckdb cli中直接调用是正常的.

Compatibility with MotherDuck connection string

I see that this current repo works with local duckdb server. Is there on the roadmap any plans for a connection to a duckdb server that is hosted on Motherduck using the connection string?

Undefined symbol linking DuckDB 0.9.2

I am getting undefined symbol when running in Ubuntu 22.04 the DuckDB FDW linked with DuckDB v0.9.2.
It runs properly with DuckDB v0.8.1.

Error:
could not load library "/duckdb_fdw.so": /duckdb_fdw.so: undefined symbol: _ZN6duckdb13KeywordHelper9IsKeywordERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE

Same issue in PostgreSQL 15.5 or 16.1.

Please, do you know what is the problem?

Dose duckdb_fdw install on windows?

What about "Add a directory of pg_config to PATH"? Postgresql 14 install on windows 10, and pg_config.exe is in "E:\Postgre\14\bin". I add this directory to system envirment variable PATH. Is it correct?
When I git clone https://github.com/alitrack/duckdb_fdw, and

PS E:\temp\polars_20221023\duckdb_fdw> make USE_PGXS=1
process_begin: CreateProcess(NULL, uname, ...) failed.
Makefile:23: pipe: No error
Makefile:40: *** PostgreSQL 10, 11, 12, 13, 14 or 15 is required to compile this extension.  Stop.

cannot find -lduckdb

Great work! Trying to pull this into a docker container for PostGIS but hitting an issue. Here is the Docker code I am running:

RUN apt install unzip

RUN wget https://github.com/alitrack/duckdb_fdw/archive/refs/heads/main.zip \
    && unzip main.zip \
    && cd duckdb_fdw-main 

RUN wget -c https://github.com/duckdb/duckdb/releases/download/v0.10.0/libduckdb-linux-amd64.zip \
    && unzip -d . libduckdb-linux-amd64.zip 

RUN cp libduckdb.so "/usr/lib/postgresql/16/bin/"

RUN cd duckdb_fdw-main \
    export PATH="/usr/lib/postgresql/16/bin/pg_config" \
    && make USE_PGXS=1 \
    && make install USE_PGXS=1 \
    && cd ..

Error that it's getting stuck on is - /usr/bin/ld: cannot find -lduckdb: No such file or directory

create extension error on PG 14

use this docker image:

# 拉取镜像, 第一次拉取一次即可. 或者需要的时候执行, 将更新到最新镜像版本.  
docker pull registry.cn-hangzhou.aliyuncs.com/digoal/opensource_database:pg14_with_exts_arm64  
  
# 启动容器  
docker run -d -it -P --cap-add=SYS_PTRACE --cap-add SYS_ADMIN --privileged=true --name pg --shm-size=1g registry.cn-hangzhou.aliyuncs.com/digoal/opensource_database:pg14_with_exts_arm64

##### 如果你想学习备份恢复、修改参数等需要重启数据库实例的case, 换个启动参数, 使用参数--entrypoint将容器根进程换成bash更好. 如下: 
docker run -d -it -P --cap-add=SYS_PTRACE --cap-add SYS_ADMIN --privileged=true --name pg --shm-size=1g --entrypoint /bin/bash registry.cn-hangzhou.aliyuncs.com/digoal/opensource_database:pg14_with_exts_arm64  
##### 以上启动方式需要进入容器后手工启动数据库实例: su - postgres; pg_ctl start;  
  
# 进入容器  
docker exec -ti pg bash  
  
# 连接数据库  
psql  
postgres=# create extension duckdb_fdw ;
ERROR:  could not load library "/usr/lib/postgresql/14/lib/duckdb_fdw.so": /usr/lib/postgresql/14/lib/duckdb_fdw.so: undefined symbol: _ZN6duckdb9Exception25ConstructMessageRecursiveERKSsRSt6vectorINS_20ExceptionFormatValueESaIS4_EE

no output and no errors

summary

I tried to access one of my duckdb-databases from within PostgreSQL. Rights are fine, I didn't get any error - but also no functionality. What am I doing wrong?

my database

$ chmod 777 /tmp/mydb
$ duckdb /tmp/mydb
v0.10.1 4a89d97db8
Enter ".help" for usage hints.
D SELECT count(*) FROM mydata;
┌──────────────┐
│ count_star() │
│    int64     │
├──────────────┤
│     72749940 │
└──────────────┘

inside postgresql

CREATE EXTENSION duckdb_fdw;

SELECT duckdb_fdw_version();
┌────────────────────┐
│ duckdb_fdw_version │
├────────────────────┤
│              20101 │
└────────────────────┘
(1 row)


CREATE SERVER myduckdb_server FOREIGN DATA WRAPPER duckdb_fdw OPTIONS ( database '/tmp/mydb' );
CREATE SCHEMA myduckdb;
IMPORT FOREIGN SCHEMA myduckdb FROM SERVER myduckdb_server INTO myduckdb;

-- has no tables
SELECT table_name FROM information_schema.tables WHERE table_schema = 'myduckdb';

SELECT * FROM information_schema.foreign_tables;
┌───────────────────────┬──────────────────────┬────────────────────┬────────────────────────┬─────────────────────┐
│ foreign_table_catalog │ foreign_table_schema │ foreign_table_name │ foreign_server_catalog │ foreign_server_name │
├───────────────────────┼──────────────────────┼────────────────────┼────────────────────────┼─────────────────────┤
└───────────────────────┴──────────────────────┴────────────────────┴────────────────────────┴─────────────────────┘
(0 rows)

-- connection is fine
SELECT duckdb_execute('myduckdb_server', 'SELECT count(*) FROM mydata;');
┌────────────────┐
│ duckdb_execute │
├────────────────┤
│                │
└────────────────┘
(1 row)

my install chain

git clone --depth=1 https://github.com/alitrack/duckdb_fdw
cd duckdb_fdw/

git remote add pr-author https://github.com/alitrack/duckdb_fdw.git
git fetch pr-author pull/38/head:pr-38
git checkout pr-38

wget https://github.com/duckdb/duckdb/releases/download/v0.10.1/libduckdb-linux-amd64.zip
unzip libduckdb-linux-amd64.zip
cp -a libduckdb.so "$(pg_config --libdir)"

# rm -rf /usr/lib/postgresql/16/lib/bitcode/duckdb_fdw/
# USE_PGXS=1 make uninstall
# USE_PGXS=1 make distclean
USE_PGXS=1 make
USE_PGXS=1 make install

Not able to get more than 19 rows with duckdb_fdw?

Here is a reproduction of the issue. 19 rows are displayed ok, but more than that the query is stuck.

CREATE EXTENSION duckdb_fdw;
CREATE SERVER duckdb_server FOREIGN DATA WRAPPER duckdb_fdw;
SELECT duckdb_execute('duckdb_server','CREATE TABLE s3table (a integer, b integer);');
SELECT duckdb_execute('duckdb_server','INSERT INTO s3table VALUES (1,2);');
SELECT duckdb_execute('duckdb_server','INSERT INTO s3table VALUES (3,222);');
SELECT duckdb_execute('duckdb_server','INSERT INTO s3table VALUES (12,215);');
SELECT duckdb_execute('duckdb_server','INSERT INTO s3table VALUES (122,14);');
SELECT duckdb_execute('duckdb_server','INSERT INTO s3table VALUES (121142,1512);');
SELECT duckdb_execute('duckdb_server','INSERT INTO s3table VALUES (512,1312);');
SELECT duckdb_execute('duckdb_server','INSERT INTO s3table VALUES (1432,1);');
SELECT duckdb_execute('duckdb_server','INSERT INTO s3table VALUES (152,12);');
SELECT duckdb_execute('duckdb_server','INSERT INTO s3table VALUES (312,2);');
SELECT duckdb_execute('duckdb_server','INSERT INTO s3table VALUES (112,11);');
SELECT duckdb_execute('duckdb_server','INSERT INTO s3table VALUES (6512,11442);');
SELECT duckdb_execute('duckdb_server','INSERT INTO s3table VALUES (412,1152);');
SELECT duckdb_execute('duckdb_server','INSERT INTO s3table VALUES (2212,1172);');
SELECT duckdb_execute('duckdb_server','INSERT INTO s3table VALUES (812,112);');
SELECT duckdb_execute('duckdb_server','INSERT INTO s3table VALUES (412,1132);');
SELECT duckdb_execute('duckdb_server','INSERT INTO s3table VALUES (122,1152);');
SELECT duckdb_execute('duckdb_server','INSERT INTO s3table VALUES (1312,54112);');
SELECT duckdb_execute('duckdb_server','INSERT INTO s3table VALUES (912,1152);');
SELECT duckdb_execute('duckdb_server','INSERT INTO s3table VALUES (512,3112);');
SELECT duckdb_execute('duckdb_server','INSERT INTO s3table VALUES (8142,2112);');
SELECT duckdb_execute('duckdb_server','INSERT INTO s3table VALUES (132,12);');
SELECT duckdb_execute('duckdb_server','INSERT INTO s3table VALUES (72,12);');
IMPORT FOREIGN SCHEMA public FROM SERVER duckdb_server INTO public;
SELECT * FROM s3table LIMIT 13;
SELECT * FROM s3table LIMIT 19;
SELECT * FROM s3table LIMIT 20;
SELECT * FROM s3table LIMIT 21;

Fail to build with new version of duckdb 0.8.0

Hello,

The build process failed with the new version of duckdb 0.8.0.

All errors seem similar to this one:

sqlite3_api_wrapper.cpp:91:9: error: reference to ‘unique_ptr’ is ambiguous
   91 |         unique_ptr<char[]> data;
      |         ^~~~~~~~~~
In file included from /usr/include/c++/11/memory:76,
                 from duckdb.hpp:55,
                 from sqlite3_api_wrapper.cpp:3:
/usr/include/c++/11/bits/unique_ptr.h:242:11: note: candidates are: ‘template<class _Tp, class _Dp> class std::unique_ptr’
  242 |     class unique_ptr
      |           ^~~~~~~~~~
In file included from sqlite3_api_wrapper.cpp:3:
duckdb.hpp:851:7: note:                 ‘template<class _Tp, class _Dp, bool SAFE> class duckdb::unique_ptr’
  851 | class unique_ptr : public std::unique_ptr<_Tp, _Dp> {

I tried to solve but my knowledge of C++ is bad.

Thanks for this software.

support postgres 14

Hello, please do you plan to support also postgresql 14?

I already used the fdw in 13 (btw this fdw, and of course DuckDb, simplified a lot my work, so thanks a lot!), but as expected, when try to install it for 14 I got:
Makefile:41: *** PostgreSQL 9.6, 10, 11, 12 or 13 is required to compile this extension.

compile error for PostgreSQL 14

root@93d85422181e:/tmp/duckdb_fdw# USE_PGXS=1 make  
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -moutline-atomics -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fPIC -I. -I./ -I/usr/include/postgresql/14/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o connection.o connection.c
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -moutline-atomics -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fPIC -I. -I./ -I/usr/include/postgresql/14/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o option.o option.c
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -moutline-atomics -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fPIC -I. -I./ -I/usr/include/postgresql/14/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o deparse.o deparse.c
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -moutline-atomics -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fPIC -I. -I./ -I/usr/include/postgresql/14/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o sqlite_query.o sqlite_query.c
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -moutline-atomics -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fPIC -I. -I./ -I/usr/include/postgresql/14/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o duckdb_fdw.o duckdb_fdw.c
g++ -Wall -Wpointer-arith -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -moutline-atomics -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fPIC -I. -I./ -I/usr/include/postgresql/14/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2   -c -o sqlite3_api_wrapper.o sqlite3_api_wrapper.cpp
sqlite3_api_wrapper.cpp:124:22: error: template argument 1 is invalid
  124 |  duckdb::vector<Value> bound_values;
      |                      ^
sqlite3_api_wrapper.cpp: In function ‘int sqlite3_prepare_v2(sqlite3*, const char*, int, sqlite3_stmt**, const char**)’:
sqlite3_api_wrapper.cpp:277:23: error: request for member ‘push_back’ in ‘stmt.duckdb::unique_ptr<sqlite3_stmt>::operator->()->sqlite3_stmt::bound_values’, which is of non-class type ‘int’
  277 |    stmt->bound_values.push_back(Value());
      |                       ^~~~~~~~~
sqlite3_api_wrapper.cpp:277:33: error: reference to ‘Value’ is ambiguous
  277 |    stmt->bound_values.push_back(Value());
      |                                 ^~~~~
In file included from sqlite3_api_wrapper.cpp:3:
duckdb.hpp:5187:7: note: candidates are: ‘class duckdb::Value’
 5187 | class Value {
      |       ^~~~~
In file included from /usr/include/postgresql/14/server/nodes/parsenodes.h:28,
                 from /usr/include/postgresql/14/server/catalog/objectaddress.h:17,
                 from /usr/include/postgresql/14/server/catalog/pg_type.h:22,
                 from sqlite3_api_wrapper.cpp:10:
/usr/include/postgresql/14/server/nodes/value.h:50:3: note:                 ‘typedef struct Value Value’
   50 | } Value;
      |   ^~~~~
sqlite3_api_wrapper.cpp: At global scope:
sqlite3_api_wrapper.cpp:582:69: error: reference to ‘Value’ is ambiguous
  582 | static bool sqlite3_column_get_value(sqlite3_stmt *pStmt, int iCol, Value &val) {
      |                                                                     ^~~~~
In file included from sqlite3_api_wrapper.cpp:3:
duckdb.hpp:5187:7: note: candidates are: ‘class duckdb::Value’
 5187 | class Value {
      |       ^~~~~
In file included from /usr/include/postgresql/14/server/nodes/parsenodes.h:28,
                 from /usr/include/postgresql/14/server/catalog/objectaddress.h:17,
                 from /usr/include/postgresql/14/server/catalog/pg_type.h:22,
                 from sqlite3_api_wrapper.cpp:10:
/usr/include/postgresql/14/server/nodes/value.h:50:3: note:                 ‘typedef struct Value Value’
   50 | } Value;
      |   ^~~~~
sqlite3_api_wrapper.cpp:582:69: error: ‘Value’ has not been declared
  582 | static bool sqlite3_column_get_value(sqlite3_stmt *pStmt, int iCol, Value &val) {
      |                                                                     ^~~~~
sqlite3_api_wrapper.cpp: In function ‘bool sqlite3_column_get_value(sqlite3_stmt*, int, int&)’:
sqlite3_api_wrapper.cpp:592:49: error: cannot convert ‘duckdb::Value’ to ‘int’ in assignment
  592 |  val = pStmt->current_chunk->data[iCol].GetValue(pStmt->current_row);
      |        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
      |                                                 |
      |                                                 duckdb::Value
sqlite3_api_wrapper.cpp: At global scope:
sqlite3_api_wrapper.cpp:596:94: error: reference to ‘Value’ is ambiguous
  596 | static bool sqlite3_column_has_value(sqlite3_stmt *pStmt, int iCol, LogicalType target_type, Value &val) {
      |                                                                                              ^~~~~
In file included from sqlite3_api_wrapper.cpp:3:
duckdb.hpp:5187:7: note: candidates are: ‘class duckdb::Value’
 5187 | class Value {
      |       ^~~~~
In file included from /usr/include/postgresql/14/server/nodes/parsenodes.h:28,
                 from /usr/include/postgresql/14/server/catalog/objectaddress.h:17,
                 from /usr/include/postgresql/14/server/catalog/pg_type.h:22,
                 from sqlite3_api_wrapper.cpp:10:
/usr/include/postgresql/14/server/nodes/value.h:50:3: note:                 ‘typedef struct Value Value’
   50 | } Value;
      |   ^~~~~
sqlite3_api_wrapper.cpp:596:94: error: ‘Value’ has not been declared
  596 | static bool sqlite3_column_has_value(sqlite3_stmt *pStmt, int iCol, LogicalType target_type, Value &val) {
      |                                                                                              ^~~~~
sqlite3_api_wrapper.cpp: In function ‘bool sqlite3_column_has_value(sqlite3_stmt*, int, duckdb::LogicalType, int&)’:
sqlite3_api_wrapper.cpp:599:14: error: request for member ‘CastAs’ in ‘val’, which is of non-class type ‘int’
  599 |    val = val.CastAs(*pStmt->db->con->context, target_type);
      |              ^~~~~~
sqlite3_api_wrapper.cpp: In function ‘double sqlite3_column_double(sqlite3_stmt*, int)’:
sqlite3_api_wrapper.cpp:608:2: error: reference to ‘Value’ is ambiguous
  608 |  Value val;
      |  ^~~~~
In file included from sqlite3_api_wrapper.cpp:3:
duckdb.hpp:5187:7: note: candidates are: ‘class duckdb::Value’
 5187 | class Value {
      |       ^~~~~
In file included from /usr/include/postgresql/14/server/nodes/parsenodes.h:28,
                 from /usr/include/postgresql/14/server/catalog/objectaddress.h:17,
                 from /usr/include/postgresql/14/server/catalog/pg_type.h:22,
                 from sqlite3_api_wrapper.cpp:10:
/usr/include/postgresql/14/server/nodes/value.h:50:3: note:                 ‘typedef struct Value Value’
   50 | } Value;
      |   ^~~~~
sqlite3_api_wrapper.cpp:609:65: error: ‘val’ was not declared in this scope
  609 |  if (!sqlite3_column_has_value(stmt, iCol, LogicalType::DOUBLE, val)) {
      |                                                                 ^~~
sqlite3_api_wrapper.cpp:612:26: error: ‘val’ was not declared in this scope
  612 |  return DoubleValue::Get(val);
      |                          ^~~
sqlite3_api_wrapper.cpp: In function ‘int sqlite3_column_int(sqlite3_stmt*, int)’:
sqlite3_api_wrapper.cpp:616:2: error: reference to ‘Value’ is ambiguous
  616 |  Value val;
      |  ^~~~~
In file included from sqlite3_api_wrapper.cpp:3:
duckdb.hpp:5187:7: note: candidates are: ‘class duckdb::Value’
 5187 | class Value {
      |       ^~~~~
In file included from /usr/include/postgresql/14/server/nodes/parsenodes.h:28,
                 from /usr/include/postgresql/14/server/catalog/objectaddress.h:17,
                 from /usr/include/postgresql/14/server/catalog/pg_type.h:22,
                 from sqlite3_api_wrapper.cpp:10:
/usr/include/postgresql/14/server/nodes/value.h:50:3: note:                 ‘typedef struct Value Value’
   50 | } Value;
      |   ^~~~~
sqlite3_api_wrapper.cpp:617:66: error: ‘val’ was not declared in this scope
  617 |  if (!sqlite3_column_has_value(stmt, iCol, LogicalType::INTEGER, val)) {
      |                                                                  ^~~
sqlite3_api_wrapper.cpp:620:27: error: ‘val’ was not declared in this scope
  620 |  return IntegerValue::Get(val);
      |                           ^~~
sqlite3_api_wrapper.cpp: In function ‘sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int)’:
sqlite3_api_wrapper.cpp:624:2: error: reference to ‘Value’ is ambiguous
  624 |  Value val;
      |  ^~~~~
In file included from sqlite3_api_wrapper.cpp:3:
duckdb.hpp:5187:7: note: candidates are: ‘class duckdb::Value’
 5187 | class Value {
      |       ^~~~~
In file included from /usr/include/postgresql/14/server/nodes/parsenodes.h:28,
                 from /usr/include/postgresql/14/server/catalog/objectaddress.h:17,
                 from /usr/include/postgresql/14/server/catalog/pg_type.h:22,
                 from sqlite3_api_wrapper.cpp:10:
/usr/include/postgresql/14/server/nodes/value.h:50:3: note:                 ‘typedef struct Value Value’
   50 | } Value;
      |   ^~~~~
sqlite3_api_wrapper.cpp:625:65: error: ‘val’ was not declared in this scope
  625 |  if (!sqlite3_column_has_value(stmt, iCol, LogicalType::BIGINT, val)) {
      |                                                                 ^~~
sqlite3_api_wrapper.cpp:628:26: error: ‘val’ was not declared in this scope
  628 |  return BigIntValue::Get(val);
      |                          ^~~
sqlite3_api_wrapper.cpp: In function ‘const unsigned char* sqlite3_column_text(sqlite3_stmt*, int)’:
sqlite3_api_wrapper.cpp:632:2: error: reference to ‘Value’ is ambiguous
  632 |  Value val;
      |  ^~~~~
In file included from sqlite3_api_wrapper.cpp:3:
duckdb.hpp:5187:7: note: candidates are: ‘class duckdb::Value’
 5187 | class Value {
      |       ^~~~~
In file included from /usr/include/postgresql/14/server/nodes/parsenodes.h:28,
                 from /usr/include/postgresql/14/server/catalog/objectaddress.h:17,
                 from /usr/include/postgresql/14/server/catalog/pg_type.h:22,
                 from sqlite3_api_wrapper.cpp:10:
/usr/include/postgresql/14/server/nodes/value.h:50:3: note:                 ‘typedef struct Value Value’
   50 | } Value;
      |   ^~~~~
sqlite3_api_wrapper.cpp:633:67: error: ‘val’ was not declared in this scope
  633 |  if (!sqlite3_column_has_value(pStmt, iCol, LogicalType::VARCHAR, val)) {
      |                                                                   ^~~
sqlite3_api_wrapper.cpp:644:37: error: ‘val’ was not declared in this scope
  644 |    auto &str_val = StringValue::Get(val);
      |                                     ^~~
sqlite3_api_wrapper.cpp: In function ‘const void* sqlite3_column_blob(sqlite3_stmt*, int)’:
sqlite3_api_wrapper.cpp:657:2: error: reference to ‘Value’ is ambiguous
  657 |  Value val;
      |  ^~~~~
In file included from sqlite3_api_wrapper.cpp:3:
duckdb.hpp:5187:7: note: candidates are: ‘class duckdb::Value’
 5187 | class Value {
      |       ^~~~~
In file included from /usr/include/postgresql/14/server/nodes/parsenodes.h:28,
                 from /usr/include/postgresql/14/server/catalog/objectaddress.h:17,
                 from /usr/include/postgresql/14/server/catalog/pg_type.h:22,
                 from sqlite3_api_wrapper.cpp:10:
/usr/include/postgresql/14/server/nodes/value.h:50:3: note:                 ‘typedef struct Value Value’
   50 | } Value;
      |   ^~~~~
sqlite3_api_wrapper.cpp:658:64: error: ‘val’ was not declared in this scope
  658 |  if (!sqlite3_column_has_value(pStmt, iCol, LogicalType::BLOB, val)) {
      |                                                                ^~~
sqlite3_api_wrapper.cpp:669:37: error: ‘val’ was not declared in this scope
  669 |    auto &str_val = StringValue::Get(val);
      |                                     ^~~
sqlite3_api_wrapper.cpp: At global scope:
sqlite3_api_wrapper.cpp:681:41: error: reference to ‘Value’ is ambiguous
  681 | static bool duckdb_value_as_datum(const Value &val, Oid pgType, Datum *value) {
      |                                         ^~~~~
In file included from sqlite3_api_wrapper.cpp:3:
duckdb.hpp:5187:7: note: candidates are: ‘class duckdb::Value’
 5187 | class Value {
      |       ^~~~~
In file included from /usr/include/postgresql/14/server/nodes/parsenodes.h:28,
                 from /usr/include/postgresql/14/server/catalog/objectaddress.h:17,
                 from /usr/include/postgresql/14/server/catalog/pg_type.h:22,
                 from sqlite3_api_wrapper.cpp:10:
/usr/include/postgresql/14/server/nodes/value.h:50:3: note:                 ‘typedef struct Value Value’
   50 | } Value;
      |   ^~~~~
sqlite3_api_wrapper.cpp: In function ‘bool duckdb_value_as_datum(const int&, Oid, Datum*)’:
sqlite3_api_wrapper.cpp:682:39: error: request for member ‘type’ in ‘val’, which is of non-class type ‘const int’
  682 |  const LogicalType &column_type = val.type();
      |                                       ^~~~
sqlite3_api_wrapper.cpp:687:16: error: request for member ‘GetValue’ in ‘val’, which is of non-class type ‘const int’
  687 |   bool v = val.GetValue<bool>();
      |                ^~~~~~~~
sqlite3_api_wrapper.cpp:687:25: error: expected primary-expression before ‘bool’
  687 |   bool v = val.GetValue<bool>();
      |                         ^~~~
sqlite3_api_wrapper.cpp:693:18: error: request for member ‘GetValue’ in ‘val’, which is of non-class type ‘const int’
  693 |   int8_t v = val.GetValue<int8_t>();
      |                  ^~~~~~~~
sqlite3_api_wrapper.cpp:693:33: error: expected primary-expression before ‘>’ token
  693 |   int8_t v = val.GetValue<int8_t>();
      |                                 ^
sqlite3_api_wrapper.cpp:693:35: error: expected primary-expression before ‘)’ token
  693 |   int8_t v = val.GetValue<int8_t>();
      |                                   ^
sqlite3_api_wrapper.cpp:699:19: error: request for member ‘GetValue’ in ‘val’, which is of non-class type ‘const int’
  699 |   int16_t v = val.GetValue<int16_t>();
      |                   ^~~~~~~~
sqlite3_api_wrapper.cpp:699:35: error: expected primary-expression before ‘>’ token
  699 |   int16_t v = val.GetValue<int16_t>();
      |                                   ^
sqlite3_api_wrapper.cpp:699:37: error: expected primary-expression before ‘)’ token
  699 |   int16_t v = val.GetValue<int16_t>();
      |                                     ^
sqlite3_api_wrapper.cpp:705:19: error: request for member ‘GetValue’ in ‘val’, which is of non-class type ‘const int’
  705 |   int32_t v = val.GetValue<int32_t>();
      |                   ^~~~~~~~
sqlite3_api_wrapper.cpp:705:35: error: expected primary-expression before ‘>’ token
  705 |   int32_t v = val.GetValue<int32_t>();
      |                                   ^
sqlite3_api_wrapper.cpp:705:37: error: expected primary-expression before ‘)’ token
  705 |   int32_t v = val.GetValue<int32_t>();
      |                                     ^
sqlite3_api_wrapper.cpp:711:19: error: request for member ‘GetValue’ in ‘val’, which is of non-class type ‘const int’
  711 |   int64_t v = val.GetValue<int64_t>();
      |                   ^~~~~~~~
sqlite3_api_wrapper.cpp:711:35: error: expected primary-expression before ‘>’ token
  711 |   int64_t v = val.GetValue<int64_t>();
      |                                   ^
sqlite3_api_wrapper.cpp:711:37: error: expected primary-expression before ‘)’ token
  711 |   int64_t v = val.GetValue<int64_t>();
      |                                     ^
sqlite3_api_wrapper.cpp:717:18: error: request for member ‘GetValue’ in ‘val’, which is of non-class type ‘const int’
  717 |   float4 v = val.GetValue<float4>();
      |                  ^~~~~~~~
sqlite3_api_wrapper.cpp:717:33: error: expected primary-expression before ‘>’ token
  717 |   float4 v = val.GetValue<float4>();
      |                                 ^
sqlite3_api_wrapper.cpp:717:35: error: expected primary-expression before ‘)’ token
  717 |   float4 v = val.GetValue<float4>();
      |                                   ^
sqlite3_api_wrapper.cpp:723:18: error: request for member ‘GetValue’ in ‘val’, which is of non-class type ‘const int’
  723 |   float8 v = val.GetValue<float8>();
      |                  ^~~~~~~~
sqlite3_api_wrapper.cpp:723:33: error: expected primary-expression before ‘>’ token
  723 |   float8 v = val.GetValue<float8>();
      |                                 ^
sqlite3_api_wrapper.cpp:723:35: error: expected primary-expression before ‘)’ token
  723 |   float8 v = val.GetValue<float8>();
      |                                   ^
sqlite3_api_wrapper.cpp:744:30: error: request for member ‘ToString’ in ‘val’, which is of non-class type ‘const int’
  744 |    std::string value_s = val.ToString();
      |                              ^~~~~~~~
sqlite3_api_wrapper.cpp:764:30: error: invalid initialization of reference of type ‘const int&’ from expression of type ‘const duckdb::Value’
  764 |    if (duckdb_value_as_datum(child, element_type, &child_value)) {
      |                              ^~~~~
sqlite3_api_wrapper.cpp:681:48: note: in passing argument 1 of ‘bool duckdb_value_as_datum(const int&, Oid, Datum*)’
  681 | static bool duckdb_value_as_datum(const Value &val, Oid pgType, Datum *value) {
      |                                   ~~~~~~~~~~~~~^~~
sqlite3_api_wrapper.cpp:780:29: error: request for member ‘ToString’ in ‘val’, which is of non-class type ‘const int’
  780 |   std::string value_s = val.ToString();
      |                             ^~~~~~~~
sqlite3_api_wrapper.cpp: In function ‘bool sqlite3_column_value_datum(sqlite3_stmt*, int, Oid, Datum*)’:
sqlite3_api_wrapper.cpp:794:2: error: reference to ‘Value’ is ambiguous
  794 |  Value val;
      |  ^~~~~
In file included from sqlite3_api_wrapper.cpp:3:
duckdb.hpp:5187:7: note: candidates are: ‘class duckdb::Value’
 5187 | class Value {
      |       ^~~~~
In file included from /usr/include/postgresql/14/server/nodes/parsenodes.h:28,
                 from /usr/include/postgresql/14/server/catalog/objectaddress.h:17,
                 from /usr/include/postgresql/14/server/catalog/pg_type.h:22,
                 from sqlite3_api_wrapper.cpp:10:
/usr/include/postgresql/14/server/nodes/value.h:50:3: note:                 ‘typedef struct Value Value’
   50 | } Value;
      |   ^~~~~
sqlite3_api_wrapper.cpp:795:44: error: ‘val’ was not declared in this scope; did you mean ‘value’?
  795 |  if (sqlite3_column_get_value(pStmt, iCol, val) && duckdb_value_as_datum(val, pgType, value)) {
      |                                            ^~~
      |                                            value
sqlite3_api_wrapper.cpp: At global scope:
sqlite3_api_wrapper.cpp:833:62: error: reference to ‘Value’ is ambiguous
  833 | int sqlite3_internal_bind_value(sqlite3_stmt *stmt, int idx, Value value) {
      |                                                              ^~~~~
In file included from sqlite3_api_wrapper.cpp:3:
duckdb.hpp:5187:7: note: candidates are: ‘class duckdb::Value’
 5187 | class Value {
      |       ^~~~~
In file included from /usr/include/postgresql/14/server/nodes/parsenodes.h:28,
                 from /usr/include/postgresql/14/server/catalog/objectaddress.h:17,
                 from /usr/include/postgresql/14/server/catalog/pg_type.h:22,
                 from sqlite3_api_wrapper.cpp:10:
/usr/include/postgresql/14/server/nodes/value.h:50:3: note:                 ‘typedef struct Value Value’
   50 | } Value;
      |   ^~~~~
sqlite3_api_wrapper.cpp:833:62: error: ‘Value’ has not been declared
  833 | int sqlite3_internal_bind_value(sqlite3_stmt *stmt, int idx, Value value) {
      |                                                              ^~~~~
sqlite3_api_wrapper.cpp: In function ‘int sqlite3_internal_bind_value(sqlite3_stmt*, int, int)’:
sqlite3_api_wrapper.cpp:840:20: error: invalid types ‘int[int]’ for array subscript
  840 |  stmt->bound_values[idx - 1] = value;
      |                    ^
sqlite3_api_wrapper.cpp: In function ‘int sqlite3_bind_int(sqlite3_stmt*, int, int)’:
sqlite3_api_wrapper.cpp:845:48: error: reference to ‘Value’ is ambiguous
  845 |  return sqlite3_internal_bind_value(stmt, idx, Value::INTEGER(val));
      |                                                ^~~~~
In file included from sqlite3_api_wrapper.cpp:3:
duckdb.hpp:5187:7: note: candidates are: ‘class duckdb::Value’
 5187 | class Value {
      |       ^~~~~
In file included from /usr/include/postgresql/14/server/nodes/parsenodes.h:28,
                 from /usr/include/postgresql/14/server/catalog/objectaddress.h:17,
                 from /usr/include/postgresql/14/server/catalog/pg_type.h:22,
                 from sqlite3_api_wrapper.cpp:10:
/usr/include/postgresql/14/server/nodes/value.h:50:3: note:                 ‘typedef struct Value Value’
   50 | } Value;
      |   ^~~~~
sqlite3_api_wrapper.cpp: In function ‘int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64)’:
sqlite3_api_wrapper.cpp:849:48: error: reference to ‘Value’ is ambiguous
  849 |  return sqlite3_internal_bind_value(stmt, idx, Value::BIGINT(val));
      |                                                ^~~~~
In file included from sqlite3_api_wrapper.cpp:3:
duckdb.hpp:5187:7: note: candidates are: ‘class duckdb::Value’
 5187 | class Value {
      |       ^~~~~
In file included from /usr/include/postgresql/14/server/nodes/parsenodes.h:28,
                 from /usr/include/postgresql/14/server/catalog/objectaddress.h:17,
                 from /usr/include/postgresql/14/server/catalog/pg_type.h:22,
                 from sqlite3_api_wrapper.cpp:10:
/usr/include/postgresql/14/server/nodes/value.h:50:3: note:                 ‘typedef struct Value Value’
   50 | } Value;
      |   ^~~~~
sqlite3_api_wrapper.cpp: In function ‘int sqlite3_bind_double(sqlite3_stmt*, int, double)’:
sqlite3_api_wrapper.cpp:853:48: error: reference to ‘Value’ is ambiguous
  853 |  return sqlite3_internal_bind_value(stmt, idx, Value::DOUBLE(val));
      |                                                ^~~~~
In file included from sqlite3_api_wrapper.cpp:3:
duckdb.hpp:5187:7: note: candidates are: ‘class duckdb::Value’
 5187 | class Value {
      |       ^~~~~
In file included from /usr/include/postgresql/14/server/nodes/parsenodes.h:28,
                 from /usr/include/postgresql/14/server/catalog/objectaddress.h:17,
                 from /usr/include/postgresql/14/server/catalog/pg_type.h:22,
                 from sqlite3_api_wrapper.cpp:10:
/usr/include/postgresql/14/server/nodes/value.h:50:3: note:                 ‘typedef struct Value Value’
   50 | } Value;
      |   ^~~~~
sqlite3_api_wrapper.cpp: In function ‘int sqlite3_bind_null(sqlite3_stmt*, int)’:
sqlite3_api_wrapper.cpp:857:48: error: reference to ‘Value’ is ambiguous
  857 |  return sqlite3_internal_bind_value(stmt, idx, Value());
      |                                                ^~~~~
In file included from sqlite3_api_wrapper.cpp:3:
duckdb.hpp:5187:7: note: candidates are: ‘class duckdb::Value’
 5187 | class Value {
      |       ^~~~~
In file included from /usr/include/postgresql/14/server/nodes/parsenodes.h:28,
                 from /usr/include/postgresql/14/server/catalog/objectaddress.h:17,
                 from /usr/include/postgresql/14/server/catalog/pg_type.h:22,
                 from sqlite3_api_wrapper.cpp:10:
/usr/include/postgresql/14/server/nodes/value.h:50:3: note:                 ‘typedef struct Value Value’
   50 | } Value;
      |   ^~~~~
sqlite3_api_wrapper.cpp: In function ‘int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int, void (*)(void*))’:
sqlite3_api_wrapper.cpp:880:49: error: reference to ‘Value’ is ambiguous
  880 |   return sqlite3_internal_bind_value(stmt, idx, Value(value));
      |                                                 ^~~~~
In file included from sqlite3_api_wrapper.cpp:3:
duckdb.hpp:5187:7: note: candidates are: ‘class duckdb::Value’
 5187 | class Value {
      |       ^~~~~
In file included from /usr/include/postgresql/14/server/nodes/parsenodes.h:28,
                 from /usr/include/postgresql/14/server/catalog/objectaddress.h:17,
                 from /usr/include/postgresql/14/server/catalog/pg_type.h:22,
                 from sqlite3_api_wrapper.cpp:10:
/usr/include/postgresql/14/server/nodes/value.h:50:3: note:                 ‘typedef struct Value Value’
   50 | } Value;
      |   ^~~~~
sqlite3_api_wrapper.cpp: In function ‘int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int, void (*)(void*))’:
sqlite3_api_wrapper.cpp:890:2: error: reference to ‘Value’ is ambiguous
  890 |  Value blob;
      |  ^~~~~
In file included from sqlite3_api_wrapper.cpp:3:
duckdb.hpp:5187:7: note: candidates are: ‘class duckdb::Value’
 5187 | class Value {
      |       ^~~~~
In file included from /usr/include/postgresql/14/server/nodes/parsenodes.h:28,
                 from /usr/include/postgresql/14/server/catalog/objectaddress.h:17,
                 from /usr/include/postgresql/14/server/catalog/pg_type.h:22,
                 from sqlite3_api_wrapper.cpp:10:
/usr/include/postgresql/14/server/nodes/value.h:50:3: note:                 ‘typedef struct Value Value’
   50 | } Value;
      |   ^~~~~
sqlite3_api_wrapper.cpp:892:3: error: ‘blob’ was not declared in this scope
  892 |   blob = Value::BLOB(string((const char *)val));
      |   ^~~~
sqlite3_api_wrapper.cpp:892:10: error: reference to ‘Value’ is ambiguous
  892 |   blob = Value::BLOB(string((const char *)val));
      |          ^~~~~
In file included from sqlite3_api_wrapper.cpp:3:
duckdb.hpp:5187:7: note: candidates are: ‘class duckdb::Value’
 5187 | class Value {
      |       ^~~~~
In file included from /usr/include/postgresql/14/server/nodes/parsenodes.h:28,
                 from /usr/include/postgresql/14/server/catalog/objectaddress.h:17,
                 from /usr/include/postgresql/14/server/catalog/pg_type.h:22,
                 from sqlite3_api_wrapper.cpp:10:
/usr/include/postgresql/14/server/nodes/value.h:50:3: note:                 ‘typedef struct Value Value’
   50 | } Value;
      |   ^~~~~
sqlite3_api_wrapper.cpp:894:3: error: ‘blob’ was not declared in this scope
  894 |   blob = Value::BLOB((const_data_ptr_t)val, length);
      |   ^~~~
sqlite3_api_wrapper.cpp:894:10: error: reference to ‘Value’ is ambiguous
  894 |   blob = Value::BLOB((const_data_ptr_t)val, length);
      |          ^~~~~
In file included from sqlite3_api_wrapper.cpp:3:
duckdb.hpp:5187:7: note: candidates are: ‘class duckdb::Value’
 5187 | class Value {
      |       ^~~~~
In file included from /usr/include/postgresql/14/server/nodes/parsenodes.h:28,
                 from /usr/include/postgresql/14/server/catalog/objectaddress.h:17,
                 from /usr/include/postgresql/14/server/catalog/pg_type.h:22,
                 from sqlite3_api_wrapper.cpp:10:
/usr/include/postgresql/14/server/nodes/value.h:50:3: note:                 ‘typedef struct Value Value’
   50 | } Value;
      |   ^~~~~
sqlite3_api_wrapper.cpp:901:49: error: ‘blob’ was not declared in this scope
  901 |   return sqlite3_internal_bind_value(stmt, idx, blob);
      |                                                 ^~~~
sqlite3_api_wrapper.cpp: At global scope:
sqlite3_api_wrapper.cpp:596:13: warning: ‘bool sqlite3_column_has_value(sqlite3_stmt*, int, duckdb::LogicalType, int&)’ defined but not used [-Wunused-function]
  596 | static bool sqlite3_column_has_value(sqlite3_stmt *pStmt, int iCol, LogicalType target_type, Value &val) {
      |             ^~~~~~~~~~~~~~~~~~~~~~~~
make: *** [<builtin>: sqlite3_api_wrapper.o] Error 1

support UUID type

It would be great to allow the UUID type. ATM you'll get an error, that it's not supported.

A workaround is to create the column in duckdb's table with type UUID and the PostgreSQL foreign table's type with type TEXT.

Runtime crash with libduckdb 1.0.0

postgres=# create extension duckdb_fdw;
CREATE EXTENSION
postgres=#  CREATE SERVER duckdb_server
postgres-#  FOREIGN DATA WRAPPER duckdb_fdw
postgres-#  OPTIONS (
postgres(#           database '/tmp/duck.db'
postgres(#  );
CREATE SERVER
postgres=# CREATE FOREIGN TABLE t1 (
postgres(#   a integer,
postgres(#   b text
postgres(# )
postgres-# SERVER duckdb_server
postgres-# OPTIONS (
postgres(#   table 't1_duckdb'
postgres(# );
CREATE FOREIGN TABLE
postgres=# select * from t1;
server closed the connection unexpectedly
	This probably means the server terminated abnormally
	before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.
The connection to the server was lost. Attempting reset: Failed.

postgres=# \errverbose
There is no previous error.
postgres=# insert into t1 values (1,'a');
server closed the connection unexpectedly
	This probably means the server terminated abnormally
	before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.
The connection to the server was lost. Attempting reset: Failed.
!?> ^C
!?> \q
[postgres@build-el8 tmp]$ psql -E
psql (16.3)
Type "help" for help.

postgres=# \errverbose
There is no previous error.
postgres=# select * from t1;
server closed the connection unexpectedly
	This probably means the server terminated abnormally
	before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.
The connection to the server was lost. Attempting reset: Failed.
!?> \errverbose
server closed the connection unexpectedly
	This probably means the server terminated abnormally
	before or while processing the request.

[question] Correct way to integrate with external database in remote storage (GCS)

Context

Hi! we're attempting to run DuckDB via duckdb_fdw extension inside a PostgreSQL database that is running in our Kubernetes cluster via CNPG operator.

Our ultimate goal is to be able to leverage duckdb to manage data that is currently stored in (geo)parquet files in our Google Cloud Storage buckets.

The database pods already have the GOOGLE_APPLICATION_CREDENTIALS set and we've verified that accessing data in a GCS bucket is possible (we did this via raster2pgpsql, using out-db COG rasters that are stored in GCS)

We strongly prefer to have all the duckdb storage remotely (either having the database itself stored in GCS or working in-memory only and persisting data to .parquet files)

Problem description

UPDATE: I was able to load the extension using the ':memory:' or directory approach locally directly using the image from the shared Dockerfile without issues. One difference between both is that the base path in the Docker container is /var/lib/postgresql/data/ whereas in the CNPG pod it is /var/lib/postgresql/data/pgdata

We're able to load the extension and create a foreign server without issues, see below:

A) Creating the server using the in-memory option:

SELECT current_user;
--   current_user
--  --------------
--   postgres
--  (1 row)

-- DROP SERVER IF EXISTS duckdb_svr CASCADE;

CREATE SERVER duckdb_svr FOREIGN DATA WRAPPER duckdb_fdw OPTIONS (database ':memory:');
-- CREATE SERVER

SELECT duckdb_execute('duckdb_svr','CREATE TABLE test (a INTEGER, b INTEGER, c VARCHAR(10));');
--  duckdb_execute
--  ----------------
--  
--  (1 row)

CREATE FOREIGN TABLE public.terraclimate_duckdb_ft (
    h3             bigint,
    value          numeric
)
SERVER duckdb_svr
OPTIONS (
    table 'read_parquet("gs://cambium-earth-general/parquet/terraclimate/*.parquet")'
);
-- CREATE FOREIGN TABLE


SELECT duckdb_execute('duckdb_svr','CREATE PERSISTENT SECRET (TYPE GCS, KEY_ID ''GOOG1EXXXXXXXXXX'', SECRET ''XXXXXXXXXX'');');
-- ERROR:  SQL error during prepare: Extension Autoloading Error: An error occurred while trying to automatically install the required extension 'httpfs':
-- Failed to create directory "/var/lib/postgresql/.duckdb/"! CREATE PERSISTENT SECRET (TYPE GCS, KEY_ID 'GOOG1EXXXXXXXXXX', SECRET 'XXXXXXXXXX');

B) Creating the server using local storage

SELECT current_user;
-- current_user
--  --------------
--   postgres
--  (1 row)

-- DROP SERVER IF EXISTS duckdb_svr CASCADE;

CREATE SERVER duckdb_svr FOREIGN DATA WRAPPER duckdb_fdw OPTIONS (database 'db');
-- CREATE SERVER

SELECT duckdb_execute('duckdb_svr','CREATE TABLE test (a INTEGER, b INTEGER, c VARCHAR(10));');
--  duckdb_execute
--  ----------------
--  
--  (1 row)

CREATE FOREIGN TABLE public.terraclimate_duckdb_ft (
    h3             bigint,
    value          numeric
)
SERVER duckdb_svr
OPTIONS (
    table 'read_parquet("gs://cambium-earth-general/parquet/terraclimate/*.parquet")'
);
-- CREATE FOREIGN TABLE


SELECT duckdb_execute('duckdb_svr','CREATE PERSISTENT SECRET (TYPE GCS, KEY_ID ''GOOG1EXXXXXXXXXX'', SECRET ''XXXXXXXXXX'');');
-- ERROR:  SQL error during prepare: Extension Autoloading Error: An error occurred while trying to automatically install the required extension 'httpfs':
-- Failed to create directory "/var/lib/postgresql/.duckdb/"! CREATE PERSISTENT SECRET (TYPE GCS, KEY_ID 'GOOG1EXXXXXXXXXX', SECRET 'XXXXXXXXXX');

I believe that the 'Failed to create directory' error could be related to permissions to create the directory, perhaps related to CNPG internals.

C) Creating the server using remote storage

SELECT current_user;
-- current_user
--  --------------
--   postgres
--  (1 row)

-- DROP SERVER IF EXISTS duckdb_svr CASCADE;

CREATE SERVER duckdb_svr FOREIGN DATA WRAPPER duckdb_fdw OPTIONS (database 'gs://cambium-earth-general/test.db');
-- CREATE SERVER

SELECT duckdb_execute('duckdb_svr','CREATE TABLE test (a INTEGER, b INTEGER, c VARCHAR(10));');
-- ERROR:  failed to open SQLite DB. rc=1 path=gs://cambium-earth-general/test.db

Questions

  1. What is the recommended approach for leveraging a remote storage such as Google Cloud Storage as in this case, to store the database information instead of using a local postgres route?

  2. Is it possible to load remote extensions using the ':memory:' option?

Additional information

Versions

  • Cloud Native PG 1.22.2
  • PostgreSQL: 14.11
  • DuckDB: 0.10.1

Dockerfile

Expand Dockerfile
# Specify the exact base image version for consistency
FROM postgis/postgis:14-3.4

# Set environment variables
ENV POSTGRES_VERSION 14
ENV POSTGIS_VERSION 3

# Do not split the description, otherwise we will see a blank space in the labels
LABEL name="PostgreSQL + PostGIS Container Images" \
      vendor="The CloudNativePG Contributors" \
      version="${PG_VERSION}" \
      release="42" \
      summary="PostgreSQL + PostGIS Container images." \
      description="This Docker image contains PostgreSQL, PostGIS and Barman Cloud based on Postgres 14-3.4."

# Copy requirements files
COPY requirements.txt /
COPY requirements-udf.txt /

# Install packages excluding cmake
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
        python3-pip python3-psycopg2 python3-setuptools wget make gcc \
        libtool unzip pgxnclient libpq-dev postgresql-server-dev-${POSTGRES_VERSION} \
        lsb-release \
        ca-certificates build-essential autoconf automake zlib1g-dev \
        libxml2-dev postgresql-server-dev-all git \
        libboost-atomic1.74.0 libboost-chrono1.74.0 libboost-graph1.74.0 \
        libboost-date-time1.74.0 libboost-program-options1.74.0 libboost-system1.74.0 \
        libboost-thread1.74.0 libboost-dev && \
    apt-get install -y python3 postgresql-plpython3-${POSTGRES_VERSION} && \
    pip3 install --upgrade pip && \
    pip3 install -r requirements-udf.txt && \
    pip3 install --no-deps -r requirements.txt

# Install additional extensions
RUN set -xe; \
	apt-get update; \
	apt-get install -y --no-install-recommends \
		"postgresql-${POSTGRES_VERSION}-pgaudit" \
		"postgresql-${POSTGRES_VERSION}-pg-failover-slots" \
		"postgresql-${POSTGRES_VERSION}-pgrouting" \
	; \
	rm -fr /tmp/* ; \
	rm -rf /var/lib/apt/lists/*;

# Install barman-cloud
RUN set -xe; \
	apt-get update; \
	apt-get install -y --no-install-recommends \
		python3-pip \
		python3-psycopg2 \
		python3-setuptools \
	; \
	pip3 install --upgrade pip; \
# TODO: Remove --no-deps once https://github.com/pypa/pip/issues/9644 is solved
	pip3 install --no-deps -r requirements.txt; \
	rm -rf /var/lib/apt/lists/*;

# Install TimescaleDB
RUN echo "deb https://packagecloud.io/timescale/timescaledb/debian/ $(lsb_release -c -s) main" | tee /etc/apt/sources.list.d/timescaledb.list && \
    wget --quiet -O - https://packagecloud.io/timescale/timescaledb/gpgkey | apt-key add - && \
    apt-get update && \
    apt-get install -y "timescaledb-2-postgresql-${POSTGRES_VERSION}"

# Manually install a compatible version of cmake
RUN apt-get remove -y cmake && \
    wget https://github.com/Kitware/CMake/releases/download/v3.24.1/cmake-3.24.1-Linux-x86_64.sh -O /tmp/cmake-install.sh && \
    chmod +x /tmp/cmake-install.sh && \
    /tmp/cmake-install.sh --skip-license -- prefix=/usr/local && \
    rm /tmp/cmake-install.sh && \
    ln -sf /usr/local/bin/cmake /usr/bin/cmake

# Clone h3-pg repository
RUN git clone https://github.com/zachasme/h3-pg.git

# Replace the FindPostgreSQL.cmake with the custom version
COPY FindPostgreSQL.cmake /h3-pg/cmake/FindPostgreSQL.cmake

# Build h3-pg
RUN cd h3-pg && \
    cmake -B build -DCMAKE_BUILD_TYPE=Release -DPostgreSQL_FIND_VERSION=14 && \
    cmake --build build && \
    cmake --install build --component h3-pg


# Clone duckdb_fdw repository
RUN git clone https://github.com/alitrack/duckdb_fdw

# Adjust the path to pg_config as necessary
ENV PG_CONFIG=/usr/lib/postgresql/14/bin/pg_config

# duckdb foreign data wrapper installation
RUN cd duckdb_fdw && \
    wget -c https://github.com/duckdb/duckdb/releases/download/v0.10.1/libduckdb-linux-amd64.zip && \
    unzip -o libduckdb-linux-amd64.zip && \
    cp libduckdb.so $($PG_CONFIG --libdir) && \
    make USE_PGXS=1 PG_CONFIG=$PG_CONFIG && \
    make install USE_PGXS=1 PG_CONFIG=$PG_CONFIG

# Install pointcloud extension
RUN apt-get update \
    && apt-get install -y --no-install-recommends \
        git \
        ca-certificates \
        build-essential \
        autoconf \
        automake \
        cmake \
        zlib1g-dev \
        postgresql-server-dev-all \
        libxml2-dev \
    && rm -rf /var/lib/apt/lists/* \
    && git clone https://github.com/verma/laz-perf.git \
    && cd laz-perf \
    && cmake . \
    && make \
    && make install \
    && cd .. \
    && rm -r laz-perf \
    && git clone https://github.com/pgpointcloud/pointcloud \
    && cd pointcloud \
    && ./autogen.sh \
    && ./configure --with-lazperf=/usr/local --with-pgconfig=/usr/lib/postgresql/${POSTGRES_VERSION}/bin/pg_config CFLAGS="-Wall -Werror -O2 -g" \
    && make \
    && make install \
    && apt-get purge -y --auto-remove \
        git \
        ca-certificates \
        build-essential \
        autoconf \
        automake \
        cmake \
        zlib1g-dev \
        postgresql-server-dev-all \
        libxml2-dev

# Final Cleanup
RUN apt-get purge -y --auto-remove wget lsb-release && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# Change the uid of postgres to 26
RUN usermod -u 26 postgres

# Set user to postgres
USER 26

Error for new connections

Thanks for this project. I am running into an issue and I am unsure if it is my fault.

Trying to access parquet files via duckdb and for each new connection, I have to re-run duckdb_execute to get the query to work.

Here is my setup:

CREATE EXTENSION duckdb_fdw;

CREATE SERVER DuckDB_server
FOREIGN DATA WRAPPER duckdb_fdw;

SELECT duckdb_execute(
	'duckdb_server',
	'create or replace view markers as select * from parquet_scan(''/var/annotations/samples/*.parquet'');'
);

CREATE SCHEMA parquet;

IMPORT FOREIGN SCHEMA public
             limit to (markers) 
          FROM SERVER duckdb_server
                 INTO parquet;

select * from parquet.markers limit 100;

This last query works great. However, on creating a new connection, the final SELECT statement fails.

ERROR:  SQL error during prepare: Catalog Error: Table with name markers does not exist!
Did you mean "duckdb_views"?
LINE 1: ... "is_phased", "is_het", "quality" FROM main."markers"
^ SELECT "hgvs_g", "total_depth", "alt_depth", "ref_depth", "vaf", "vaf_alt", "sample_name", "is_phased", "is_het", "quality" FROM main."markers".

I notice the schema says main in the error message. If I run the following in a NEW connection, it works great:

SELECT duckdb_execute(
	'duckdb_server',
	'create or replace view markers as select * from parquet_scan(''/var/annotations/samples/*.parquet'');'
);

select * from parquet.markers limit 100;

Using Postgres 14 in an Alpine Docker instance. Let me know if there are any other details required.

Thanks in advance, Ian

Enable concurrent connection

Hello @alitrack,

Every time there is more than one connection I get the following error:
ERROR: failed to open SQLite DB. rc=1 path=/var/lib/postgresql/database.duckdb

Do you know how i can set postgres to behave in read only mode when making a connection to the duckdb database so it can allow multiple connections ?

See duckdb/duckdb#77

concurrent read&write

does it support concurrent read?
If i try to read same table from two different processes, one of the processes will fail.

WARNING: terminating connection because of crash of another server process
DETAIL: The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.
HINT: In a moment you should be able to reconnect to the database and repeat your command.
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.

array_agg is performed by PostgreSQL not by duckdb

Hi, first of all, thank you very much for developing this amazing tool!

I am facing one issue executing a query that includes the array_agg function.

Without "array_agg" query plan looks great:
image
image

But when I add array_agg function, it is not included in the query to run in Duckdb, but it is perfomed by PostgreSQL:
image
image

The performance is very much worse, please, what I am doing wrong?, is there an issue?
Thanks in advance

Can't find $libdir/duckdb_fdw

Hello,

I am trying to install the extension using this Dockerfile:

FROM postgres

RUN apt-get update && apt-get install -y \
  git \
  build-essential \
  cmake

RUN git clone https://github.com/cwida/duckdb.git \
  && cd duckdb \
  && make

RUN apt-get install -y postgresql-server-dev-13
ENV PATH="/usr/include/postgresql/13/server/:${PATH}"

RUN git clone https://github.com/alitrack/duckdb_fdw.git  \
   && cd duckdb_fdw \
   && cp -R /duckdb/build/release/tools/sqlite3_api_wrapper/* .  \
   && cp -R /duckdb/tools/sqlite3_api_wrapper/include/* .  \
   && make USE_PGXS=1 \
   && make install USE_PGXS=1

RUN cp -R duckdb_fdw/* /usr/share/postgresql/13/extension/
RUN cp -R duckdb_fdw/sql/* /usr/share/postgresql/13/extension/

COPY ./db.sql /docker-entrypoint-initdb.d/

db.sql

CREATE EXTENSION duckdb_fdw;
CREATE SERVER DuckDB_server FOREIGN DATA WRAPPER duckdb_fdw OPTIONS (database '/tmp/test.db');

But then I have this error when I run PostgreSQL:

2021-01-24 15:28:42.387 UTC [47] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2021-01-24 15:28:42.401 UTC [48] LOG:  database system was shut down at 2021-01-24 15:28:41 UTC
2021-01-24 15:28:42.414 UTC [47] LOG:  database system is ready to accept connections
2021-01-24 15:28:43.233 UTC [91] ERROR:  could not access file "$libdir/duckdb_fdw": No such file or directory
2021-01-24 15:28:43.233 UTC [91] STATEMENT:  CREATE EXTENSION duckdb_fdw;

May I know how can I install the extension properly ? Thanks !

服务器异常中止,连接不上服务

在使用过程中遇到了连接不上的报错,请问是哪里有问题吗,具体过程如下:

postgres=# CREATE EXTENSION duckdb_fdw;
postgres=# CREATE SERVER duckdb_server FOREIGN DATA WRAPPER duckdb_fdw OPTIONS (database '/opt/fdw/data/data');
postgres=# IMPORT FOREIGN SCHEMA public FROM SERVER duckdb_server INTO public;
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.
!>

duckdb版本为:v0.6.1
pgsql版本为 :PostgreSQL 12.15 (Ubuntu 12.15-0ubuntu0.20.04.1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0, 64-bit
创建的'/opt/fdw/data/data'数据库是用v0.6.1创建的

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.