diff --git a/contrib/amcheck/verify_heapam.c b/contrib/amcheck/verify_heapam.c index 30064d0aba9..9abeca607d7 100644 --- a/contrib/amcheck/verify_heapam.c +++ b/contrib/amcheck/verify_heapam.c @@ -549,10 +549,11 @@ sanity_check_relation(Relation rel) { if (rel->rd_rel->relkind != RELKIND_RELATION && rel->rd_rel->relkind != RELKIND_MATVIEW && - rel->rd_rel->relkind != RELKIND_TOASTVALUE) + rel->rd_rel->relkind != RELKIND_TOASTVALUE && + rel->rd_rel->relkind != RELKIND_DIRECTORY_TABLE) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("\"%s\" is not a table, materialized view, or TOAST table", + errmsg("\"%s\" is not a table, directory table, materialized view, or TOAST table", RelationGetRelationName(rel)))); if (rel->rd_rel->relam != HEAP_TABLE_AM_OID) ereport(ERROR, diff --git a/contrib/oid2name/oid2name.c b/contrib/oid2name/oid2name.c index af198e87b89..4803fec9302 100644 --- a/contrib/oid2name/oid2name.c +++ b/contrib/oid2name/oid2name.c @@ -479,7 +479,7 @@ sql_exec_dumpalltables(PGconn *conn, struct options *opts) " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace " " LEFT JOIN pg_catalog.pg_database d ON d.datname = pg_catalog.current_database()," " pg_catalog.pg_tablespace t " - "WHERE relkind IN (" CppAsString2(RELKIND_RELATION) "," + "WHERE relkind IN (" CppAsString2(RELKIND_RELATION) "," CppAsString2(RELKIND_DIRECTORY_TABLE) "," CppAsString2(RELKIND_MATVIEW) "%s%s) AND " " %s" " t.oid = CASE" @@ -553,6 +553,7 @@ sql_exec_searchtables(PGconn *conn, struct options *opts) CppAsString2(RELKIND_MATVIEW) "," CppAsString2(RELKIND_INDEX) "," CppAsString2(RELKIND_SEQUENCE) "," + CppAsString2(RELKIND_DIRECTORY_TABLE) "," CppAsString2(RELKIND_TOASTVALUE) ") AND\n" " t.oid = CASE\n" " WHEN reltablespace <> 0 THEN reltablespace\n" diff --git a/contrib/pg_surgery/heap_surgery.c b/contrib/pg_surgery/heap_surgery.c index d31e5f31fd4..6ad14c6fcf1 100644 --- a/contrib/pg_surgery/heap_surgery.c +++ b/contrib/pg_surgery/heap_surgery.c @@ -374,7 +374,8 @@ sanity_check_relation(Relation rel) { if (rel->rd_rel->relkind != RELKIND_RELATION && rel->rd_rel->relkind != RELKIND_MATVIEW && - rel->rd_rel->relkind != RELKIND_TOASTVALUE) + rel->rd_rel->relkind != RELKIND_TOASTVALUE && + rel->rd_rel->relkind != RELKIND_DIRECTORY_TABLE) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("\"%s\" is not a table, materialized view, or TOAST table", diff --git a/contrib/pg_visibility/pg_visibility.c b/contrib/pg_visibility/pg_visibility.c index 7d384d3e2ce..10baf368d3c 100644 --- a/contrib/pg_visibility/pg_visibility.c +++ b/contrib/pg_visibility/pg_visibility.c @@ -778,7 +778,8 @@ check_relation_relkind(Relation rel) { if (rel->rd_rel->relkind != RELKIND_RELATION && rel->rd_rel->relkind != RELKIND_MATVIEW && - rel->rd_rel->relkind != RELKIND_TOASTVALUE) + rel->rd_rel->relkind != RELKIND_TOASTVALUE && + rel->rd_rel->relkind != RELKIND_DIRECTORY_TABLE) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("\"%s\" is not a table, materialized view, or TOAST table", diff --git a/contrib/pgstattuple/pgstatapprox.c b/contrib/pgstattuple/pgstatapprox.c index cf71af7a0ce..cebe6a6a6ac 100644 --- a/contrib/pgstattuple/pgstatapprox.c +++ b/contrib/pgstattuple/pgstatapprox.c @@ -289,10 +289,11 @@ pgstattuple_approx_internal(Oid relid, FunctionCallInfo fcinfo) rel->rd_rel->relkind == RELKIND_AOBLOCKDIR || rel->rd_rel->relkind == RELKIND_AOVISIMAP || rel->rd_rel->relkind == RELKIND_MATVIEW || - rel->rd_rel->relkind == RELKIND_TOASTVALUE)) + rel->rd_rel->relkind == RELKIND_TOASTVALUE || + rel->rd_rel->relkind == RELKIND_DIRECTORY_TABLE)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("\"%s\" is not a table, materialized view, or TOAST table", + errmsg("\"%s\" is not a table, directory table, materialized view, or TOAST table", RelationGetRelationName(rel)))); if (rel->rd_rel->relam != HEAP_TABLE_AM_OID) diff --git a/contrib/pgstattuple/pgstatindex.c b/contrib/pgstattuple/pgstatindex.c index 5368bb30f0c..f7763b2e2fc 100644 --- a/contrib/pgstattuple/pgstatindex.c +++ b/contrib/pgstattuple/pgstatindex.c @@ -766,9 +766,10 @@ check_relation_relkind(Relation rel) rel->rd_rel->relkind != RELKIND_INDEX && rel->rd_rel->relkind != RELKIND_MATVIEW && rel->rd_rel->relkind != RELKIND_SEQUENCE && - rel->rd_rel->relkind != RELKIND_TOASTVALUE) + rel->rd_rel->relkind != RELKIND_TOASTVALUE && + rel->rd_rel->relkind != RELKIND_DIRECTORY_TABLE) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("\"%s\" is not a table, index, materialized view, sequence, or TOAST table", + errmsg("\"%s\" is not a table, directory table, index, materialized view, sequence, or TOAST table", RelationGetRelationName(rel)))); } diff --git a/contrib/pgstattuple/pgstattuple.c b/contrib/pgstattuple/pgstattuple.c index 9226e459a84..ae0f09fd05e 100644 --- a/contrib/pgstattuple/pgstattuple.c +++ b/contrib/pgstattuple/pgstattuple.c @@ -261,6 +261,7 @@ pgstat_relation(Relation rel, FunctionCallInfo fcinfo) case RELKIND_AOSEGMENTS: case RELKIND_AOBLOCKDIR: case RELKIND_AOVISIMAP: + case RELKIND_DIRECTORY_TABLE: return pgstat_heap(rel, fcinfo); case RELKIND_INDEX: switch (rel->rd_rel->relam) diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c index e5c5d6d927b..b68868d5472 100644 --- a/contrib/postgres_fdw/postgres_fdw.c +++ b/contrib/postgres_fdw/postgres_fdw.c @@ -5368,6 +5368,7 @@ postgresImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid) CppAsString2(RELKIND_VIEW) "," CppAsString2(RELKIND_FOREIGN_TABLE) "," CppAsString2(RELKIND_MATVIEW) "," + CppAsString2(RELKIND_DIRECTORY_TABLE) "," CppAsString2(RELKIND_PARTITIONED_TABLE) ") " " AND n.nspname = "); deparseStringLiteral(&buf, stmt->remote_schema); diff --git a/gpMgmt/bin/Makefile b/gpMgmt/bin/Makefile index ea978e3f281..181b5c1bc87 100644 --- a/gpMgmt/bin/Makefile +++ b/gpMgmt/bin/Makefile @@ -9,6 +9,7 @@ endif SUBDIRS = stream gpcheckcat_modules gpconfig_modules gpssh_modules gppylib lib SUBDIRS += ifaddrs +SUBDIRS += cbload $(recurse) diff --git a/gpMgmt/bin/cbload/Makefile b/gpMgmt/bin/cbload/Makefile new file mode 100644 index 00000000000..d6226382ad3 --- /dev/null +++ b/gpMgmt/bin/cbload/Makefile @@ -0,0 +1,25 @@ +subdir = gpMgmt/bin/cbload +top_builddir = ../../.. +include $(top_builddir)/src/Makefile.global + +.DEFAULT_GOAL := all + +export GOPROXY ?= https://proxy.golang.org + +all: build + +build : + go mod download + go build -o cbload github.com/cloudberrydb/cbload + +clean : + rm -f cbload + +install: all + $(INSTALL_PROGRAM) 'cbload' $(bindir) + +uninstall: + rm -f $(bindir)/cbload + +distclean: + rm -f cbload diff --git a/gpMgmt/bin/cbload/go.mod b/gpMgmt/bin/cbload/go.mod new file mode 100644 index 00000000000..86c8b57390c --- /dev/null +++ b/gpMgmt/bin/cbload/go.mod @@ -0,0 +1,25 @@ +module github.com/cloudberrydb/cbload + +go 1.19 + +require ( + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jackc/chunkreader/v2 v2.0.1 // indirect + github.com/jackc/pgconn v1.14.1 // indirect + github.com/jackc/pgio v1.0.0 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgproto3/v2 v2.3.2 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/mattn/go-colorable v0.1.1 // indirect + github.com/mattn/go-isatty v0.0.7 // indirect + github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/spf13/cobra v1.8.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/x-cray/logrus-prefixed-formatter v0.5.2 // indirect + golang.org/x/crypto v0.6.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/term v0.16.0 // indirect + golang.org/x/text v0.7.0 // indirect +) diff --git a/gpMgmt/bin/cbload/go.sum b/gpMgmt/bin/cbload/go.sum new file mode 100644 index 00000000000..70bdf7b843c --- /dev/null +++ b/gpMgmt/bin/cbload/go.sum @@ -0,0 +1,173 @@ +github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= +github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= +github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= +github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= +github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= +github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= +github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= +github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= +github.com/jackc/pgconn v1.14.1 h1:smbxIaZA08n6YuxEX1sDyjV/qkbtUtkH20qLkR9MUR4= +github.com/jackc/pgconn v1.14.1/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E= +github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= +github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= +github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= +github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= +github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= +github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.3.2 h1:7eY55bdBeCz1F2fTzSz69QC+pG46jYq9/jtSPiJ5nn0= +github.com/jackc/pgproto3/v2 v2.3.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= +github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= +github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= +github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= +github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= +github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= +github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= +github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= +github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg= +github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/gpMgmt/bin/cbload/loader/loader.go b/gpMgmt/bin/cbload/loader/loader.go new file mode 100644 index 00000000000..05fa252bc69 --- /dev/null +++ b/gpMgmt/bin/cbload/loader/loader.go @@ -0,0 +1,261 @@ +package loader + +import ( + "context" + "fmt" + "os" + "os/signal" + "path/filepath" + "time" + + "github.com/cloudberrydb/cbload/log" + "github.com/cloudberrydb/cbload/option" + "github.com/cloudberrydb/cbload/worker" + "github.com/jackc/pgconn" + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +type Loader struct { + option *option.Option + conns []*pgconn.PgConn + workMgr *worker.WorkManager +} + +func NewLoader() *Loader { + l := &Loader{} + + l.option = option.NewOption() + + return l +} + +func (l *Loader) makeConnection() (*pgconn.PgConn, error) { + url := fmt.Sprintf("application_name=cbload user=%v password='%v' host=%v port=%v dbname=%v", + l.option.User, l.option.Password, l.option.Host, l.option.Port, l.option.Database) + + config, err := pgconn.ParseConfig(url) + if err != nil { + return nil, err + } + + conn, err := pgconn.ConnectConfig(context.Background(), config) + if err != nil { + return nil, err + } + + return conn, nil +} + +func (l *Loader) listFiles(prefix string, patterns []string) ([]string, []string, error) { + files := make(map[string]struct{}) + + for _, p := range patterns { + matches, err := filepath.Glob(p) + if err != nil { + return nil, nil, err + } + + for _, f := range matches { + files[f] = struct{}{} + } + } + + localFiles := make([]string, 0) + destFiles := make([]string, 0) + for k, _ := range files { + localFiles = append(localFiles, k) + destFiles = append(destFiles, filepath.Join(prefix, k)) + } + + return localFiles, destFiles, nil +} + +func (l *Loader) populateFiles(prefix string, files []string) ([]string, []string, error) { + isDirMode, err := l.option.IsDirectoryMode() + if err != nil { + return nil, nil, err + } + + if !isDirMode { + return l.listFiles(prefix, files) + } + + localFiles := make([]string, 0) + destFiles := make([]string, 0) + err = filepath.Walk(files[0], func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + if info.IsDir() { + return nil + } + + if info.Size() == 0 { + log.Logger.Infof("Ignore empty file: \"%v\"", path) + return nil + } + + localFiles = append(localFiles, path) + + relPath, _ := filepath.Rel(files[0], path) + destFiles = append(destFiles, filepath.Join(prefix, relPath)) + return nil + }) + + if err != nil { + return nil, nil, err + } + return localFiles, destFiles, nil +} + +func (l *Loader) dispatchFiles(localFiles, destFiles []string) ([][]string, [][]string) { + localTaskFiles := make([][]string, l.option.NumTasks) + destTaskFiles := make([][]string, l.option.NumTasks) + for i := 0; i < l.option.NumTasks; i++ { + localTaskFiles[i] = make([]string, 0) + destTaskFiles[i] = make([]string, 0) + } + + for i, file := range localFiles { + j := i % l.option.NumTasks + localTaskFiles[j] = append(localTaskFiles[j], file) + destTaskFiles[j] = append(destTaskFiles[j], destFiles[i]) + } + + return localTaskFiles, destTaskFiles +} + +func (l *Loader) start() (chan struct{}, chan struct{}, error) { + // step 0 retrieve files + lTotalFiles, rTotalFiles, err := l.populateFiles(l.option.DestPath, l.option.InputFile) + if err != nil { + return nil, nil, err + } + + if len(lTotalFiles) == 0 { + return nil, nil, nil + } + + // step 1 dispatch files + if len(lTotalFiles) < l.option.NumTasks { + l.option.NumTasks = len(lTotalFiles) + } + localTaskFiles, destTaskFiles := l.dispatchFiles(lTotalFiles, rTotalFiles) + + // step 2 making connection + l.conns = make([]*pgconn.PgConn, l.option.NumTasks) + log.Logger.Debug("Making database connection...") + for i := 0; i < len(l.conns); i++ { + conn, err := l.makeConnection() + if err != nil { + return nil, nil, err + } + + l.conns[i] = conn + } + log.Logger.Debug("Successfully connected to database") + + // step 3 create worker + log.Logger.Debug("Creating worker instance...") + l.workMgr = worker.NewWorkManager(l.option.Table, l.option.Tag, l.conns, localTaskFiles, destTaskFiles, l.option.StopOnError) + doneCh, quickDieCh := l.workMgr.Start() + log.Logger.Debug("Worker instances created successfully") + + return doneCh, quickDieCh, nil +} + +func (l *Loader) stop() { + // stop worker + log.Logger.Debug("Stopping worker instance...") + if l.workMgr != nil { + l.workMgr.Stop() + } + log.Logger.Debug("Worker instances have stopped") + + // closing connection + log.Logger.Debug("Closing database connection...") + for _, conn := range l.conns { + if conn != nil { + conn.Close(context.Background()) + } + } + log.Logger.Debug("Database connections have closed") +} + +func (l *Loader) Initialize(cmd *cobra.Command) { + flagSet := cmd.Flags() + + flagSet.StringVar(&l.option.Host, option.HOST, "", "Host to connect to (default localhost)") + flagSet.IntVar(&l.option.Port, option.PORT, 0, "Port to connect to (default 5432)") + flagSet.StringVar(&l.option.User, option.USER, "", "User to connect as (default gpadmin)") + flagSet.StringVar(&l.option.Database, option.DATABASE, "", "Database to connect to (default gpadmin)") + flagSet.BoolVar(&l.option.ForcePasswordAuth, option.FORCE_PASSWORD_AUTH, false, "Force a password prompt (default false)") + flagSet.StringVar(&l.option.Table, option.TABLE, "", "Table to load to") + flagSet.StringVar(&l.option.Tag, option.TAG, "", "File tag") + flagSet.StringVar(&l.option.DestPath, option.DEST_PATH, "", "Path relative to the table root directory (default: root directory of the table)") + flagSet.StringSliceVar(&l.option.InputFile, option.INPUT_FILE, []string{}, "Input files or directory") + flagSet.IntVar(&l.option.NumTasks, option.TASKS, 1, "The maximum number of files that concurrently loads") + flagSet.StringVar(&l.option.LogFile, option.LOGFILE, "", "Log output to logfile (default none)") + flagSet.BoolVar(&l.option.StopOnError, option.STOP_ON_ERROR, false, "Stop loading files when an error occurs (default false)") + flagSet.BoolVar(&l.option.Verbose, option.VERBOSE, false, "Indicates that the tool should generate verbose output (default false)") + flagSet.Bool("help", false, "Print help info and exit") + flagSet.Bool("version", false, "Print version info and exit") + + cmd.MarkFlagRequired(option.TABLE) + cmd.MarkFlagRequired(option.INPUT_FILE) +} + +func (l *Loader) GetVersion() string { + return "1.0.0" +} + +func (l *Loader) Run(cmd *cobra.Command, args []string) { + // initialize log + log.Initialize(l.option.LogFile, l.option.Verbose) + defer log.ShutDown() + + // parse options + err := l.option.Parse() + if err != nil { + log.Logger.Fatalf("%v", err) + } + + interrupt := make(chan os.Signal, 1) + signal.Notify(interrupt, os.Interrupt) + + // start loader + doneCh, quickDieCh, err := l.start() + if err != nil { + log.Logger.Fatalf("Failed to start loader: %v", err) + } + + if doneCh != nil { + loop: + for { + select { + case <-interrupt: + err = errors.New("Caught interrupt signal, exitting...") + log.Logger.Errorf("%v", err) + break loop + case <-quickDieCh: + err = errors.New("Caught internal error, exitting...") + log.Logger.Errorf("%v", err) + break loop + case <-doneCh: + log.Logger.Infof("successfully loaded %v files, failed %v files", + l.workMgr.GetNumSucceedFiles(), l.workMgr.GetNumFailedFiles()) + break loop + case <-time.After(25 * time.Millisecond): + log.Logger.Debug("Event loop") + } + } + } + + l.stop() + + if err != nil { + os.Exit(1) + } +} diff --git a/gpMgmt/bin/cbload/log/log.go b/gpMgmt/bin/cbload/log/log.go new file mode 100644 index 00000000000..4a0a45405be --- /dev/null +++ b/gpMgmt/bin/cbload/log/log.go @@ -0,0 +1,59 @@ +package log + +import ( + "io" + "os" + "strings" + + "github.com/sirupsen/logrus" + prefixed "github.com/x-cray/logrus-prefixed-formatter" +) + +var Logger = logrus.New() +var logFileHandle *os.File + +func Initialize(file string, verbose bool) (err error) { + formater := new(prefixed.TextFormatter) + formater.TimestampFormat = "2006-01-02 15:04:05" + formater.FullTimestamp = true + + Logger.Formatter = formater + + if len(file) > 0 { + logFileHandle, err = os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) + if err != nil { + return err + } + + Logger.Out = io.MultiWriter(logFileHandle, os.Stderr) + } + + if verbose { + setLogLevel("debug") + } else { + setLogLevel("info") + } + + return nil +} + +func setLogLevel(logLevelString string) { + switch strings.ToLower(logLevelString) { + case "debug": + Logger.SetLevel(logrus.DebugLevel) + case "info": + Logger.SetLevel(logrus.InfoLevel) + case "warning": + Logger.SetLevel(logrus.WarnLevel) + case "error": + Logger.SetLevel(logrus.ErrorLevel) + case "fatal": + Logger.SetLevel(logrus.FatalLevel) + default: + Logger.Warn("Unknown log level \"" + logLevelString + "\". Falling back to INFO.") + } +} + +func ShutDown() { + logFileHandle.Close() +} diff --git a/gpMgmt/bin/cbload/main.go b/gpMgmt/bin/cbload/main.go new file mode 100644 index 00000000000..12e4bbbdac5 --- /dev/null +++ b/gpMgmt/bin/cbload/main.go @@ -0,0 +1,20 @@ +package main + +import ( + "github.com/cloudberrydb/cbload/loader" + "github.com/spf13/cobra" +) + +func main() { + l := loader.NewLoader() + + var rootCmd = &cobra.Command{ + Use: "cbload", + Short: "load file(s) into Cloudberry Database", + Version: l.GetVersion(), + Run: l.Run, + } + + l.Initialize(rootCmd) + rootCmd.Execute() +} diff --git a/gpMgmt/bin/cbload/option/option.go b/gpMgmt/bin/cbload/option/option.go new file mode 100644 index 00000000000..a8f0720b76c --- /dev/null +++ b/gpMgmt/bin/cbload/option/option.go @@ -0,0 +1,286 @@ +package option + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" + "syscall" + + "github.com/cloudberrydb/cbload/log" + "github.com/pkg/errors" + "golang.org/x/term" +) + +const ( + HOST = "host" + PORT = "port" + USER = "user" + DATABASE = "database" + FORCE_PASSWORD_AUTH = "force-password-auth" + TABLE = "table" + TAG = "tag" + DEST_PATH = "dest-path" + INPUT_FILE = "input-file" + TASKS = "tasks" + LOGFILE = "logfile" + STOP_ON_ERROR = "stop-on-error" + VERBOSE = "verbose" +) + +type Option struct { + Host string + Port int + User string + Database string + Password string + ForcePasswordAuth bool + Table string + Tag string + DestPath string + InputFile []string + LogFile string + NumTasks int + StopOnError bool + Verbose bool +} + +func NewOption() *Option { + o := &Option{} + + return o +} + +func (o *Option) Parse() error { + var err error + + o.Host = o.getHostOrDefault(o.Host) + o.Port = o.getPortOrDefault(o.Port) + o.User = o.getUserOrDefault(o.User) + o.Database = o.getDatabaseOrDefault(o.Database) + o.Password, err = o.getPasswordOrDefault(o.ForcePasswordAuth) + if err != nil { + return err + } + + if o.NumTasks > 256 || o.NumTasks < 1 { + return errors.Errorf("Invalid value: \"%v\" for --tasks option, the number of tasks must be in the range of 1 to 256", o.NumTasks) + } + + return nil +} + +func (o *Option) getHostOrDefault(host string) string { + result := host + + if len(result) == 0 { + result = os.Getenv("PGHOST") + } + + if len(result) == 0 { + result = "localhost" + } + + return result +} + +func (o *Option) getPortOrDefault(port int) int { + result := port + + if result == 0 { + p, err := strconv.Atoi(os.Getenv("PGPORT")) + if err == nil { + result = p + } + } + + if result == 0 { + result = 5432 + } + + return result +} + +func (o *Option) getUserOrDefault(user string) string { + result := user + + if len(result) == 0 { + result = os.Getenv("PGUSER") + } + + if len(result) == 0 { + result = os.Getenv("USER") + if len(o.User) == 0 { + result = os.Getenv("LOGNAME") + } + if len(o.User) == 0 { + result = os.Getenv("USERNAME") + } + } + + if len(result) == 0 { + result = "gpadmin" + } + + return result +} + +func (o *Option) getDatabaseOrDefault(database string) string { + result := database + + if len(result) == 0 { + result = os.Getenv("PGDATABASE") + } + + if len(result) == 0 { + result = o.User + } + + return result +} + +func (o *Option) getPasswordOrDefault(forcePasswordAuth bool) (string, error) { + result := "" + var err error + + if forcePasswordAuth { + fmt.Printf("Password: ") + bp, err := term.ReadPassword(int(syscall.Stdin)) + fmt.Printf("\n") + if err != nil { + return result, err + } + result = string(bp) + } + + if len(result) == 0 { + result = os.Getenv("PGPASSWORD") + } + + if len(result) == 0 { + passFile := os.Getenv("PGPASSFILE") + if len(passFile) == 0 { + dir := os.Getenv("HOME") + if len(dir) == 0 { + dir = "." + } + passFile = dir + "/.pgpass" + } + + result, err = o.readPGPass(passFile) + if err != nil { + return result, err + } + } + + return result, nil +} + +func (o *Option) readPGPass(file string) (string, error) { + password := "" + + f, err := os.Open(file) + if err != nil { + log.Logger.Debugf("%v", err) + return password, nil + } + + defer f.Close() + sc := bufio.NewScanner(f) + + for sc.Scan() { + elems := o.splitPGPassLine(sc.Text()) + if len(elems) != 5 { + return password, errors.Errorf("pgpass file: invalid line \"%v\":there should be 5 fields in a line, seperated by colon", sc.Text()) + } + + if elems[0] != "*" && strings.ToLower(elems[0]) != strings.ToLower(o.Host) { + continue + } + + if elems[1] != "*" { + p, err := strconv.Atoi(elems[1]) + + if err != nil { + return password, errors.Errorf("pgpass file: invalid line \"%v\":port number should be integer", sc.Text()) + } + + if p != o.Port { + continue + } + } + + if elems[2] != "*" && elems[2] != o.Database { + continue + } + + if elems[3] != "*" && elems[3] != o.User { + continue + } + + password = elems[4] + break + } + + return password, nil +} + +func (o *Option) splitPGPassLine(line string) []string { + escape := false + results := make([]string, 0) + elem := make([]byte, 0) + bline := []byte(line) + + for _, c := range bline { + if !escape && c == '\\' { + escape = true + } else if !escape && c == ':' { + results = append(results, string(elem)) + elem = make([]byte, 0) + } else { + elem = append(elem, c) + escape = false + } + } + + if escape { + elem = append(elem, '\\') + } + + results = append(results, string(elem)) + + return results +} + +func (o *Option) IsDirectoryMode() (bool, error) { + numDirs := 0 + for _, file := range o.InputFile { + stat, err := os.Stat(file) + if err != nil { + return false, err + } + + if stat.IsDir() { + numDirs++ + } + } + + if len(o.InputFile) == 1 { + if numDirs == 1 { + return true, nil + } + + return false, nil + } + + if numDirs == len(o.InputFile) { + return false, errors.Errorf("Only one directory can be specified") + } + + if numDirs > 0 { + return false, errors.Errorf("File and directory cannot be specified at the same time") + } + + return false, nil +} diff --git a/gpMgmt/bin/cbload/worker/worker.go b/gpMgmt/bin/cbload/worker/worker.go new file mode 100644 index 00000000000..0d0460b7af3 --- /dev/null +++ b/gpMgmt/bin/cbload/worker/worker.go @@ -0,0 +1,168 @@ +package worker + +import ( + "bufio" + "context" + "fmt" + "os" + "sync" + "sync/atomic" + + "github.com/cloudberrydb/cbload/log" + "github.com/jackc/pgconn" +) + +type Worker struct { + context context.Context + cancelContextFunc context.CancelFunc + conn *pgconn.PgConn + id int + localFiles []string + destFiles []string + manager *WorkManager +} + +type WorkManager struct { + sync.Mutex + waitGroup sync.WaitGroup + table string + tag string + conns []*pgconn.PgConn + localFiles [][]string + destFiles [][]string + workers []*Worker + doneCh chan struct{} + quickDieCh chan struct{} + syncCh chan struct{} + numFileSucceed atomic.Uint32 + numFileFailed atomic.Uint32 + stopOnError bool +} + +func NewWorkManager(table, tag string, conns []*pgconn.PgConn, localFiles, destFiles [][]string, stopOnError bool) *WorkManager { + wm := &WorkManager{ + table: table, + tag: tag, + conns: conns, + localFiles: localFiles, + destFiles: destFiles, + stopOnError: stopOnError, + workers: make([]*Worker, len(conns)), + doneCh: make(chan struct{}, 1), + quickDieCh: make(chan struct{}, 1), + syncCh: make(chan struct{}, 1), + } + return wm +} + +func (wm *WorkManager) Start() (chan struct{}, chan struct{}) { + log.Logger.Debug("WorkManager starting...") + numWorkers := len(wm.conns) + + wm.waitGroup.Add(numWorkers) + for i := 0; i < numWorkers; i++ { + wm.workers[i] = newWorker(wm, i, wm.conns[i], wm.localFiles[i], wm.destFiles[i]) + go wm.workers[i].Run() + } + + go func() { + wm.waitGroup.Wait() + log.Logger.Debug("All workers have completed") + wm.syncCh <- struct{}{} + wm.doneCh <- struct{}{} + log.Logger.Debug("The main thread has already been notified") + }() + + return wm.doneCh, wm.quickDieCh +} + +func (wm *WorkManager) GetNumSucceedFiles() uint32 { + return wm.numFileSucceed.Load() +} + +func (wm *WorkManager) GetNumFailedFiles() uint32 { + return wm.numFileFailed.Load() +} + +func (wm *WorkManager) Stop() { + log.Logger.Debug("WorkManager stopping...") + + numWorkers := len(wm.conns) + for i := 0; i < numWorkers; i++ { + wm.workers[i].Stop() + } + + <-wm.syncCh + log.Logger.Debug("WorkManager stopped") +} + +func newWorker(manager *WorkManager, id int, conn *pgconn.PgConn, localFiles, destFiles []string) *Worker { + ctx, cancelFunc := context.WithCancel(context.Background()) + worker := &Worker{ctx, cancelFunc, conn, id, localFiles, destFiles, manager} + return worker +} + +func (w *Worker) Run() { + defer w.manager.waitGroup.Done() + + log.Logger.Debugf("Worker [%v]: started", w.id) + +loop: + for i, file := range w.localFiles { + fh, err := os.Open(file) + if err != nil { + if w.handleError("unable to open file", file, err) { + break + } + continue + } + + log.Logger.Infof("Worker [%v]: loading file \"%v\" into \"%v:%v\"...", w.id, file, w.manager.table, w.destFiles[i]) + + _, err = w.conn.CopyFrom(w.context, + bufio.NewReader(fh), + w.formCopyStatement(w.destFiles[i])) + if err != nil { + if w.handleError("unable to upload file", file, err) { + break + } + continue + } + + w.manager.numFileSucceed.Add(1) + fh.Close() + log.Logger.Infof("Worker [%v]: successfully loaded", w.id) + + select { + case <-w.context.Done(): + break loop + default: + } + } + + log.Logger.Debugf("Worker [%v]: stopped", w.id) +} + +func (w *Worker) handleError(title, file string, err error) bool { + w.manager.numFileFailed.Add(1) + log.Logger.Errorf("Worker [%v]: %v \"%v\": %v", w.id, title, file, err) + if w.manager.stopOnError { + w.manager.quickDieCh <- struct{}{} + return true + } + + return false +} + +func (w *Worker) formCopyStatement(file string) string { + if len(w.manager.tag) == 0 { + return fmt.Sprintf("copy binary %s from stdin '%s';", w.manager.table, file) + } + + return fmt.Sprintf("copy binary %s from stdin '%s' with tag '%s';", w.manager.table, file, w.manager.tag) +} + +func (w *Worker) Stop() { + log.Logger.Debugf("Worker [%v]: stopping...", w.id) + w.cancelContextFunc() +} diff --git a/gpMgmt/bin/gpcheckcat b/gpMgmt/bin/gpcheckcat index b1e43728f14..ea8ed134180 100755 --- a/gpMgmt/bin/gpcheckcat +++ b/gpMgmt/bin/gpcheckcat @@ -1579,6 +1579,10 @@ def checkTableInconsistentEntry(cat): columns.remove("passhistpasswordsetat") castcols.remove("passhistpasswordsetat") + if catname == "pg_directory_table": + columns.remove("dtlocation") + castcols.remove("dtlocation") + if cat.tableHasConsistentOids(): qry = inconsistentEntryQuery(GV.max_content, catname, ['oid'], columns, castcols) else: @@ -2926,7 +2930,7 @@ class GPObject: # Report missing issues if len(self.missingIssues): - omitlist = ['pg_attribute', 'pg_attribute_encoding', 'pg_type', 'pg_appendonly', 'pg_index', 'pg_password_history'] + omitlist = ['pg_attribute', 'pg_attribute_encoding', 'pg_type', 'pg_appendonly', 'pg_index', 'pg_password_history', 'pg_directory_table'] if 'pg_class' in self.missingIssues: myprint(' Name of test which found this issue: missing_extraneous_pg_class') for name in omitlist: diff --git a/gpcontrib/gp_distribution_policy/gp_distribution_policy.c b/gpcontrib/gp_distribution_policy/gp_distribution_policy.c index 506f7aab7f2..04a79963625 100644 --- a/gpcontrib/gp_distribution_policy/gp_distribution_policy.c +++ b/gpcontrib/gp_distribution_policy/gp_distribution_policy.c @@ -62,7 +62,8 @@ gp_distribution_policy_table_check(PG_FUNCTION_ARGS) /* Validate that the relation is a table */ if (rel->rd_rel->relkind != RELKIND_RELATION && - rel->rd_rel->relkind != RELKIND_MATVIEW) + rel->rd_rel->relkind != RELKIND_MATVIEW && + rel->rd_rel->relkind != RELKIND_DIRECTORY_TABLE) { ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), diff --git a/src/backend/access/aocs/aocsam_handler.c b/src/backend/access/aocs/aocsam_handler.c index a310138cded..995d69ee712 100644 --- a/src/backend/access/aocs/aocsam_handler.c +++ b/src/backend/access/aocs/aocsam_handler.c @@ -1267,7 +1267,8 @@ aoco_relation_set_new_filenode(Relation rel, { Assert(rel->rd_rel->relkind == RELKIND_RELATION || rel->rd_rel->relkind == RELKIND_MATVIEW || - rel->rd_rel->relkind == RELKIND_TOASTVALUE); + rel->rd_rel->relkind == RELKIND_TOASTVALUE || + rel->rd_rel->relkind == RELKIND_DIRECTORY_TABLE); smgrcreate(srel, INIT_FORKNUM, false); log_smgrcreate(newrnode, INIT_FORKNUM, SMGR_AO); smgrimmedsync(srel, INIT_FORKNUM); diff --git a/src/backend/access/appendonly/appendonlyam_handler.c b/src/backend/access/appendonly/appendonlyam_handler.c index fea0028596b..c1d63e8e071 100644 --- a/src/backend/access/appendonly/appendonlyam_handler.c +++ b/src/backend/access/appendonly/appendonlyam_handler.c @@ -1142,6 +1142,7 @@ appendonly_relation_set_new_filenode(Relation rel, { Assert(rel->rd_rel->relkind == RELKIND_RELATION || rel->rd_rel->relkind == RELKIND_MATVIEW || + rel->rd_rel->relkind == RELKIND_DIRECTORY_TABLE || rel->rd_rel->relkind == RELKIND_TOASTVALUE); smgrcreate(srel, INIT_FORKNUM, false); log_smgrcreate(newrnode, INIT_FORKNUM, SMGR_AO); diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c index 0f3a1ed6bf4..fc9edaf7f7c 100644 --- a/src/backend/access/common/reloptions.c +++ b/src/backend/access/common/reloptions.c @@ -166,6 +166,15 @@ static relopt_bool boolRelOpts[] = }, true }, + { + { + "stage", + "Declare a tablespace as a dfs staged tablespace", + RELOPT_KIND_TABLESPACE, + AccessExclusiveLock + }, + false + }, /* list terminator */ {{NULL}} }; @@ -546,6 +555,24 @@ static relopt_enum enumRelOpts[] = static relopt_string stringRelOpts[] = { + { + { + "server", + "the server used by the dfs tablespace", + RELOPT_KIND_TABLESPACE, + AccessExclusiveLock + }, + 0, true, NULL, NULL, NULL + }, + { + { + "path", + "the path of the dfs tablespace", + RELOPT_KIND_TABLESPACE, + AccessExclusiveLock + }, + 0, true, NULL, NULL, NULL + }, /* list terminator */ {{NULL}} }; @@ -1403,6 +1430,7 @@ extractRelOptions(HeapTuple tuple, TupleDesc tupdesc, case RELKIND_RELATION: case RELKIND_TOASTVALUE: case RELKIND_MATVIEW: + case RELKIND_DIRECTORY_TABLE: options = table_reloptions((tamoptions_function)amoptions, datum, classForm->relkind, false); break; case RELKIND_PARTITIONED_TABLE: @@ -2028,6 +2056,7 @@ bytea * table_reloptions(tamoptions_function amoptions, Datum reloptions, char relkind, bool validate) { Assert(relkind == RELKIND_RELATION || + relkind == RELKIND_DIRECTORY_TABLE || relkind == RELKIND_TOASTVALUE || relkind == RELKIND_MATVIEW); if (amoptions == NULL) @@ -2098,7 +2127,10 @@ tablespace_reloptions(Datum reloptions, bool validate) {"random_page_cost", RELOPT_TYPE_REAL, offsetof(TableSpaceOpts, random_page_cost)}, {"seq_page_cost", RELOPT_TYPE_REAL, offsetof(TableSpaceOpts, seq_page_cost)}, {"effective_io_concurrency", RELOPT_TYPE_INT, offsetof(TableSpaceOpts, effective_io_concurrency)}, - {"maintenance_io_concurrency", RELOPT_TYPE_INT, offsetof(TableSpaceOpts, maintenance_io_concurrency)} + {"maintenance_io_concurrency", RELOPT_TYPE_INT, offsetof(TableSpaceOpts, maintenance_io_concurrency)}, + {"stage", RELOPT_TYPE_BOOL, offsetof(TableSpaceOpts, stage)}, + {"server", RELOPT_TYPE_STRING, offsetof(TableSpaceOpts, serverOffset)}, + {"path", RELOPT_TYPE_STRING, offsetof(TableSpaceOpts, pathOffset)} }; return (bytea *) build_reloptions(reloptions, validate, diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c index c7b8fb0e86b..1f03527353f 100644 --- a/src/backend/access/heap/heapam_handler.c +++ b/src/backend/access/heap/heapam_handler.c @@ -621,6 +621,7 @@ heapam_relation_set_new_filenode(Relation rel, { Assert(rel->rd_rel->relkind == RELKIND_RELATION || rel->rd_rel->relkind == RELKIND_MATVIEW || + rel->rd_rel->relkind == RELKIND_DIRECTORY_TABLE || rel->rd_rel->relkind == RELKIND_TOASTVALUE || rel->rd_rel->relkind == RELKIND_AOSEGMENTS || rel->rd_rel->relkind == RELKIND_AOVISIMAP || diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile index e8b1560acc8..c3ccbdc18e4 100644 --- a/src/backend/catalog/Makefile +++ b/src/backend/catalog/Makefile @@ -52,7 +52,8 @@ OBJS += pg_extprotocol.o \ pg_appendonly.o \ oid_dispatch.o aocatalog.o storage_tablespace.o storage_database.o \ storage_tablespace_twophase.o storage_tablespace_xact.o \ - gp_partition_template.o pg_task.o pg_task_run_history.o + gp_partition_template.o pg_task.o pg_task_run_history.o \ + pg_directory_table.o storage_directory_table.o CATALOG_JSON:= $(addprefix $(top_srcdir)/gpMgmt/bin/gppylib/data/, $(addsuffix .json,$(GP_MAJORVERSION))) @@ -92,7 +93,8 @@ CATALOG_HEADERS := \ pg_collation.h pg_partitioned_table.h pg_range.h pg_transform.h \ pg_sequence.h pg_publication.h pg_publication_rel.h pg_subscription.h \ pg_subscription_rel.h gp_partition_template.h pg_task.h pg_task_run_history.h \ - pg_profile.h pg_password_history.h + pg_profile.h pg_password_history.h pg_directory_table.h gp_storage_server.h \ + gp_storage_user_mapping.h USE_INTERNAL_FTS_FOUND := $(if $(findstring USE_INTERNAL_FTS,$(CFLAGS)),true,false) diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index 066f8c75d63..c579dbffc52 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -27,6 +27,7 @@ #include "catalog/binary_upgrade.h" #include "catalog/catalog.h" #include "catalog/dependency.h" +#include "catalog/gp_storage_server.h" #include "catalog/heap.h" #include "catalog/indexing.h" #include "catalog/objectaccess.h" @@ -270,6 +271,9 @@ restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs, case OBJECT_FOREIGN_SERVER: whole_mask = ACL_ALL_RIGHTS_FOREIGN_SERVER; break; + case OBJECT_STORAGE_SERVER: + whole_mask = ACL_ALL_RIGHTS_STORAGE_SERVER; + break; case OBJECT_EVENT_TRIGGER: elog(ERROR, "grantable rights not supported for event triggers"); /* not reached, but keep compiler quiet */ @@ -528,6 +532,10 @@ ExecuteGrantStmt(GrantStmt *stmt) all_privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER; errormsg = gettext_noop("invalid privilege type %s for foreign server"); break; + case OBJECT_STORAGE_SERVER: + all_privileges = ACL_ALL_RIGHTS_STORAGE_SERVER; + errormsg = gettext_noop("invalid privilege type %s from storage server"); + break; case OBJECT_EXTPROTOCOL: all_privileges = ACL_ALL_RIGHTS_EXTPROTOCOL; errormsg = gettext_noop("invalid privilege type %s for external protocol"); @@ -922,6 +930,8 @@ objectsInSchemaToOids(ObjectType objtype, List *nspnames) objects = list_concat(objects, objs); objs = getRelationsInNamespace(namespaceId, RELKIND_PARTITIONED_TABLE); objects = list_concat(objects, objs); + objs = getRelationsInNamespace(namespaceId, RELKIND_DIRECTORY_TABLE); + objects = list_concat(objects, objs); break; case OBJECT_SEQUENCE: objs = getRelationsInNamespace(namespaceId, RELKIND_SEQUENCE); @@ -3691,6 +3701,9 @@ aclcheck_error(AclResult aclerr, ObjectType objtype, case OBJECT_DOMAIN: msg = gettext_noop("permission denied for domain %s"); break; + case OBJECT_DIRECTORY_TABLE: + msg = gettext_noop("permission denied for directory table %s"); + break; case OBJECT_EVENT_TRIGGER: msg = gettext_noop("permission denied for event trigger %s"); break; @@ -3751,6 +3764,9 @@ aclcheck_error(AclResult aclerr, ObjectType objtype, case OBJECT_STATISTIC_EXT: msg = gettext_noop("permission denied for statistics object %s"); break; + case OBJECT_STORAGE_SERVER: + msg = gettext_noop("permission denied for storage server %s"); + break; case OBJECT_SUBSCRIPTION: msg = gettext_noop("permission denied for subscription %s"); break; @@ -3796,6 +3812,7 @@ aclcheck_error(AclResult aclerr, ObjectType objtype, case OBJECT_TSTEMPLATE: case OBJECT_USER_MAPPING: case OBJECT_PROFILE: + case OBJECT_STORAGE_USER_MAPPING: elog(ERROR, "unsupported object type %d", objtype); } @@ -3825,6 +3842,9 @@ aclcheck_error(AclResult aclerr, ObjectType objtype, case OBJECT_DOMAIN: msg = gettext_noop("must be owner of domain %s"); break; + case OBJECT_DIRECTORY_TABLE: + msg = gettext_noop("must be owner of directory table %s"); + break; case OBJECT_EVENT_TRIGGER: msg = gettext_noop("must be owner of event trigger %s"); break; @@ -3938,6 +3958,8 @@ aclcheck_error(AclResult aclerr, ObjectType objtype, case OBJECT_TSTEMPLATE: case OBJECT_USER_MAPPING: case OBJECT_PROFILE: + case OBJECT_STORAGE_SERVER: + case OBJECT_STORAGE_USER_MAPPING: elog(ERROR, "unsupported object type %d", objtype); } @@ -4828,6 +4850,65 @@ pg_foreign_server_aclmask(Oid srv_oid, Oid roleid, return result; } +/* + * Exported routine for examining a user's privileges for a storage + * server. + */ +AclMode +gp_storage_server_aclmask(Oid srv_oid, Oid roleid, + AclMode mask, AclMaskHow how) +{ + AclMode result; + HeapTuple tuple; + Datum aclDatum; + bool isNull; + Acl *acl; + Oid ownerId; + + Form_gp_storage_server srvForm; + + /* Bypass permission checks for superusers */ + if (superuser_arg(roleid)) + return mask; + + tuple = SearchSysCache1(STORAGESERVEROID, ObjectIdGetDatum(srv_oid)); + if (!HeapTupleIsValid(tuple)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("storage server with OID %u does not exist", + srv_oid))); + srvForm = (Form_gp_storage_server) GETSTRUCT(tuple); + + /* + * Normal case: get the storage server's ACL from gp_storage_server + */ + ownerId = srvForm->srvowner; + + aclDatum = SysCacheGetAttr(STORAGESERVEROID, tuple, + Anum_gp_storage_server_srvacl, &isNull); + if (isNull) + { + /* No ACL, so build default ACL */ + acl = acldefault(OBJECT_STORAGE_SERVER, ownerId); + aclDatum = (Datum) 0; + } + else + { + /* detoast rel's ACL if necessary */ + acl = DatumGetAclP(aclDatum); + } + + result = aclmask(acl, roleid, ownerId, mask, how); + + /* if we have a detoasted copy, free it */ + if (acl && (Pointer) acl != DatumGetPointer(aclDatum)) + pfree(acl); + + ReleaseSysCache(tuple); + + return result; +} + /* * Exported routine for examining a user's privileges for a type. */ @@ -5245,6 +5326,19 @@ pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mode) return ACLCHECK_NO_PRIV; } +/* + * Exported routine for checking a user's access privileges to a storage + * server + */ +AclResult +gp_storage_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mode) +{ + if (gp_storage_server_aclmask(srv_oid, roleid, mode, ACLMASK_ANY) != 0) + return ACLCHECK_OK; + else + return ACLCHECK_NO_PRIV; +} + /* * Exported routine for checking a user's access privileges to a type */ @@ -5661,6 +5755,33 @@ pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid) return has_privs_of_role(roleid, ownerId); } +/* + * Ownership check for a storage server (specified by OID). + */ +bool +gp_storage_server_ownercheck(Oid srv_oid, Oid roleid) +{ + HeapTuple tuple; + Oid ownerId; + + /* Superusers bypass all permission checking. */ + if (superuser_arg(roleid)) + return true; + + tuple = SearchSysCache1(STORAGESERVEROID, ObjectIdGetDatum(srv_oid)); + if (!HeapTupleIsValid(tuple)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("storage server with OID %u does not exist", + srv_oid))); + + ownerId = ((Form_gp_storage_server) GETSTRUCT(tuple))->srvowner; + + ReleaseSysCache(tuple); + + return has_privs_of_role(roleid, ownerId); +} + /* * Ownership check for an event trigger (specified by OID). */ @@ -6679,6 +6800,7 @@ CopyRelationAcls(Oid srcId, Oid destId) if (pg_class_tuple->relkind != RELKIND_RELATION && pg_class_tuple->relkind != RELKIND_PARTITIONED_TABLE && + pg_class_tuple->relkind != RELKIND_DIRECTORY_TABLE && pg_class_tuple->relkind != RELKIND_FOREIGN_TABLE) elog(ERROR, "unexpected relkind %c", pg_class_tuple->relkind); diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.c index 81b9ebf44ba..8c4c7023921 100644 --- a/src/backend/catalog/catalog.c +++ b/src/backend/catalog/catalog.c @@ -58,6 +58,8 @@ #include "catalog/gp_configuration_history.h" #include "catalog/gp_id.h" +#include "catalog/gp_storage_server.h" +#include "catalog/gp_storage_user_mapping.h" #include "catalog/gp_version_at_initdb.h" #include "catalog/gp_warehouse.h" #include "catalog/pg_event_trigger.h" @@ -439,6 +441,9 @@ IsSharedRelation(Oid relationId) #endif relationId == AuthTimeConstraintRelationId || + relationId == StorageUserMappingRelationId || + relationId == StorageServerRelationId || + relationId == ProfileRelationId || relationId == PasswordHistoryRelationId) return true; @@ -486,6 +491,10 @@ IsSharedRelation(Oid relationId) #endif relationId == AuthTimeConstraintAuthIdIndexId || relationId == AuthIdRolProfileIndexId || + relationId == StorageUserMappingOidIndexId || + relationId == StorageUserMappingServerIndexId || + relationId == StorageServerOidIndexId || + relationId == StorageServerNameIndexId || relationId == ProfilePrfnameIndexId || relationId == ProfileOidIndexId || relationId == ProfileVerifyFunctionIndexId || @@ -524,6 +533,13 @@ IsSharedRelation(Oid relationId) } #endif + /* GPDB added toast tables and toast indexes */ + if (relationId == GpStorageUserMappingToastTable || + relationId == GpStorageUserMappingToastIndex || + relationId == GpStorageServerToastTable || + relationId == GpStorageServerToastIndex) + return true; + /* GPDB added task tables and their indexes */ if (relationId == TaskRelationId || relationId == TaskJobNameUserNameIndexId || diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index d9f5ac7e23d..6be702e488b 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -20,6 +20,8 @@ #include "access/table.h" #include "access/xact.h" #include "catalog/dependency.h" +#include "catalog/gp_storage_server.h" +#include "catalog/gp_storage_user_mapping.h" #include "catalog/heap.h" #include "catalog/index.h" #include "catalog/namespace.h" @@ -36,6 +38,7 @@ #include "catalog/pg_database.h" #include "catalog/pg_default_acl.h" #include "catalog/pg_depend.h" +#include "catalog/pg_directory_table.h" #include "catalog/pg_event_trigger.h" #include "catalog/pg_extension.h" #include "catalog/pg_foreign_data_wrapper.h" @@ -202,6 +205,9 @@ static const Oid object_classes[] = { /* GPDB additions */ ProfileRelationId, /* OCLASS_PROFILE */ PasswordHistoryRelationId, /* OCLASS_PASSWORDHISTORY */ + DirectoryTableRelationId, /* OCLASS_DIRECTORY_TABLE */ + StorageServerRelationId, /* OCLASS_STORAGE_SERVER */ + StorageUserMappingRelationId, /* OCLASS_STORAGE_USER_MAPPING */ ExtprotocolRelationId, /* OCLASS_EXTPROTOCOL */ TaskRelationId /* OCLASS_TASK */ }; @@ -1579,6 +1585,8 @@ doDeletion(const ObjectAddress *object, int flags) case OCLASS_SUBSCRIPTION: case OCLASS_PROFILE: case OCLASS_PASSWORDHISTORY: + case OCLASS_STORAGE_SERVER: + case OCLASS_STORAGE_USER_MAPPING: elog(ERROR, "global objects cannot be deleted by doDeletion"); break; @@ -2970,6 +2978,15 @@ getObjectClass(const ObjectAddress *object) case TaskRelationId: return OCLASS_TASK; + case DirectoryTableRelationId: + return OCLASS_DIRTABLE; + + case StorageServerRelationId: + return OCLASS_STORAGE_SERVER; + + case StorageUserMappingRelationId: + return OCLASS_STORAGE_USER_MAPPING; + default: { struct CustomObjectClass *coc; diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 57b4de0ad90..3183d113696 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -60,6 +60,7 @@ #include "catalog/pg_collation.h" #include "catalog/pg_constraint.h" #include "catalog/pg_database.h" +#include "catalog/pg_directory_table.h" #include "catalog/pg_foreign_table.h" #include "catalog/pg_inherits.h" #include "catalog/pg_namespace.h" @@ -70,6 +71,7 @@ #include "catalog/pg_tablespace.h" #include "catalog/pg_type.h" #include "catalog/storage.h" +#include "catalog/storage_directory_table.h" #include "catalog/storage_xlog.h" #include "commands/tablecmds.h" #include "commands/typecmds.h" @@ -485,6 +487,7 @@ heap_create(const char *relname, case RELKIND_RELATION: case RELKIND_TOASTVALUE: case RELKIND_MATVIEW: + case RELKIND_DIRECTORY_TABLE: table_relation_set_new_filenode(rel, &rel->rd_node, relpersistence, relfrozenxid, relminmxid); @@ -1365,6 +1368,7 @@ AddNewRelationTuple(Relation pg_class_desc, case RELKIND_AOSEGMENTS: case RELKIND_AOBLOCKDIR: case RELKIND_AOVISIMAP: + case RELKIND_DIRECTORY_TABLE: /* The relation is real, but as yet empty */ new_rel_reltup->relpages = 0; new_rel_reltup->reltuples = -1; @@ -1599,6 +1603,7 @@ heap_create_with_catalog(const char *relname, case RELKIND_MATVIEW: case RELKIND_FOREIGN_TABLE: case RELKIND_PARTITIONED_TABLE: + case RELKIND_DIRECTORY_TABLE: relacl = get_user_default_acl(OBJECT_TABLE, ownerid, relnamespace); break; @@ -1852,6 +1857,7 @@ heap_create_with_catalog(const char *relname, * main table depends on it. */ if (relkind == RELKIND_RELATION || + relkind == RELKIND_DIRECTORY_TABLE || relkind == RELKIND_MATVIEW) { ObjectAddressSet(referenced, AccessMethodRelationId, accessmtd); @@ -1894,6 +1900,7 @@ heap_create_with_catalog(const char *relname, Assert(relkind == RELKIND_RELATION || relkind == RELKIND_PARTITIONED_TABLE || + relkind == RELKIND_DIRECTORY_TABLE || relkind == RELKIND_MATVIEW || relkind == RELKIND_FOREIGN_TABLE); @@ -1925,6 +1932,9 @@ heap_create_with_catalog(const char *relname, case RELKIND_MATVIEW: subtyp = "MATVIEW"; break; + case RELKIND_DIRECTORY_TABLE: + subtyp = "DIRECTORY TABLE"; + break; default: doIt = false; } @@ -2468,6 +2478,15 @@ heap_drop_with_catalog(Oid relid) if (relid == defaultPartOid) update_default_partition_oid(parentOid, InvalidOid); + /* + * Remove entry in pg_directory_table + */ + if (rel->rd_rel->relkind == RELKIND_DIRECTORY_TABLE) + { + RemoveDirectoryTableEntry(relid); + DirectoryTableDropStorage(rel); + } + /* * Schedule unlinking of the relation's physical files at commit. */ @@ -2480,6 +2499,7 @@ heap_drop_with_catalog(Oid relid) if (rel->rd_rel->relkind == RELKIND_RELATION || rel->rd_rel->relkind == RELKIND_MATVIEW || rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE || + rel->rd_rel->relkind == RELKIND_DIRECTORY_TABLE || rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) { GpPolicyRemove(relid); @@ -2489,6 +2509,7 @@ heap_drop_with_catalog(Oid relid) * Attribute encoding */ if (rel->rd_rel->relkind == RELKIND_RELATION || + rel->rd_rel->relkind == RELKIND_DIRECTORY_TABLE || rel->rd_rel->relkind == RELKIND_MATVIEW || rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) { diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index fb0fd99dda0..852af0f6759 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -22,6 +22,8 @@ #include "access/sysattr.h" #include "access/table.h" #include "catalog/catalog.h" +#include "catalog/gp_storage_server.h" +#include "catalog/gp_storage_user_mapping.h" #include "catalog/objectaddress.h" #include "catalog/pg_am.h" #include "catalog/pg_amop.h" @@ -76,6 +78,7 @@ #include "commands/proclang.h" #include "commands/queue.h" #include "commands/resgroupcmds.h" +#include "commands/storagecmds.h" #include "commands/tablespace.h" #include "commands/trigger.h" #include "foreign/foreign.h" @@ -297,6 +300,20 @@ static const ObjectPropertyType ObjectProperty[] = OBJECT_FOREIGN_SERVER, true }, + { + "storage server", + StorageServerRelationId, + StorageServerOidIndexId, + STORAGESERVEROID, + STORAGESERVERNAME, + Anum_gp_storage_server_oid, + Anum_gp_storage_server_srvname, + InvalidAttrNumber, + Anum_gp_storage_server_srvowner, + Anum_gp_storage_server_srvacl, + OBJECT_STORAGE_SERVER, + true + }, { "function", ProcedureRelationId, @@ -655,6 +672,20 @@ static const ObjectPropertyType ObjectProperty[] = OBJECT_USER_MAPPING, false }, + { + "storage user mapping", + StorageUserMappingRelationId, + StorageUserMappingOidIndexId, + STORAGEUSERMAPPINGOID, + -1, + Anum_gp_storage_user_mapping_oid, + InvalidAttrNumber, + InvalidAttrNumber, + InvalidAttrNumber, + InvalidAttrNumber, + OBJECT_STORAGE_USER_MAPPING, + false + }, /* GPDB additions */ { @@ -899,6 +930,18 @@ static const struct object_type_map /* OCLASS_PROFILE */ { "profile", OBJECT_PROFILE + }, + /* OCLASS_DIRECTORY_TABLE */ + { + "directory table", OBJECT_DIRECTORY_TABLE + }, + /* OCLASS_STORAGE_SERVER */ + { + "storage server", OBJECT_STORAGE_SERVER + }, + /* OCLASS_STORAGE_USER_MAPPING */ + { + "storage user mapping", OBJECT_STORAGE_USER_MAPPING } }; @@ -1014,6 +1057,7 @@ get_object_address(ObjectType objtype, Node *object, case OBJECT_VIEW: case OBJECT_MATVIEW: case OBJECT_FOREIGN_TABLE: + case OBJECT_DIRECTORY_TABLE: address = get_relation_by_qualified_name(objtype, castNode(List, object), &relation, lockmode, @@ -1073,6 +1117,8 @@ get_object_address(ObjectType objtype, Node *object, case OBJECT_RESQUEUE: case OBJECT_RESGROUP: case OBJECT_PROFILE: + case OBJECT_STORAGE_SERVER: + case OBJECT_STORAGE_USER_MAPPING: address = get_object_address_unqualified(objtype, (Value *) object, missing_ok); break; @@ -1397,6 +1443,11 @@ get_object_address_unqualified(ObjectType objtype, address.objectId = get_profile_oid(name, missing_ok); address.objectSubId = 0; break; + case OBJECT_STORAGE_SERVER: + address.classId = StorageServerRelationId; + address.objectId = get_storage_server_oid(name, missing_ok); + address.objectSubId = 0; + break; default: elog(ERROR, "unrecognized objtype: %d", (int) objtype); /* placate compiler, which doesn't know elog won't return */ @@ -1453,6 +1504,13 @@ get_relation_by_qualified_name(ObjectType objtype, List *object, errmsg("\"%s\" is not a table", RelationGetRelationName(relation)))); break; + case OBJECT_DIRECTORY_TABLE: + if (relation->rd_rel->relkind != RELKIND_DIRECTORY_TABLE) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not a directory table", + RelationGetRelationName(relation)))); + break; case OBJECT_VIEW: if (relation->rd_rel->relkind != RELKIND_VIEW) ereport(ERROR, @@ -2289,6 +2347,7 @@ pg_get_object_address(PG_FUNCTION_ARGS) case OBJECT_DOMCONSTRAINT: case OBJECT_CAST: case OBJECT_USER_MAPPING: + case OBJECT_STORAGE_USER_MAPPING: case OBJECT_PUBLICATION_REL: case OBJECT_DEFACL: case OBJECT_TRANSFORM: @@ -2350,6 +2409,7 @@ pg_get_object_address(PG_FUNCTION_ARGS) case OBJECT_TABCONSTRAINT: case OBJECT_OPCLASS: case OBJECT_OPFAMILY: + case OBJECT_DIRECTORY_TABLE: objnode = (Node *) name; break; case OBJECT_ACCESS_METHOD: @@ -2358,6 +2418,7 @@ pg_get_object_address(PG_FUNCTION_ARGS) case OBJECT_EXTENSION: case OBJECT_FDW: case OBJECT_FOREIGN_SERVER: + case OBJECT_STORAGE_SERVER: case OBJECT_LANGUAGE: case OBJECT_PUBLICATION: case OBJECT_ROLE: @@ -2389,6 +2450,9 @@ pg_get_object_address(PG_FUNCTION_ARGS) case OBJECT_USER_MAPPING: objnode = (Node *) list_make2(linitial(name), linitial(args)); break; + case OBJECT_STORAGE_USER_MAPPING: + objnode = (Node *) list_make2(linitial(name), linitial(args)); + break; case OBJECT_DEFACL: objnode = (Node *) lcons(linitial(args), name); break; @@ -2458,6 +2522,7 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address, case OBJECT_INDEX: case OBJECT_SEQUENCE: case OBJECT_TABLE: + case OBJECT_DIRECTORY_TABLE: case OBJECT_VIEW: case OBJECT_MATVIEW: case OBJECT_FOREIGN_TABLE: @@ -2547,6 +2612,11 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address, aclcheck_error(ACLCHECK_NOT_OWNER, objtype, strVal((Value *) object)); break; + case OBJECT_STORAGE_SERVER: + if (!gp_storage_server_ownercheck(address.objectId, roleid)) + aclcheck_error(ACLCHECK_NOT_OWNER, objtype, + strVal((Value *) object)); + break; case OBJECT_EVENT_TRIGGER: if (!pg_event_trigger_ownercheck(address.objectId, roleid)) aclcheck_error(ACLCHECK_NOT_OWNER, objtype, @@ -4080,6 +4150,50 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok) break; } + case OCLASS_STORAGE_SERVER: + { + StorageServer *srv; + + srv = GetStorageServerExtended(object->objectId, missing_ok); + if (srv) + appendStringInfo(&buffer, _("storage server %s"), srv->servername); + break; + } + + case OCLASS_STORAGE_USER_MAPPING: + { + HeapTuple tup; + Oid useid; + char *usename; + Form_gp_storage_user_mapping umform; + StorageServer *srv; + + tup = SearchSysCache1(STORAGEUSERMAPPINGOID, + ObjectIdGetDatum(object->objectId)); + if (!HeapTupleIsValid(tup)) + { + if (!missing_ok) + elog(ERROR, "cache lookup failed for storage user mapping %u", + object->objectId); + break; + } + + umform = (Form_gp_storage_user_mapping) GETSTRUCT(tup); + useid = umform->umuser; + srv = GetStorageServer(umform->umserver); + + ReleaseSysCache(tup); + + if (OidIsValid(useid)) + usename = GetUserNameFromId(useid, false); + else + usename = "public"; + + appendStringInfo(&buffer, _("storage user mapping for %s on storage server %s"), usename, + srv->servername); + break; + } + default: { struct CustomObjectClass *coc; @@ -4150,6 +4264,10 @@ getRelationDescription(StringInfo buffer, Oid relid, bool missing_ok) appendStringInfo(buffer, _("table %s"), relname); break; + case RELKIND_DIRECTORY_TABLE: + appendStringInfo(buffer, _("directory table %s"), + relname); + break; case RELKIND_INDEX: case RELKIND_PARTITIONED_INDEX: appendStringInfo(buffer, _("index %s"), @@ -4659,6 +4777,18 @@ getObjectTypeDescription(const ObjectAddress *object, bool missing_ok) appendStringInfoString(&buffer, "password_history"); break; + case OCLASS_DIRTABLE: + appendStringInfoString(&buffer, "directory table"); + break; + + case OCLASS_STORAGE_SERVER: + appendStringInfoString(&buffer, "storage server"); + break; + + case OCLASS_STORAGE_USER_MAPPING: + appendStringInfoString(&buffer, "storage user mapping"); + break; + default: { struct CustomObjectClass *coc; @@ -4709,6 +4839,9 @@ getRelationTypeDescription(StringInfo buffer, Oid relid, int32 objectSubId, case RELKIND_PARTITIONED_TABLE: appendStringInfoString(buffer, "table"); break; + case RELKIND_DIRECTORY_TABLE: + appendStringInfoString(buffer, "directory table"); + break; case RELKIND_INDEX: case RELKIND_PARTITIONED_INDEX: appendStringInfoString(buffer, "index"); @@ -5648,6 +5781,24 @@ getObjectIdentityParts(const ObjectAddress *object, break; } + case OCLASS_STORAGE_SERVER: + { + StorageServer *srv; + + srv = GetStorageServerExtended(object->objectId, + missing_ok); + + if (srv) + { + appendStringInfoString(&buffer, + quote_identifier(srv->servername)); + + if (objname) + *objname = list_make1(pstrdup(srv->servername)); + } + break; + } + case OCLASS_USER_MAPPING: { HeapTuple tup; @@ -5688,6 +5839,46 @@ getObjectIdentityParts(const ObjectAddress *object, break; } + case OCLASS_STORAGE_USER_MAPPING: + { + HeapTuple tup; + Oid useid; + Form_gp_storage_user_mapping umform; + StorageServer *srv; + const char *usename; + + tup = SearchSysCache1(STORAGEUSERMAPPINGOID, + ObjectIdGetDatum(object->objectId)); + if (!HeapTupleIsValid(tup)) + { + if (!missing_ok) + elog(ERROR, "cache lookup failed for storage user mapping %u", + object->objectId); + break; + } + umform = (Form_gp_storage_user_mapping) GETSTRUCT(tup); + useid = umform->umuser; + srv = GetStorageServer(umform->umserver); + + ReleaseSysCache(tup); + + if (OidIsValid(useid)) + usename = GetUserNameFromId(useid, false); + else + usename = "public"; + + if (objname) + { + *objname = list_make1(pstrdup(usename)); + *objargs = list_make1(pstrdup(srv->servername)); + } + + appendStringInfo(&buffer, "%s on storage server %s", + quote_identifier(usename), + srv->servername); + break; + } + case OCLASS_DEFACL: { Relation defaclrel; @@ -6200,6 +6391,8 @@ get_relkind_objtype(char relkind) return OBJECT_FOREIGN_TABLE; case RELKIND_TOASTVALUE: return OBJECT_TABLE; + case RELKIND_DIRECTORY_TABLE: + return OBJECT_DIRECTORY_TABLE; default: /* Per above, don't raise an error */ return OBJECT_TABLE; diff --git a/src/backend/catalog/oid_dispatch.c b/src/backend/catalog/oid_dispatch.c index fe7bf12a8f2..01c95a4644a 100644 --- a/src/backend/catalog/oid_dispatch.c +++ b/src/backend/catalog/oid_dispatch.c @@ -81,6 +81,8 @@ #include "catalog/catalog.h" #include "catalog/indexing.h" +#include "catalog/gp_storage_server.h" +#include "catalog/gp_storage_user_mapping.h" #include "catalog/pg_am.h" #include "catalog/pg_amop.h" #include "catalog/pg_amproc.h" @@ -778,6 +780,23 @@ GetNewOidForForeignServer(Relation relation, Oid indexId, AttrNumber oidcolumn, } +Oid +GetNewOidForStorageServer(Relation relation, Oid indexId, AttrNumber oidcolumn, + char *srvname) +{ + OidAssignment key; + + Assert(RelationGetRelid(relation) == StorageServerRelationId); + Assert(indexId == StorageServerOidIndexId); + Assert(oidcolumn == Anum_gp_storage_server_oid); + + memset(&key, 0, sizeof(OidAssignment)); + key.type = T_OidAssignment; + key.objname = srvname; + return GetNewOrPreassignedOid(relation, indexId, oidcolumn, &key); + +} + Oid GetNewOidForLanguage(Relation relation, Oid indexId, AttrNumber oidcolumn, char *lanname) @@ -1161,6 +1180,23 @@ GetNewOidForUserMapping(Relation relation, Oid indexId, AttrNumber oidcolumn, return GetNewOrPreassignedOid(relation, indexId, oidcolumn, &key); } +Oid +GetNewOidForStorageUserMapping(Relation relation, Oid indexId, AttrNumber oidcolumn, + Oid umuser, Oid umserver) +{ + OidAssignment key; + + Assert(RelationGetRelid(relation) == StorageUserMappingRelationId); + Assert(indexId == StorageUserMappingOidIndexId); + Assert(oidcolumn == Anum_gp_storage_user_mapping_oid); + + memset(&key, 0, sizeof(OidAssignment)); + key.type = T_OidAssignment; + key.keyOid1 = umuser; + key.keyOid2 = umserver; + return GetNewOrPreassignedOid(relation, indexId, oidcolumn, &key); +} + Oid GetNewOidForPublication(Relation relation, Oid indexId, AttrNumber oidcolumn, char *pubname) diff --git a/src/backend/catalog/pg_directory_table.c b/src/backend/catalog/pg_directory_table.c new file mode 100644 index 00000000000..49df145148f --- /dev/null +++ b/src/backend/catalog/pg_directory_table.c @@ -0,0 +1,375 @@ +/*------------------------------------------------------------------------- + * + * pg_directory_table.c + * support for directory table. + * + * Copyright (c) 2016-Present Hashdata, Inc. + * + * IDENTIFICATION + * src/backend/catalog/pg_directory_table.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "access/htup_details.h" +#include "access/xact.h" +#include "catalog/index.h" +#include "catalog/indexing.h" +#include "catalog/pg_collation.h" +#include "catalog/pg_opclass.h" +#include "cdb/cdbhash.h" +#include "cdb/cdbutil.h" +#include "parser/parser.h" +#include "parser/parse_func.h" +#include "catalog/pg_directory_table.h" +#include "catalog/gp_distribution_policy.h" +#include "catalog/pg_tablespace.h" +#include "storage/lmgr.h" +#include "utils/builtins.h" +#include "utils/inval.h" +#include "utils/lsyscache.h" +#include "utils/syscache.h" +#include "utils/varlena.h" + +typedef FileAm* (*File_handler) (void); +/* Hash table for tablespace file handler */ +static HTAB *TableSpaceFileHandlerHash = NULL; + +typedef struct TableSpaceFileAmEntry +{ + Oid spcId; /* tablespace oid */ + FileAm *fileAm; /* tablespace file am */ +} TableSpaceFileAmEntry; + +static void +InvalidateTableSpaceFileAmCallBack(Datum arg, int cacheid, uint32 hashvalue) +{ + HASH_SEQ_STATUS status; + TableSpaceFileAmEntry *fileAmEntry; + + hash_seq_init(&status, TableSpaceFileHandlerHash); + while ((fileAmEntry = (TableSpaceFileAmEntry *) hash_seq_search(&status)) != NULL) + { + hash_search(TableSpaceFileHandlerHash, + (void *) &fileAmEntry->spcId, + HASH_REMOVE, + NULL); + } +} + +static void +InitializeTableSpaceFileHandlerHash(void) +{ + HASHCTL ctl; + + /* Initialize the hash table. */ + ctl.keysize = sizeof(Oid); + ctl.entrysize = sizeof(TableSpaceFileAmEntry); + TableSpaceFileHandlerHash = + hash_create("TableSpace File Handler hash", 8, &ctl, + HASH_ELEM | HASH_BLOBS); + + /* Make sure we've initialized CacheMemoryContext. */ + if (!CacheMemoryContext) + CreateCacheMemoryContext(); + + /* Watch for invalidation events. */ + CacheRegisterSyscacheCallback(TABLESPACEOID, + InvalidateTableSpaceFileAmCallBack, + (Datum) 0); +} + +FileAm * +GetTablespaceFileHandler(Oid spcId) +{ + HeapTuple tuple; + Datum datum; + bool isNull; + char *filehandlersrc; + char *filehandlerbin; + Form_pg_tablespace tblspcForm; + void *libraryhandle; + File_handler file_handler; + TableSpaceFileAmEntry *fileAmEntry; + FileAm *fileAm = NULL; + bool found; + + if (!TableSpaceFileHandlerHash) + InitializeTableSpaceFileHandlerHash(); + + fileAmEntry = (TableSpaceFileAmEntry *) hash_search(TableSpaceFileHandlerHash, + (void *) &spcId, + HASH_FIND, + &found); + + if (found) + return fileAmEntry->fileAm; + + tuple = SearchSysCache1(TABLESPACEOID, ObjectIdGetDatum(spcId)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for table space %u", spcId); + + tblspcForm = (Form_pg_tablespace) GETSTRUCT(tuple); + datum = SysCacheGetAttr(TABLESPACEOID, + tuple, + Anum_pg_tablespace_spcfilehandlerbin, + &isNull); + if (!isNull) + { + filehandlerbin = TextDatumGetCString(datum); + + datum = SysCacheGetAttr(TABLESPACEOID, + tuple, + Anum_pg_tablespace_spcfilehandlersrc, + &isNull); + filehandlersrc = TextDatumGetCString(datum); + + file_handler = (File_handler) load_external_function(filehandlerbin, filehandlersrc, true, &libraryhandle); + + if (file_handler) + fileAm = (*file_handler) (); + + if (fileAm == NULL || fileAm == &localFileAm) + elog(ERROR, "tablespace file handler did not return a FileAm struct"); + } + else + { + fileAm = &localFileAm; + } + + ReleaseSysCache(tuple); + + Assert(fileAm != NULL); + Assert(fileAm->open != NULL); + Assert(fileAm->close != NULL); + Assert(fileAm->read != NULL); + Assert(fileAm->write != NULL); + Assert(fileAm->size != NULL); + Assert(fileAm->unlink != NULL); + Assert(fileAm->formatPathName != NULL); + Assert(fileAm->exists != NULL); + Assert(fileAm->name != NULL); + Assert(fileAm->getLastError != NULL); + + fileAmEntry = (TableSpaceFileAmEntry *) hash_search(TableSpaceFileHandlerHash, + (void *) &spcId, + HASH_ENTER, + &found); + if (found) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("extra tablespace oid \"%u\" already exists", spcId))); + + fileAmEntry->fileAm = fileAm; + + return fileAm; +} + +/* + * GetDirectoryTable - look up the directory table definition by relId. + */ +DirectoryTable * +GetDirectoryTable(Oid relId) +{ + Form_pg_directory_table dirtableForm; + HeapTuple tuple; + Datum datum; + bool isNull; + DirectoryTable *dirTable; + + tuple = SearchSysCache1(DIRECTORYTABLEREL, ObjectIdGetDatum(relId)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for directory table %u", relId); + + dirtableForm = (Form_pg_directory_table) GETSTRUCT(tuple); + + dirTable = (DirectoryTable *) palloc(sizeof(DirectoryTable)); + dirTable->relId = relId; + dirTable->spcId = dirtableForm->dttablespace; + GetTablespaceFileHandler(dirtableForm->dttablespace); + + datum = SysCacheGetAttr(DIRECTORYTABLEREL, + tuple, + Anum_pg_directory_table_dtlocation, + &isNull); + Assert(!isNull); + + dirTable->location = TextDatumGetCString(datum); + ReleaseSysCache(tuple); + + return dirTable; +} + +bool +RelationIsDirectoryTable(Oid relId) +{ + HeapTuple tuple; + + tuple = SearchSysCache1(DIRECTORYTABLEREL, ObjectIdGetDatum(relId)); + if (!HeapTupleIsValid(tuple)) + return false; + + ReleaseSysCache(tuple); + return true; +} + +List * +GetDirectoryTableSchema(void) +{ + List *result = NIL; + + ColumnDef *columnDef = makeNode(ColumnDef); + columnDef->colname = "relative_path"; + columnDef->typeName = SystemTypeName("text"); + columnDef->is_local = true; + result = lappend(result, columnDef); + + columnDef = makeNode(ColumnDef); + columnDef->colname = "size"; + columnDef->typeName = SystemTypeName("int8"); + columnDef->is_local = true; + result = lappend(result, columnDef); + + columnDef = makeNode(ColumnDef); + columnDef->colname = "last_modified"; + columnDef->typeName = SystemTypeName("timestamptz"); + columnDef->is_local =true; + result = lappend(result, columnDef); + + columnDef = makeNode(ColumnDef); + columnDef->colname = "md5"; + columnDef->typeName = SystemTypeName("text"); + columnDef->is_local = true; + result = lappend(result, columnDef); + + columnDef = makeNode(ColumnDef); + columnDef->colname = "tag"; + columnDef->typeName = SystemTypeName("text"); + columnDef->is_local = true; + result = lappend(result, columnDef); + + return result; +} + +DistributedBy * +GetDirectoryTableDistributedBy(void) +{ + Oid opclassoid = InvalidOid; + HeapTuple ht_opc; + Form_pg_opclass opcrec; + char *opcname; + char *nspname; + + DistributedBy *distributedBy = makeNode(DistributedBy); + distributedBy->ptype = POLICYTYPE_PARTITIONED; + distributedBy->numsegments = -1; + DistributionKeyElem *elem = makeNode(DistributionKeyElem); + elem->name = "relative_path"; + if (gp_use_legacy_hashops) + opclassoid = get_legacy_cdbhash_opclass_for_base_type(TEXTOID); + + if (!OidIsValid(opclassoid)) + opclassoid = cdb_default_distribution_opclass_for_type(TEXTOID); + + ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclassoid)); + if (!HeapTupleIsValid(ht_opc)) + elog(ERROR, "cache lookup failed for opclass %u", opclassoid); + opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc); + nspname = get_namespace_name(opcrec->opcnamespace); + opcname = pstrdup(NameStr(opcrec->opcname)); + elem->opclass = list_make2(makeString(nspname), makeString(opcname)); + + elem->location = -1; + distributedBy->keyCols = lappend(distributedBy->keyCols, elem); + distributedBy->numsegments = GP_POLICY_DEFAULT_NUMSEGMENTS(); + + ReleaseSysCache(ht_opc); + + return distributedBy; +} + +Oid +CreateDirectoryTableIndex(Relation rel) +{ + char dirtable_idxname[NAMEDATALEN]; + Oid dirtable_idxid; + Oid collationObjectId; + IndexInfo *indexInfo; + List *indexColNames; + Oid classObjectId[1]; + int16 coloptions[1]; + HeapTuple tuple; + Datum collationDatum; + bool isNull; + + snprintf(dirtable_idxname, sizeof(dirtable_idxname), + "%s_pkey", RelationGetRelationName(rel)); + + classObjectId[0] = TEXT_BTREE_OPS_OID; + + coloptions[0] = 0; + + indexInfo = makeNode(IndexInfo); + indexInfo->ii_NumIndexAttrs = 1; + indexInfo->ii_NumIndexKeyAttrs = 1; + indexInfo->ii_IndexAttrNumbers[0] = 1; + indexInfo->ii_Expressions = NIL; + indexInfo->ii_ExpressionsState = NIL; + indexInfo->ii_Predicate = NIL; + indexInfo->ii_PredicateState = NULL; + indexInfo->ii_Unique = true; + indexInfo->ii_Concurrent = false; + indexColNames = list_make1("relative_path"); + + tuple = SearchSysCache2(ATTNUM, + ObjectIdGetDatum(RelationGetRelid(rel)), + Int16GetDatum(1)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for directory_table %u", + RelationGetRelid(rel)); + collationDatum = SysCacheGetAttr(ATTNUM, tuple, Anum_pg_attribute_attcollation, + &isNull); + collationObjectId = DatumGetObjectId(collationDatum); + + dirtable_idxid = index_create(rel, + dirtable_idxname, + InvalidOid, + InvalidOid, + InvalidOid, + InvalidOid, + indexInfo, + indexColNames, + BTREE_AM_OID, + InvalidOid, + &collationObjectId, classObjectId, coloptions, (Datum) 0, + INDEX_CREATE_IS_PRIMARY, 0, true, true, NULL); + + ReleaseSysCache(tuple); + + /* Make this table visible, else index creation will fail */ + CommandCounterIncrement(); + + /* Unlock the index -- no one can see it anyway */ + UnlockRelationOid(dirtable_idxid, AccessExclusiveLock); + + return dirtable_idxid; +} + +void +RemoveDirectoryTableEntry(Oid relId) +{ + Relation rel; + HeapTuple tuple; + + rel = table_open(DirectoryTableRelationId, RowExclusiveLock); + + tuple = SearchSysCache1(DIRECTORYTABLEREL, ObjectIdGetDatum(relId)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for directory table %u", relId); + + CatalogTupleDelete(rel, &tuple->t_self); + + ReleaseSysCache(tuple); + table_close(rel, RowExclusiveLock); +} diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c index 730dc0ec3e2..9c101a9fdb0 100644 --- a/src/backend/catalog/pg_shdepend.c +++ b/src/backend/catalog/pg_shdepend.c @@ -21,6 +21,8 @@ #include "access/xact.h" #include "catalog/catalog.h" #include "catalog/dependency.h" +#include "catalog/gp_storage_server.h" +#include "catalog/gp_storage_user_mapping.h" #include "catalog/indexing.h" #include "catalog/pg_authid.h" #include "catalog/pg_collation.h" @@ -1221,6 +1223,26 @@ shdepLockAndCheckObject(Oid classId, Oid objectId) break; } + case StorageServerRelationId: + { + if (!SearchSysCacheExists1(STORAGESERVEROID, ObjectIdGetDatum(objectId))) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("storage server %u was concurrently dropped", + objectId))); + break; + } + + case StorageUserMappingRelationId: + { + if (!SearchSysCacheExists1(STORAGEUSERMAPPINGUSERSERVER, ObjectIdGetDatum(objectId))) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("storage user mapping %u was concurrently dropped", + objectId))); + break; + } + default: elog(ERROR, "unrecognized shared classId: %u", classId); @@ -1275,6 +1297,8 @@ storeObjectDescription(StringInfo descs, appendStringInfo(descs, _("tablespace for %s"), objdesc); else if (deptype == SHARED_DEPENDENCY_PROFILE) appendStringInfo(descs, _("profile of %s"), objdesc); + else if (deptype == SHARED_DEPENDENCY_STORAGE_SERVER) + appendStringInfo(descs, _("storage server of %s"), objdesc); else elog(ERROR, "unrecognized dependency type: %d", (int) deptype); @@ -1743,4 +1767,22 @@ changeProfileDependency(Oid roleId, Oid newprofileId) SHARED_DEPENDENCY_PROFILE); table_close(sdepRel, RowExclusiveLock); +} + +/* + * recordStorageServerDependency + * + * A convenient wrapper of recordSharedDependencyOn -- register the specified + * storage user mapping of attached to storage server. + */ +void +recordStorageServerDependency(Oid classId, Oid objectId, Oid srvId) +{ + ObjectAddress myself, + referenced; + + ObjectAddressSet(myself, classId, objectId); + ObjectAddressSet(referenced, StorageServerRelationId, srvId); + + recordSharedDependencyOn(&myself, &referenced, SHARED_DEPENDENCY_STORAGE_SERVER); } \ No newline at end of file diff --git a/src/backend/catalog/storage.c b/src/backend/catalog/storage.c index 1c4b56672be..6d80abce254 100644 --- a/src/backend/catalog/storage.c +++ b/src/backend/catalog/storage.c @@ -27,6 +27,7 @@ #include "access/xloginsert.h" #include "access/xlogutils.h" #include "catalog/storage.h" +#include "catalog/storage_directory_table.h" #include "catalog/storage_xlog.h" #include "common/relpath.h" #include "commands/dbcommands.h" @@ -637,6 +638,8 @@ smgrDoPendingDeletes(bool isCommit) maxrels = 0; SMgrRelation *srels = NULL; + UFileDoDeletesActions(isCommit); + prev = NULL; for (pending = pendingDeletes; pending != NULL; pending = next) { @@ -933,6 +936,8 @@ AtSubCommit_smgr(void) int nestLevel = GetCurrentTransactionNestLevel(); PendingRelDelete *pending; + UFileAtSubCommitSmgr(); + for (pending = pendingDeletes; pending != NULL; pending = pending->next) { if (pending->nestLevel >= nestLevel) @@ -950,6 +955,7 @@ AtSubCommit_smgr(void) void AtSubAbort_smgr(void) { + UFileAtSubAbortSmgr(); smgrDoPendingDeletes(false); } diff --git a/src/backend/catalog/storage_directory_table.c b/src/backend/catalog/storage_directory_table.c new file mode 100644 index 00000000000..8619e2b46e1 --- /dev/null +++ b/src/backend/catalog/storage_directory_table.c @@ -0,0 +1,240 @@ +/*------------------------------------------------------------------------- + * + * Storage manipulation for directory table. + * + * Copyright (c) 2016-Present Hashdata, Inc. + * + * src/backend/catalog/storage_directory_table.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/heapam.h" +#include "access/parallel.h" +#include "access/relscan.h" +#include "access/table.h" +#include "access/tableam.h" +#include "access/xact.h" +#include "catalog/pg_directory_table.h" +#include "catalog/pg_tablespace.h" +#include "catalog/storage_directory_table.h" +#include "storage/smgr.h" +#include "storage/ufile.h" +#include "utils/acl.h" +#include "utils/memutils.h" +#include "utils/rel.h" +#include "cdb/cdbvars.h" + +/* + * TODO: Redo pending delete + * + * We do not support deleteing files during WAL redo, this is because deleting + * files requires a connection to object storage system. In order to establish + * the connection to the object storage, we need to access the catalog table to + * retrieve the connection configuration info, which is impossible during WAL + * redo. + */ + +typedef struct UFileNodePendingDelete +{ + char relkind; + Oid spcId; /* directory table needs an extra tabpespace */ + char *relativePath; +} UFileNodePendingDelete; + +typedef struct PendingRelDeleteUFile +{ + UFileNodePendingDelete filenode; /* relation that may need to be deleted */ + bool atCommit; /* T=delete at commit; F=delete at abort */ + int nestLevel; /* xact nesting level of request */ + struct PendingRelDeleteUFile *next; /* linked-list link */ +} PendingRelDeleteUFile; + +static PendingRelDeleteUFile *pendingDeleteUFiles = NULL; /* head of linked list */ + +void +DirectoryTableDropStorage(Relation rel) +{ + char *filePath; + DirectoryTable *dirTable; + PendingRelDeleteUFile *pending; + TableScanDesc scandesc; + Relation spcrel; + HeapTuple tuple; + Form_pg_tablespace spcform; + ScanKeyData entry[1]; + Oid tablespaceoid; + char *tablespace_name; + + dirTable = GetDirectoryTable(RelationGetRelid(rel)); + + /* + * Find the tablespace by spaceId + */ + spcrel = table_open(TableSpaceRelationId, RowExclusiveLock); + + ScanKeyInit(&entry[0], + Anum_pg_tablespace_oid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(dirTable->spcId)); + scandesc = table_beginscan_catalog(spcrel, 1, entry); + tuple = heap_getnext(scandesc, ForwardScanDirection); + + if (!HeapTupleIsValid(tuple)) + { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("tablespace \"%d\" does not exist", + dirTable->spcId))); + } + + spcform = (Form_pg_tablespace) GETSTRUCT(tuple); + tablespaceoid = spcform->oid; + tablespace_name = pstrdup(NameStr(((Form_pg_tablespace) GETSTRUCT(tuple))->spcname)); + + /* Must be tablespace owner */ + if (!pg_tablespace_ownercheck(tablespaceoid, GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TABLESPACE, + tablespace_name); + + table_endscan(scandesc); + table_close(spcrel, RowExclusiveLock); + + filePath = psprintf("%s", dirTable->location); + + /* Add the relation to the list of stuff to delete at commit */ + pending = (PendingRelDeleteUFile *) + MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDeleteUFile)); + pending->filenode.relkind = rel->rd_rel->relkind; + pending->filenode.relativePath = MemoryContextStrdup(TopMemoryContext, filePath); + pending->filenode.spcId = dirTable->spcId; + + pending->atCommit = true; /* delete if commit */ + pending->nestLevel = GetCurrentTransactionNestLevel(); + pending->next = pendingDeleteUFiles; + + pendingDeleteUFiles = pending; + + pfree(filePath); + + /* + * Make sure the connection to the corresponding tablespace has + * been cached. + * + * UFileDoDeletesActions->UFileUnlink is called outside of the + * transaction, if we don't establish a connection here. we may + * face the issus of accessing the catalog outside of the + * transaction. + */ + forceCacheUFileResource(dirTable->spcId); +} + +void +UFileAddCreatePendingEntry(Relation rel, Oid spcId, char *relativePath) +{ + PendingRelDeleteUFile *pending; + + /* Add the relation to the list of stuff to delete at abort */ + pending = (PendingRelDeleteUFile *) + MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDeleteUFile)); + pending->filenode.relkind = rel->rd_rel->relkind; + pending->filenode.relativePath = MemoryContextStrdup(TopMemoryContext, relativePath); + pending->filenode.spcId = spcId; + + pending->atCommit = false; /* delete if abort */ + pending->nestLevel = GetCurrentTransactionNestLevel(); + pending->next = pendingDeleteUFiles; + + pendingDeleteUFiles = pending; + + /* + * Make sure the spccache to the corresponding tablespace has + * been cached. + */ + forceCacheUFileResource(spcId); +} + +void +UFileAddDeletePendingEntry(Relation rel, Oid spcId, char *relativePath) +{ + PendingRelDeleteUFile *pending; + + /* Add the relation to the list of stuff to delete at abort */ + pending = (PendingRelDeleteUFile *) + MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDeleteUFile)); + pending->filenode.relkind = rel->rd_rel->relkind; + pending->filenode.relativePath = MemoryContextStrdup(TopMemoryContext, relativePath); + pending->filenode.spcId = spcId; + + pending->atCommit = true; /* delete if commit */ + pending->nestLevel = GetCurrentTransactionNestLevel(); + pending->next = pendingDeleteUFiles; + + pendingDeleteUFiles = pending; + + /* + * Make sure the spccache to the corresponding tablespace has + * been cached. + */ + forceCacheUFileResource(spcId); +} + +void +UFileDoDeletesActions(bool isCommit) +{ + int nestLevel = GetCurrentTransactionNestLevel(); + PendingRelDeleteUFile *pending; + PendingRelDeleteUFile *prev; + PendingRelDeleteUFile *next; + + prev = NULL; + for (pending = pendingDeleteUFiles; pending != NULL; pending = next) + { + next = pending->next; + if (pending->nestLevel < nestLevel) + { + /* outer-level entries should not be processed yet */ + prev = pending; + } + else + { + /* unlink list entry first, so we don't retry on failure */ + if (prev) + prev->next = next; + else + pendingDeleteUFiles = next; + + /* do deletion if called for */ + if (pending->atCommit == isCommit) + UFileUnlink(pending->filenode.spcId, pending->filenode.relativePath); + + /* must explicitly free the list entry */ + if (pending->filenode.relativePath) + pfree(pending->filenode.relativePath); + + pfree(pending); + /* prev does not change */ + } + } +} + +void +UFileAtSubCommitSmgr(void) +{ + int nestLevel = GetCurrentTransactionNestLevel(); + PendingRelDeleteUFile *pending; + + for (pending = pendingDeleteUFiles; pending != NULL; pending = pending->next) + { + if (pending->nestLevel >= nestLevel) + pending->nestLevel = nestLevel - 1; + } +} + +void +UFileAtSubAbortSmgr(void) +{ + UFileDoDeletesActions(false); +} diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index a077f595df0..c7c46d820f3 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -1702,6 +1702,8 @@ CREATE VIEW pg_user_mappings AS REVOKE ALL ON pg_user_mapping FROM public; +REVOKE ALL ON gp_storage_user_mapping FROM public; + CREATE VIEW pg_replication_origin_status AS SELECT * FROM pg_show_replication_origin_status(); diff --git a/src/backend/commands/Makefile b/src/backend/commands/Makefile index 94e0485ac13..2fe51b415ba 100644 --- a/src/backend/commands/Makefile +++ b/src/backend/commands/Makefile @@ -33,6 +33,7 @@ OBJS = \ createas.o \ dbcommands.o \ define.o \ + dirtablecmds.o \ discard.o \ dropcmds.o \ event_trigger.o \ @@ -64,7 +65,8 @@ OBJS = \ vacuum.o \ variable.o \ view.o \ - pg_profile.o + pg_profile.o \ + storagecmds.o OBJS += analyzefuncs.o analyzeutils.o extprotocolcmds.o exttablecmds.o queue.o OBJS += resgroupcmds.o tablecmds_gp.o vacuum_ao.o taskcmds.o diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c index 38ca72b479c..df43eb8e69b 100644 --- a/src/backend/commands/alter.c +++ b/src/backend/commands/alter.c @@ -555,6 +555,7 @@ ExecAlterObjectSchemaStmt_internal(AlterObjectSchemaStmt *stmt, case OBJECT_TABLE: case OBJECT_VIEW: case OBJECT_MATVIEW: + case OBJECT_DIRECTORY_TABLE: address = AlterTableNamespace(stmt, oldSchemaAddr ? &oldNspOid : NULL); break; @@ -733,6 +734,8 @@ AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid, case OCLASS_TASK: case OCLASS_PROFILE: case OCLASS_PASSWORDHISTORY: + case OCLASS_STORAGE_SERVER: + case OCLASS_STORAGE_USER_MAPPING: /* ignore object types that don't have schema-qualified names */ break; diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index c2c93e6c3c4..6e6d6b03327 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -344,7 +344,8 @@ analyze_rel_internal(Oid relid, RangeVar *relation, * Check that it's of an analyzable relkind, and set up appropriately. */ if (onerel->rd_rel->relkind == RELKIND_RELATION || - onerel->rd_rel->relkind == RELKIND_MATVIEW) + onerel->rd_rel->relkind == RELKIND_MATVIEW || + onerel->rd_rel->relkind == RELKIND_DIRECTORY_TABLE) { /* Regular table, so we'll use the regular row acquisition function */ if (onerel->rd_tableam) @@ -1984,7 +1985,8 @@ acquire_inherited_sample_rows(Relation onerel, int elevel, /* Check table type (MATVIEW can't happen, but might as well allow) */ if (childrel->rd_rel->relkind == RELKIND_RELATION || - childrel->rd_rel->relkind == RELKIND_MATVIEW) + childrel->rd_rel->relkind == RELKIND_MATVIEW || + childrel->rd_rel->relkind == RELKIND_DIRECTORY_TABLE) { /* Regular table, so use the regular row acquisition function */ if (childrel->rd_tableam) diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index b8e5f14ccbc..906405718e2 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -98,10 +98,11 @@ CommentObject(CommentStmt *stmt) relation->rd_rel->relkind != RELKIND_MATVIEW && relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE && relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE && + relation->rd_rel->relkind != RELKIND_DIRECTORY_TABLE && relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("\"%s\" is not a table, view, materialized view, composite type, or foreign table", + errmsg("\"%s\" is not a table, directory table, view, materialized view, composite type, or foreign table", RelationGetRelationName(relation)))); break; default: diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 7e1bf331326..daaca78cd7e 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -792,6 +792,15 @@ ProcessCopyOptions(ParseState *pstate, errmsg("conflicting or redundant options"))); opts_out->skip_foreign_partitions = true; } + else if (strcmp(defel->defname, "tag") == 0) + { + if (opts_out->tags) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"), + parser_errposition(pstate, defel->location))); + opts_out->tags = defGetString(defel); + } else if (!rel_is_external_table(rel_oid)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), @@ -965,6 +974,11 @@ ProcessCopyOptions(ParseState *pstate, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("CSV quote character must not appear in the NULL specification"))); + if (opts_out->tags != NULL && !is_from) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("COPY with tag only available using COPY FROM"))); + /* * DELIMITER * @@ -1033,6 +1047,84 @@ ProcessCopyOptions(ParseState *pstate, } } +void +ProcessCopyDirectoryTableOptions(ParseState *pstate, + CopyFormatOptions *opts_out, + bool is_from, + List *options, + Oid rel_oid) +{ + bool format_specified = false; + ListCell *option; + + /* Support external use for option sanity checking */ + if (opts_out == NULL) + opts_out = (CopyFormatOptions *) palloc0(sizeof(CopyFormatOptions)); + + opts_out->file_encoding = -1; + + /* Extract options from the statement node tree */ + foreach(option, options) + { + DefElem *defel = lfirst_node(DefElem, option); + + if (strcmp(defel->defname, "format") == 0) + { + char *fmt = defGetString(defel); + + if (format_specified) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"), + parser_errposition(pstate, defel->location))); + format_specified = true; + if (strcmp(fmt, "binary") == 0) + opts_out->binary = true; + else + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("format option is not allowed in copy binary from directory table."), + parser_errposition(pstate, defel->location))); + } + else if (strcmp(defel->defname, "tag") == 0) + { + if (opts_out->tags) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"), + parser_errposition(pstate, defel->location))); + opts_out->tags = defGetString(defel); + } + else + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("option \"%s\" not recognized", + defel->defname), + parser_errposition(pstate, defel->location))); + } + + opts_out->eol_type = EOL_UNKNOWN; + + /* Set defaults for omitted options */ + if (!opts_out->delim) + opts_out->delim = opts_out->csv_mode ? "," : "\t"; + + if (!opts_out->null_print) + opts_out->null_print = opts_out->csv_mode ? "" : "\\N"; + opts_out->null_print_len = strlen(opts_out->null_print); + + if (opts_out->csv_mode) + { + if (!opts_out->quote) + opts_out->quote = "\""; + if (!opts_out->escape) + opts_out->escape = opts_out->quote; + } + + if (!opts_out->csv_mode && !opts_out->escape) + opts_out->escape = "\\"; /* default escape for text mode */ +} + /* * Dispatch a COPY ON SEGMENT statement to QEs. */ diff --git a/src/backend/commands/copyfrom.c b/src/backend/commands/copyfrom.c index acb01d91ec6..29de4e79fdd 100644 --- a/src/backend/commands/copyfrom.c +++ b/src/backend/commands/copyfrom.c @@ -31,13 +31,20 @@ #include "access/xact.h" #include "access/xlog.h" #include "catalog/namespace.h" +#include "catalog/pg_directory_table.h" +#include "catalog/storage_directory_table.h" #include "cdb/cdbaocsam.h" #include "cdb/cdbappendonlyam.h" +#include "cdb/cdbdisp.h" #include "cdb/cdbvars.h" #include "commands/copy.h" #include "commands/copyfrom_internal.h" #include "commands/progress.h" +#include "commands/tablespace.h" #include "commands/trigger.h" +#include "common/base64.h" +#include "common/cryptohash.h" +#include "common/md5.h" #include "executor/execPartition.h" #include "executor/executor.h" #include "executor/nodeModifyTable.h" @@ -50,7 +57,9 @@ #include "pgstat.h" #include "rewrite/rewriteHandler.h" #include "storage/fd.h" +#include "storage/ufile.h" #include "tcop/tcopprot.h" +#include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/portal.h" @@ -205,6 +214,10 @@ static void FreeDistributionData(GpDistributionData *distData); static void InitCopyFromDispatchSplit(CopyFromState cstate, GpDistributionData *distData, EState *estate); static unsigned int GetTargetSeg(GpDistributionData *distData, TupleTableSlot *slot); +static uint64 CopyFromDirectoryTable(CopyFromState cstate); +static CopyFromState BeginCopyFromDirectoryTable(ParseState *pstate, const char *fileName, + Relation rel, List *options); + /* * No more than this many tuples per CopyMultiInsertBuffer * @@ -225,6 +238,9 @@ static unsigned int GetTargetSeg(GpDistributionData *distData, TupleTableSlot *s /* Trim the list of buffers back down to this number after flushing */ #define MAX_PARTITION_BUFFERS 32 +/* The buffer size of directory table files */ +#define DIR_FILE_BUFF_SIZE 8192 + /* Stores multi-insert data related to a single relation in CopyFrom. */ typedef struct CopyMultiInsertBuffer { @@ -666,6 +682,779 @@ CopyMultiInsertInfoStore(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri, miinfo->bufferedBytes += tuplen; } +static CopyStmt * +convertToCopyTextStmt(CopyStmt *stmt) +{ + CopyStmt *copiedStmt = copyObject(stmt); + + copiedStmt->options = NIL; + + return copiedStmt; +} + +static char * +trimFilePath(char *filePath, char c) +{ + char *end; + + while (*filePath == c) + filePath++; + + end = filePath + strlen(filePath) - 1; + while (end > filePath && *end == c) + end--; + + *(end + 1) = '\0'; + + return filePath; +} + +static void +formDirTableSlot(CopyFromState cstate, + Oid spcId, + char *relativePath, + int64 fileSize, + char *md5sum, + char *tags, + StringInfo buf, + Datum *values, + bool *nulls) +{ + TupleDesc tupDesc; + AttrNumber num_phys_attrs; + ListCell *cur; + char *field[6]; + FmgrInfo *in_functions = cstate->in_functions; + Oid *typioparams = cstate->typioparams; + List *attnumlist = cstate->qd_attnumlist; + pg_time_t stampTime = (pg_time_t) time(NULL); + char lastModified[128]; + char *encode_file; + int encode_file_len; + + encode_file_len = pg_b64_enc_len(buf->len); + encode_file = (char *) palloc0(encode_file_len + 1); + + encode_file_len = pg_b64_encode(buf->data, buf->len, encode_file, encode_file_len); + if (encode_file_len < 0) + { + elog(ERROR, "base 64 encode failed in copy from directory table"); + } + encode_file[encode_file_len] = '\0'; + if (buf->data) + { + pfree(buf->data); + } + + pg_strftime(lastModified, sizeof(lastModified), + "%Y-%m-%d %H:%M:%S", + pg_localtime(&stampTime, log_timezone)); + + tupDesc = RelationGetDescr(cstate->rel); + num_phys_attrs = tupDesc->natts; + + MemSet(values, 0, num_phys_attrs * sizeof(Datum)); + MemSet(nulls, false, num_phys_attrs * sizeof(bool)); + + field[0] = relativePath; /* relative_path */ + field[1] = psprintf(INT64_FORMAT, fileSize); /* size */ + field[2] = lastModified; /* last_modified */ + field[3] = md5sum; /* md5sum */ + field[4] = tags; /* tags */ + if (tags == NULL) + nulls[4] = true; + field[5] = encode_file; + + /* Loop to read the user attributes on the line. */ + foreach(cur, attnumlist) + { + int attnum = lfirst_int(cur); + int m = attnum - 1; + char *value; + Form_pg_attribute att = TupleDescAttr(tupDesc, m); + + value = field[m]; + + values[m] = InputFunctionCall(&in_functions[m], + value, + typioparams[m], + att->atttypmod); + } +} + +/* + * Copy From file to directory table. + */ +static uint64 +CopyFromDirectoryTable(CopyFromState cstate) +{ + ResultRelInfo *resultRelInfo; + ResultRelInfo *target_resultRelInfo; + EState *estate = CreateExecutorState(); + TupleTableSlot *myslot = NULL; + StringInfoData buf; + ExprContext *econtext; + int bytesRead; + char hexMd5Sum[256]; + char buffer[DIR_FILE_BUFF_SIZE]; + int64 processed = 0; + int64 fileSize = 0; + CdbCopy *cdbCopy = NULL; + char *dirTablePath; + char *orgiFileName; + char *relaFileDirPointer; + char relaFileDir[MAXPGPATH] = {0}; + char *orgiFileDir = NULL; + char *relaFileName; + TupleDesc tupdesc; + unsigned int targetSeg; + DirectoryTable *dirTable; + pg_cryptohash_ctx *hashCtx; + uint8 md5Sum[MD5_DIGEST_LENGTH]; + GpDistributionData *distData = NULL; /* distribution data used to compute target seg */ + + /* + * We need a ResultRelInfo so we can use the regular executor's + * index-entry-making machinery. (There used to be a huge amount of code + * here that basically duplicated execUtils.c ...) + */ + ExecInitRangeTable(estate, cstate->range_table); + resultRelInfo = target_resultRelInfo = makeNode(ResultRelInfo); + ExecInitResultRelation(estate, resultRelInfo, 1); + + ExecOpenIndices(resultRelInfo, false); + + /* Prepare to catch AFTER triggers. */ + AfterTriggerBeginQuery(); + + /* + * If there are any triggers with transition tables on the named relation, + * we need to be prepared to capture transition tuples. + */ + cstate->transition_capture = MakeTransitionCaptureState(cstate->rel->trigdesc, + RelationGetRelid(cstate->rel), + CMD_INSERT); + + /* + * Check BEFORE STATEMENT insertion triggers. It's debatable whether we + * should do this for COPY, since it's not really an "INSERT" statement as + * such. However, executing these triggers maintains consistency with the + * EACH ROW triggers that we already fire on COPY. + */ + ExecBSInsertTriggers(estate, resultRelInfo); + + /* Assemble directory table file location. */ + relaFileName = trimFilePath(glob_copystmt->dirfilename, '/'); + relaFileDirPointer = strrchr(relaFileName, '/'); + if (relaFileDirPointer) + { + memcpy(relaFileDir, relaFileName, relaFileDirPointer - relaFileName); + } + + dirTable = GetDirectoryTable(RelationGetRelid(cstate->rel)); + dirTablePath = dirTable->location; + orgiFileName = psprintf("%s/%s", dirTablePath, relaFileName); + if (relaFileDir[0] != '\0') + orgiFileDir = psprintf("%s/%s", dirTablePath, relaFileDir); + + /* + * build tupledesc and slot for copy from + */ + tupdesc = CreateTemplateTupleDesc(6); + TupleDescInitEntry(tupdesc, (AttrNumber) 1, "relative_path", + TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 2, "size", + INT8OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 3, "last_modified", + TIMESTAMPTZOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 4, "md5", + TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 5, "tag", + TEXTOID, -1 ,0); + TupleDescInitEntry(tupdesc, (AttrNumber) 6, "file", + TEXTOID, -1, 0); + + myslot = MakeSingleTupleTableSlot(tupdesc, &TTSOpsVirtual); + + if (cstate->dispatch_mode == COPY_DISPATCH) + { + /* + * Initialize information about distribution keys, needed to compute target + * segment for each row. + */ + distData = InitDistributionData(cstate, estate); + + /* Determine which fields we need to parse in the QD. */ + InitCopyFromDispatchSplit(cstate, distData, estate); + } + + if (cstate->dispatch_mode == COPY_DISPATCH || + cstate->dispatch_mode == COPY_EXECUTOR) + { + /* + * Now split the attnumlist into the parts that are parsed in the QD, and + * in QE. + */ + ListCell *lc; + int i = 0; + List *qd_attnumlist = NIL; + List *qe_attnumlist = NIL; + int first_qe_processed_field; + + first_qe_processed_field = cstate->first_qe_processed_field; + + foreach(lc, cstate->attnumlist) + { + int attnum = lfirst_int(lc); + + if (i < first_qe_processed_field) + qd_attnumlist = lappend_int(qd_attnumlist, attnum); + else + qe_attnumlist = lappend_int(qe_attnumlist, attnum); + i++; + } + cstate->qd_attnumlist = qd_attnumlist; + cstate->qe_attnumlist = qe_attnumlist; + } + + if (cstate->dispatch_mode == COPY_DISPATCH) + { + /* + * We are the QD node, and we are receiving rows from client, or + * reading them from a file. We are not writing any data locally, + * instead, we determine the correct target segment for row, + * and forward each to the correct segment. + */ + + /* + * pre-allocate buffer for constructing a message. + */ + cstate->dispatch_msgbuf = makeStringInfo(); + enlargeStringInfo(cstate->dispatch_msgbuf, SizeOfCopyFromDispatchRow); + + /* + * prepare to COPY data into segDBs: + */ + cdbCopy = makeCdbCopyFrom(cstate); + + /* + * Dispatch the COPY command. + */ + elog(DEBUG5, "COPY command sent to segdbs"); + + cdbCopyStart(cdbCopy, convertToCopyTextStmt(glob_copystmt), cstate->file_encoding); + + /* + * Header processing. + */ + SendCopyFromForwardedHeader(cstate, cdbCopy); + + /* FIXME: + * + * Even if we use FileExist function, writing to the same file in two + * concurrent sessions can still cause the file content to be corrupted. + * + * 1. Some DFS don't support renaming files, which means we can't use + * the common technique of generating a random filename for upload and + * then renaming it to the final name once it's complete. + * + * 2. Seems like unique index could be a good solution to fix the issue, + * But unique indexes can cause concurrent sessions to wait for each + * other(see comments in _bt_doinsert), and uploads can take a long time, + * so transactions waiting for each other for a long time without releasing + * resources is also not ideal(I know that we can set lock timeout). + * + * Another reason for not using unique index is that the file is uploading + * in the copy context, based on the current copy protocol, we are not able + * to insert a record first, then, once the file is uploaded, we could update + * the record. + * + * 3. We should probably create a file status table in catalog service + * to keep track of files currrently being uploaded. + */ + initStringInfo(&buf); + + hashCtx = pg_cryptohash_create(PG_MD5); + if (hashCtx == NULL) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("failed to create md5hash context: out of memory"))); + pg_cryptohash_init(hashCtx); + + for (;;) + { + CHECK_FOR_INTERRUPTS(); + + bytesRead = CopyReadBinaryData(cstate, buffer, DIR_FILE_BUFF_SIZE); + + if (bytesRead > 0) + { + appendBinaryStringInfo(&buf, buffer, bytesRead); + + fileSize += bytesRead; + pg_cryptohash_update(hashCtx, (const uint8 *) buffer, bytesRead); + } + + if (bytesRead != DIR_FILE_BUFF_SIZE) + { + Assert(cstate->raw_reached_eof == true); + break; + } + } + + pg_cryptohash_final(hashCtx, md5Sum, sizeof(md5Sum)); + pg_cryptohash_free(hashCtx); + bytesToHex(md5Sum, hexMd5Sum); + + formDirTableSlot(cstate, + dirTable->spcId, + relaFileName, + fileSize, + hexMd5Sum, + cstate->opts.tags, + &buf, + myslot->tts_values, + myslot->tts_isnull); + ExecStoreVirtualTuple(myslot); + + targetSeg = GetTargetSeg(distData, myslot); + /* in the QD, forward the row to the correct segment(s). */ + SendCopyFromForwardedTuple(cstate, cdbCopy, false, + targetSeg, + resultRelInfo->ri_RelationDesc, + cstate->cur_lineno, + cstate->line_buf.data, + cstate->line_buf.len, + myslot->tts_values, + myslot->tts_isnull); + { + int64 total_completed_from_qes; + int64 total_rejected_from_qes; + + cdbCopyEnd(cdbCopy, + &total_completed_from_qes, + &total_rejected_from_qes); + + processed = total_completed_from_qes; + } + } + else if (cstate->dispatch_mode == COPY_EXECUTOR) + { +#define DIRECTORY_TABLE_COLUMNS 5 + List *recheckIndexes = NIL; + TupleTableSlot *tmpslot = NULL; + CommandId mycid = GetCurrentCommandId(true); + MemoryContext oldcontext = CurrentMemoryContext; + char errorMessage[256]; + UFile *file; + char *file_buf; + int i; + char *decode_file; + int decode_file_len; + + econtext = GetPerTupleExprContext(estate); + + if (NextCopyFromExecute(cstate, econtext, myslot->tts_values, myslot->tts_isnull)) + { + if (tupdesc) + pfree(tupdesc); + + tupdesc = CreateTemplateTupleDesc(DIRECTORY_TABLE_COLUMNS); + TupleDescInitEntry(tupdesc, (AttrNumber) 1, "relative_path", + TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 2, "size", + INT8OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 3, "last_modified", + TIMESTAMPTZOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 4, "md5", + TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 5, "tag", + TEXTOID, -1 ,0); + + tmpslot = MakeSingleTupleTableSlot(tupdesc, &TTSOpsVirtual); + + for (i = 0; i < DIRECTORY_TABLE_COLUMNS; i++) + { + tmpslot->tts_values[i] = myslot->tts_values[i]; + tmpslot->tts_isnull[i] = myslot->tts_isnull[i]; + } + + cstate->rel->rd_att = CreateTupleDescCopy(tupdesc); + cstate->rel->rd_att->tdrefcount = 1; /* mark as refcounted */ + + /* + * Reset the per-tuple exprcontext. We do this after every tuple, to + * clean-up after expression evaluations etc. + */ + ResetPerTupleExprContext(estate); + + /* + * Switch to per-tuple context before calling NextCopyFrom, which does + * evaluate default expressions etc. and requires per-tuple context. + */ + MemoryContextSwitchTo(GetPerTupleMemoryContext(estate)); + + /* + * NextCopyFromExecute set up estate->es_result_relation_info, + * and stored the tuple in the correct slot. + */ + resultRelInfo = estate->es_result_relations[0]; + + ExecStoreVirtualTuple(tmpslot); + + /* + * Constraints and where clause might reference the tableoid column, + * so (re-)initialize tts_tableOid before evaluating them. + */ + tmpslot->tts_tableOid = RelationGetRelid(target_resultRelInfo->ri_RelationDesc); + + /* Triggers and stuff need to be invoked in query context. */ + MemoryContextSwitchTo(oldcontext); + + /* OK, store the tuple and create index entries for it */ + table_tuple_insert(resultRelInfo->ri_RelationDesc, + tmpslot, mycid, 0, NULL); + + recheckIndexes = ExecInsertIndexTuples(resultRelInfo, + tmpslot, + estate, + false, + false, + NULL, + NIL); + + /* AFTER ROW INSERT Triggers */ + ExecARInsertTriggers(estate, resultRelInfo, tmpslot, + recheckIndexes, cstate->transition_capture); + + list_free(recheckIndexes); + + if (tupdesc) + pfree(tupdesc); + + if (UFileExists(dirTable->spcId, orgiFileName)) + { + UFileUnlink(dirTable->spcId, orgiFileName); + } + + if (orgiFileDir) + UFileEnsurePath(dirTable->spcId, orgiFileDir); + + file = UFileOpen(dirTable->spcId, + orgiFileName, + O_CREAT | O_WRONLY, + errorMessage, + sizeof(errorMessage)); + if (file == NULL) + ereport(ERROR, + (errcode(ERRCODE_IO_ERROR), + errmsg("failed to open file \"%s\": %s", orgiFileName, errorMessage))); + + /* Delete uploaded file when the transaction fails */ + UFileAddCreatePendingEntry(cstate->rel, dirTable->spcId, orgiFileName); + + file_buf = TextDatumGetCString(myslot->tts_values[5]); + decode_file_len = strlen(file_buf); + decode_file = (char *) palloc0(decode_file_len); + decode_file_len = pg_b64_decode(file_buf, strlen(file_buf), decode_file, decode_file_len); + + if (decode_file_len < 0) + { + elog(ERROR, "can not decode in copy from directory table, b64_msg is empty"); + } + + if (UFileWrite(file, decode_file, decode_file_len) == -1) + ereport(ERROR, + (errcode(ERRCODE_IO_ERROR), + errmsg("failed to write file \"%s\": %s", orgiFileName, UFileGetLastError(file)))); + + if (UFileSync(file) != 0) + ereport(ERROR, + (errcode(ERRCODE_IO_ERROR), + errmsg("unable to sync file \"%s\": %s", glob_copystmt->dirfilename, UFileGetLastError(file)))); + + UFileClose(file); + + ExecClearTuple(myslot); + ExecClearTuple(tmpslot); + + /* + * We count only tuples not suppressed by a BEFORE INSERT trigger + * or FDW; this is the same definition used by nodeModifyTable.c + * for counting tuples inserted by an INSERT command. Update + * progress of the COPY command as well. + * + * MPP: incrementing this counter here only matters for utility + * mode. in dispatch mode only the dispatcher COPY collects row + * count, so this counter is meaningless. + */ + pgstat_progress_update_param(PROGRESS_COPY_TUPLES_PROCESSED, + ++processed); + } + } + else + { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("This copy from dispatch mode is not supported."))); + } + + cstate->filename = NULL; + + /* Execute AFTER STATEMENT insertion triggers */ + ExecASInsertTriggers(estate, resultRelInfo, cstate->transition_capture); + + /* Handle queued AFTER triggers */ + AfterTriggerEndQuery(estate); + + /* + * In QE, send the number of rejected rows to the client (QD COPY) if + * SREH is on, always send the number of completed rows. + */ + if (Gp_role == GP_ROLE_EXECUTE) + { + SendNumRows((cstate->errMode != ALL_OR_NOTHING) ? cstate->cdbsreh->rejectcount : 0, processed); + } + + ExecResetTupleTable(estate->es_tupleTable, false); + + /* Close the result relations, including any trigger target relations */ + ExecCloseResultRelations(estate); + ExecCloseRangeTableRelations(estate); + + FreeDistributionData(distData); + FreeExecutorState(estate); + + return processed; +} + +/* + * Setup to read tuple from a file for COPY FROM. + * + * 'rel': Used as a template for the tuples + * 'options': List of DefElem. See copy_opt_item in gram.y for selections. + * + * Returns a CopyFromState, to be passed to NextCopyFrom and related functions. + */ +static CopyFromState +BeginCopyFromDirectoryTable(ParseState *pstate, + const char *filename, + Relation rel, + List *options) +{ + CopyFromState cstate; + bool pipe; + MemoryContext oldcontext; + TupleDesc tupDesc; + AttrNumber num_phys_attrs; + FmgrInfo *in_functions; + Oid *typioparams; + int attnum; + Oid in_func_oid; + const int progress_cols[] = { + PROGRESS_COPY_COMMAND, + PROGRESS_COPY_TYPE, + PROGRESS_COPY_BYTES_TOTAL + }; + int64 progress_vals[] = { + PROGRESS_COPY_COMMAND_FROM, + 0, + 0 + }; + + if (!glob_copystmt->dirfilename) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("Copy from directory table file name can't be null."))); + + /* Allocate workspace and zero all fields */ + cstate = (CopyFromStateData *) palloc0(sizeof(CopyFromStateData)); + + /* + * We allocate everything used by a cstate in a new memory context. This + * avoids memory leaks during repeated use of COPY in a query. + */ + cstate->copycontext = AllocSetContextCreate(CurrentMemoryContext, + "COPY", + ALLOCSET_DEFAULT_SIZES); + + oldcontext = MemoryContextSwitchTo(cstate->copycontext); + + /* Process the target relation */ + cstate->rel = rel; + + /* Check whether copy directory table options allowed */ + ProcessCopyDirectoryTableOptions(pstate, &cstate->opts, true, options, rel->rd_id); + + if (Gp_role == GP_ROLE_DISPATCH && !cstate->opts.binary) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Only support copy binary from directory table."))); + + cstate->copy_src = COPY_FILE; /* default */ + + /* + * Determine the mode + */ + if (Gp_role == GP_ROLE_DISPATCH && + cstate->rel && cstate->rel->rd_cdbpolicy && + cstate->rel->rd_cdbpolicy->ptype != POLICYTYPE_ENTRY) + cstate->dispatch_mode = COPY_DISPATCH; + else if (Gp_role == GP_ROLE_EXECUTE) + cstate->dispatch_mode = COPY_EXECUTOR; + + cstate->cur_relname = RelationGetRelationName(cstate->rel); + cstate->cur_lineno = 0; + cstate->cur_attname = NULL; + cstate->cur_attval = NULL; + if (filename) + cstate->filename = pstrdup(filename); + cstate->file_encoding = GetDatabaseEncoding(); + + /* + * Allocate buffers for the input pipeline. + */ + cstate->raw_buf = palloc(RAW_BUF_SIZE + 1); + cstate->raw_buf_index = cstate->raw_buf_len = 0; + MemSet(cstate->raw_buf, ' ', RAW_BUF_SIZE * sizeof(char)); + cstate->raw_buf[RAW_BUF_SIZE] = '\0'; + cstate->raw_reached_eof = false; + + initStringInfo(&cstate->line_buf); + + /* Assign range table, we'll need it in CopyFrom. */ + if (pstate) + cstate->range_table = pstate->p_rtable; + + /* + * build tupledesc and slot for copy from + */ + tupDesc = CreateTemplateTupleDesc(6); + TupleDescInitEntry(tupDesc, (AttrNumber) 1, "relative_path", + TEXTOID, -1, 0); + TupleDescInitEntry(tupDesc, (AttrNumber) 2, "size", + INT8OID, -1, 0); + TupleDescInitEntry(tupDesc, (AttrNumber) 3, "last_modified", + TIMESTAMPTZOID, -1, 0); + TupleDescInitEntry(tupDesc, (AttrNumber) 4, "md5", + TEXTOID, -1, 0); + TupleDescInitEntry(tupDesc, (AttrNumber) 5, "tag", + TEXTOID, -1 ,0); + TupleDescInitEntry(tupDesc, (AttrNumber) 6, "file", + TEXTOID, -1, 0); + + num_phys_attrs = tupDesc->natts; + + cstate->rel->rd_att = CreateTupleDescCopy(tupDesc); + cstate->rel->rd_att->tdrefcount = 1; /* mark as refcounted */ + cstate->attnumlist = CopyGetAttnums(tupDesc, cstate->rel, NIL); + + /* + * Pick up the required catalog information for each attribute in the + * relation, including the input function, the element type (to pass to + * the input function), and info about defaults and constraints. (Which + * input function we use depends on text/binary format choice.) + */ + in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo)); + typioparams = (Oid *) palloc(num_phys_attrs * sizeof(Oid)); + + for (attnum = 1; attnum <= num_phys_attrs; attnum++) + { + Form_pg_attribute att = TupleDescAttr(tupDesc, attnum - 1); + + /* Fetch the input function and typioparam info */ + getTypeInputInfo(att->atttypid, + &in_func_oid, &typioparams[attnum - 1]); + fmgr_info(in_func_oid, &in_functions[attnum - 1]); + } + + /* initialize progress */ + pgstat_progress_start_command(PROGRESS_COMMAND_COPY, + cstate->rel ? RelationGetRelid(cstate->rel) : InvalidOid); + cstate->bytes_processed = 0; + + /* We keep those variables in cstate. */ + cstate->in_functions = in_functions; + cstate->typioparams = typioparams; + cstate->is_program = false; + + pipe = (filename == NULL || cstate->dispatch_mode == COPY_EXECUTOR); + + if (pipe) + { + progress_vals[1] = PROGRESS_COPY_TYPE_PIPE; + if (whereToSendOutput == DestRemote) + ReceiveCopyBegin(cstate); + else + cstate->copy_file = stdin; + } + else + { + struct stat st; + + cstate->filename = pstrdup(filename); + + progress_vals[1] = PROGRESS_COPY_TYPE_FILE; + cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_R); + if (cstate->copy_file == NULL) + { + /* copy errno because ereport subfunctions might change it */ + int save_errno = errno; + + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not open file \"%s\" for reading: %m", + cstate->filename), + (save_errno == ENOENT || save_errno == EACCES) ? + errhint("COPY FROM instructs the PostgreSQL server process to read a file. " + "You may want a client-side facility such as psql's \\copy.") : 0)); + } + + // Increase buffer size to improve performance (cmcdevitt) + /* GPDB_14_MERGE_FIXME: Ret value process. */ + setvbuf(cstate->copy_file, NULL, _IOFBF, 393216); // 384 Kbytes + + if (fstat(fileno(cstate->copy_file), &st)) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not stat file \"%s\": %m", + cstate->filename))); + + if (S_ISDIR(st.st_mode)) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is a directory", cstate->filename))); + + progress_vals[2] = st.st_size; + } + + pgstat_progress_update_multi_param(3, progress_cols, progress_vals); + + if (cstate->dispatch_mode == COPY_EXECUTOR && cstate->copy_src != COPY_CALLBACK) + { + /* Read special header from QD */ + char readSig[sizeof(QDtoQESignature)]; + copy_from_dispatch_header header_frame; + + if (CopyGetData(cstate, &readSig, sizeof(QDtoQESignature), sizeof(QDtoQESignature)) != sizeof(QDtoQESignature) || + memcmp(readSig, QDtoQESignature, sizeof(QDtoQESignature)) != 0) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("QD->QE COPY communication signature not recognized"))); + + if (CopyGetData(cstate, &header_frame, sizeof(header_frame), sizeof(header_frame)) != sizeof(header_frame)) + ereport(ERROR, + (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), + errmsg("invalid QD->QD COPY communication header"))); + + cstate->first_qe_processed_field = header_frame.first_qe_processed_field; + } + + MemoryContextSwitchTo(oldcontext); + + return cstate; +} + /* * Copy FROM file to relation. */ @@ -707,6 +1496,7 @@ CopyFrom(CopyFromState cstate) * allowed on views, so we only hint about them in the view case.) */ if (cstate->rel->rd_rel->relkind != RELKIND_RELATION && + cstate->rel->rd_rel->relkind != RELKIND_DIRECTORY_TABLE && cstate->rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE && cstate->rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE && !(cstate->rel->trigdesc && @@ -735,6 +1525,9 @@ CopyFrom(CopyFromState cstate) RelationGetRelationName(cstate->rel)))); } + if (cstate->rel->rd_rel->relkind == RELKIND_DIRECTORY_TABLE) + return CopyFromDirectoryTable(cstate); + /* * If the target file is new-in-transaction, we assume that checking FSM * for free space is a waste of time. This could possibly be wrong, but @@ -807,7 +1600,8 @@ CopyFrom(CopyFromState cstate) ExecInitResultRelation(estate, resultRelInfo, 1); /* Verify the named relation is a valid target for INSERT */ - CheckValidResultRel(resultRelInfo, CMD_INSERT); + if (!(cstate->rel->rd_rel->relkind == RELKIND_DIRECTORY_TABLE)) + CheckValidResultRel(resultRelInfo, CMD_INSERT, NULL); ExecOpenIndices(resultRelInfo, false); @@ -1689,6 +2483,9 @@ BeginCopyFrom(ParseState *pstate, 0 }; + if (rel->rd_rel->relkind == RELKIND_DIRECTORY_TABLE) + return BeginCopyFromDirectoryTable(pstate, filename, rel, options); + /* Allocate workspace and zero all fields */ cstate = (CopyFromStateData *) palloc0(sizeof(CopyFromStateData)); @@ -3109,12 +3906,37 @@ SendCopyFromForwardedError(CopyFromState cstate, CdbCopy *cdbCopy, char *errorms cdbCopySendData(cdbCopy, target_seg, msgbuf->data, msgbuf->len); } +static void +EndCopyFromDirectoryTable(CopyFromState cstate) +{ + /* No COPY FROM related resources except memory. */ + if (cstate->copy_file && FreeFile(cstate->copy_file)) + { + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not close file \"%s\": %m", + cstate->filename))); + } + + /* Clean up single row error handling related memory */ + if (cstate->cdbsreh) + destroyCdbSreh(cstate->cdbsreh); + + pgstat_progress_end_command(); + + MemoryContextDelete(cstate->copycontext); + pfree(cstate); +} + /* * Clean up storage and release resources for COPY FROM. */ void EndCopyFrom(CopyFromState cstate) { + if (cstate->rel->rd_rel->relkind == RELKIND_DIRECTORY_TABLE) + return EndCopyFromDirectoryTable(cstate); + /* No COPY FROM related resources except memory. */ if (cstate->is_program) { diff --git a/src/backend/commands/dirtablecmds.c b/src/backend/commands/dirtablecmds.c new file mode 100644 index 00000000000..e1d18938cff --- /dev/null +++ b/src/backend/commands/dirtablecmds.c @@ -0,0 +1,475 @@ +/*------------------------------------------------------------------------- + * + * directorycmds.c + * directory table creation/manipulation commands + * + * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group + * + * + * IDENTIFICATION + * src/backend/commands/directorycmds.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include + +#include "access/htup_details.h" +#include "access/reloptions.h" +#include "access/table.h" +#include "access/xact.h" +#include "catalog/catalog.h" +#include "catalog/dependency.h" +#include "catalog/heap.h" +#include "catalog/index.h" +#include "catalog/indexing.h" +#include "catalog/objectaccess.h" +#include "catalog/oid_dispatch.h" +#include "catalog/pg_collation.h" +#include "catalog/pg_directory_table.h" +#include "catalog/pg_opclass.h" +#include "catalog/pg_proc.h" +#include "catalog/pg_tablespace.h" +#include "catalog/pg_type.h" +#include "catalog/pg_user_mapping.h" +#include "catalog/storage_directory_table.h" +#include "cdb/cdbdisp_query.h" +#include "cdb/cdbdispatchresult.h" +#include "cdb/cdboidsync.h" +#include "cdb/cdbvars.h" +#include "commands/defrem.h" +#include "commands/dirtablecmds.h" +#include "commands/tablespace.h" +#include "miscadmin.h" +#include "nodes/makefuncs.h" +#include "parser/parse_func.h" +#include "storage/ufile.h" +#include "tcop/utility.h" +#include "utils/acl.h" +#include "utils/builtins.h" +#include "utils/faultinjector.h" +#include "utils/lsyscache.h" +#include "utils/rel.h" +#include "utils/syscache.h" +#include "libpq-fe.h" +#include "cdb/cdbdisp_query.h" +#include "cdb/cdbdispatchresult.h" +#include "cdb/cdbvars.h" +#include "funcapi.h" + +typedef struct TableFunctionContext +{ + Relation relation; + TableScanDesc scanDesc; + TupleTableSlot *slot; + DirectoryTable *dirTable; +} TableFunctionContext; + +Datum directory_table(PG_FUNCTION_ARGS); + +static Oid +chooseTableSpace(CreateDirectoryTableStmt *stmt) +{ + Oid tablespaceId = InvalidOid; + + /* + * Select tablespace to use: an explicitly indicated one, or (in the case + * of a partitioned table) the parent's, if it has one. + */ + if (stmt->tablespacename) + { + /* + * Tablespace specified on the command line, or was passed down by + * dispatch. + */ + tablespaceId = get_tablespace_oid(stmt->tablespacename, false); + } + + /* still nothing? use the default */ + if (!OidIsValid(tablespaceId)) + tablespaceId = GetDefaultTablespace(stmt->base.relation->relpersistence, false); + + if (!OidIsValid(tablespaceId)) + tablespaceId = tablespaceId ? tablespaceId : MyDatabaseTableSpace; + + /* Check permissions except when using database's default */ + if (OidIsValid(tablespaceId) && tablespaceId != MyDatabaseTableSpace) + { + AclResult aclresult; + + aclresult = pg_tablespace_aclcheck(tablespaceId, GetUserId(), + ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, OBJECT_TABLESPACE, + get_tablespace_name(tablespaceId)); + } + + /* In all cases disallow placing user relations in pg_global */ + if (tablespaceId == GLOBALTABLESPACE_OID) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("only shared relations can be placed in pg_global tablespace"))); + + return tablespaceId; +} + +void +CreateDirectoryTable(CreateDirectoryTableStmt *stmt, Oid relId) +{ + Relation dirRelation; + Datum values[Natts_pg_directory_table]; + bool nulls[Natts_pg_directory_table]; + HeapTuple tuple; + char *dirTablePath; + Form_pg_class pg_class_tuple; + HeapTuple class_tuple; + Oid spcId = chooseTableSpace(stmt); + RelFileNode relFileNode = {0}; + + class_tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relId)); + if (!HeapTupleIsValid(class_tuple)) + elog(ERROR, "cache lookup failed for relation %u", relId); + pg_class_tuple = (Form_pg_class) GETSTRUCT(class_tuple); + + relFileNode.spcNode = spcId; + relFileNode.dbNode = MyDatabaseId; + relFileNode.relNode = pg_class_tuple->relfilenode; + dirTablePath = UFileFormatPathName(&relFileNode); + + ReleaseSysCache(class_tuple); + + /* + * Acquire DirectoryTableLock to ensure that no DROP DIRECTORY TABLE + * or CREATE DIRECTORY TABLE is running concurrently. + */ + LWLockAcquire(DirectoryTableLock, LW_EXCLUSIVE); + + UFileEnsurePath(spcId, dirTablePath); + + /* + * Advance command counter to ensure the pg_attribute tuple is visible; + * the tuple might be updated to add constraints in previous step. + */ + CommandCounterIncrement(); + + dirRelation = table_open(DirectoryTableRelationId, RowExclusiveLock); + /* + * Insert tuple into pg_directory_table. + */ + memset(values, 0, sizeof(values)); + memset(nulls, false, sizeof(nulls)); + + values[Anum_pg_directory_table_dttablespace - 1] = spcId; + values[Anum_pg_directory_table_dtrelid - 1] = ObjectIdGetDatum(relId); + values[Anum_pg_directory_table_dtlocation - 1] = CStringGetTextDatum(dirTablePath); + + tuple = heap_form_tuple(dirRelation->rd_att, values, nulls); + + CatalogTupleInsert(dirRelation, tuple); + + heap_freetuple(tuple); + + table_close(dirRelation, RowExclusiveLock); + + LWLockRelease(DirectoryTableLock); +} + +static Datum +getFileContent(Oid spcId, char *scopedFileUrl) +{ + char errorMessage[256]; + char buffer[4096]; + char *data; + int curPos = 0; + int bytesRead; + bytea *content; + UFile *file; + int64 fileSize; + + file = UFileOpen(spcId, + scopedFileUrl, + O_RDONLY, + errorMessage, + sizeof(errorMessage)); + + if (file == NULL) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("failed to open file \"%s\": %s,", scopedFileUrl, errorMessage))); + + fileSize = UFileSize(file); + if (fileSize > MaxAllocSize - VARHDRSZ) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("out of memory"))); + + content = (bytea *) palloc(fileSize + VARHDRSZ); + SET_VARSIZE(content, fileSize + VARHDRSZ); + data = VARDATA(content); + + while (true) + { + bytesRead = UFileRead(file, buffer, sizeof(buffer)); + if (bytesRead == -1) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("failed to read file \"%s\": %s", scopedFileUrl, UFileGetLastError(file)))); + + if (bytesRead == 0) + break; + + memcpy(data + curPos, buffer, bytesRead); + curPos += bytesRead; + } + + UFileClose(file); + + PG_RETURN_BYTEA_P(content); +} + +static char * +getScopedFileUrl(DirectoryTable *dirTable, char *relativePath) +{ + return psprintf("%s/%s", dirTable->location, relativePath); +} + +Datum +directory_table(PG_FUNCTION_ARGS) +{ +#define DIRECTORY_TABLE_FUNCTION_COLUMNS 7 + Oid relId = PG_GETARG_OID(0); + Datum values[DIRECTORY_TABLE_FUNCTION_COLUMNS]; + bool nulls[DIRECTORY_TABLE_FUNCTION_COLUMNS]; + HeapTuple tuple; + Datum result; + FuncCallContext *funcCtx; + TableFunctionContext *context; + + if (SRF_IS_FIRSTCALL()) + { + Snapshot snapshot; + TupleDesc newTupDesc; + MemoryContext oldContext; + + funcCtx = SRF_FIRSTCALL_INIT(); + + oldContext = MemoryContextSwitchTo(funcCtx->multi_call_memory_ctx); + + newTupDesc = CreateTemplateTupleDesc(DIRECTORY_TABLE_FUNCTION_COLUMNS); + TupleDescInitEntry(newTupDesc, (AttrNumber) 1, "scoped_file_url", TEXTOID, -1, 0); + TupleDescInitEntry(newTupDesc, (AttrNumber) 2, "relative_path", TEXTOID, -1, 0); + TupleDescInitEntry(newTupDesc, (AttrNumber) 3, "tag", TEXTOID, -1, 0); + TupleDescInitEntry(newTupDesc, (AttrNumber) 4, "size", INT8OID, -1, 0); + TupleDescInitEntry(newTupDesc, (AttrNumber) 5, "last_modified", TIMESTAMPTZOID, -1, 0); + TupleDescInitEntry(newTupDesc, (AttrNumber) 6, "md5", TEXTOID, -1, 0); + TupleDescInitEntry(newTupDesc, (AttrNumber) 7, "content", BYTEAOID, -1, 0); + + funcCtx->tuple_desc = BlessTupleDesc(newTupDesc); + + context = (TableFunctionContext *) palloc0(sizeof(TableFunctionContext)); + context->relation = table_open(relId, AccessShareLock); + + SIMPLE_FAULT_INJECTOR("directory_table_inject"); + + if (!RelationIsDirectoryTable(relId)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("'%s' is not a directory table", + RelationGetRelationName(context->relation)))); + + context->slot = MakeSingleTupleTableSlot(RelationGetDescr(context->relation), + table_slot_callbacks(context->relation)); + context->dirTable = GetDirectoryTable(RelationGetRelid(context->relation)); + + snapshot = GetLatestSnapshot(); + context->scanDesc = table_beginscan(context->relation, snapshot, 0, NULL); + + funcCtx->user_fctx = (void *) context; + + MemoryContextSwitchTo(oldContext); + } + + funcCtx = SRF_PERCALL_SETUP(); + context = (TableFunctionContext *) funcCtx->user_fctx; + + if (table_scan_getnextslot(context->scanDesc, ForwardScanDirection, context->slot)) + { + Datum attrRelativePath; + Datum attrSize; + Datum attrLastModified; + Datum attrMd5Sum; + Datum attrTags; + bool isNull; + char *scopedFileUrl; + + slot_getallattrs(context->slot); + + attrRelativePath = slot_getattr(context->slot, 1, &isNull); + Assert(isNull == false); + attrSize = slot_getattr(context->slot, 2, &isNull); + Assert(isNull == false); + attrLastModified = slot_getattr(context->slot, 3, &isNull); + Assert(isNull == false); + attrMd5Sum = slot_getattr(context->slot, 4, &isNull); + Assert(isNull == false); + attrTags = slot_getattr(context->slot, 5, &isNull); + + MemSet(values, 0, sizeof(values)); + MemSet(nulls, 0, sizeof(nulls)); + + scopedFileUrl = getScopedFileUrl(context->dirTable, TextDatumGetCString(attrRelativePath)); + + values[0] = PointerGetDatum(cstring_to_text(scopedFileUrl)); + values[1] = attrRelativePath; + values[2] = attrTags; + nulls[2] = isNull; + values[3] = attrSize; + values[4] = attrLastModified; + values[5] = attrMd5Sum; + values[6] = getFileContent(context->dirTable->spcId, scopedFileUrl); + + tuple = heap_form_tuple(funcCtx->tuple_desc, values, nulls); + result = HeapTupleGetDatum(tuple); + + SRF_RETURN_NEXT(funcCtx, result); + } + + table_endscan(context->scanDesc); + ExecDropSingleTupleTableSlot(context->slot); + table_close(context->relation, AccessShareLock); + + pfree(context); + funcCtx->user_fctx = NULL; + + SRF_RETURN_DONE(funcCtx); +} + +Datum +remove_file_segment(PG_FUNCTION_ARGS) +{ + Relation relation; + ScanKeyData scankey; + SysScanDesc scan; + HeapTuple tuple; + Oid indexOid; + List *indexOids; + Oid relId; + char *relativePath; + char *fullPathName; + bool exist = false; + DirectoryTable *dirTable; + + if (PG_ARGISNULL(0)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("relation name cannot be NULL"))); + relId = PG_GETARG_OID(0); + + if (PG_ARGISNULL(1)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("file path cannot be null"))); + relativePath = PG_GETARG_CSTRING(1); + + dirTable = GetDirectoryTable(relId); + relation = table_open(relId, AccessExclusiveLock); + + SIMPLE_FAULT_INJECTOR("remove_file_inject"); + + indexOids = RelationGetIndexList(relation); + Assert(list_length(indexOids) == 1); + + indexOid = list_nth_oid(indexOids, 0); + ScanKeyInit(&scankey, + 1, /* relative_path */ + BTEqualStrategyNumber, F_TEXTEQ, + CStringGetTextDatum(relativePath)); + + scan = systable_beginscan(relation, indexOid, true, NULL, 1, &scankey); + tuple = systable_getnext(scan); + if (HeapTupleIsValid(tuple)) + { + CatalogTupleDelete(relation, &tuple->t_self); + fullPathName = psprintf("%s/%s", dirTable->location, relativePath); + UFileAddDeletePendingEntry(relation, dirTable->spcId, fullPathName); + exist = true; + } + + systable_endscan(scan); + list_free(indexOids); + + table_close(relation, NoLock); + + PG_RETURN_BOOL(exist); +} + +Datum +remove_file(PG_FUNCTION_ARGS) +{ + Relation relation; + Oid relId; + char *relativePath; + char *query; + int numDeletes; + int i; + CdbPgResults cdbPgresults = {NULL, 0}; + + if (PG_ARGISNULL(0)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("relation name cannot be NULL"))); + relId = PG_GETARG_OID(0); + + if (PG_ARGISNULL(1)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("file path cannot be null"))); + relativePath = PG_GETARG_CSTRING(1); + + relation = table_open(relId, AccessExclusiveLock); + + if (Gp_role != GP_ROLE_DISPATCH) + ereport(ERROR, + (errcode(ERRCODE_GP_COMMAND_ERROR), + errmsg("remove_file() could only be called on QD"))); + + query = psprintf("select pg_catalog.remove_file_segment(%u, '%s')", relId, relativePath); + + CdbDispatchCommand(query, DF_WITH_SNAPSHOT | DF_CANCEL_ON_ERROR, &cdbPgresults); + + numDeletes = 0; + for (i = 0; i < cdbPgresults.numResults; i++) + { + Datum value; + struct pg_result *pgresult = cdbPgresults.pg_results[i]; + + if (PQresultStatus(pgresult) != PGRES_TUPLES_OK) + { + cdbdisp_clearCdbPgResults(&cdbPgresults); + ereport(ERROR, + (errmsg("unexpected result from segment: %d", PQresultStatus(pgresult)))); + } + + if (PQntuples(pgresult) != 1 || PQnfields(pgresult) != 1) + { + cdbdisp_clearCdbPgResults(&cdbPgresults); + ereport(ERROR, + (errmsg("unexpected shape of result from segment (%d rows, %d cols)", + PQntuples(pgresult), PQnfields(pgresult)))); + } + if (PQgetisnull(pgresult, 0, 0)) + value = 0; + else + value = DirectFunctionCall1(boolin, + CStringGetDatum(PQgetvalue(pgresult, 0, 0))); + + numDeletes += value; + } + + cdbdisp_clearCdbPgResults(&cdbPgresults); + + table_close(relation, NoLock); + + PG_RETURN_BOOL(numDeletes > 0); +} diff --git a/src/backend/commands/dropcmds.c b/src/backend/commands/dropcmds.c index a6ddfa17b39..8e39c30699a 100644 --- a/src/backend/commands/dropcmds.c +++ b/src/backend/commands/dropcmds.c @@ -456,6 +456,10 @@ does_not_exist_skipping(ObjectType objtype, Node *object) msg = gettext_noop("server \"%s\" does not exist, skipping"); name = strVal((Value *) object); break; + case OBJECT_STORAGE_SERVER: + msg = gettext_noop("storage server \"%s\" does not exist, skipping"); + name = strVal((Value *) object); + break; case OBJECT_OPCLASS: { List *opcname = list_copy_tail(castNode(List, object), 1); diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c index 8b2994a3448..0b984fbb431 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -942,6 +942,8 @@ EventTriggerSupportsObjectType(ObjectType obtype) case OBJECT_TABLESPACE: case OBJECT_ROLE: case OBJECT_PROFILE: + case OBJECT_STORAGE_SERVER: + case OBJECT_STORAGE_USER_MAPPING: /* no support for global objects */ return false; case OBJECT_EVENT_TRIGGER: @@ -958,6 +960,7 @@ EventTriggerSupportsObjectType(ObjectType obtype) case OBJECT_CONVERSION: case OBJECT_DEFACL: case OBJECT_DEFAULT: + case OBJECT_DIRECTORY_TABLE: case OBJECT_DOMAIN: case OBJECT_DOMCONSTRAINT: case OBJECT_EXTENSION: @@ -1025,6 +1028,8 @@ EventTriggerSupportsObjectClass(ObjectClass objclass) case OCLASS_ROLE: case OCLASS_PROFILE: case OCLASS_PASSWORDHISTORY: + case OCLASS_STORAGE_SERVER: + case OCLASS_STORAGE_USER_MAPPING: /* no support for global objects */ return false; case OCLASS_EVENT_TRIGGER: @@ -1064,6 +1069,7 @@ EventTriggerSupportsObjectClass(ObjectClass objclass) case OCLASS_PUBLICATION_REL: case OCLASS_SUBSCRIPTION: case OCLASS_TRANSFORM: + case OCLASS_DIRTABLE: return true; case OCLASS_EXTPROTOCOL: case OCLASS_TASK: @@ -2115,6 +2121,8 @@ stringify_grant_objtype(ObjectType objtype) return "FOREIGN DATA WRAPPER"; case OBJECT_FOREIGN_SERVER: return "FOREIGN SERVER"; + case OBJECT_STORAGE_SERVER: + return "STORAGE SERVER"; case OBJECT_FUNCTION: return "FUNCTION"; case OBJECT_LANGUAGE: @@ -2166,11 +2174,13 @@ stringify_grant_objtype(ObjectType objtype) case OBJECT_TSPARSER: case OBJECT_TSTEMPLATE: case OBJECT_USER_MAPPING: + case OBJECT_STORAGE_USER_MAPPING: case OBJECT_VIEW: case OBJECT_EXTPROTOCOL: case OBJECT_RESQUEUE: case OBJECT_RESGROUP: case OBJECT_PROFILE: + case OBJECT_DIRECTORY_TABLE: elog(ERROR, "unsupported object type: %d", (int) objtype); } @@ -2201,6 +2211,8 @@ stringify_adefprivs_objtype(ObjectType objtype) return "FOREIGN DATA WRAPPERS"; case OBJECT_FOREIGN_SERVER: return "FOREIGN SERVERS"; + case OBJECT_STORAGE_SERVER: + return "STORAGE SERVERS"; case OBJECT_FUNCTION: return "FUNCTIONS"; case OBJECT_LANGUAGE: @@ -2252,11 +2264,13 @@ stringify_adefprivs_objtype(ObjectType objtype) case OBJECT_TSPARSER: case OBJECT_TSTEMPLATE: case OBJECT_USER_MAPPING: + case OBJECT_STORAGE_USER_MAPPING: case OBJECT_VIEW: case OBJECT_EXTPROTOCOL: case OBJECT_RESQUEUE: case OBJECT_RESGROUP: case OBJECT_PROFILE: + case OBJECT_DIRECTORY_TABLE: elog(ERROR, "unsupported object type: %d", (int) objtype); } diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index a6db5e14fd9..9066ce3bb40 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -31,6 +31,7 @@ #include "catalog/indexing.h" #include "catalog/pg_am.h" #include "catalog/pg_constraint.h" +#include "catalog/pg_directory_table.h" #include "catalog/pg_inherits.h" #include "catalog/pg_opclass.h" #include "catalog/pg_opfamily.h" @@ -704,6 +705,9 @@ DefineIndex(Oid relationId, bool shouldDispatch; Oid blkdirrelid = InvalidOid; + if (RelationIsDirectoryTable(relationId)) + elog(ERROR, "Disallowed to create index on directory table \"%s\".", get_rel_name(relationId)); + shouldDispatch = (Gp_role == GP_ROLE_DISPATCH && ENABLE_DISPATCH() && !IsBootstrapProcessingMode()); @@ -847,6 +851,7 @@ DefineIndex(Oid relationId, case RELKIND_RELATION: case RELKIND_MATVIEW: case RELKIND_PARTITIONED_TABLE: + case RELKIND_DIRECTORY_TABLE: /* OK */ break; case RELKIND_FOREIGN_TABLE: @@ -3507,6 +3512,7 @@ ReindexMultipleTables(ReindexStmt *stmt, ReindexParams *params) * are processed. */ if (classtuple->relkind != RELKIND_RELATION && + classtuple->relkind != RELKIND_DIRECTORY_TABLE && classtuple->relkind != RELKIND_MATVIEW) continue; @@ -3967,6 +3973,7 @@ ReindexRelationConcurrently(ReindexStmt *stmt, Oid relationOid, ReindexParams *p case RELKIND_RELATION: case RELKIND_MATVIEW: case RELKIND_TOASTVALUE: + case RELKIND_DIRECTORY_TABLE: { /* * In the case of a relation, find all its indexes including diff --git a/src/backend/commands/seclabel.c b/src/backend/commands/seclabel.c index 487ef4417b2..a0dd92b2e04 100644 --- a/src/backend/commands/seclabel.c +++ b/src/backend/commands/seclabel.c @@ -41,6 +41,7 @@ SecLabelSupportsObjectType(ObjectType objtype) case OBJECT_AGGREGATE: case OBJECT_COLUMN: case OBJECT_DATABASE: + case OBJECT_DIRECTORY_TABLE: case OBJECT_DOMAIN: case OBJECT_EVENT_TRIGGER: case OBJECT_FOREIGN_TABLE: @@ -95,6 +96,8 @@ SecLabelSupportsObjectType(ObjectType objtype) case OBJECT_EXTPROTOCOL: case OBJECT_RESQUEUE: case OBJECT_RESGROUP: + case OBJECT_STORAGE_SERVER: + case OBJECT_STORAGE_USER_MAPPING: return false; /* @@ -190,6 +193,7 @@ ExecSecLabelStmt(SecLabelStmt *stmt) relation->rd_rel->relkind != RELKIND_MATVIEW && relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE && relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE && + relation->rd_rel->relkind != RELKIND_DIRECTORY_TABLE && relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), diff --git a/src/backend/commands/statscmds.c b/src/backend/commands/statscmds.c index fb2251b6291..00869b12115 100644 --- a/src/backend/commands/statscmds.c +++ b/src/backend/commands/statscmds.c @@ -135,6 +135,7 @@ CreateStatistics(CreateStatsStmt *stmt) /* Restrict to allowed relation types */ if (rel->rd_rel->relkind != RELKIND_RELATION && + rel->rd_rel->relkind != RELKIND_DIRECTORY_TABLE && rel->rd_rel->relkind != RELKIND_MATVIEW && rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE && rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE) diff --git a/src/backend/commands/storagecmds.c b/src/backend/commands/storagecmds.c new file mode 100644 index 00000000000..249cf56a812 --- /dev/null +++ b/src/backend/commands/storagecmds.c @@ -0,0 +1,957 @@ +/*------------------------------------------------------------------------- + * + * storagecmds.c + * storage server/user_mapping creation/manipulation commands + * + * Copyright (c) 2016-Present Hashdata, Inc. + * + * + * IDENTIFICATION + * src/backend/commands/storagecmds.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/htup_details.h" +#include "access/reloptions.h" +#include "access/table.h" +#include "catalog/dependency.h" +#include "catalog/gp_storage_server.h" +#include "catalog/gp_storage_user_mapping.h" +#include "catalog/objectaccess.h" +#include "catalog/oid_dispatch.h" +#include "cdb/cdbdisp_query.h" +#include "cdb/cdbvars.h" +#include "commands/defrem.h" +#include "commands/storagecmds.h" +#include "executor/execdesc.h" +#include "nodes/pg_list.h" +#include "utils/acl.h" +#include "utils/builtins.h" +#include "utils/syscache.h" + +Oid +get_storage_server_oid(const char *servername, bool missing_ok) +{ + Oid oid; + + oid = GetSysCacheOid1(STORAGESERVERNAME, Anum_gp_storage_server_oid, + CStringGetDatum(servername)); + + if (!OidIsValid(oid) && !missing_ok) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("server \"%s\" does not exist", servername))); + return oid; +} + +/* + * GetStorageServerExtended - look up the storage server definition. If + * flags uses FSV_MISSING_OK, return NULL if the object cannot be found + * instead of raising an error. + */ +StorageServer * +GetStorageServerExtended(Oid serverid, bits16 flags) +{ + Form_gp_storage_server serverform; + StorageServer *server; + HeapTuple tp; + Datum datum; + bool isnull; + + tp = SearchSysCache1(STORAGESERVEROID, ObjectIdGetDatum(serverid)); + + if (!HeapTupleIsValid(tp)) + { + if ((flags & SSV_MISSING_OK) == 0) + elog(ERROR, "cache lookup failed for storage server %u", serverid); + return NULL; + } + + serverform = (Form_gp_storage_server) GETSTRUCT(tp); + + server = (StorageServer *) palloc(sizeof(StorageServer)); + server->serverid = serverid; + server->servername = pstrdup(NameStr(serverform->srvname)); + server->owner = serverform->srvowner; + + /* Extract the srvoptions */ + datum = SysCacheGetAttr(STORAGESERVEROID, + tp, + Anum_gp_storage_server_srvoptions, + &isnull); + if (isnull) + server->options = NIL; + else + server->options = untransformRelOptions(datum); + + ReleaseSysCache(tp); + + return server; +} + +/* + * GetStorageServer - look up the storage server definition. + */ +StorageServer * +GetStorageServer(Oid serverid) +{ + return GetStorageServerExtended(serverid, 0); +} + +/* + * GetStorageServerByName - look up the storage server definition by name. + */ +StorageServer * +GetStorageServerByName(const char *srvname, bool missing_ok) +{ + Oid serverid = get_storage_server_oid(srvname, missing_ok); + + if (!OidIsValid(serverid)) + return NULL; + + return GetStorageServer(serverid); +} + +/* + * GetStorgeUserMapping - look up the storage user mapping. + * + * If no mapping is found for the supplied user, we also look for + * PUBLIC mappings (userid == InvalidOid). + */ +StorageUserMapping * +GetStorageUserMapping(Oid userid, Oid serverid) +{ + Datum datum; + HeapTuple tp; + bool isnull; + StorageUserMapping *um; + + tp = SearchSysCache2(STORAGEUSERMAPPINGUSERSERVER, + ObjectIdGetDatum(userid), + ObjectIdGetDatum(serverid)); + + if (!HeapTupleIsValid(tp)) + { + /* Not found for the specific user -- try PUBLIC */ + tp = SearchSysCache2(STORAGEUSERMAPPINGUSERSERVER, + ObjectIdGetDatum(InvalidOid), + ObjectIdGetDatum(serverid)); + } + + if (!HeapTupleIsValid(tp)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("storage user mapping not found for \"%s\"", + StorageMappingUserName(userid)))); + + um = (StorageUserMapping *) palloc(sizeof(StorageUserMapping)); + um->umid = ((Form_gp_storage_user_mapping) GETSTRUCT(tp))->oid; + um->userid = userid; + um->serverid = serverid; + + /* Extract the umoptions */ + datum = SysCacheGetAttr(STORAGEUSERMAPPINGUSERSERVER, + tp, + Anum_gp_storage_user_mapping_umoptions, + &isnull); + if (isnull) + um->options = NIL; + else + um->options = untransformRelOptions(datum); + + ReleaseSysCache(tp); + + return um; +} + + +/* + * Convert a DefElem list to the text array format that is used in + * gp_storage_server, gp_storage_user_mapping. + * + * Returns the array in the form of a Datum, or PointerGetDatum(NULL) + * if the list is empty. + * + * Note: The array is usually stored to database without further + * processing, hence any validation should be done before this + * conversion. + */ +static Datum +optionListToArray(List *options) +{ + ArrayBuildState *astate = NULL; + ListCell *cell; + + foreach(cell, options) + { + DefElem *def = lfirst(cell); + const char *value; + Size len; + text *t; + + value = defGetString(def); + len = VARHDRSZ + strlen(def->defname) + 1 + strlen(value); + t = palloc(len + 1); + SET_VARSIZE(t, len); + sprintf(VARDATA(t), "%s=%s", def->defname, value); + + astate = accumArrayResult(astate, PointerGetDatum(t), + false, TEXTOID, + CurrentMemoryContext); + } + + if (astate) + return makeArrayResult(astate, CurrentMemoryContext); + + return PointerGetDatum(NULL); +} + +/* + * Transform a list of DefElem into text array format. This is substantially + * the same thing as optionListToArray(), except we recognize SET/ADD/DROP + * actions for modifying an existing list of options, which is passed in + * Datum form as oldOptions. + * + * Returns the array in the form of a Datum, or PointerGetDatum(NULL) + * if the list is empty. + * + * This is used by CREATE/ALTER of STORAGE SERVER/USER MAPPING + */ +Datum +transformStorageGenericOptions(Oid catalogId, + Datum oldOptions, + List *options) +{ + List *resultOptions = untransformRelOptions(oldOptions); + ListCell *optcell; + Datum result; + + foreach(optcell, options) + { + DefElem *od = lfirst(optcell); + ListCell *cell; + + /* + * Find the element in resultOptions. We need this for validation in + * all cases. + */ + foreach(cell, resultOptions) + { + DefElem *def = lfirst(cell); + + if (strcmp(def->defname, od->defname) == 0) + break; + } + + /* + * It is possible to perform multiple SET/DROP actions on the same + * option. The standard permits this, as long as the options to be + * added are unique. Note that an unspecified action is taken to be + * ADD. + */ + switch (od->defaction) + { + case DEFELEM_DROP: + if (!cell) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("option \"%s\" not found", + od->defname))); + resultOptions = list_delete_cell(resultOptions, cell); + break; + + case DEFELEM_SET: + if (!cell) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("option \"%s\" not found", + od->defname))); + lfirst(cell) = od; + break; + + case DEFELEM_ADD: + case DEFELEM_UNSPEC: + if (cell) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("option \"%s\" provided more than once", + od->defname))); + resultOptions = lappend(resultOptions, od); + break; + + default: + elog(ERROR, "unrecognized action %d on option \"%s\"", + (int) od->defaction, od->defname); + break; + } + } + + result = optionListToArray(resultOptions); + + return result; +} + +/* + * Common routine to check permission for storage-user-mapping-related DDL + * commands. We allow server owners to operate on any mapping, and + * users to operate on their own mapping. + */ +static void +storage_user_mapping_ddl_aclcheck(Oid umuserid, Oid serverid, const char *servername) +{ + Oid curuserid = GetUserId(); + + if (!gp_storage_server_ownercheck(serverid, curuserid)) + { + if (umuserid == curuserid) + { + AclResult aclresult; + + aclresult = gp_storage_server_aclcheck(serverid, curuserid, ACL_USAGE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, OBJECT_STORAGE_SERVER, servername); + } + else + aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_STORAGE_SERVER, + servername); + } +} + +/* + * Create a storage server + */ +ObjectAddress +CreateStorageServer(CreateStorageServerStmt *stmt) +{ + Relation rel; + Datum srvoptions; + Datum values[Natts_gp_storage_server]; + bool nulls[Natts_gp_storage_server]; + HeapTuple tuple; + Oid srvId; + Oid ownerId; + ObjectAddress myself = {0}; + + rel = table_open(StorageServerRelationId, RowExclusiveLock); + + /* For now the owner cannot be specified on create. Use effective user ID. */ + ownerId = GetUserId(); + + /* + * Check that there is no other storage server by this name. Do nothing if + * IF NOT EXISTS was enforced. + */ + if (GetStorageServerByName(stmt->servername, true) != NULL) + { + if (stmt->if_not_exists) + { + ereport(NOTICE, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("storage server \"%s\" already exists, skipping", + stmt->servername))); + table_close(rel, RowExclusiveLock); + return InvalidObjectAddress; + } + else + { + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("storage server \"%s\" already exists", + stmt->servername))); + } + } + + /* + * Insert tuple into gp_storage_server. + */ + memset(values, 0, sizeof(values)); + memset(nulls, false, sizeof(nulls)); + + srvId = GetNewOidForStorageServer(rel, StorageServerOidIndexId, + Anum_gp_storage_server_oid, + stmt->servername); + values[Anum_gp_storage_server_oid - 1] = ObjectIdGetDatum(srvId); + values[Anum_gp_storage_server_srvname - 1] = + DirectFunctionCall1(namein, CStringGetDatum(stmt->servername)); + values[Anum_gp_storage_server_srvowner -1] = ObjectIdGetDatum(ownerId); + /* Start with a blank acl */ + nulls[Anum_gp_storage_server_srvacl - 1] = true; + + /* Add storage server options */ + srvoptions = transformStorageGenericOptions(StorageServerRelationId, + PointerGetDatum(NULL), + stmt->options); + + if (PointerIsValid(DatumGetPointer(srvoptions))) + values[Anum_gp_storage_server_srvoptions - 1] = srvoptions; + else + nulls[Anum_gp_storage_server_srvoptions - 1] = true; + + tuple = heap_form_tuple(rel->rd_att, values, nulls); + + CatalogTupleInsert(rel, tuple); + + heap_freetuple(tuple); + + /* Post creation hook for new storage server */ + InvokeObjectPostCreateHook(StorageServerRelationId, srvId, 0); + + if (Gp_role == GP_ROLE_DISPATCH) + { + CdbDispatchUtilityStatement((Node *) stmt, + DF_WITH_SNAPSHOT | DF_CANCEL_ON_ERROR | DF_NEED_TWO_PHASE, + GetAssignedOidsForDispatch(), + NULL); + } + + table_close(rel, RowExclusiveLock); + + return myself; +} + +/* + * Alter Storage Server + */ +ObjectAddress +AlterStorageServer(AlterStorageServerStmt *stmt) +{ + Relation rel; + HeapTuple tp; + Datum repl_val[Natts_gp_storage_server]; + bool repl_null[Natts_gp_storage_server]; + bool repl_repl[Natts_gp_storage_server]; + Oid srvId; + Form_gp_storage_server srvForm; + ObjectAddress address = {0}; + + rel = table_open(StorageServerRelationId, RowExclusiveLock); + + tp = SearchSysCacheCopy1(STORAGESERVERNAME, + CStringGetDatum(stmt->servername)); + + if (!HeapTupleIsValid(tp)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("storage server \"%s\" does not exist", stmt->servername))); + + srvForm = (Form_gp_storage_server) GETSTRUCT(tp); + srvId = srvForm->oid; + + /* + * Only owner or a superuser can ALTER a STORAGE SERVER. + */ + if (!gp_storage_server_ownercheck(srvId, GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_STORAGE_SERVER, + stmt->servername); + + memset(repl_val, 0, sizeof(repl_val)); + memset(repl_null, false, sizeof(repl_null)); + memset(repl_repl, false, sizeof(repl_repl)); + + if (stmt->options) + { + Datum datum; + bool isnull; + + /* Extract the current srvoptions */ + datum = SysCacheGetAttr(STORAGESERVEROID, + tp, + Anum_gp_storage_server_srvoptions, + &isnull); + if (isnull) + datum = PointerGetDatum(NULL); + + /* Prepare the options array */ + datum = transformStorageGenericOptions(StorageServerRelationId, + datum, + stmt->options); + if (PointerIsValid(DatumGetPointer(datum))) + repl_val[Anum_gp_storage_server_srvoptions - 1] = datum; + else + repl_null[Anum_gp_storage_server_srvoptions - 1] = true; + + repl_repl[Anum_gp_storage_server_srvoptions - 1] = true; + } + /* Everything looks good - update the tuple */ + tp = heap_modify_tuple(tp, RelationGetDescr(rel), + repl_val, repl_null, repl_repl); + + CatalogTupleUpdate(rel, &tp->t_self, tp); + + InvokeObjectPostAlterHook(StorageServerRelationId, srvId, 0); + + ObjectAddressSet(address, StorageServerRelationId, srvId); + + heap_freetuple(tp); + + if (Gp_role == GP_ROLE_DISPATCH) + { + CdbDispatchUtilityStatement((Node *) stmt, + DF_WITH_SNAPSHOT | DF_CANCEL_ON_ERROR | DF_NEED_TWO_PHASE, + GetAssignedOidsForDispatch(), + NULL); + } + + table_close(rel, RowExclusiveLock); + + return address; +} + +/* + * Remove Storage Server + */ +Oid +RemoveStorageServer(DropStorageServerStmt *stmt) +{ + Relation rel; + Oid serverId; + Oid srvOwnerId; + Oid curuserid; + ScanKeyData scankey; + SysScanDesc sscan; + HeapTuple tuple; + char *detail; + char *detail_log; + + curuserid = GetUserId(); + + rel = table_open(StorageServerRelationId, RowExclusiveLock); + /* + * Check that if the storage server exists. Do nothing if IF NOT + * EXISTS was enforced. + */ + serverId = GetSysCacheOid1(STORAGESERVERNAME, Anum_gp_storage_server_oid, + CStringGetDatum(stmt->servername)); + + if (!OidIsValid(serverId)) + { + if (stmt->missing_ok) + { + ereport(NOTICE, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("storage server \"%s\" not exists, skipping", + stmt->servername))); + table_close(rel, RowExclusiveLock); + return InvalidOid; + } + else + { + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("storage server \"%s\" not exists", + stmt->servername))); + } + } + + srvOwnerId = GetSysCacheOid1(STORAGESERVERNAME, Anum_gp_storage_server_srvowner, + CStringGetDatum(stmt->servername)); + + if (!gp_storage_server_ownercheck(serverId, curuserid)) + { + if (srvOwnerId == curuserid) + { + AclResult aclresult; + + aclresult = gp_storage_server_aclcheck(serverId, curuserid, ACL_USAGE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, OBJECT_STORAGE_SERVER, stmt->servername); + } + else + aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_STORAGE_SERVER, + stmt->servername); + } + + ScanKeyInit(&scankey, + Anum_gp_storage_server_oid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(serverId)); + sscan = systable_beginscan(rel, StorageServerOidIndexId, + true, NULL, 1, &scankey); + + tuple = systable_getnext(sscan); + + /* + * Lock the storage server, so nobody can add dependencies to her while we drop + * her. We keep the lock until the end of transaction. + */ + LockSharedObject(StorageServerRelationId, serverId, 0, AccessExclusiveLock); + + /* Check for pg_shdepend entries depending on this profile */ + if (checkSharedDependencies(StorageServerRelationId, serverId, + &detail, &detail_log)) + ereport(ERROR, + (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST), + errmsg("storage server \"%s\" cannot be dropped because some objects depend on it", + stmt->servername), + errdetail_internal("%s", detail), + errdetail_log("%s", detail_log))); + + CatalogTupleDelete(rel, &tuple->t_self); + + systable_endscan(sscan); + table_close(rel, RowExclusiveLock); + + /* + * Drop hook for the role being removed + */ + InvokeObjectDropHook(StorageServerRelationId, serverId, 0); + + /* + * Delete shared dependency references related to this server object. + */ + deleteSharedDependencyRecordsFor(StorageServerRelationId, serverId, 0); + + if (Gp_role == GP_ROLE_DISPATCH) + { + CdbDispatchUtilityStatement((Node *) stmt, + DF_WITH_SNAPSHOT | DF_CANCEL_ON_ERROR | DF_NEED_TWO_PHASE, + GetAssignedOidsForDispatch(), + NULL); + } + + return serverId; +} + +/* + * Create Storage User Mapping + */ +ObjectAddress +CreateStorageUserMapping(CreateStorageUserMappingStmt *stmt) +{ + Relation rel; + Datum useoptions; + Datum values[Natts_gp_storage_user_mapping]; + bool nulls[Natts_gp_storage_user_mapping]; + HeapTuple tuple; + Oid useId; + Oid umId; + StorageServer *srv; + ObjectAddress myself; + RoleSpec *role = (RoleSpec *) stmt->user; + + rel = table_open(StorageUserMappingRelationId, RowExclusiveLock); + + if (role->roletype == ROLESPEC_PUBLIC) + useId = ACL_ID_PUBLIC; + else + useId = get_rolespec_oid(stmt->user, false); + + /* Check that the server exists. */ + srv = GetStorageServerByName(stmt->servername, false); + + storage_user_mapping_ddl_aclcheck(useId, srv->serverid, stmt->servername); + + /* + * Check that the user mapping is unique within server. + */ + umId = GetSysCacheOid2(STORAGEUSERMAPPINGUSERSERVER, Anum_gp_storage_user_mapping_oid, + ObjectIdGetDatum(useId), + ObjectIdGetDatum(srv->serverid)); + + if (OidIsValid(umId)) + { + if (stmt->if_not_exists) + { + ereport(NOTICE, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("storage user mapping for \"%s\" already exists for storage server \"%s\", skipping", + StorageMappingUserName(useId), + stmt->servername))); + + table_close(rel, RowExclusiveLock); + return InvalidObjectAddress; + } + else + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("storage user mapping for \"%s\" already exists for storage server \"%s\"", + StorageMappingUserName(useId), + stmt->servername))); + } + + /* + * Insert tuple into gp_storage_user_mapping. + */ + memset(values, 0, sizeof(values)); + memset(nulls, 0, sizeof(nulls)); + + umId = GetNewOidForStorageUserMapping(rel, StorageUserMappingOidIndexId, + Anum_gp_storage_user_mapping_oid, + useId, srv->serverid); + values[Anum_gp_storage_user_mapping_oid -1] = ObjectIdGetDatum(umId); + values[Anum_gp_storage_user_mapping_umuser -1] = ObjectIdGetDatum(useId); + values[Anum_gp_storage_user_mapping_umserver - 1] = ObjectIdGetDatum(srv->serverid); + + /* Add user options */ + useoptions = transformStorageGenericOptions(StorageUserMappingRelationId, + PointerGetDatum(NULL), + stmt->options); + + if (PointerIsValid(DatumGetPointer(useoptions))) + values[Anum_gp_storage_user_mapping_umoptions - 1] = useoptions; + else + nulls[Anum_gp_storage_user_mapping_umoptions - 1] = true; + + tuple = heap_form_tuple(rel->rd_att, values, nulls); + + CatalogTupleInsert(rel, tuple); + + heap_freetuple(tuple); + + myself.classId = StorageUserMappingRelationId; + myself.objectId = umId; + myself.objectSubId = 0; + + recordStorageServerDependency(StorageUserMappingRelationId, umId, srv->serverid); + + if (OidIsValid(useId)) + { + /* Record the mapped user dependency */ + recordDependencyOnOwner(StorageUserMappingRelationId, umId, useId); + } + + /* + * Perhaps someday there should be a recordDependencyOnCurrentExtension + * call here; but since roles aren't members of extensions, it seems like + * storage user mappings shouldn't be either. Note that the grammar and pg_dump + * would need to be extended too if we change this. + */ + + /* Post creation hook for new storage user mapping */ + InvokeObjectPostCreateHook(StorageUserMappingRelationId, umId, 0); + + if (Gp_role == GP_ROLE_DISPATCH) + { + CdbDispatchUtilityStatement((Node *) stmt, + DF_WITH_SNAPSHOT | DF_CANCEL_ON_ERROR | DF_NEED_TWO_PHASE, + GetAssignedOidsForDispatch(), + NULL); + } + + table_close(rel, RowExclusiveLock); + + return myself; +} + +/* + * Alter storage user mapping + */ +ObjectAddress +AlterStorageUserMapping(AlterStorageUserMappingStmt *stmt) +{ + Relation rel; + HeapTuple tp; + Datum repl_val[Natts_gp_storage_user_mapping]; + bool repl_null[Natts_gp_storage_user_mapping]; + bool repl_repl[Natts_gp_storage_user_mapping]; + Oid useId; + Oid umId; + StorageServer *srv; + ObjectAddress address; + RoleSpec *role = (RoleSpec *) stmt->user; + + rel = table_open(StorageUserMappingRelationId, RowExclusiveLock); + + if (role->roletype == ROLESPEC_PUBLIC) + useId = ACL_ID_PUBLIC; + else + useId = get_rolespec_oid(stmt->user, false); + + srv = GetStorageServerByName(stmt->servername, false); + + umId = GetSysCacheOid2(STORAGEUSERMAPPINGUSERSERVER, Anum_gp_storage_user_mapping_oid, + ObjectIdGetDatum(useId), + ObjectIdGetDatum(srv->serverid)); + + if (!OidIsValid(umId)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("storage user mapping for \"%s\" does not exist for server \"%s\"", + StorageMappingUserName(useId), stmt->servername))); + + storage_user_mapping_ddl_aclcheck(useId, srv->serverid, stmt->servername); + + tp = SearchSysCacheCopy1(STORAGEUSERMAPPINGOID, ObjectIdGetDatum(umId)); + + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for storage user mapping %u", umId); + + memset(repl_val, 0, sizeof(repl_val)); + memset(repl_null, false, sizeof(repl_null)); + memset(repl_repl, false, sizeof(repl_repl)); + + if (stmt->options) + { + Datum datum; + bool isnull; + + /* + * Process the options. + */ + datum = SysCacheGetAttr(STORAGEUSERMAPPINGUSERSERVER, + tp, + Anum_gp_storage_user_mapping_umoptions, + &isnull); + + if (isnull) + datum = PointerGetDatum(NULL); + + /* Prepare the options array */ + datum = transformStorageGenericOptions(StorageUserMappingRelationId, + datum, + stmt->options); + + if (PointerIsValid(DatumGetPointer(datum))) + repl_val[Anum_gp_storage_user_mapping_umoptions - 1] = datum; + else + repl_null[Anum_gp_storage_user_mapping_umoptions - 1] = true; + + repl_repl[Anum_gp_storage_user_mapping_umoptions - 1] = true; + } + + /* Everything looks good - update the tuple */ + tp = heap_modify_tuple(tp, RelationGetDescr(rel), + repl_val, repl_null, repl_repl); + + CatalogTupleUpdate(rel, &tp->t_self, tp); + + InvokeObjectPostAlterHook(StorageUserMappingRelationId, + umId, 0); + + ObjectAddressSet(address, StorageUserMappingRelationId, umId); + + heap_freetuple(tp); + + if (Gp_role == GP_ROLE_DISPATCH) + { + CdbDispatchUtilityStatement((Node *) stmt, + DF_WITH_SNAPSHOT | DF_CANCEL_ON_ERROR | DF_NEED_TWO_PHASE, + GetAssignedOidsForDispatch(), + NULL); + } + + table_close(rel, RowExclusiveLock); + + return address; +} + +/* + * Drop storage user mapping + */ +Oid +RemoveStorageUserMapping(DropStorageUserMappingStmt *stmt) +{ + Oid useId; + Oid umId; + StorageServer *srv; + RoleSpec *role = (RoleSpec *) stmt->user; + Relation gp_storage_user_mapping_rel; + ScanKeyData scankey; + SysScanDesc sscan; + HeapTuple tuple; + + if (role->roletype == ROLESPEC_PUBLIC) + useId = ACL_ID_PUBLIC; + else + { + useId = get_rolespec_oid(stmt->user, stmt->missing_ok); + if (!OidIsValid(useId)) + { + /* + * IF EXISTS specified, role not found and not public. Notice this + * and leave. + */ + elog(NOTICE, "role \"%s\" does not exist, skipping", + role->rolename); + return InvalidOid; + } + } + + srv = GetStorageServerByName(stmt->servername, true); + + if (!srv) + { + if (!stmt->missing_ok) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("storage server \"%s\" does not exist", + stmt->servername))); + /* IF EXISTS, just note it */ + ereport(NOTICE, + (errmsg("storage server \"%s\" does not exist, skipping", + stmt->servername))); + return InvalidOid; + } + + umId = GetSysCacheOid2(STORAGEUSERMAPPINGUSERSERVER, Anum_gp_storage_user_mapping_oid, + ObjectIdGetDatum(useId), + ObjectIdGetDatum(srv->serverid)); + + if (!OidIsValid(umId)) + { + if (!stmt->missing_ok) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("storage user mapping for \"%s\" does not exist for storage server \"%s\"", + StorageMappingUserName(useId), stmt->servername))); + + /* IF EXISTS specified, just note it */ + ereport(NOTICE, + (errmsg("storage user mapping for \"%s\" does not exist for storage server \"%s\", skipping", + StorageMappingUserName(useId), stmt->servername))); + return InvalidOid; + } + + storage_user_mapping_ddl_aclcheck(useId, srv->serverid, srv->servername); + + gp_storage_user_mapping_rel = table_open(StorageUserMappingRelationId, RowExclusiveLock); + + ScanKeyInit(&scankey, + Anum_gp_storage_user_mapping_oid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(umId)); + sscan = systable_beginscan(gp_storage_user_mapping_rel, InvalidOid, + false, NULL, 1, &scankey); + + tuple = systable_getnext(sscan); + if (!HeapTupleIsValid(tuple)) + { + if (!stmt->missing_ok) + { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("role \"%s\" does not exist", role->rolename))); + } + if (Gp_role != GP_ROLE_EXECUTE) + { + ereport(NOTICE, + (errmsg("role \"%s\" does not exist, skipping", + role->rolename))); + } + } + + CatalogTupleDelete(gp_storage_user_mapping_rel, &tuple->t_self); + + systable_endscan(sscan); + table_close(gp_storage_user_mapping_rel, RowExclusiveLock); + + /* DROP hook for the role being removed */ + InvokeObjectDropHook(StorageUserMappingRelationId, umId, 0); + + /* + * Delete shared dependency references related to this role object. + */ + deleteSharedDependencyRecordsFor(StorageUserMappingRelationId, umId, 0); + + if (Gp_role == GP_ROLE_DISPATCH) + { + CdbDispatchUtilityStatement((Node *) stmt, + DF_WITH_SNAPSHOT | DF_CANCEL_ON_ERROR | DF_NEED_TWO_PHASE, + GetAssignedOidsForDispatch(), + NULL); + } + return umId; +} diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index bfbfd36c904..d4041864640 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -43,6 +43,7 @@ #include "catalog/pg_compression.h" #include "catalog/pg_constraint.h" #include "catalog/pg_depend.h" +#include "catalog/pg_directory_table.h" #include "catalog/pg_foreign_table.h" #include "catalog/pg_inherits.h" #include "catalog/pg_namespace.h" @@ -186,6 +187,12 @@ static const struct dropmsgstrings dropmsgstringarray[] = { gettext_noop("table \"%s\" does not exist, skipping"), gettext_noop("\"%s\" is not a table"), gettext_noop("Use DROP TABLE to remove a table.")}, + {RELKIND_DIRECTORY_TABLE, + ERRCODE_UNDEFINED_TABLE, + gettext_noop("directory table \"%s\" does not exist"), + gettext_noop("directory table \"%s\" does not exist, skipping"), + gettext_noop("\"%s\" is not a directory table"), + gettext_noop("Use DROP DIRECTORY TABLE to remove a directory table.")}, {RELKIND_SEQUENCE, ERRCODE_UNDEFINED_TABLE, gettext_noop("sequence \"%s\" does not exist"), @@ -259,6 +266,7 @@ struct DropRelationCallbackState #define ATT_COMPOSITE_TYPE 0x0010 #define ATT_FOREIGN_TABLE 0x0020 #define ATT_PARTITIONED_INDEX 0x0040 +#define ATT_DIRECTORY_TABLE 0x0080 /* * ForeignTruncateInfo @@ -629,17 +637,25 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, */ schema = NIL; cooked_constraints = NIL; - foreach(listptr, stmt->tableElts) + if (relkind == RELKIND_DIRECTORY_TABLE) { - Node *node = lfirst(listptr); - - if (IsA(node, CookedConstraint)) + schema = GetDirectoryTableSchema(); + stmt->distributedBy = GetDirectoryTableDistributedBy(); + } + else + { + foreach(listptr, stmt->tableElts) { - Assert(Gp_role == GP_ROLE_EXECUTE); - cooked_constraints = lappend(cooked_constraints, node); + Node *node = lfirst(listptr); + + if (IsA(node, CookedConstraint)) + { + Assert(Gp_role == GP_ROLE_EXECUTE); + cooked_constraints = lappend(cooked_constraints, node); + } + else + schema = lappend(schema, node); } - else - schema = lappend(schema, node); } /* @@ -733,6 +749,12 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, inheritOids = lappend_oid(inheritOids, parentOid); } + /* + * Directory table never has partitions. + */ + AssertImply(relkind == RELKIND_DIRECTORY_TABLE, !partitioned); + AssertImply(relkind == RELKIND_DIRECTORY_TABLE, !stmt->inhRelations); + /* * Select tablespace to use: an explicitly indicated one, or (in the case * of a partitioned table) the parent's, if it has one. @@ -803,7 +825,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, * If the statement hasn't specified an access method, but we're defining * a type of relation that needs one, use the default. */ - if (stmt->accessMethod != NULL) + if (stmt->accessMethod != NULL && relkind != RELKIND_DIRECTORY_TABLE) { accessMethod = stmt->accessMethod; @@ -813,6 +835,8 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, errmsg("specifying a table access method is not supported on a partitioned table"))); } + else if (relkind == RELKIND_DIRECTORY_TABLE) + accessMethod = DEFAULT_TABLE_ACCESS_METHOD; else if (relkind == RELKIND_RELATION || relkind == RELKIND_TOASTVALUE || relkind == RELKIND_MATVIEW) @@ -838,7 +862,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, */ if (AMHandlerIsAO(amHandlerOid)) { - Assert(relkind == RELKIND_MATVIEW || relkind == RELKIND_RELATION ); + Assert(relkind == RELKIND_MATVIEW || relkind == RELKIND_RELATION || relkind == RELKIND_DIRECTORY_TABLE); /* * Extract and process any WITH options supplied, otherwise use defaults @@ -1021,7 +1045,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, * This is done in dispatcher (and in utility mode). In QE, we receive * the already-processed options from the QD. */ - if ((relkind == RELKIND_RELATION || relkind == RELKIND_MATVIEW) && + if ((relkind == RELKIND_RELATION || relkind == RELKIND_MATVIEW || relkind == RELKIND_DIRECTORY_TABLE) && Gp_role != GP_ROLE_EXECUTE) { const TableAmRoutine *tam = GetTableAmRoutineByAmId(accessMethodId); @@ -1152,6 +1176,11 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, */ rel = relation_open(relationId, AccessExclusiveLock); + if (relkind == RELKIND_DIRECTORY_TABLE) + { + CreateDirectoryTableIndex(rel); + } + /* * If this is an append-only relation, create the auxliary tables necessary */ @@ -1645,6 +1674,8 @@ RemoveRelations(DropStmt *drop) ListCell *cell; int flags = 0; LOCKMODE lockmode = AccessExclusiveLock; + HeapTuple indexTuple; + Form_pg_index index; /* DROP CONCURRENTLY uses a weaker lock, and has some restrictions */ if (drop->concurrent) @@ -1699,6 +1730,10 @@ RemoveRelations(DropStmt *drop) relkind = RELKIND_FOREIGN_TABLE; break; + case OBJECT_DIRECTORY_TABLE: + relkind = RELKIND_DIRECTORY_TABLE; + break; + default: elog(ERROR, "unrecognized drop object type: %d", (int) drop->removeType); @@ -1747,6 +1782,23 @@ RemoveRelations(DropStmt *drop) continue; } + if (relkind == RELKIND_INDEX) + { + indexTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(relOid)); + if (!HeapTupleIsValid(indexTuple) && !drop->missing_ok) /* should not happen */ + elog(ERROR, "cache lookup failed for index %u", relOid); + if (HeapTupleIsValid(indexTuple)) + { + index = (Form_pg_index) GETSTRUCT(indexTuple); + if (RelationIsDirectoryTable(index->indrelid)) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Disallowed to drop index \"%s\" on directory table \"%s\"", + get_rel_name(index->indexrelid), get_rel_name(index->indrelid)))); + ReleaseSysCache(indexTuple); + } + } + /* * Decide if concurrent mode needs to be used here or not. The * callback retrieved the rel's persistence for us. @@ -2590,6 +2642,13 @@ truncate_check_rel(Oid relid, Form_pg_class reltuple) errmsg("cannot truncate foreign table \"%s\"", relname))); } + else if (reltuple->relkind == RELKIND_DIRECTORY_TABLE) + { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot truncate directory table \"%s\"", + relname))); + } else if (reltuple->relkind != RELKIND_RELATION && reltuple->relkind != RELKIND_PARTITIONED_TABLE && (!IsBinaryUpgrade || ( @@ -4262,6 +4321,11 @@ RenameRelation(RenameStmt *stmt) * if we already acquired AccessExclusiveLock with an index, however. */ relkind = get_rel_relkind(relid); + if (relkind == RELKIND_DIRECTORY_TABLE) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("Rename directory table is not allowed."))); + obj_is_index = (relkind == RELKIND_INDEX || relkind == RELKIND_PARTITIONED_INDEX); if (obj_is_index || is_index_stmt == obj_is_index) @@ -5181,7 +5245,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, pass = AT_PASS_DROP; break; case AT_SetStatistics: /* ALTER COLUMN SET STATISTICS */ - ATSimplePermissions(rel, ATT_TABLE | ATT_MATVIEW | ATT_INDEX | ATT_PARTITIONED_INDEX | ATT_FOREIGN_TABLE); + ATSimplePermissions(rel, ATT_TABLE | ATT_MATVIEW | ATT_INDEX | ATT_PARTITIONED_INDEX | ATT_FOREIGN_TABLE | ATT_DIRECTORY_TABLE); ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context); /* No command-specific prep needed */ pass = AT_PASS_MISC; @@ -5214,7 +5278,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, pass = AT_PASS_DROP; break; case AT_AddIndex: /* ADD INDEX */ - ATSimplePermissions(rel, ATT_TABLE); + ATSimplePermissions(rel, ATT_TABLE | ATT_DIRECTORY_TABLE); /* This command never recurses */ /* No command-specific prep needed */ pass = AT_PASS_ADD_INDEX; @@ -5341,7 +5405,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, pass = AT_PASS_MISC; break; } - ATSimplePermissions(rel, ATT_TABLE); + ATSimplePermissions(rel, ATT_TABLE | ATT_DIRECTORY_TABLE); if (!recursing) /* MPP-5772, MPP-5784 */ { @@ -5517,7 +5581,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, case AT_DisableTrig: /* DISABLE TRIGGER variants */ case AT_DisableTrigAll: case AT_DisableTrigUser: - ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE); + ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE | ATT_DIRECTORY_TABLE); if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context); pass = AT_PASS_MISC; @@ -5532,7 +5596,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, case AT_DisableRowSecurity: case AT_ForceRowSecurity: case AT_NoForceRowSecurity: - ATSimplePermissions(rel, ATT_TABLE); + ATSimplePermissions(rel, ATT_TABLE | ATT_DIRECTORY_TABLE); /* These commands never recurse */ /* No command-specific prep needed */ pass = AT_PASS_MISC; @@ -7399,6 +7463,9 @@ ATSimplePermissions(Relation rel, int allowed_targets) case RELKIND_FOREIGN_TABLE: actual_target = ATT_FOREIGN_TABLE; break; + case RELKIND_DIRECTORY_TABLE: + actual_target = ATT_DIRECTORY_TABLE; + break; case RELKIND_AOSEGMENTS: case RELKIND_AOBLOCKDIR: @@ -7468,7 +7535,7 @@ ATWrongRelkindError(Relation rel, int allowed_targets) case ATT_TABLE | ATT_MATVIEW | ATT_INDEX | ATT_PARTITIONED_INDEX: msg = _("\"%s\" is not a table, materialized view, index, or partitioned index"); break; - case ATT_TABLE | ATT_MATVIEW | ATT_INDEX | ATT_PARTITIONED_INDEX | ATT_FOREIGN_TABLE: + case ATT_TABLE | ATT_MATVIEW | ATT_INDEX | ATT_PARTITIONED_INDEX | ATT_FOREIGN_TABLE | ATT_DIRECTORY_TABLE: msg = _("\"%s\" is not a table, materialized view, index, partitioned index, or foreign table"); break; case ATT_TABLE | ATT_MATVIEW | ATT_FOREIGN_TABLE: @@ -7492,6 +7559,15 @@ ATWrongRelkindError(Relation rel, int allowed_targets) case ATT_FOREIGN_TABLE: msg = _("\"%s\" is not a foreign table"); break; + case ATT_TABLE | ATT_DIRECTORY_TABLE: + msg = _("\"%s\" is not a table or directory table"); + break; + case ATT_TABLE | ATT_FOREIGN_TABLE | ATT_DIRECTORY_TABLE: + msg = _("\"%s\" is not a table, foreign table, or directory table"); + break; + case ATT_DIRECTORY_TABLE: + msg = _("\"%s\" is not a directory table"); + break; default: /* shouldn't get here, add all necessary cases above */ msg = _("\"%s\" is of the wrong type"); @@ -14037,6 +14113,8 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, case OCLASS_TASK: case OCLASS_PROFILE: case OCLASS_PASSWORDHISTORY: + case OCLASS_STORAGE_SERVER: + case OCLASS_STORAGE_USER_MAPPING: /* * We don't expect any of these sorts of objects to depend on @@ -15117,6 +15195,7 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock case RELKIND_MATVIEW: case RELKIND_FOREIGN_TABLE: case RELKIND_PARTITIONED_TABLE: + case RELKIND_DIRECTORY_TABLE: /* ok to change owner */ break; case RELKIND_INDEX: @@ -15292,6 +15371,7 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock tuple_class->relkind == RELKIND_PARTITIONED_TABLE || tuple_class->relkind == RELKIND_MATVIEW || tuple_class->relkind == RELKIND_TOASTVALUE || + tuple_class->relkind == RELKIND_DIRECTORY_TABLE || tuple_class->relnamespace == PG_EXTAUX_NAMESPACE || IsAppendonlyMetadataRelkind(tuple_class->relkind)) { @@ -18515,6 +18595,7 @@ ATExecSetDistributedBy(Relation rel, Node *node, AlterTableCmd *cmd) ldistro = make_distributedby_for_rel(rel); if (rel->rd_rel->relkind == RELKIND_RELATION || + rel->rd_rel->relkind == RELKIND_DIRECTORY_TABLE || rel->rd_rel->relkind == RELKIND_MATVIEW) { need_reorg = true; @@ -19709,6 +19790,7 @@ AlterTableNamespaceInternal(Relation rel, Oid oldNspOid, Oid nspOid, /* Fix other dependent stuff */ if (rel->rd_rel->relkind == RELKIND_RELATION || + rel->rd_rel->relkind == RELKIND_DIRECTORY_TABLE || rel->rd_rel->relkind == RELKIND_MATVIEW || rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) { @@ -20183,10 +20265,11 @@ RangeVarCallbackOwnsTable(const RangeVar *relation, if (!relkind) return; if (relkind != RELKIND_RELATION && relkind != RELKIND_TOASTVALUE && - relkind != RELKIND_MATVIEW && relkind != RELKIND_PARTITIONED_TABLE) + relkind != RELKIND_MATVIEW && relkind != RELKIND_PARTITIONED_TABLE && + relkind != RELKIND_DIRECTORY_TABLE) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("\"%s\" is not a table or materialized view", relation->relname))); + errmsg("\"%s\" is not a table, directory table or materialized view", relation->relname))); /* Check permissions */ if (!pg_class_ownercheck(relId, GetUserId())) @@ -20338,6 +20421,11 @@ RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("\"%s\" is not a composite type", rv->relname))); + if (reltype == OBJECT_DIRECTORY_TABLE && relkind != RELKIND_DIRECTORY_TABLE) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not a directory table", rv->relname))); + if (reltype == OBJECT_INDEX && relkind != RELKIND_INDEX && relkind != RELKIND_PARTITIONED_INDEX && !IsA(stmt, RenameStmt)) @@ -20361,6 +20449,7 @@ RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid, */ if (IsA(stmt, AlterObjectSchemaStmt) && relkind != RELKIND_RELATION && + relkind != RELKIND_DIRECTORY_TABLE && relkind != RELKIND_VIEW && relkind != RELKIND_MATVIEW && relkind != RELKIND_SEQUENCE && @@ -20368,7 +20457,7 @@ RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid, relkind != RELKIND_PARTITIONED_TABLE) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("\"%s\" is not a table, view, materialized view, sequence, or foreign table", + errmsg("\"%s\" is not a table, directory table, view, materialized view, sequence, or foreign table", rv->relname))); ReleaseSysCache(tuple); diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c index 811a2c17ab7..e5c53e7180b 100644 --- a/src/backend/commands/tablespace.c +++ b/src/backend/commands/tablespace.c @@ -83,6 +83,7 @@ #include "commands/tablespace.h" #include "common/file_perm.h" #include "miscadmin.h" +#include "parser/parse_func.h" #include "postmaster/bgwriter.h" #include "storage/bufmgr.h" #include "storage/fd.h" @@ -269,6 +270,7 @@ CreateTableSpace(CreateTableSpaceStmt *stmt) Oid ownerId; Datum newOptions; List *nonContentOptions = NIL; + char *fileHandler = NULL; /* Must be super user */ if (!superuser()) @@ -324,6 +326,9 @@ CreateTableSpace(CreateTableSpaceStmt *stmt) if (!location) location = pstrdup(stmt->location); + if (stmt->filehandler) + fileHandler = pstrdup(stmt->filehandler); + /* Unix-ify the offered path, and strip any trailing slashes */ canonicalize_path(location); @@ -420,6 +425,26 @@ CreateTableSpace(CreateTableSpaceStmt *stmt) ObjectIdGetDatum(ownerId); nulls[Anum_pg_tablespace_spcacl - 1] = true; + if (fileHandler) + { + List *fileHandler_list; + char *spcfilehandlerbin = NULL; + char *spcfilehandlersrc = NULL; + + SplitIdentifierString(fileHandler, ',', &fileHandler_list); + + spcfilehandlerbin = (char *) linitial(fileHandler_list); + spcfilehandlersrc = (char *) lsecond(fileHandler_list); + + values[Anum_pg_tablespace_spcfilehandlerbin - 1] = CStringGetTextDatum(spcfilehandlerbin); + values[Anum_pg_tablespace_spcfilehandlersrc - 1] = CStringGetTextDatum(spcfilehandlersrc); + } + else + { + nulls[Anum_pg_tablespace_spcfilehandlersrc - 1] = true; + nulls[Anum_pg_tablespace_spcfilehandlerbin - 1] = true; + } + /* Generate new proposed spcoptions (text array) */ newOptions = transformRelOptions((Datum) 0, nonContentOptions, diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index f60aa299fc0..147d724df3d 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -210,7 +210,8 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString, * Triggers must be on tables or views, and there are additional * relation-type-specific restrictions. */ - if (rel->rd_rel->relkind == RELKIND_RELATION) + if (rel->rd_rel->relkind == RELKIND_RELATION || + rel->rd_rel->relkind == RELKIND_DIRECTORY_TABLE) { /* Tables can't have INSTEAD OF triggers */ if (stmt->timing != TRIGGER_TYPE_BEFORE && @@ -1353,6 +1354,7 @@ RemoveTriggerById(Oid trigOid) rel = table_open(relid, AccessExclusiveLock); if (rel->rd_rel->relkind != RELKIND_RELATION && + rel->rd_rel->relkind != RELKIND_DIRECTORY_TABLE && rel->rd_rel->relkind != RELKIND_VIEW && rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE && rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE) @@ -1460,11 +1462,12 @@ RangeVarCallbackForRenameTrigger(const RangeVar *rv, Oid relid, Oid oldrelid, /* only tables and views can have triggers */ if (form->relkind != RELKIND_RELATION && form->relkind != RELKIND_VIEW && + form->relkind != RELKIND_DIRECTORY_TABLE && form->relkind != RELKIND_FOREIGN_TABLE && form->relkind != RELKIND_PARTITIONED_TABLE) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("\"%s\" is not a table, view, or foreign table", + errmsg("\"%s\" is not a table, directory table, view, or foreign table", rv->relname))); /* you must own the table to rename one of its triggers */ diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 0d5f405fee6..7877659072b 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -1130,6 +1130,7 @@ get_all_vacuum_rels(int options) * them. */ if (classForm->relkind != RELKIND_RELATION && + classForm->relkind != RELKIND_DIRECTORY_TABLE && classForm->relkind != RELKIND_MATVIEW && classForm->relkind != RELKIND_PARTITIONED_TABLE) continue; @@ -1852,6 +1853,7 @@ vac_update_datfrozenxid(void) * should have InvalidTransactionId in relfrozenxid anyway). */ if (classForm->relkind != RELKIND_RELATION && + classForm->relkind != RELKIND_DIRECTORY_TABLE && classForm->relkind != RELKIND_MATVIEW && classForm->relkind != RELKIND_TOASTVALUE && classForm->relkind != RELKIND_AOSEGMENTS && @@ -2298,6 +2300,7 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params, * Check that it's of a vacuumable relkind. */ if (rel->rd_rel->relkind != RELKIND_RELATION && + rel->rd_rel->relkind != RELKIND_DIRECTORY_TABLE && rel->rd_rel->relkind != RELKIND_MATVIEW && rel->rd_rel->relkind != RELKIND_TOASTVALUE && rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE && @@ -2457,6 +2460,7 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params, */ if ((rel->rd_rel->relkind != RELKIND_RELATION && rel->rd_rel->relkind != RELKIND_MATVIEW && + rel->rd_rel->relkind != RELKIND_DIRECTORY_TABLE && rel->rd_rel->relkind != RELKIND_TOASTVALUE && rel->rd_rel->relkind != RELKIND_AOSEGMENTS && rel->rd_rel->relkind != RELKIND_AOBLOCKDIR && @@ -2558,6 +2562,7 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params, if (has_bitmap) LockRelation(rel, ShareLock); } + /* TODO: vacuum directory table's temp files */ if (!is_appendoptimized && (params->options & VACOPT_FULL)) { diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 189a6c9e31d..bdff0e8edd1 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -59,6 +59,7 @@ #include "jit/jit.h" #include "mb/pg_wchar.h" #include "miscadmin.h" +#include "nodes/plannodes.h" #include "parser/parsetree.h" #include "storage/bufmgr.h" #include "storage/lmgr.h" @@ -88,6 +89,7 @@ #include "catalog/pg_tablespace.h" #include "catalog/catalog.h" #include "catalog/oid_dispatch.h" +#include "catalog/pg_directory_table.h" #include "catalog/pg_type.h" #include "commands/copy.h" #include "commands/createas.h" @@ -1926,11 +1928,15 @@ InitPlan(QueryDesc *queryDesc, int eflags) * CheckValidRowMarkRel. */ void -CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation) +CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation, ModifyTableState *mtstate) { Relation resultRel = resultRelInfo->ri_RelationDesc; TriggerDesc *trigDesc = resultRel->trigdesc; FdwRoutine *fdwroutine; + ModifyTable *node; + int whichrel; + List *updateColnos; + ListCell *lc; switch (resultRel->rd_rel->relkind) { @@ -2088,6 +2094,40 @@ CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation) errmsg("cannot change AO visibility map relation \"%s\"", RelationGetRelationName(resultRel)))); break; + case RELKIND_DIRECTORY_TABLE: + switch(operation) + { + case CMD_INSERT: + case CMD_DELETE: + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("cannot change directory table \"%s\"", + RelationGetRelationName(resultRel)))); + break; + case CMD_UPDATE: + if (mtstate) + { + node = (ModifyTable *) mtstate->ps.plan; + whichrel = mtstate->mt_lastResultIndex; + + updateColnos = (List *) list_nth(node->updateColnosLists, whichrel); + + foreach(lc, updateColnos) + { + AttrNumber targetattnum = lfirst_int(lc); + + if (targetattnum != DIRECTORY_TABLE_TAG_COLUMN_ATTNUM) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("Only allow to update directory \"tag\" column."))); + } + } + break; + default: + elog(ERROR, "unrecognized CmdType: %d", (int) operation); + break; + } + break; default: ereport(ERROR, @@ -2153,6 +2193,14 @@ CheckValidRowMarkRel(Relation rel, RowMarkType markType) errmsg("cannot lock rows in foreign table \"%s\"", RelationGetRelationName(rel)))); break; + case RELKIND_DIRECTORY_TABLE: + /* Allow referencing a directory table, but not actual locking clauses */ + if (markType != ROW_MARK_REFERENCE) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("cannot lock rows in directory table \"%s\"", + RelationGetRelationName(rel)))); + break; default: ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c index fc2b4adb1f7..c8241f7ed64 100644 --- a/src/backend/executor/execPartition.c +++ b/src/backend/executor/execPartition.c @@ -360,7 +360,7 @@ ExecFindPartition(ModifyTableState *mtstate, if (rri) { /* Verify this ResultRelInfo allows INSERTs */ - CheckValidResultRel(rri, CMD_INSERT); + CheckValidResultRel(rri, CMD_INSERT, NULL); /* * Initialize information needed to insert this and @@ -526,7 +526,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate, * partition-key becomes a DELETE+INSERT operation, so this check is still * required when the operation is CMD_UPDATE. */ - CheckValidResultRel(leaf_part_rri, CMD_INSERT); + CheckValidResultRel(leaf_part_rri, CMD_INSERT, NULL); /* * Open partition indices. The user may have asked to check for conflicts diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index 0e76ca1f710..5ae87f1644a 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -2651,6 +2651,7 @@ ExecModifyTable(PlanState *pstate) relkind = resultRelInfo->ri_RelationDesc->rd_rel->relkind; if (relkind == RELKIND_RELATION || + relkind == RELKIND_DIRECTORY_TABLE || relkind == RELKIND_MATVIEW || relkind == RELKIND_PARTITIONED_TABLE) { @@ -3068,7 +3069,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) /* * Verify result relation is a valid target for the current operation */ - CheckValidResultRel(resultRelInfo, operation); + CheckValidResultRel(resultRelInfo, operation, mtstate); if (RelationIsAoRows(resultRelInfo->ri_RelationDesc)) appendonly_dml_init(resultRelInfo->ri_RelationDesc, operation); @@ -3131,6 +3132,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) relkind = resultRelInfo->ri_RelationDesc->rd_rel->relkind; if (relkind == RELKIND_RELATION || + relkind == RELKIND_DIRECTORY_TABLE || relkind == RELKIND_MATVIEW || relkind == RELKIND_PARTITIONED_TABLE) { diff --git a/src/backend/gpopt/gpdbwrappers.cpp b/src/backend/gpopt/gpdbwrappers.cpp index 16a0f060817..da5e774032a 100644 --- a/src/backend/gpopt/gpdbwrappers.cpp +++ b/src/backend/gpopt/gpdbwrappers.cpp @@ -66,7 +66,7 @@ using namespace gpos; void debug_gpos_assert(const char *filename, long line, const char *msg) { - elog(LOG, "[debug_gpos_assert]: '%s':%ld %s", filename, line, msg); + elog(DEBUG1, "[debug_gpos_assert]: '%s':%ld %s", filename, line, msg); } bool diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index cd5c0cadb7b..7fe3e7d0836 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -4089,6 +4089,7 @@ _copyCopyStmt(const CopyStmt *from) COPY_SCALAR_FIELD(is_from); COPY_SCALAR_FIELD(is_program); COPY_STRING_FIELD(filename); + COPY_STRING_FIELD(dirfilename); COPY_NODE_FIELD(options); COPY_NODE_FIELD(whereClause); COPY_NODE_FIELD(sreh); @@ -4870,6 +4871,7 @@ _copyCreateTableSpaceStmt(const CreateTableSpaceStmt *from) COPY_NODE_FIELD(owner); COPY_STRING_FIELD(location); COPY_NODE_FIELD(options); + COPY_STRING_FIELD(filehandler); return newnode; } @@ -5001,6 +5003,40 @@ _copyAlterForeignServerStmt(const AlterForeignServerStmt *from) return newnode; } +static CreateStorageServerStmt * +_copyCreateStorageServerStmt(const CreateStorageServerStmt *from) +{ + CreateStorageServerStmt *newnode = makeNode(CreateStorageServerStmt); + + COPY_STRING_FIELD(servername); + COPY_SCALAR_FIELD(if_not_exists); + COPY_NODE_FIELD(options); + + return newnode; +} + +static AlterStorageServerStmt * +_copyAlterStorageServerStmt(const AlterStorageServerStmt *from) +{ + AlterStorageServerStmt *newnode = makeNode(AlterStorageServerStmt); + + COPY_STRING_FIELD(servername); + COPY_NODE_FIELD(options); + + return newnode; +} + +static DropStorageServerStmt * +_copyDropStorageServerStmt(const DropStorageServerStmt *from) +{ + DropStorageServerStmt *newnode = makeNode(DropStorageServerStmt); + + COPY_STRING_FIELD(servername); + COPY_SCALAR_FIELD(missing_ok); + + return newnode; +} + static CreateUserMappingStmt * _copyCreateUserMappingStmt(const CreateUserMappingStmt *from) { @@ -5038,6 +5074,43 @@ _copyDropUserMappingStmt(const DropUserMappingStmt *from) return newnode; } +static CreateStorageUserMappingStmt * +_copyCreateStorageUserMappingStmt(const CreateStorageUserMappingStmt *from) +{ + CreateStorageUserMappingStmt *newnode = makeNode(CreateStorageUserMappingStmt); + + COPY_NODE_FIELD(user); + COPY_STRING_FIELD(servername); + COPY_SCALAR_FIELD(if_not_exists); + COPY_NODE_FIELD(options); + + return newnode; +} + +static AlterStorageUserMappingStmt * +_copyAlterStorageUserMappingStmt(const AlterStorageUserMappingStmt *from) +{ + AlterStorageUserMappingStmt *newnode = makeNode(AlterStorageUserMappingStmt); + + COPY_NODE_FIELD(user); + COPY_STRING_FIELD(servername); + COPY_NODE_FIELD(options); + + return newnode; +} + +static DropStorageUserMappingStmt * +_copyDropStorageUserMappingStmt(const DropStorageUserMappingStmt *from) +{ + DropStorageUserMappingStmt *newnode = makeNode(DropStorageUserMappingStmt); + + COPY_NODE_FIELD(user); + COPY_STRING_FIELD(servername); + COPY_SCALAR_FIELD(missing_ok); + + return newnode; +} + static CreateForeignTableStmt * _copyCreateForeignTableStmt(const CreateForeignTableStmt *from) { @@ -6027,6 +6100,18 @@ _copyAlteredTableInfo(const AlteredTableInfo *from) return newnode; } +static CreateDirectoryTableStmt * +_copyCreateDirectoryTableStmt(const CreateDirectoryTableStmt *from) +{ + CreateDirectoryTableStmt *newnode = makeNode(CreateDirectoryTableStmt); + + CopyCreateStmtFields((const CreateStmt *) from, (CreateStmt *) newnode); + + COPY_STRING_FIELD(tablespacename); + + return newnode; +} + static EphemeralNamedRelationInfo* _copyEphemeralNamedRelationInfo(const EphemeralNamedRelationInfo *from) { @@ -6771,6 +6856,15 @@ copyObjectImpl(const void *from) case T_AlterForeignServerStmt: retval = _copyAlterForeignServerStmt(from); break; + case T_CreateStorageServerStmt: + retval = _copyCreateStorageServerStmt(from); + break; + case T_AlterStorageServerStmt: + retval = _copyAlterStorageServerStmt(from); + break; + case T_DropStorageServerStmt: + retval = _copyDropStorageServerStmt(from); + break; case T_CreateUserMappingStmt: retval = _copyCreateUserMappingStmt(from); break; @@ -6780,6 +6874,15 @@ copyObjectImpl(const void *from) case T_DropUserMappingStmt: retval = _copyDropUserMappingStmt(from); break; + case T_CreateStorageUserMappingStmt: + retval = _copyCreateStorageUserMappingStmt(from); + break; + case T_AlterStorageUserMappingStmt: + retval = _copyAlterStorageUserMappingStmt(from); + break; + case T_DropStorageUserMappingStmt: + retval = _copyDropStorageUserMappingStmt(from); + break; case T_CreateForeignTableStmt: retval = _copyCreateForeignTableStmt(from); break; @@ -7149,6 +7252,11 @@ copyObjectImpl(const void *from) case T_AlteredTableInfo: retval = _copyAlteredTableInfo(from); break; + + case T_CreateDirectoryTableStmt: + retval = _copyCreateDirectoryTableStmt(from); + break; + case T_EphemeralNamedRelationInfo: retval = _copyEphemeralNamedRelationInfo(from); break; diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index d95179fb339..283a5c5d552 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -1359,6 +1359,7 @@ _equalCopyStmt(const CopyStmt *a, const CopyStmt *b) COMPARE_SCALAR_FIELD(is_from); COMPARE_SCALAR_FIELD(is_program); COMPARE_STRING_FIELD(filename); + COMPARE_STRING_FIELD(dirfilename); COMPARE_NODE_FIELD(options); COMPARE_NODE_FIELD(whereClause); COMPARE_NODE_FIELD(sreh); @@ -2031,6 +2032,7 @@ _equalCreateTableSpaceStmt(const CreateTableSpaceStmt *a, const CreateTableSpace COMPARE_NODE_FIELD(owner); COMPARE_STRING_FIELD(location); COMPARE_NODE_FIELD(options); + COMPARE_STRING_FIELD(filehandler); return true; } @@ -2144,6 +2146,34 @@ _equalAlterForeignServerStmt(const AlterForeignServerStmt *a, const AlterForeign return true; } +static bool +_equalCreateStorageServerStmt(const CreateStorageServerStmt *a, const CreateStorageServerStmt *b) +{ + COMPARE_STRING_FIELD(servername); + COMPARE_SCALAR_FIELD(if_not_exists); + COMPARE_NODE_FIELD(options); + + return true; +} + +static bool +_equalAlterStorageServerStmt(const AlterStorageServerStmt *a, const AlterStorageServerStmt *b) +{ + COMPARE_STRING_FIELD(servername); + COMPARE_NODE_FIELD(options); + + return true; +} + +static bool +_equalDropStorageServerStmt(const DropStorageServerStmt *a, const DropStorageServerStmt *b) +{ + COMPARE_STRING_FIELD(servername); + COMPARE_SCALAR_FIELD(missing_ok); + + return true; +} + static bool _equalCreateUserMappingStmt(const CreateUserMappingStmt *a, const CreateUserMappingStmt *b) { @@ -2175,6 +2205,37 @@ _equalDropUserMappingStmt(const DropUserMappingStmt *a, const DropUserMappingStm return true; } +static bool +_equalCreateStorageUserMappingStmt(const CreateStorageUserMappingStmt *a, const CreateStorageUserMappingStmt *b) +{ + COMPARE_NODE_FIELD(user); + COMPARE_STRING_FIELD(servername); + COMPARE_SCALAR_FIELD(if_not_exists); + COMPARE_NODE_FIELD(options); + + return true; +} + +static bool +_equalAlterStorageUserMappingStmt(const AlterStorageUserMappingStmt *a, const AlterStorageUserMappingStmt *b) +{ + COMPARE_NODE_FIELD(user); + COMPARE_STRING_FIELD(servername); + COMPARE_NODE_FIELD(options); + + return true; +} + +static bool +_equalDropStorageUserMappingStmt(const DropStorageUserMappingStmt *a, const DropStorageUserMappingStmt *b) +{ + COMPARE_NODE_FIELD(user); + COMPARE_STRING_FIELD(servername); + COMPARE_SCALAR_FIELD(missing_ok); + + return true; +} + static bool _equalCreateForeignTableStmt(const CreateForeignTableStmt *a, const CreateForeignTableStmt *b) { @@ -3334,6 +3395,17 @@ _equalPartitionCmd(const PartitionCmd *a, const PartitionCmd *b) return true; } +static bool +_equalCreateDirectoryTableStmt(const CreateDirectoryTableStmt *a, const CreateDirectoryTableStmt *b) +{ + if (!_equalCreateStmt(&a->base, &b->base)) + return false; + + COMPARE_STRING_FIELD(tablespacename); + + return true; +} + /* * Stuff from pg_list.h */ @@ -3934,6 +4006,15 @@ equal(const void *a, const void *b) case T_AlterForeignServerStmt: retval = _equalAlterForeignServerStmt(a, b); break; + case T_CreateStorageServerStmt: + retval = _equalCreateStorageServerStmt(a, b); + break; + case T_AlterStorageServerStmt: + retval = _equalAlterStorageServerStmt(a, b); + break; + case T_DropStorageServerStmt: + retval = _equalDropStorageServerStmt(a, b); + break; case T_CreateUserMappingStmt: retval = _equalCreateUserMappingStmt(a, b); break; @@ -3943,6 +4024,15 @@ equal(const void *a, const void *b) case T_DropUserMappingStmt: retval = _equalDropUserMappingStmt(a, b); break; + case T_CreateStorageUserMappingStmt: + retval = _equalCreateStorageUserMappingStmt(a, b); + break; + case T_AlterStorageUserMappingStmt: + retval = _equalAlterStorageUserMappingStmt(a, b); + break; + case T_DropStorageUserMappingStmt: + retval = _equalDropStorageUserMappingStmt(a, b); + break; case T_CreateForeignTableStmt: retval = _equalCreateForeignTableStmt(a, b); break; @@ -4249,6 +4339,9 @@ equal(const void *a, const void *b) case T_DistributionKeyElem: retval = _equalDistributionKeyElem(a, b); break; + case T_CreateDirectoryTableStmt: + retval = _equalCreateDirectoryTableStmt(a, b); + break; default: elog(ERROR, "unrecognized node type: %d", diff --git a/src/backend/nodes/outfast.c b/src/backend/nodes/outfast.c index 102e8a30c90..043a2b8af6c 100644 --- a/src/backend/nodes/outfast.c +++ b/src/backend/nodes/outfast.c @@ -651,6 +651,33 @@ _outAlterForeignServerStmt(StringInfo str, AlterForeignServerStmt *node) WRITE_BOOL_FIELD(has_version); } +static void +_outCreateStorageServerStmt(StringInfo str, CreateStorageServerStmt *node) +{ + WRITE_NODE_TYPE("CREATESTORAGESERVERSTMT"); + + WRITE_STRING_FIELD(servername); + WRITE_NODE_FIELD(options); +} + +static void +_outAlterStorageServerStmt(StringInfo str, AlterStorageServerStmt *node) +{ + WRITE_NODE_TYPE("ALTERSTORAGESERVERSTMT"); + + WRITE_STRING_FIELD(servername); + WRITE_NODE_FIELD(options); +} + +static void +_outDropStorageServerStmt(StringInfo str, DropStorageServerStmt *node) +{ + WRITE_NODE_TYPE("DROPSTORAGESERVERSTMT"); + + WRITE_STRING_FIELD(servername); + WRITE_BOOL_FIELD(missing_ok); +} + static void _outCreateUserMappingStmt(StringInfo str, CreateUserMappingStmt *node) { @@ -671,6 +698,46 @@ _outAlterUserMappingStmt(StringInfo str, AlterUserMappingStmt *node) WRITE_NODE_FIELD(options); } +static void +_outDropUserMappingStmt(StringInfo str, DropUserMappingStmt *node) +{ + WRITE_NODE_TYPE("DROPUSERMAPPINGSTMT"); + + WRITE_NODE_FIELD(user); + WRITE_STRING_FIELD(servername); + WRITE_BOOL_FIELD(missing_ok); +} + +static void +_outCreateStorageUserMappingStmt(StringInfo str, CreateStorageUserMappingStmt *node) +{ + WRITE_NODE_TYPE("CREATEUSERMAPPINGSTMT"); + + WRITE_NODE_FIELD(user); + WRITE_STRING_FIELD(servername); + WRITE_NODE_FIELD(options); +} + +static void +_outAlterStorageUserMappingStmt(StringInfo str, AlterStorageUserMappingStmt *node) +{ + WRITE_NODE_TYPE("ALTERSTORAGEUSERMAPPINGSTMT"); + + WRITE_NODE_FIELD(user); + WRITE_STRING_FIELD(servername); + WRITE_NODE_FIELD(options); +} + +static void +_outDropStorageUserMappingStmt(StringInfo str, DropStorageUserMappingStmt *node) +{ + WRITE_NODE_TYPE("DROPSTORAGEUSERMAPPINGSTMT"); + + WRITE_NODE_FIELD(user); + WRITE_STRING_FIELD(servername); + WRITE_BOOL_FIELD(missing_ok); +} + static void _outAlterObjectDependsStmt(StringInfo str, const AlterObjectDependsStmt *node) { @@ -698,16 +765,6 @@ _outCustomScan(StringInfo str, const CustomScan *node) WRITE_STRING_FIELD(methods->CustomName); } -static void -_outDropUserMappingStmt(StringInfo str, DropUserMappingStmt *node) -{ - WRITE_NODE_TYPE("DROPUSERMAPPINGSTMT"); - - WRITE_NODE_FIELD(user); - WRITE_STRING_FIELD(servername); - WRITE_BOOL_FIELD(missing_ok); -} - static void _outAccessPriv(StringInfo str, AccessPriv *node) { @@ -1672,6 +1729,15 @@ _outNode(StringInfo str, void *obj) case T_CreateUserMappingStmt: _outCreateUserMappingStmt(str, obj); break; + case T_CreateStorageUserMappingStmt: + _outCreateStorageUserMappingStmt(str, obj); + break; + case T_AlterStorageUserMappingStmt: + _outAlterStorageUserMappingStmt(str, obj); + break; + case T_DropStorageUserMappingStmt: + _outDropStorageUserMappingStmt(str, obj); + break; case T_AlterForeignServerStmt: _outAlterForeignServerStmt(str, obj); break; @@ -1681,6 +1747,15 @@ _outNode(StringInfo str, void *obj) case T_AlterFdwStmt: _outAlterFdwStmt(str, obj); break; + case T_CreateStorageServerStmt: + _outCreateStorageServerStmt(str, obj); + break; + case T_AlterStorageServerStmt: + _outAlterStorageServerStmt(str, obj); + break; + case T_DropStorageServerStmt: + _outDropStorageServerStmt(str, obj); + break; case T_CreateFdwStmt: _outCreateFdwStmt(str, obj); break; @@ -1785,6 +1860,9 @@ _outNode(StringInfo str, void *obj) case T_ReturnStmt: _outReturnStmt(str, obj); break; + case T_CreateDirectoryTableStmt: + _outCreateDirectoryTableStmt(str, obj); + break; case T_EphemeralNamedRelationInfo: _outEphemeralNamedRelationInfo(str, obj); break; diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 8900df8cd9c..4d0dee54f2c 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -4022,6 +4022,15 @@ _outPartitionRangeDatum(StringInfo str, const PartitionRangeDatum *node) WRITE_LOCATION_FIELD(location); } +static void +_outCreateDirectoryTableStmt(StringInfo str, const CreateDirectoryTableStmt *node) +{ + WRITE_NODE_TYPE("CREATEDIRECTORYTABLESTMT"); + + _outCreateStmtInfo(str, (const CreateStmt *) node); + WRITE_STRING_FIELD(tablespacename); +} + #include "outfuncs_common.c" #ifndef COMPILING_BINARY_FUNCS /* @@ -5157,6 +5166,9 @@ outNode(StringInfo str, const void *obj) case T_EphemeralNamedRelationInfo: _outEphemeralNamedRelationInfo(str, obj); break; + case T_CreateDirectoryTableStmt: + _outCreateDirectoryTableStmt(str, obj); + break; default: /* diff --git a/src/backend/nodes/outfuncs_common.c b/src/backend/nodes/outfuncs_common.c index 4d42f6e21bf..76e766e55d2 100644 --- a/src/backend/nodes/outfuncs_common.c +++ b/src/backend/nodes/outfuncs_common.c @@ -209,6 +209,7 @@ _outCopyStmt(StringInfo str, const CopyStmt *node) WRITE_BOOL_FIELD(is_from); WRITE_BOOL_FIELD(is_program); WRITE_STRING_FIELD(filename); + WRITE_STRING_FIELD(dirfilename); WRITE_NODE_FIELD(options); WRITE_NODE_FIELD(sreh); } @@ -1483,6 +1484,7 @@ _outCreateTableSpaceStmt(StringInfo str, const CreateTableSpaceStmt *node) WRITE_NODE_FIELD(owner); WRITE_STRING_FIELD(location); WRITE_NODE_FIELD(options); + WRITE_STRING_FIELD(filehandler); } static void diff --git a/src/backend/nodes/readfast.c b/src/backend/nodes/readfast.c index 0faa0c40f1e..96e42bff0cd 100644 --- a/src/backend/nodes/readfast.c +++ b/src/backend/nodes/readfast.c @@ -758,6 +758,7 @@ _readCreateStmt_common(CreateStmt *local_node) local_node->relKind == RELKIND_COMPOSITE_TYPE || local_node->relKind == RELKIND_FOREIGN_TABLE || local_node->relKind == RELKIND_MATVIEW || + local_node->relKind == RELKIND_DIRECTORY_TABLE || IsAppendonlyMetadataRelkind(local_node->relKind)); Assert(local_node->oncommit <= ONCOMMIT_DROP); } @@ -818,6 +819,7 @@ _readCopyStmt(void) READ_BOOL_FIELD(is_from); READ_BOOL_FIELD(is_program); READ_STRING_FIELD(filename); + READ_STRING_FIELD(dirfilename); READ_NODE_FIELD(options); READ_NODE_FIELD(sreh); @@ -1129,6 +1131,7 @@ _readCreateTableSpaceStmt(void) READ_NODE_FIELD(owner); READ_STRING_FIELD(location); READ_NODE_FIELD(options); + READ_STRING_FIELD(filehandler); READ_DONE(); } @@ -1447,6 +1450,39 @@ _readAlterForeignServerStmt(void) READ_DONE(); } +static CreateStorageServerStmt * +_readCreateStorageServerStmt(void) +{ + READ_LOCALS(CreateStorageServerStmt); + + READ_STRING_FIELD(servername); + READ_NODE_FIELD(options); + + READ_DONE(); +} + +static AlterStorageServerStmt * +_readAlterStorageServerStmt(void) +{ + READ_LOCALS(AlterStorageServerStmt); + + READ_STRING_FIELD(servername); + READ_NODE_FIELD(options); + + READ_DONE(); +} + +static DropStorageServerStmt * +_readDropStorageServerStmt(void) +{ + READ_LOCALS(DropStorageServerStmt); + + READ_STRING_FIELD(servername); + READ_BOOL_FIELD(missing_ok); + + READ_DONE(); +} + static CreateUserMappingStmt * _readCreateUserMappingStmt(void) { @@ -1483,6 +1519,42 @@ _readDropUserMappingStmt(void) READ_DONE(); } +static CreateStorageUserMappingStmt * +_readCreateStorageUserMappingStmt(void) +{ + READ_LOCALS(CreateStorageUserMappingStmt); + + READ_NODE_FIELD(user); + READ_STRING_FIELD(servername); + READ_NODE_FIELD(options); + + READ_DONE(); +} + +static AlterStorageUserMappingStmt * +_readAlterStorageUserMappingStmt(void) +{ + READ_LOCALS(AlterStorageUserMappingStmt); + + READ_NODE_FIELD(user); + READ_STRING_FIELD(servername); + READ_NODE_FIELD(options); + + READ_DONE(); +} + +static DropStorageUserMappingStmt * +_readDropStorageUserMappingStmt(void) +{ + READ_LOCALS(DropStorageUserMappingStmt); + + READ_NODE_FIELD(user); + READ_STRING_FIELD(servername); + READ_BOOL_FIELD(missing_ok); + + READ_DONE(); +} + static AccessPriv * _readAccessPriv(void) { @@ -1642,6 +1714,18 @@ _readCreateStatsStmt(void) READ_DONE(); } +static CreateDirectoryTableStmt * +_readCreateDirectoryTableStmt(void) +{ + READ_LOCALS(CreateDirectoryTableStmt); + + _readCreateStmt_common(&local_node->base); + + READ_STRING_FIELD(tablespacename); + + READ_DONE(); +} + static EphemeralNamedRelationInfo * _readEphemeralNamedRelationInfo(void) { @@ -2573,6 +2657,15 @@ readNodeBinary(void) case T_CreateUserMappingStmt: return_value = _readCreateUserMappingStmt(); break; + case T_CreateStorageUserMappingStmt: + return_value = _readCreateStorageUserMappingStmt(); + break; + case T_AlterStorageUserMappingStmt: + return_value = _readAlterStorageUserMappingStmt(); + break; + case T_DropStorageUserMappingStmt: + return_value = _readDropStorageUserMappingStmt(); + break; case T_AlterForeignServerStmt: return_value = _readAlterForeignServerStmt(); break; @@ -2582,6 +2675,15 @@ readNodeBinary(void) case T_AlterFdwStmt: return_value = _readAlterFdwStmt(); break; + case T_CreateStorageServerStmt: + return_value = _readCreateStorageServerStmt(); + break; + case T_AlterStorageServerStmt: + return_value = _readAlterStorageServerStmt(); + break; + case T_DropStorageServerStmt: + return_value = _readDropStorageServerStmt(); + break; case T_CreateFdwStmt: return_value = _readCreateFdwStmt(); break; @@ -2671,6 +2773,9 @@ readNodeBinary(void) case T_EphemeralNamedRelationInfo: return_value = _readEphemeralNamedRelationInfo(); break; + case T_CreateDirectoryTableStmt: + return_value = _readCreateDirectoryTableStmt(); + break; default: return_value = NULL; /* keep the compiler silent */ elog(ERROR, "could not deserialize unrecognized node type: %d", diff --git a/src/backend/optimizer/util/appendinfo.c b/src/backend/optimizer/util/appendinfo.c index 40b49d4d1b3..390ef9d0471 100644 --- a/src/backend/optimizer/util/appendinfo.c +++ b/src/backend/optimizer/util/appendinfo.c @@ -906,6 +906,7 @@ add_row_identity_columns(PlannerInfo *root, Index rtindex, Assert(commandType == CMD_UPDATE || commandType == CMD_DELETE); if (relkind == RELKIND_RELATION || + relkind == RELKIND_DIRECTORY_TABLE || relkind == RELKIND_MATVIEW || relkind == RELKIND_PARTITIONED_TABLE) { diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 832635cb981..27a88b9452e 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -1202,6 +1202,7 @@ estimate_rel_size(Relation rel, int32 *attr_widths, switch (rel->rd_rel->relkind) { case RELKIND_RELATION: + case RELKIND_DIRECTORY_TABLE: case RELKIND_MATVIEW: case RELKIND_TOASTVALUE: case RELKIND_AOSEGMENTS: diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index cdd1670c0f1..92a10d81a07 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -57,6 +57,7 @@ #include "catalog/pg_am.h" #include "catalog/pg_foreign_server.h" #include "catalog/pg_trigger.h" +#include "catalog/pg_directory_table.h" #include "commands/defrem.h" #include "commands/trigger.h" #include "nodes/makefuncs.h" @@ -67,6 +68,7 @@ #include "utils/date.h" #include "utils/datetime.h" #include "utils/numeric.h" +#include "utils/varlena.h" #include "utils/xml.h" #include "cdb/cdbutil.h" #include "cdb/cdbvars.h" @@ -281,17 +283,18 @@ static void check_expressions_in_partition_key(PartitionSpec *spec, core_yyscan_ AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterEnumStmt AlterFdwStmt AlterForeignServerStmt AlterGroupStmt AlterObjectDependsStmt AlterObjectSchemaStmt AlterOwnerStmt - AlterOperatorStmt AlterTypeStmt AlterSeqStmt AlterSystemStmt AlterTableStmt + AlterOperatorStmt AlterTypeStmt AlterSeqStmt AlterStorageServerStmt AlterSystemStmt AlterTableStmt AlterTblSpcStmt AlterExtensionStmt AlterExtensionContentsStmt - AlterCompositeTypeStmt AlterUserMappingStmt + AlterCompositeTypeStmt AlterUserMappingStmt AlterStorageUserMappingStmt AlterRoleStmt AlterRoleSetStmt AlterPolicyStmt AlterStatsStmt AlterDefaultPrivilegesStmt DefACLAction AnalyzeStmt CallStmt ClosePortalStmt ClusterStmt CommentStmt ConstraintsSetStmt CopyStmt CreateAsStmt CreateCastStmt CreateDomainStmt CreateExtensionStmt CreateGroupStmt CreateOpClassStmt CreateOpFamilyStmt AlterOpFamilyStmt CreatePLangStmt - CreateSchemaStmt CreateSeqStmt CreateStmt CreateStatsStmt CreateTableSpaceStmt - CreateFdwStmt CreateForeignServerStmt CreateForeignTableStmt + CreateSchemaStmt CreateSeqStmt CreateStmt CreateStatsStmt + CreateStorageServerStmt CreateStorageUserMappingStmt + CreateTableSpaceStmt CreateFdwStmt CreateForeignServerStmt CreateForeignTableStmt CreateDirectoryTableStmt CreateAssertionStmt CreateTransformStmt CreateTrigStmt CreateEventTrigStmt CreateUserStmt CreateUserMappingStmt CreateRoleStmt CreatePolicyStmt CreatedbStmt CreateWarehouseStmt DeclareCursorStmt DefineStmt DeleteStmt DiscardStmt DoStmt @@ -299,7 +302,7 @@ static void check_expressions_in_partition_key(PartitionSpec *spec, core_yyscan_ DropCastStmt DropRoleStmt DropdbStmt DropTableSpaceStmt DropTransformStmt - DropUserMappingStmt ExplainStmt FetchStmt + DropUserMappingStmt DropStorageServerStmt DropStorageUserMappingStmt ExplainStmt FetchStmt GrantStmt GrantRoleStmt ImportForeignSchemaStmt IndexStmt InsertStmt ListenStmt LoadStmt LockStmt NotifyStmt ExplainableStmt PreparableStmt CreateFunctionStmt AlterFunctionStmt ReindexStmt RemoveAggrStmt @@ -409,7 +412,7 @@ static void check_expressions_in_partition_key(PartitionSpec *spec, core_yyscan_ %type copy_file_name access_method_clause attr_name table_access_method_clause name cursor_name file_name - opt_index_name cluster_index_specification + opt_index_name cluster_index_specification opt_file_name %type func_name handler_name qual_Op qual_all_Op subquery_Op opt_class opt_inline_handler opt_validator validator_clause @@ -640,6 +643,9 @@ static void check_expressions_in_partition_key(PartitionSpec *spec, core_yyscan_ %type constraints_set_list %type constraints_set_mode %type OptTableSpace OptConsTableSpace +%type OptServer +%type OptFileHandler + %type OptTableSpaceOwner %type DistributedBy OptDistributedBy %type OptTabPartitionRangeInclusive @@ -755,7 +761,7 @@ static void check_expressions_in_partition_key(PartitionSpec *spec, core_yyscan_ DATA_P DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS DEPENDS DEPTH DESC - DETACH DICTIONARY DISABLE_P DISCARD DISTINCT DO DOCUMENT_P DOMAIN_P + DETACH DICTIONARY DIRECTORY DISABLE_P DISCARD DISTINCT DO DOCUMENT_P DOMAIN_P DOUBLE_P DROP EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ENDPOINT ENUM_P ESCAPE EVENT EXCEPT @@ -871,6 +877,8 @@ static void check_expressions_in_partition_key(PartitionSpec *spec, core_yyscan_ SCATTER SEGMENT SEGMENTS SPLIT SUBPARTITION + TAG + TASK SCHEDULE THRESHOLD @@ -1396,6 +1404,7 @@ stmt: | AlterQueueStmt | AlterResourceGroupStmt | AlterSeqStmt + | AlterStorageServerStmt | AlterSystemStmt | AlterTableStmt | AlterTblSpcStmt @@ -1408,6 +1417,7 @@ stmt: | AlterTSConfigurationStmt | AlterTSDictionaryStmt | AlterUserMappingStmt + | AlterStorageUserMappingStmt | AnalyzeStmt | CallStmt | CheckPointStmt @@ -1422,6 +1432,7 @@ stmt: | CreateCastStmt | CreateConversionStmt | CreateDomainStmt + | CreateDirectoryTableStmt | CreateExtensionStmt | CreateExternalStmt | CreateFdwStmt @@ -1445,6 +1456,8 @@ stmt: | CreateStmt | CreateSubscriptionStmt | CreateStatsStmt + | CreateStorageServerStmt + | CreateStorageUserMappingStmt | CreateTableSpaceStmt | CreateTaskStmt | CreateTransformStmt @@ -1475,6 +1488,8 @@ stmt: | DropRoleStmt | DropUserMappingStmt | DropdbStmt + | DropStorageServerStmt + | DropStorageUserMappingStmt | DropWarehouseStmt | ExecuteStmt | ExplainStmt @@ -4487,7 +4502,7 @@ ClosePortalStmt: *****************************************************************************/ CopyStmt: COPY opt_binary qualified_name opt_column_list - copy_from opt_program copy_file_name copy_delimiter opt_with + copy_from opt_program copy_file_name opt_file_name copy_delimiter opt_with copy_options where_clause OptSingleRowErrorHandling { CopyStmt *n = makeNode(CopyStmt); @@ -4497,8 +4512,9 @@ CopyStmt: COPY opt_binary qualified_name opt_column_list n->is_from = $5; n->is_program = $6; n->filename = $7; - n->whereClause = $11; - n->sreh = $12; + n->dirfilename = $8; + n->whereClause = $12; + n->sreh = $13; if (n->is_program && n->filename == NULL) ereport(ERROR, @@ -4510,16 +4526,16 @@ CopyStmt: COPY opt_binary qualified_name opt_column_list ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("WHERE clause not allowed with COPY TO"), - parser_errposition(@11))); + parser_errposition(@12))); n->options = NIL; /* Concatenate user-supplied flags */ if ($2) n->options = lappend(n->options, $2); - if ($8) - n->options = lappend(n->options, $8); - if ($10) - n->options = list_concat(n->options, $10); + if ($9) + n->options = lappend(n->options, $9); + if ($11) + n->options = list_concat(n->options, $11); $$ = (Node *)n; } | COPY '(' PreparableStmt ')' TO opt_program copy_file_name opt_with copy_options @@ -4573,6 +4589,11 @@ copy_file_name: | STDOUT { $$ = NULL; } ; +opt_file_name: + Sconst { $$ = $1; } + | /* EMPTY */ { $$ = NULL; } + ; + copy_options: copy_opt_list { $$ = $1; } | '(' copy_generic_opt_list ')' { $$ = $2; } ; @@ -4656,6 +4677,10 @@ copy_opt_item: { $$ = makeDefElem("skip_foreign_partitions", (Node *)makeInteger(true), @1); } + | TAG Sconst + { + $$ = makeDefElem("tag", (Node *)makeString($2), @1); + } ; /* The following exist for backward compatibility with very old versions */ @@ -7137,13 +7162,38 @@ opt_procedural: * *****************************************************************************/ -CreateTableSpaceStmt: CREATE TABLESPACE name OptTableSpaceOwner LOCATION Sconst opt_reloptions +CreateTableSpaceStmt: CREATE TABLESPACE name OptTableSpaceOwner LOCATION Sconst opt_reloptions OptServer OptFileHandler { CreateTableSpaceStmt *n = makeNode(CreateTableSpaceStmt); + List *fileHandler_list; + char *tmpfilehandler; n->tablespacename = $3; n->owner = $4; n->location = $6; n->options = $7; + + if ($8 != NULL) + { + n->options = lappend(n->options, $8); + n->options = lappend(n->options, + makeDefElem("path", (Node *)makeString($6), @6)); + } + n->filehandler = $9; + if (n->filehandler) + { + tmpfilehandler = pstrdup(n->filehandler); + if (tmpfilehandler && !SplitIdentifierString(tmpfilehandler, ',', &fileHandler_list)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("invalid list syntax for \"handler\""), + parser_errposition(@9))); + if (tmpfilehandler && list_length(fileHandler_list) != 2) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("invalid list syntax for \"handler\""), + parser_errposition(@9))); + } + $$ = (Node *) n; } ; @@ -7152,6 +7202,16 @@ OptTableSpaceOwner: OWNER RoleSpec { $$ = $2; } | /*EMPTY */ { $$ = NULL; } ; +OptServer: SERVER name { $$ = makeDefElem("server", (Node *)makeString($2), @1); } + | /* EMPTY */ { $$ = NULL; } + ; + +OptFileHandler: + HANDLER Sconst { $$ = $2; } + | HANDLER { $$ = NULL; } + | /* EMPTY */ { $$ = NULL; } + ; + /***************************************************************************** * * QUERY: @@ -7589,7 +7649,7 @@ AlterFdwStmt: ALTER FOREIGN DATA_P WRAPPER name opt_fdw_options alter_generic_op } ; -/* Options definition for CREATE FDW, SERVER and USER MAPPING */ +/* Options definition for CREATE FDW, SERVER, STORAGE SERVER and USER MAPPING */ create_generic_options: OPTIONS '(' generic_option_list ')' { $$ = $3; } | /*EMPTY*/ { $$ = NIL; } @@ -7741,6 +7801,74 @@ AlterForeignServerStmt: ALTER SERVER name foreign_server_version alter_generic_o } ; +/***************************************************************************** + * + * QUERY: + * CREATE STORAGE SERVER name [OPTIONS] + * + *****************************************************************************/ + +CreateStorageServerStmt: + CREATE STORAGE SERVER name create_generic_options + { + CreateStorageServerStmt *n = makeNode(CreateStorageServerStmt); + n->servername = $4; + n->if_not_exists = false; + n->options = $5; + $$ = (Node *) n; + } + | CREATE STORAGE SERVER IF_P NOT EXISTS name create_generic_options + { + CreateStorageServerStmt *n = makeNode(CreateStorageServerStmt); + n->servername = $7; + n->if_not_exists = true; + n->options = $8; + $$ = (Node *) n; + } + ; + +/***************************************************************************** + * + * QUERY : + * ALTER STORAGE SERVER name OPTIONS + * + ****************************************************************************/ + +AlterStorageServerStmt: + ALTER STORAGE SERVER name alter_generic_options + { + AlterStorageServerStmt *n = makeNode(AlterStorageServerStmt); + n->servername = $4; + n->options = $5; + $$ = (Node *) n; + } + ; + +/***************************************************************************** + * + * QUERY : + * DROP STORAGE SERVER name + * + ****************************************************************************/ + +DropStorageServerStmt: + DROP STORAGE SERVER name + { + DropStorageServerStmt *n = makeNode(DropStorageServerStmt); + n->servername = $4; + n->missing_ok = false; + $$ = (Node *) n; + } + | DROP STORAGE SERVER IF_P EXISTS name + { + DropStorageServerStmt *n = makeNode(DropStorageServerStmt); + n->servername = $6; + n->missing_ok = true; + $$ = (Node *) n; + } + ; + + /***************************************************************************** * * QUERY: @@ -7962,6 +8090,141 @@ AlterUserMappingStmt: ALTER USER MAPPING FOR auth_ident SERVER name alter_generi } ; +/***************************************************************************** + * + * QUERY: + * CREAT STORAGE USER MAPPING FOR auth_ident STORAGE SERVER name [OPTIONS] + * + *****************************************************************************/ + +CreateStorageUserMappingStmt: + CREATE STORAGE USER MAPPING FOR auth_ident STORAGE SERVER name create_generic_options + { + CreateStorageUserMappingStmt *n = makeNode(CreateStorageUserMappingStmt); + n->user = $6; + n->servername = $9; + n->options = $10; + n->if_not_exists = false; + $$ = (Node *) n; + } + | CREATE STORAGE USER MAPPING IF_P NOT EXISTS FOR auth_ident + STORAGE SERVER name create_generic_options + { + CreateStorageUserMappingStmt *n = makeNode(CreateStorageUserMappingStmt); + n->user = $9; + n->servername = $12; + n->options = $13; + n->if_not_exists = true; + $$ = (Node *) n; + } + ; + +/***************************************************************************** + * + * QUERY : + * DROP STORAGE USER MAPPING FOR auth_ident STORAGE SERVER name + * + * XXX you'd think this should have a CASCADE/RESTRICT option, even if it's + * only pro forma; but the SQL standard doesn't show one. + ****************************************************************************/ + +DropStorageUserMappingStmt: + DROP STORAGE USER MAPPING FOR auth_ident STORAGE SERVER name + { + DropStorageUserMappingStmt *n = makeNode(DropStorageUserMappingStmt); + n->user = $6; + n->servername = $9; + n->missing_ok = false; + $$ = (Node *) n; + } + | DROP STORAGE USER MAPPING IF_P EXISTS FOR auth_ident STORAGE SERVER name + { + DropStorageUserMappingStmt *n = makeNode(DropStorageUserMappingStmt); + n->user = $8; + n->servername = $11; + n->missing_ok = true; + $$ = (Node *) n; + } + ; + +/***************************************************************************** + * + * QUERY : + * ALTER STORAGE USER MAPPING FOR auth_ident STORAGE SERVER name OPTIONS + * + ****************************************************************************/ + +AlterStorageUserMappingStmt: + ALTER STORAGE USER MAPPING FOR auth_ident STORAGE SERVER name alter_generic_options + { + AlterStorageUserMappingStmt *n = makeNode(AlterStorageUserMappingStmt); + n->user = $6; + n->servername = $9; + n->options = $10; + $$ = (Node *) n; + } + ; + +/***************************************************************************** + * + * QUERY: + * CREATE DIRECTORY TABLE relname SERVER name (...) + * + *****************************************************************************/ + +CreateDirectoryTableStmt: + CREATE DIRECTORY TABLE qualified_name + table_access_method_clause OptTableSpace OptDistributedBy + { + CreateDirectoryTableStmt *n = makeNode(CreateDirectoryTableStmt); + $4->relpersistence = RELPERSISTENCE_PERMANENT; + n->base.relation = $4; + n->base.inhRelations = NIL; + n->base.ofTypename = NULL; + n->base.constraints = NIL; + n->base.options = NIL; + n->base.oncommit = ONCOMMIT_NOOP; + /* TODO: support tablespace for data table ? */ + n->base.tablespacename = NULL; + n->base.if_not_exists = false; + n->base.distributedBy = (DistributedBy *) $7; + if (n->base.distributedBy != NULL) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Create directory table is not allowed to set distributed by."), + parser_errposition(@7))); + n->base.relKind = RELKIND_DIRECTORY_TABLE; + n->tablespacename = $6; + + $$ = (Node *) n; + } + | CREATE DIRECTORY TABLE IF_P NOT EXISTS qualified_name + table_access_method_clause OptTableSpace OptDistributedBy + { + CreateDirectoryTableStmt *n = makeNode(CreateDirectoryTableStmt); + $7->relpersistence = RELPERSISTENCE_PERMANENT; + n->base.relation = $7; + n->base.inhRelations = NIL; + n->base.ofTypename = NULL; + n->base.constraints = NIL; + n->base.options = NIL; + n->base.oncommit = ONCOMMIT_NOOP; + /* TODO: support tablespace for data table? */ + n->base.tablespacename = NULL; + n->base.if_not_exists = true; + n->base.distributedBy = (DistributedBy *) $10; + if (n->base.distributedBy != NULL) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Create directory table is not allowed to set distributed by."), + parser_errposition(@10))); + n->base.relKind = RELKIND_DIRECTORY_TABLE; + n->tablespacename = $9; + + $$ = (Node *) n; + } + ; + /***************************************************************************** * * QUERIES: @@ -9093,7 +9356,8 @@ object_type_any_name: | INDEX { $$ = OBJECT_INDEX; } | FOREIGN TABLE { $$ = OBJECT_FOREIGN_TABLE; } | EXTERNAL TABLE { $$ = OBJECT_FOREIGN_TABLE; } - | EXTERNAL WEB TABLE { $$ = OBJECT_FOREIGN_TABLE; } + | EXTERNAL WEB TABLE { $$ = OBJECT_FOREIGN_TABLE; } + | DIRECTORY TABLE { $$ = OBJECT_DIRECTORY_TABLE; } | COLLATION { $$ = OBJECT_COLLATION; } | CONVERSION_P { $$ = OBJECT_CONVERSION; } | STATISTICS { $$ = OBJECT_STATISTIC_EXT; } @@ -18742,6 +19006,7 @@ unreserved_keyword: | DEPTH | DETACH | DICTIONARY + | DIRECTORY | DISABLE_P | DISCARD | DOCUMENT_P @@ -18984,6 +19249,7 @@ unreserved_keyword: | SYSTEM_P | TABLES | TABLESPACE + | TAG | TASK | TEMP | TEMPLATE @@ -19112,6 +19378,7 @@ PartitionIdentKeyword: ABORT_P | DEPTH | DETACH | DICTIONARY + | DIRECTORY | DISABLE_P | DOMAIN_P | DOUBLE_P @@ -19663,6 +19930,7 @@ bare_label_keyword: | DESC | DETACH | DICTIONARY + | DIRECTORY | DISABLE_P | DISCARD | DISTINCT @@ -19967,6 +20235,7 @@ bare_label_keyword: | TABLES | TABLESAMPLE | TABLESPACE + | TAG | TASK | TEMP | TEMPLATE diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 7db57c7e106..de1f9626dfa 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -1319,7 +1319,8 @@ transformFromClauseItem(ParseState *pstate, Node *n, if (rte->rtekind != RTE_RELATION || (rte->relkind != RELKIND_RELATION && rte->relkind != RELKIND_MATVIEW && - rte->relkind != RELKIND_PARTITIONED_TABLE)) + rte->relkind != RELKIND_PARTITIONED_TABLE && + rte->relkind != RELKIND_DIRECTORY_TABLE)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("TABLESAMPLE clause can only be applied to tables and materialized views"), diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index 7001a143134..87126e78517 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -1486,7 +1486,8 @@ addRangeTableEntry(ParseState *pstate, RelationIsAppendOptimized(rel)) pstate->p_canOptSelectLockingClause = false; - if (rel->rd_rel->relkind == RELKIND_MATVIEW) + if (rel->rd_rel->relkind == RELKIND_MATVIEW || + rel->rd_rel->relkind == RELKIND_DIRECTORY_TABLE) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("cannot lock rows in materialized view \"%s\"", diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index b83ebc67524..446af6f3cf0 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -1081,6 +1081,7 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla relation = relation_openrv(table_like_clause->relation, AccessShareLock); if (relation->rd_rel->relkind != RELKIND_RELATION && + relation->rd_rel->relkind != RELKIND_DIRECTORY_TABLE && relation->rd_rel->relkind != RELKIND_VIEW && relation->rd_rel->relkind != RELKIND_MATVIEW && relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE && @@ -1088,7 +1089,7 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("\"%s\" is not a table, view, materialized view, composite type, or foreign table", + errmsg("\"%s\" is not a table, directory table, view, materialized view, composite type, or foreign table", RelationGetRelationName(relation)))); cancel_parser_errposition_callback(&pcbstate); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 7a10cc913a5..6a82a5ec3db 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -2173,6 +2173,7 @@ do_autovacuum(void) bool wraparound; if (classForm->relkind != RELKIND_RELATION && + classForm->relkind != RELKIND_DIRECTORY_TABLE && classForm->relkind != RELKIND_MATVIEW && classForm->relkind != RELKIND_AOSEGMENTS && classForm->relkind != RELKIND_AOBLOCKDIR && @@ -2362,7 +2363,8 @@ do_autovacuum(void) * completely unrelated to the one we saw before. */ if (!((classForm->relkind == RELKIND_RELATION || - classForm->relkind == RELKIND_MATVIEW) && + classForm->relkind == RELKIND_MATVIEW || + classForm->relkind == RELKIND_DIRECTORY_TABLE) && classForm->relpersistence == RELPERSISTENCE_TEMP)) { UnlockRelationOid(relid, AccessExclusiveLock); @@ -2859,6 +2861,7 @@ extract_autovac_opts(HeapTuple tup, TupleDesc pg_class_desc) Assert(((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_RELATION || ((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_MATVIEW || + ((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_DIRECTORY_TABLE || ((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_TOASTVALUE || ((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_AOSEGMENTS || ((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_AOBLOCKDIR || diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c index 6df8ffd2ead..19973c195da 100644 --- a/src/backend/rewrite/rewriteDefine.c +++ b/src/backend/rewrite/rewriteDefine.c @@ -295,12 +295,13 @@ DefineQueryRewrite(const char *rulename, * blocks them for users. Don't mention them in the error message. */ if (event_relation->rd_rel->relkind != RELKIND_RELATION && + event_relation->rd_rel->relkind != RELKIND_DIRECTORY_TABLE && event_relation->rd_rel->relkind != RELKIND_MATVIEW && event_relation->rd_rel->relkind != RELKIND_VIEW && event_relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("\"%s\" is not a table or view", + errmsg("\"%s\" is not a table, directory table or view", RelationGetRelationName(event_relation)))); if (!allowSystemTableMods && IsSystemRelation(event_relation)) @@ -468,7 +469,8 @@ DefineQueryRewrite(const char *rulename, RelationGetRelationName(event_relation)))); /* only case left: */ - Assert(event_relation->rd_rel->relkind == RELKIND_RELATION); + Assert(event_relation->rd_rel->relkind == RELKIND_RELATION || + event_relation->rd_rel->relkind == RELKIND_DIRECTORY_TABLE); if (event_relation->rd_rel->relispartition) ereport(ERROR, diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 6050794b6dd..7ba5f9a56bc 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -2685,6 +2685,7 @@ view_query_is_auto_updatable(Query *viewquery, bool check_cols) if (base_rte->rtekind != RTE_RELATION || (base_rte->relkind != RELKIND_RELATION && base_rte->relkind != RELKIND_FOREIGN_TABLE && + base_rte->relkind != RELKIND_DIRECTORY_TABLE && base_rte->relkind != RELKIND_VIEW && base_rte->relkind != RELKIND_PARTITIONED_TABLE)) return gettext_noop("Views that do not select from a single table or view are not automatically updatable."); diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 33241bfdddc..577d120e21a 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -3137,6 +3137,7 @@ RelationGetNumberOfBlocksInFork(Relation relation, ForkNumber forkNum) return smgrnblocks(relation->rd_smgr, forkNum); case RELKIND_RELATION: + case RELKIND_DIRECTORY_TABLE: case RELKIND_TOASTVALUE: case RELKIND_MATVIEW: case RELKIND_AOSEGMENTS: diff --git a/src/backend/storage/file/Makefile b/src/backend/storage/file/Makefile index 7f07a740afa..07dfb28e0d2 100644 --- a/src/backend/storage/file/Makefile +++ b/src/backend/storage/file/Makefile @@ -17,7 +17,8 @@ OBJS = \ copydir.o \ fd.o \ reinit.o \ - sharedfileset.o + sharedfileset.o \ + ufile.o OBJS += execute_pipe.o gp_compress.o diff --git a/src/backend/storage/file/ufile.c b/src/backend/storage/file/ufile.c new file mode 100644 index 00000000000..66726a2c41f --- /dev/null +++ b/src/backend/storage/file/ufile.c @@ -0,0 +1,470 @@ +/*------------------------------------------------------------------------- + * + * Unified file abstraction and manipulation. + * + * Copyright (c) 2016-Present Hashdata, Inc. + * + * + * * IDENTIFICATION + * src/backend/storage/file/ufile.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include +#include +#include + +#include "catalog/pg_directory_table.h" +#include "catalog/pg_tablespace.h" +#include "cdb/cdbvars.h" +#include "commands/tablespace.h" +#include "common/relpath.h" +#include "storage/ufile.h" +#include "storage/fd.h" +#include "storage/lwlock.h" +#include "storage/relfilenode.h" +#include "utils/elog.h" +#include "utils/wait_event.h" + +typedef struct LocalFile +{ + FileAm * methods; + File file; + off_t offset; +} LocalFile; + +static UFile *localFileOpen(Oid spcId, const char *fileName, int fileFlags, + char *errorMessage, int errorMessageSize); +static void localFileClose(UFile *file); +static int localFileSync(UFile *file); +static int localFileRead(UFile *file, char *buffer, int amount); +static int localFileWrite(UFile *file, char *buffer, int amount); +static off_t localFileSize(UFile *file); +static void localFileUnlink(Oid spcId, const char *fileName); +static char *localFormatPathName(RelFileNode *relFileNode); +static bool localEnsurePath(Oid spcId, const char *PathName); +static bool localFileExists(Oid spcId, const char *fileName); +static const char *localFileName(UFile *file); +static const char *localGetLastError(void); +static void localGetConnection(Oid spcId); + +static char localFileErrorStr[UFILE_ERROR_SIZE]; + +struct FileAm localFileAm = { + .open = localFileOpen, + .close = localFileClose, + .sync = localFileSync, + .read = localFileRead, + .write = localFileWrite, + .size = localFileSize, + .unlink = localFileUnlink, + .formatPathName = localFormatPathName, + .ensurePath = localEnsurePath, + .exists = localFileExists, + .name = localFileName, + .getLastError = localGetLastError, + .getConnection = localGetConnection, +}; + +static UFile * +localFileOpen(Oid spcId, + const char *fileName, + int fileFlags, + char *errorMessage, + int errorMessageSize) +{ + LocalFile *result; + File file; + + file = PathNameOpenFile(fileName, fileFlags); + if (file < 0) + { + snprintf(errorMessage, errorMessageSize, "%s", strerror(errno)); + return NULL; + } + + result = palloc0(sizeof(LocalFile)); + result->methods = &localFileAm; + result->file = file; + result->offset = 0; + + return (UFile *) result; +} + +static void +localFileClose(UFile *file) +{ + LocalFile *localFile = (LocalFile *) file; + + FileClose(localFile->file); +} + +static int +localFileSync(UFile *file) +{ + int result; + LocalFile *localFile = (LocalFile *) file; + + result = FileSync(localFile->file, WAIT_EVENT_DATA_FILE_SYNC); + if (result == -1) + snprintf(localFileErrorStr, UFILE_ERROR_SIZE, "%s", strerror(errno)); + + return result; +} + +static int +localFilePread(UFile *file, char *buffer, int amount, off_t offset) +{ + int bytes; + LocalFile *localFile = (LocalFile *) file; + + localFile->offset = offset; + bytes = FileRead(localFile->file, buffer, amount, offset, WAIT_EVENT_DATA_FILE_READ); + if (bytes < 0) + { + snprintf(localFileErrorStr, UFILE_ERROR_SIZE, "%s", strerror(errno)); + return -1; + } + + localFile->offset += bytes; + return bytes; +} + +static int +localFileRead(UFile *file, char *buffer, int amount) +{ + LocalFile *localFile = (LocalFile *) file; + + return localFilePread(file, buffer, amount, localFile->offset); +} + +static int +localFilePwrite(UFile *file, char *buffer, int amount, off_t offset) +{ + int bytes; + LocalFile *localFile = (LocalFile *) file; + + localFile->offset = offset; + bytes = FileWrite(localFile->file, buffer, amount, offset, WAIT_EVENT_DATA_FILE_WRITE); + if (bytes < 0) + { + snprintf(localFileErrorStr, UFILE_ERROR_SIZE, "%s", strerror(errno)); + return -1; + } + + localFile->offset += bytes; + return bytes; +} + +static int +localFileWrite(UFile *file, char *buffer, int amount) +{ + LocalFile *localFile = (LocalFile *) file; + + return localFilePwrite(file, buffer, amount, localFile->offset); +} + +static off_t +localFileSize(UFile *file) +{ + LocalFile *localFile = (LocalFile *) file; + + return FileSize(localFile->file); +} + +static bool +destory_local_file_directories(const char* directoryName) +{ + DIR *dirdesc; + struct dirent *de; + char *subfile; + struct stat st; + + Assert(LWLockHeldByMe(DirectoryTableLock)); + + elog(DEBUG5, "destory_local_file_directories for directory %s", + directoryName); + + dirdesc = AllocateDir(directoryName); + if (dirdesc == NULL) + { + if (errno == ENOENT) + { + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not open directory \"%s\": %m", + directoryName))); + /* The symlink might still exist, so go try to remove it */ + return false; + } + } + + while ((de = ReadDir(dirdesc, directoryName)) != NULL) + { + if (strcmp(de->d_name, ".") == 0 || + strcmp(de->d_name, "..") == 0) + continue; + + subfile = psprintf("%s/%s", directoryName, de->d_name); + + if (stat(subfile, &st) == 0 && + S_ISDIR(st.st_mode)) + { + /* remove directory and file recursively */ + + if (!destory_local_file_directories(subfile)) + { + ereport(WARNING, + (errcode_for_file_access(), + errmsg("directories for directory table \"%s\" could not be removed: %m", + subfile), + errhint("You can remove the directories manually if necessary."))); + + FreeDir(dirdesc); + pfree(subfile); + + return false; + } + } + else + { + /* remove file */ + if (unlink(subfile) < 0) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not remove files \"%s\": %m", + subfile))); + } + + pfree(subfile); + } + + FreeDir(dirdesc); + + /* remove directory */ + if (rmdir(directoryName) < 0) + { + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not remove directory \"%s\": %m", + directoryName))); + } + + return true; +} + +static void +localFileUnlink(Oid spcId, const char *fileName) +{ + struct stat st; + + LWLockAcquire(DirectoryTableLock, LW_EXCLUSIVE); + if (stat(fileName, &st) == 0 && + S_ISDIR(st.st_mode)) + { + /* remove directory and file recursively */ + if (!destory_local_file_directories(fileName)) + ereport(WARNING, + (errcode_for_file_access(), + errmsg("directories for directory table \"%s\" could not be removed: %m", + fileName), + errhint("You can remove the directories manually if necessary."))); + LWLockRelease(DirectoryTableLock); + } + else + { + LWLockRelease(DirectoryTableLock); + /* remove file */ + if (unlink(fileName) < 0) + { + if (errno != ENOENT) + ereport(WARNING, + (errcode_for_file_access(), + errmsg("could not remove file \"%s\": %m", fileName))); + } + } + +} + +static char * +localFormatPathName(RelFileNode *relFileNode) +{ + if (relFileNode->spcNode == DEFAULTTABLESPACE_OID) + return psprintf("base/%u/"UINT64_FORMAT"_dirtable", + relFileNode->dbNode, relFileNode->relNode); + else + return psprintf("pg_tblspc/%u/%s/%u/"UINT64_FORMAT"_dirtable", + relFileNode->spcNode, GP_TABLESPACE_VERSION_DIRECTORY, + relFileNode->dbNode, relFileNode->relNode); +} + +bool +localEnsurePath(Oid spcId, const char *PathName) +{ + struct stat st; + char *localPath; + + localPath = pstrdup(PathName); + + if (stat(localPath, &st) != 0 && pg_mkdir_p(localPath, S_IRWXU) != 0) + { + ereport(WARNING, + (errmsg("can not recursively create directory \"%s\"", + localPath))); + return false; + } + + return true; +} + +static bool +localFileExists(Oid spcId, const char *fileName) +{ + struct stat fileStats; + + if (stat(fileName, &fileStats) != 0) + { + if (errno == ENOENT) + return false; + + ereport(ERROR, + (errcode_for_file_access(), + errmsg("unable to stat file \"%s\": %m", fileName))); + } + + return true; +} + +static const char * +localFileName(UFile *file) +{ + LocalFile *localFile = (LocalFile *) file; + + return FilePathName(localFile->file); +} + +static const char * +localGetLastError(void) +{ + return localFileErrorStr; +} + +static void +localGetConnection(Oid spcId) +{ + return; +} + +UFile * +UFileOpen(Oid spcId, + const char *fileName, + int fileFlags, + char *errorMessage, + int errorMessageSize) +{ + UFile *ufile; + FileAm *fileAm; + + fileAm = GetTablespaceFileHandler(spcId); + ufile = fileAm->open(spcId, fileName, fileFlags, errorMessage, errorMessageSize); + + return ufile; +} + +void +UFileClose(UFile *file) +{ + file->methods->close(file); + //TODO pfree move to close + pfree(file); +} + +int +UFileSync(UFile *file) +{ + return file->methods->sync(file); +} + +int +UFileRead(UFile *file, char *buffer, int amount) +{ + return file->methods->read(file, buffer, amount); +} + +int +UFileWrite(UFile *file, char *buffer, int amount) +{ + return file->methods->write(file, buffer, amount); +} + +int64_t +UFileSize(UFile *file) +{ + return file->methods->size(file); +} + +const char * +UFileName(UFile *file) +{ + return file->methods->name(file); +} + +void +UFileUnlink(Oid spcId, const char *fileName) +{ + FileAm *fileAm; + + fileAm = GetTablespaceFileHandler(spcId); + + fileAm->unlink(spcId, fileName); +} + +char * +UFileFormatPathName(RelFileNode *relFileNode) +{ + FileAm *fileAm; + + fileAm = GetTablespaceFileHandler(relFileNode->spcNode); + + return fileAm->formatPathName(relFileNode); +} + +bool +UFileEnsurePath(Oid spcId, const char *pathName) +{ + FileAm *fileAm; + + fileAm = GetTablespaceFileHandler(spcId); + + return fileAm->ensurePath(spcId, pathName); +} + +bool +UFileExists(Oid spcId, const char *fileName) +{ + FileAm *fileAm; + + fileAm = GetTablespaceFileHandler(spcId); + + return fileAm->exists(spcId, fileName); +} + +const char * +UFileGetLastError(UFile *file) +{ + return file->methods->getLastError(); +} + +void +forceCacheUFileResource(Oid spcId) +{ + FileAm *fileAm; + + fileAm = GetTablespaceFileHandler(spcId); + + return fileAm->getConnection(spcId); +} + diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 93e6152ae84..3ff56accb7b 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -2079,6 +2079,7 @@ GlobalVisHorizonKindForRel(Relation rel) Assert(!rel || rel->rd_rel->relkind == RELKIND_RELATION || rel->rd_rel->relkind == RELKIND_MATVIEW || + rel->rd_rel->relkind == RELKIND_DIRECTORY_TABLE || rel->rd_rel->relkind == RELKIND_AOSEGMENTS || rel->rd_rel->relkind == RELKIND_AOVISIMAP || rel->rd_rel->relkind == RELKIND_AOBLOCKDIR || diff --git a/src/backend/storage/lmgr/lwlocknames.txt b/src/backend/storage/lmgr/lwlocknames.txt index a3496fc00c9..c8f283198ce 100644 --- a/src/backend/storage/lmgr/lwlocknames.txt +++ b/src/backend/storage/lmgr/lwlocknames.txt @@ -74,3 +74,4 @@ GpParallelDSMHashLock 64 LoginFailedControlLock 65 LoginFailedSharedMemoryLock 66 GPIVMResLock 67 +DirectoryTableLock 68 diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index c0f7b54a29f..21b27c2806d 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -5355,10 +5355,10 @@ PostgresMain(int argc, char *argv[], initStringInfo(&input_message); - /* Reset elog globals */ - currentSliceId = UNSET_SLICE_ID; - if (Gp_role == GP_ROLE_EXECUTE) - gp_command_count = 0; + /* Reset elog globals */ + currentSliceId = UNSET_SLICE_ID; + if (Gp_role == GP_ROLE_EXECUTE) + gp_command_count = 0; /* * Do deactiving and runaway detecting before ReadyForQuery(), diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 49d0dbce11b..55105efebd0 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -37,6 +37,7 @@ #include "commands/createas.h" #include "commands/dbcommands.h" #include "commands/defrem.h" +#include "commands/dirtablecmds.h" #include "commands/discard.h" #include "commands/event_trigger.h" #include "commands/explain.h" @@ -54,6 +55,7 @@ #include "commands/schemacmds.h" #include "commands/seclabel.h" #include "commands/sequence.h" +#include "commands/storagecmds.h" #include "commands/subscriptioncmds.h" #include "commands/tablecmds.h" #include "commands/tablespace.h" @@ -181,6 +183,7 @@ ClassifyUtilityCommandAsReadOnly(Node *parsetree) case T_AlterTableStmt: case T_AlterTypeStmt: case T_AlterUserMappingStmt: + case T_AlterStorageUserMappingStmt: case T_CommentStmt: case T_CompositeTypeStmt: case T_CreateAmStmt: @@ -210,7 +213,11 @@ ClassifyUtilityCommandAsReadOnly(Node *parsetree) case T_CreateTableSpaceStmt: case T_CreateTransformStmt: case T_CreateTrigStmt: + case T_CreateStorageServerStmt: + case T_AlterStorageServerStmt: + case T_DropStorageServerStmt: case T_CreateUserMappingStmt: + case T_CreateStorageUserMappingStmt: case T_CreatedbStmt: case T_DefineStmt: case T_DropOwnedStmt: @@ -219,6 +226,7 @@ ClassifyUtilityCommandAsReadOnly(Node *parsetree) case T_DropSubscriptionStmt: case T_DropTableSpaceStmt: case T_DropUserMappingStmt: + case T_DropStorageUserMappingStmt: case T_DropdbStmt: case T_GrantRoleStmt: case T_GrantStmt: @@ -236,6 +244,7 @@ ClassifyUtilityCommandAsReadOnly(Node *parsetree) case T_AlterProfileStmt: case T_AlterQueueStmt: case T_AlterResourceGroupStmt: + case T_CreateDirectoryTableStmt: case T_CreateProfileStmt: case T_CreateQueueStmt: case T_CreateResourceGroupStmt: @@ -1358,6 +1367,7 @@ ProcessUtilitySlow(ParseState *pstate, case T_CreateStmt: case T_CreateForeignTableStmt: + case T_CreateDirectoryTableStmt: { List *stmts; RangeVar *table_rv = NULL; @@ -1544,6 +1554,27 @@ ProcessUtilitySlow(ParseState *pstate, secondaryObject, stmt); } + else if (IsA(stmt, CreateDirectoryTableStmt)) + { + CreateDirectoryTableStmt *cstmt = (CreateDirectoryTableStmt *) stmt; + + /* Remember transformed RangeVar for LIKE */ + table_rv = cstmt->base.relation; + + /* Create the table itself */ + address = DefineRelation(&cstmt->base, + RELKIND_DIRECTORY_TABLE, + InvalidOid, NULL, + queryString, + true, + true, + cstmt->base.intoPolicy); + /* Create directory table tuple */ + CreateDirectoryTable(cstmt, address.objectId); + EventTriggerCollectSimpleCommand(address, + secondaryObject, + stmt); + } else if (IsA(stmt, TableLikeClause)) { /* @@ -2015,6 +2046,19 @@ ProcessUtilitySlow(ParseState *pstate, address = AlterForeignServer((AlterForeignServerStmt *) parsetree); break; + case T_CreateStorageServerStmt: + address = CreateStorageServer((CreateStorageServerStmt *) parsetree); + break; + + case T_AlterStorageServerStmt: + address = AlterStorageServer((AlterStorageServerStmt *) parsetree); + break; + + case T_DropStorageServerStmt: + RemoveStorageServer((DropStorageServerStmt *) parsetree); + commandCollected = true; + break; + case T_CreateUserMappingStmt: address = CreateUserMapping((CreateUserMappingStmt *) parsetree); break; @@ -2029,6 +2073,19 @@ ProcessUtilitySlow(ParseState *pstate, commandCollected = true; break; + case T_CreateStorageUserMappingStmt: + address = CreateStorageUserMapping((CreateStorageUserMappingStmt *) parsetree); + break; + + case T_AlterStorageUserMappingStmt: + address = AlterStorageUserMapping((AlterStorageUserMappingStmt *) parsetree); + break; + + case T_DropStorageUserMappingStmt: + RemoveStorageUserMapping((DropStorageUserMappingStmt *) parsetree); + commandCollected = true; + break; + case T_ImportForeignSchemaStmt: ImportForeignSchema((ImportForeignSchemaStmt *) parsetree); /* commands are stashed inside ImportForeignSchema */ @@ -2456,8 +2513,10 @@ ExecDropStmt(DropStmt *stmt, bool isTopLevel) case OBJECT_VIEW: case OBJECT_MATVIEW: case OBJECT_FOREIGN_TABLE: + case OBJECT_DIRECTORY_TABLE: RemoveRelations(stmt); break; + default: RemoveObjects(stmt); break; @@ -3026,6 +3085,18 @@ CreateCommandTag(Node *parsetree) tag = CMDTAG_ALTER_SERVER; break; + case T_CreateStorageServerStmt: + tag = CMDTAG_CREATE_STORAGE_SERVER; + break; + + case T_AlterStorageServerStmt: + tag = CMDTAG_ALTER_STORAGE_SERVER; + break; + + case T_DropStorageServerStmt: + tag = CMDTAG_DROP_STORAGE_SERVER; + break; + case T_CreateUserMappingStmt: tag = CMDTAG_CREATE_USER_MAPPING; break; @@ -3038,6 +3109,18 @@ CreateCommandTag(Node *parsetree) tag = CMDTAG_DROP_USER_MAPPING; break; + case T_CreateStorageUserMappingStmt: + tag = CMDTAG_CREATE_STORAGE_USER_MAPPING; + break; + + case T_AlterStorageUserMappingStmt: + tag = CMDTAG_ALTER_STORAGE_USER_MAPPING; + break; + + case T_DropStorageUserMappingStmt: + tag = CMDTAG_DROP_STORAGE_USER_MAPPING; + break; + case T_CreateForeignTableStmt: tag = CMDTAG_CREATE_FOREIGN_TABLE; break; @@ -3046,6 +3129,10 @@ CreateCommandTag(Node *parsetree) tag = CMDTAG_IMPORT_FOREIGN_SCHEMA; break; + case T_CreateDirectoryTableStmt: + tag = CMDTAG_CREATE_DIRECTORY_TABLE; + break; + case T_DropStmt: switch (((DropStmt *) parsetree)->removeType) { @@ -3139,6 +3226,9 @@ CreateCommandTag(Node *parsetree) case OBJECT_FOREIGN_SERVER: tag = CMDTAG_DROP_SERVER; break; + case OBJECT_STORAGE_SERVER: + tag = CMDTAG_DROP_STORAGE_SERVER; + break; case OBJECT_OPCLASS: tag = CMDTAG_DROP_OPERATOR_CLASS; break; @@ -3160,6 +3250,9 @@ CreateCommandTag(Node *parsetree) case OBJECT_STATISTIC_EXT: tag = CMDTAG_DROP_STATISTICS; break; + case OBJECT_DIRECTORY_TABLE: + tag = CMDTAG_DROP_DIRECTORY_TABLE; + break; default: tag = CMDTAG_UNKNOWN; } @@ -3891,10 +3984,17 @@ GetCommandLogLevel(Node *parsetree) case T_AlterFdwStmt: case T_CreateForeignServerStmt: case T_AlterForeignServerStmt: + case T_CreateStorageServerStmt: + case T_AlterStorageServerStmt: + case T_DropStorageServerStmt: case T_CreateUserMappingStmt: case T_AlterUserMappingStmt: case T_DropUserMappingStmt: + case T_CreateStorageUserMappingStmt: + case T_AlterStorageUserMappingStmt: + case T_DropStorageUserMappingStmt: case T_ImportForeignSchemaStmt: + case T_CreateDirectoryTableStmt: lev = LOGSTMT_DDL; break; diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index ef8478c36da..714a536e93d 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -791,6 +791,10 @@ acldefault(ObjectType objtype, Oid ownerId) world_default = ACL_NO_RIGHTS; owner_default = ACL_ALL_RIGHTS_FOREIGN_SERVER; break; + case OBJECT_STORAGE_SERVER: + world_default = ACL_NO_RIGHTS; + owner_default = ACL_ALL_RIGHTS_STORAGE_SERVER; + break; case OBJECT_EXTPROTOCOL: world_default = ACL_NO_RIGHTS; owner_default = ACL_ALL_RIGHTS_EXTPROTOCOL; diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c index 3d331afa0b3..ceec9a4afe3 100644 --- a/src/backend/utils/adt/dbsize.c +++ b/src/backend/utils/adt/dbsize.c @@ -549,6 +549,7 @@ pg_relation_size(PG_FUNCTION_ARGS) forkNumber = forkname_to_number(text_to_cstring(forkName)); + // TODO directory table size = calculate_relation_size(rel, forkNumber); if (Gp_role == GP_ROLE_DISPATCH) @@ -1176,6 +1177,7 @@ pg_relation_filenode(PG_FUNCTION_ARGS) case RELKIND_AOSEGMENTS: case RELKIND_AOBLOCKDIR: case RELKIND_AOVISIMAP: + case RELKIND_DIRECTORY_TABLE: /* okay, these have storage */ if (relform->relfilenode) result = relform->relfilenode; @@ -1260,6 +1262,7 @@ pg_relation_filepath(PG_FUNCTION_ARGS) case RELKIND_AOSEGMENTS: case RELKIND_AOVISIMAP: case RELKIND_AOBLOCKDIR: + case RELKIND_DIRECTORY_TABLE: /* okay, these have storage */ /* This logic should match RelationInitPhysicalAddr */ diff --git a/src/backend/utils/adt/pseudotypes.c b/src/backend/utils/adt/pseudotypes.c index c5da77791f6..39729db793c 100644 --- a/src/backend/utils/adt/pseudotypes.c +++ b/src/backend/utils/adt/pseudotypes.c @@ -407,6 +407,7 @@ PSEUDOTYPE_DUMMY_IO_FUNCS(trigger); PSEUDOTYPE_DUMMY_IO_FUNCS(event_trigger); PSEUDOTYPE_DUMMY_IO_FUNCS(language_handler); PSEUDOTYPE_DUMMY_IO_FUNCS(fdw_handler); +PSEUDOTYPE_DUMMY_IO_FUNCS(tblspc_handler); PSEUDOTYPE_DUMMY_IO_FUNCS(table_am_handler); PSEUDOTYPE_DUMMY_IO_FUNCS(index_am_handler); PSEUDOTYPE_DUMMY_IO_FUNCS(tsm_handler); diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index e10ebdb77da..6d38a2d0de2 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -2488,6 +2488,7 @@ schema_get_xml_visible_tables(Oid nspid) appendStringInfo(&query, "SELECT oid FROM pg_catalog.pg_class" " WHERE relnamespace = %u AND relkind IN (" CppAsString2(RELKIND_RELATION) "," + CppAsString2(RELKIND_DIRECTORY_TABLE) "," CppAsString2(RELKIND_MATVIEW) "," CppAsString2(RELKIND_VIEW) ")" " AND pg_catalog.has_table_privilege (oid, 'SELECT')" @@ -2520,6 +2521,7 @@ database_get_xml_visible_tables(void) return query_to_oid_list("SELECT oid FROM pg_catalog.pg_class" " WHERE relkind IN (" CppAsString2(RELKIND_RELATION) "," + CppAsString2(RELKIND_DIRECTORY_TABLE) "," CppAsString2(RELKIND_MATVIEW) "," CppAsString2(RELKIND_VIEW) ")" " AND pg_catalog.has_table_privilege(pg_class.oid, 'SELECT')" diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 1cb10c8d7f5..ebec2de5f07 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -1238,6 +1238,7 @@ RelationBuildDesc(Oid targetRelId, bool insertIt) case RELKIND_RELATION: case RELKIND_TOASTVALUE: case RELKIND_MATVIEW: + case RELKIND_DIRECTORY_TABLE: Assert(relation->rd_rel->relam != InvalidOid); RelationInitTableAccessMethod(relation); break; @@ -1281,7 +1282,8 @@ RelationBuildDesc(Oid targetRelId, bool insertIt) if ((relation->rd_rel->relkind == RELKIND_RELATION && !IsSystemRelation(relation)) || relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE || relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE || - relation->rd_rel->relkind == RELKIND_MATVIEW) + relation->rd_rel->relkind == RELKIND_MATVIEW || + relation->rd_rel->relkind == RELKIND_DIRECTORY_TABLE) { /* * There are many memory allocations in GpPolicyFetch(), especially @@ -3714,6 +3716,7 @@ RelationBuildLocalRelation(const char *relname, if (!IsCatalogNamespace(relnamespace) && (relkind == RELKIND_RELATION || relkind == RELKIND_MATVIEW || + relkind == RELKIND_DIRECTORY_TABLE || relkind == RELKIND_PARTITIONED_TABLE)) rel->rd_rel->relreplident = REPLICA_IDENTITY_DEFAULT; else @@ -3785,6 +3788,7 @@ RelationBuildLocalRelation(const char *relname, MemoryContextSwitchTo(oldcxt); if (relkind == RELKIND_RELATION || + relkind == RELKIND_DIRECTORY_TABLE || relkind == RELKIND_SEQUENCE || relkind == RELKIND_TOASTVALUE || relkind == RELKIND_MATVIEW) @@ -3900,6 +3904,7 @@ RelationSetNewRelfilenode(Relation relation, char persistence) case RELKIND_RELATION: case RELKIND_TOASTVALUE: case RELKIND_MATVIEW: + case RELKIND_DIRECTORY_TABLE: table_relation_set_new_filenode(relation, &newrnode, persistence, &freezeXid, &minmulti); @@ -4395,7 +4400,8 @@ RelationCacheInitializePhase3(void) (relation->rd_rel->relkind == RELKIND_RELATION || relation->rd_rel->relkind == RELKIND_SEQUENCE || relation->rd_rel->relkind == RELKIND_TOASTVALUE || - relation->rd_rel->relkind == RELKIND_MATVIEW)) + relation->rd_rel->relkind == RELKIND_MATVIEW || + relation->rd_rel->relkind == RELKIND_DIRECTORY_TABLE)) { RelationInitTableAccessMethod(relation); Assert(relation->rd_tableam != NULL); @@ -6325,6 +6331,7 @@ load_relcache_init_file(bool shared) /* Load table AM data */ if (rel->rd_rel->relkind == RELKIND_RELATION || + rel->rd_rel->relkind == RELKIND_DIRECTORY_TABLE || rel->rd_rel->relkind == RELKIND_SEQUENCE || rel->rd_rel->relkind == RELKIND_TOASTVALUE || rel->rd_rel->relkind == RELKIND_MATVIEW) diff --git a/src/backend/utils/cache/spccache.c b/src/backend/utils/cache/spccache.c index 5870f436df8..afc784e8f3d 100644 --- a/src/backend/utils/cache/spccache.c +++ b/src/backend/utils/cache/spccache.c @@ -34,13 +34,6 @@ /* Hash table for information about each tablespace */ static HTAB *TableSpaceCacheHash = NULL; -typedef struct -{ - Oid oid; /* lookup key - must be first */ - TableSpaceOpts *opts; /* options, or NULL if none */ -} TableSpaceCacheEntry; - - /* * InvalidateTableSpaceCacheCallback * Flush all cache entries when pg_tablespace is updated. @@ -102,7 +95,7 @@ InitializeTableSpaceCache(void) * Pointers returned by this function should not be stored, since a cache * flush will invalidate them. */ -static TableSpaceCacheEntry * +TableSpaceCacheEntry * get_tablespace(Oid spcid) { TableSpaceCacheEntry *spc; diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c index 3f39c506a76..f81c922e3fc 100644 --- a/src/backend/utils/cache/syscache.c +++ b/src/backend/utils/cache/syscache.c @@ -40,6 +40,7 @@ #include "catalog/pg_default_acl.h" #include "catalog/pg_depend.h" #include "catalog/pg_description.h" +#include "catalog/pg_directory_table.h" #include "catalog/pg_enum.h" #include "catalog/pg_event_trigger.h" #include "catalog/pg_foreign_data_wrapper.h" @@ -78,6 +79,8 @@ #include "catalog/pg_ts_template.h" #include "catalog/pg_type.h" #include "catalog/pg_user_mapping.h" +#include "catalog/gp_storage_user_mapping.h" +#include "catalog/gp_storage_server.h" #include "lib/qunique.h" #include "utils/catcache.h" #include "utils/rel.h" @@ -497,6 +500,28 @@ static const struct cachedesc cacheinfo[] = { }, 2 }, + {StorageServerRelationId, /* STORAGESERVERNAME */ + StorageServerNameIndexId, + 1, + { + Anum_gp_storage_server_srvname, + 0, + 0, + 0 + }, + 2 + }, + {StorageServerRelationId, /* STORAGESERVEROID */ + StorageServerOidIndexId, + 1, + { + Anum_gp_storage_server_oid, + 0, + 0, + 0 + }, + 2 + }, {ForeignTableRelationId, /* FOREIGNTABLEREL */ ForeignTableRelidIndexId, 1, @@ -1070,6 +1095,39 @@ static const struct cachedesc cacheinfo[] = { }, 64 }, + {DirectoryTableRelationId, /* DIRECTORYTABLEREL */ + DirectoryTableRelidIndexId, + 1, + { + Anum_pg_directory_table_dtrelid, + 0, + 0, + 0 + }, + 4 + }, + {StorageUserMappingRelationId, /* STORAGEUSERMAPPINGOID */ + StorageUserMappingOidIndexId, + 1, + { + Anum_gp_storage_user_mapping_oid, + 0, + 0, + 0 + }, + 2 + }, + {StorageUserMappingRelationId, /* STORAGEUSERMAPPINGUSERSERVER */ + StorageUserMappingServerIndexId, + 2, + { + Anum_gp_storage_user_mapping_umuser, + Anum_gp_storage_user_mapping_umserver, + 0, + 0 + }, + 2 + }, {UserMappingRelationId, /* USERMAPPINGOID */ UserMappingOidIndexId, 1, diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index a80f80aef6e..220e908ad3e 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -1797,7 +1797,7 @@ setup_privileges(FILE *cmdfd) " ) as a) " " WHERE relkind IN (" CppAsString2(RELKIND_RELATION) ", " CppAsString2(RELKIND_VIEW) ", " CppAsString2(RELKIND_MATVIEW) ", " - CppAsString2(RELKIND_SEQUENCE) ")" + CppAsString2(RELKIND_SEQUENCE) ", " CppAsString2(RELKIND_DIRECTORY_TABLE) ")" " AND relacl IS NULL;\n\n", "GRANT USAGE ON SCHEMA pg_catalog TO PUBLIC;\n\n", "GRANT CREATE, USAGE ON SCHEMA public TO PUBLIC;\n\n", @@ -1816,7 +1816,7 @@ setup_privileges(FILE *cmdfd) " relacl IS NOT NULL" " AND relkind IN (" CppAsString2(RELKIND_RELATION) ", " CppAsString2(RELKIND_VIEW) ", " CppAsString2(RELKIND_MATVIEW) ", " - CppAsString2(RELKIND_SEQUENCE) ");\n\n", + CppAsString2(RELKIND_SEQUENCE) ", " CppAsString2(RELKIND_DIRECTORY_TABLE) ");\n\n", "INSERT INTO pg_init_privs " " (objoid, classoid, objsubid, initprivs, privtype)" " SELECT" @@ -1832,7 +1832,7 @@ setup_privileges(FILE *cmdfd) " pg_attribute.attacl IS NOT NULL" " AND pg_class.relkind IN (" CppAsString2(RELKIND_RELATION) ", " CppAsString2(RELKIND_VIEW) ", " CppAsString2(RELKIND_MATVIEW) ", " - CppAsString2(RELKIND_SEQUENCE) ");\n\n", + CppAsString2(RELKIND_SEQUENCE) ", " CppAsString2(RELKIND_DIRECTORY_TABLE) ");\n\n", "INSERT INTO pg_init_privs " " (objoid, classoid, objsubid, initprivs, privtype)" " SELECT" diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c index 38e6d321b1c..1b2ba109c8e 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -1754,7 +1754,40 @@ dumpTablespaces(PGconn *conn) return; } - if (server_version >= 90600) + if (server_version >= 140000) + { + res = executeQuery(conn, "SELECT oid, spcname, " + "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, " + "pg_catalog.pg_tablespace_location(oid), " + "(SELECT array_agg(acl ORDER BY row_n) FROM " + " (SELECT acl, row_n FROM " + " unnest(coalesce(spcacl,acldefault('t',spcowner))) " + " WITH ORDINALITY AS perm(acl,row_n) " + " WHERE NOT EXISTS ( " + " SELECT 1 " + " FROM unnest(acldefault('t',spcowner)) " + " AS init(init_acl) " + " WHERE acl = init_acl)) AS spcacls) " + " AS spcacl, " + "(SELECT array_agg(acl ORDER BY row_n) FROM " + " (SELECT acl, row_n FROM " + " unnest(acldefault('t',spcowner)) " + " WITH ORDINALITY AS initp(acl,row_n) " + " WHERE NOT EXISTS ( " + " SELECT 1 " + " FROM unnest(coalesce(spcacl,acldefault('t',spcowner))) " + " AS permp(orig_acl) " + " WHERE acl = orig_acl)) AS rspcacls) " + " AS rspcacl, " + "array_to_string(spcoptions, ', ')," + "pg_catalog.shobj_description(oid, 'pg_tablespace'), " + "spcfilehandlersrc AS spchandlersrc, " + "spcfilehandlerbin AS spchandlerbin " + "FROM pg_catalog.pg_tablespace " + "WHERE spcname !~ '^pg_' " + "ORDER BY 1"); + } + else if (server_version >= 90600) res = executeQuery(conn, "SELECT oid, spcname, " "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, " "pg_catalog.pg_tablespace_location(oid), " @@ -1779,7 +1812,7 @@ dumpTablespaces(PGconn *conn) " WHERE acl = orig_acl)) AS rspcacls) " " AS rspcacl, " "array_to_string(spcoptions, ', ')," - "pg_catalog.shobj_description(oid, 'pg_tablespace') " + "pg_catalog.shobj_description(oid, 'pg_tablespace'), null " "FROM pg_catalog.pg_tablespace " "WHERE spcname !~ '^pg_' " "ORDER BY 1"); @@ -1789,7 +1822,7 @@ dumpTablespaces(PGconn *conn) "pg_catalog.pg_tablespace_location(oid), " "spcacl, '' as rspcacl, " "array_to_string(spcoptions, ', ')," - "pg_catalog.shobj_description(oid, 'pg_tablespace') " + "pg_catalog.shobj_description(oid, 'pg_tablespace'), null " "FROM pg_catalog.pg_tablespace " "WHERE spcname !~ '^pg_' " "ORDER BY 1"); @@ -1798,7 +1831,7 @@ dumpTablespaces(PGconn *conn) "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, " "spclocation, spcacl, '' as rspcacl, " "array_to_string(spcoptions, ', ')," - "pg_catalog.shobj_description(oid, 'pg_tablespace') " + "pg_catalog.shobj_description(oid, 'pg_tablespace'), null " "FROM pg_catalog.pg_tablespace " "WHERE spcname !~ '^pg_' " "ORDER BY 1"); @@ -1806,7 +1839,7 @@ dumpTablespaces(PGconn *conn) res = executeQuery(conn, "SELECT oid, spcname, " "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, " "spclocation, spcacl, '' as rspcacl, null, " - "pg_catalog.shobj_description(oid, 'pg_tablespace') " + "pg_catalog.shobj_description(oid, 'pg_tablespace'), null " "FROM pg_catalog.pg_tablespace " "WHERE spcname !~ '^pg_' " "ORDER BY 1"); @@ -1816,7 +1849,7 @@ dumpTablespaces(PGconn *conn) res = executeQuery(conn, "SELECT oid, spcname, " "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, " "spclocation, spcacl, '' as rspcacl, " - "null, null " + "null, null, null " "FROM pg_catalog.pg_tablespace " "WHERE spcname !~ '^pg_' " "ORDER BY 1"); @@ -1836,6 +1869,8 @@ dumpTablespaces(PGconn *conn) char *rspcacl = PQgetvalue(res, i, 5); char *spcoptions = PQgetvalue(res, i, 6); char *spccomment = PQgetvalue(res, i, 7); + char *spchandlersrc = PQgetvalue(res, i, 8); + char *spchandlerbin = PQgetvalue(res, i, 9); char *fspcname; /* needed for buildACLCommands() */ @@ -1846,6 +1881,13 @@ dumpTablespaces(PGconn *conn) appendPQExpBufferStr(buf, " LOCATION "); appendStringLiteralConn(buf, spclocation, conn); + if (spchandlerbin && spchandlerbin[0] != '\0') + { + appendPQExpBufferStr(buf, " HANDLER "); + appendStringLiteralConn(buf, spchandlerbin, conn); + appendPQExpBufferStr(buf, ", "); + appendStringLiteralConn(buf, spchandlersrc, conn); + } appendPQExpBufferStr(buf, ";\n"); if (spcoptions && spcoptions[0] != '\0') diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index fef6aa4c60a..61d23dade87 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -849,6 +849,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) case 'm': case 'i': case 's': + case 'Y': case 'E': /* PostgreSQL use dx for extension, change to dE for foreign table */ success = listTables(&cmd[1], pattern, show_verbose, show_system); break; diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 303df0068c7..5de2cefdb75 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -1330,6 +1330,7 @@ permissionsList(const char *pattern) " c.relname as \"%s\",\n" " CASE c.relkind" " WHEN " CppAsString2(RELKIND_RELATION) " THEN '%s'" + " WHEN " CppAsString2(RELKIND_DIRECTORY_TABLE) " THEN '%s'" " WHEN " CppAsString2(RELKIND_VIEW) " THEN '%s'" " WHEN " CppAsString2(RELKIND_MATVIEW) " THEN '%s'" " WHEN " CppAsString2(RELKIND_SEQUENCE) " THEN '%s'" @@ -1340,6 +1341,7 @@ permissionsList(const char *pattern) gettext_noop("Schema"), gettext_noop("Name"), gettext_noop("table"), + gettext_noop("directory table"), gettext_noop("view"), gettext_noop("materialized view"), gettext_noop("sequence"), @@ -1427,6 +1429,7 @@ permissionsList(const char *pattern) " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n" "WHERE c.relkind IN (" CppAsString2(RELKIND_RELATION) "," + CppAsString2(RELKIND_DIRECTORY_TABLE) "," CppAsString2(RELKIND_VIEW) "," CppAsString2(RELKIND_MATVIEW) "," CppAsString2(RELKIND_SEQUENCE) "," @@ -2315,6 +2318,7 @@ describeOneTableDetails(const char *schemaname, /* Identify whether we should print collation, nullable, default vals */ if (tableinfo.relkind == RELKIND_RELATION || + tableinfo.relkind == RELKIND_DIRECTORY_TABLE || tableinfo.relkind == RELKIND_VIEW || tableinfo.relkind == RELKIND_MATVIEW || tableinfo.relkind == RELKIND_FOREIGN_TABLE || @@ -2403,6 +2407,7 @@ describeOneTableDetails(const char *schemaname, /* stats target, if relevant to relkind */ if (tableinfo.relkind == RELKIND_RELATION || + tableinfo.relkind == RELKIND_DIRECTORY_TABLE || tableinfo.relkind == RELKIND_INDEX || tableinfo.relkind == RELKIND_PARTITIONED_INDEX || tableinfo.relkind == RELKIND_MATVIEW || @@ -2427,6 +2432,7 @@ describeOneTableDetails(const char *schemaname, * types, and foreign tables (cf. CommentObject() in comment.c). */ if (tableinfo.relkind == RELKIND_RELATION || + tableinfo.relkind == RELKIND_DIRECTORY_TABLE || tableinfo.relkind == RELKIND_VIEW || tableinfo.relkind == RELKIND_MATVIEW || tableinfo.relkind == RELKIND_FOREIGN_TABLE || @@ -2463,6 +2469,10 @@ describeOneTableDetails(const char *schemaname, printfPQExpBuffer(&title, _("Table \"%s.%s\""), schemaname, relationname); break; + case RELKIND_DIRECTORY_TABLE: + printfPQExpBuffer(&title, _("Directory able \"%s.%s\""), + schemaname, relationname); + break; case RELKIND_VIEW: printfPQExpBuffer(&title, _("View \"%s.%s\""), schemaname, relationname); @@ -2917,6 +2927,7 @@ describeOneTableDetails(const char *schemaname, } /* If you add relkinds here, see also "Finish printing..." stanza below */ else if (tableinfo.relkind == RELKIND_RELATION || + tableinfo.relkind == RELKIND_DIRECTORY_TABLE || tableinfo.relkind == RELKIND_MATVIEW || tableinfo.relkind == RELKIND_FOREIGN_TABLE || tableinfo.relkind == RELKIND_PARTITIONED_TABLE || @@ -3859,6 +3870,7 @@ describeOneTableDetails(const char *schemaname, * Finish printing the footer information about a table. */ if (tableinfo.relkind == RELKIND_RELATION || + tableinfo.relkind == RELKIND_DIRECTORY_TABLE || tableinfo.relkind == RELKIND_MATVIEW || tableinfo.relkind == RELKIND_FOREIGN_TABLE || tableinfo.relkind == RELKIND_PARTITIONED_TABLE || @@ -4937,6 +4949,7 @@ listDbRoleSettings(const char *pattern, const char *pattern2) * m - materialized views * s - sequences * E - foreign table (Note: different from 'f', the relkind value) + * Y - directory table * (any order of the above is fine) */ bool @@ -4949,6 +4962,7 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys bool showMatViews = strchr(tabtypes, 'm') != NULL; bool showSeq = strchr(tabtypes, 's') != NULL; bool showForeign = strchr(tabtypes, 'E') != NULL; + bool showDirectory = strchr(tabtypes, 'Y') != NULL; PQExpBufferData buf; PGresult *res; @@ -4957,8 +4971,8 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys bool translate_columns[] = {false, false, true, false, false, false, false, false, false}; /* If tabtypes is empty, we default to \dtvmsE (but see also command.c) */ - if (!(showTables || showIndexes || showViews || showMatViews || showSeq || showForeign)) - showTables = showViews = showMatViews = showSeq = showForeign = true; + if (!(showTables || showIndexes || showViews || showMatViews || showSeq || showForeign || showDirectory)) + showTables = showViews = showMatViews = showSeq = showForeign = showDirectory = true; bool showExternal = showForeign; @@ -4979,6 +4993,7 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys " c.relname as \"%s\",\n" " CASE c.relkind" " WHEN " CppAsString2(RELKIND_RELATION) " THEN '%s'" + " WHEN " CppAsString2(RELKIND_DIRECTORY_TABLE) " THEN '%s'" " WHEN " CppAsString2(RELKIND_VIEW) " THEN '%s'" " WHEN " CppAsString2(RELKIND_MATVIEW) " THEN '%s'" " WHEN " CppAsString2(RELKIND_INDEX) " THEN '%s'" @@ -4992,6 +5007,7 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys gettext_noop("Schema"), gettext_noop("Name"), gettext_noop("table"), + gettext_noop("directory table"), gettext_noop("view"), gettext_noop("materialized view"), gettext_noop("index"), @@ -5113,6 +5129,8 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys if (showSystem || pattern) appendPQExpBufferStr(&buf, CppAsString2(RELKIND_TOASTVALUE) ","); } + if (showDirectory) + appendPQExpBufferStr(&buf, CppAsString2(RELKIND_DIRECTORY_TABLE) ","); if (showViews) appendPQExpBufferStr(&buf, CppAsString2(RELKIND_VIEW) ","); if (showMatViews) diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index 0da375e667c..20a59a6ee6f 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -470,6 +470,14 @@ static const SchemaQuery Query_for_list_of_tables = { .result = "pg_catalog.quote_ident(c.relname)", }; +static const SchemaQuery Query_for_list_of_directory_tables = { + .catname = "pg_catalog.pg_class c", + .selcondition = "c.relkind IN (" CppAsString2(RELKIND_DIRECTORY_TABLE) ")", + .viscondition = "pg_catalog.pg_table_is_visible(c.oid)", + .namespace = "c.relnamespace", + .result = "pg_catalog.quote_ident(c.relname)", +}; + static const SchemaQuery Query_for_list_of_partitioned_tables = { .catname = "pg_catalog.pg_class c", .selcondition = "c.relkind IN (" CppAsString2(RELKIND_PARTITIONED_TABLE) ")", @@ -556,6 +564,7 @@ static const SchemaQuery Query_for_list_of_selectables = { .catname = "pg_catalog.pg_class c", .selcondition = "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", " + CppAsString2(RELKIND_DIRECTORY_TABLE) ", " CppAsString2(RELKIND_SEQUENCE) ", " CppAsString2(RELKIND_VIEW) ", " CppAsString2(RELKIND_MATVIEW) ", " @@ -586,6 +595,7 @@ static const SchemaQuery Query_for_list_of_analyzables = { .catname = "pg_catalog.pg_class c", .selcondition = "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", " + CppAsString2(RELKIND_DIRECTORY_TABLE) ", " CppAsString2(RELKIND_PARTITIONED_TABLE) ", " CppAsString2(RELKIND_MATVIEW) ", " CppAsString2(RELKIND_FOREIGN_TABLE) ")", @@ -599,6 +609,7 @@ static const SchemaQuery Query_for_list_of_indexables = { .catname = "pg_catalog.pg_class c", .selcondition = "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", " + CppAsString2(RELKIND_DIRECTORY_TABLE) ", " CppAsString2(RELKIND_PARTITIONED_TABLE) ", " CppAsString2(RELKIND_MATVIEW) ")", .viscondition = "pg_catalog.pg_table_is_visible(c.oid)", @@ -617,7 +628,7 @@ static const SchemaQuery Query_for_list_of_clusterables = { .catname = "pg_catalog.pg_class c", .selcondition = "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", " - CppAsString2(RELKIND_MATVIEW) ")", + CppAsString2(RELKIND_MATVIEW) ", " CppAsString2(RELKIND_DIRECTORY_TABLE) ")", .viscondition = "pg_catalog.pg_table_is_visible(c.oid)", .namespace = "c.relnamespace", .result = "pg_catalog.quote_ident(c.relname)", @@ -919,6 +930,11 @@ static const SchemaQuery Query_for_list_of_collations = { " FROM pg_catalog.pg_user_mappings "\ " WHERE substring(pg_catalog.quote_ident(usename),1,%d)='%s'" +#define Query_for_list_of_storage_servers \ +" SELECT pg_catalog.quote_ident(srvname) "\ +" FROM pg_catalog.gp_storage_server "\ +" WHERE substring(pg_catalog.quote_ident(srvname),1,%d)='%s'" + #define Query_for_list_of_access_methods \ " SELECT pg_catalog.quote_ident(amname) "\ " FROM pg_catalog.pg_am "\ @@ -1099,6 +1115,7 @@ static const pgsql_thing_t words_after_create[] = { {"DATABASE", Query_for_list_of_databases}, {"DEFAULT PRIVILEGES", NULL, NULL, NULL, THING_NO_CREATE | THING_NO_DROP}, {"DICTIONARY", Query_for_list_of_ts_dictionaries, NULL, NULL, THING_NO_SHOW}, + {"DIRECTORY TABLE", NULL, NULL, &Query_for_list_of_directory_tables}, {"DOMAIN", NULL, NULL, &Query_for_list_of_domains}, {"EVENT TRIGGER", NULL, NULL, NULL}, {"EXTENSION", Query_for_list_of_extensions}, @@ -1127,6 +1144,7 @@ static const pgsql_thing_t words_after_create[] = { {"SCHEMA", Query_for_list_of_schemas}, {"SEQUENCE", NULL, NULL, &Query_for_list_of_sequences}, {"SERVER", Query_for_list_of_servers}, + {"STORAGE SERVER", Query_for_list_of_storage_servers}, {"STATISTICS", NULL, NULL, &Query_for_list_of_statistics}, {"SUBSCRIPTION", NULL, Query_for_list_of_subscriptions}, {"SYSTEM", NULL, NULL, NULL, THING_NO_CREATE | THING_NO_DROP}, @@ -1148,6 +1166,7 @@ static const pgsql_thing_t words_after_create[] = { * TABLE ... */ {"USER", Query_for_list_of_roles " UNION SELECT 'MAPPING FOR'"}, {"USER MAPPING FOR", NULL, NULL, NULL}, + {"STORAGE USER MAPPING FOR", NULL, NULL, NULL}, {"VIEW", NULL, NULL, &Query_for_list_of_views}, {"WAREHOUSE", NULL}, {NULL} /* end of list */ @@ -1808,6 +1827,20 @@ psql_completion(const char *text, int start, int end) "INHERIT", "NO INHERIT", "OPTIONS", "OWNER TO", "RENAME", "SET", "VALIDATE CONSTRAINT"); + /* ALTER STORAGE */ + else if (Matches("ALTER", "STORAGE")) + COMPLETE_WITH("SERVER", "USER MAPPING"); + + /* ALTER DIRECTORY */ + else if (Matches("ALTER", "DIRECTORY")) + COMPLETE_WITH("TABLE"); + + /* ALTER DIRECTORY TABLE */ + else if (Matches("ALTER", "DIRECTORY", "TABLE", MatchAny)) + COMPLETE_WITH("ALTER", "DISABLE TRIGGER", "ENABLE", + "OPTIONS", "OWNER TO", + "RENAME", "SET"); + /* ALTER INDEX */ else if (Matches("ALTER", "INDEX")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, @@ -1966,6 +1999,9 @@ psql_completion(const char *text, int start, int end) /* ALTER SERVER */ else if (Matches("ALTER", "SERVER", MatchAny)) COMPLETE_WITH("VERSION", "OPTIONS", "OWNER TO", "RENAME TO"); + /* ALTER STORAGE SERVER */ + else if (Matches("ALTER", "STORAGE", "SERVER", MatchAny)) + COMPLETE_WITH("OPTIONS", "RENAME TO"); /* ALTER SERVER VERSION */ else if (Matches("ALTER", "SERVER", MatchAny, "VERSION", MatchAny)) COMPLETE_WITH("OPTIONS"); @@ -2418,7 +2454,7 @@ psql_completion(const char *text, int start, int end) "INDEX", "LANGUAGE", "POLICY", "PUBLICATION", "RULE", "SCHEMA", "SEQUENCE", "STATISTICS", "SUBSCRIPTION", "TABLE", "TYPE", "VIEW", "MATERIALIZED VIEW", - "COLUMN", "AGGREGATE", "FUNCTION", + "COLUMN", "AGGREGATE", "FUNCTION", "STORAGE SERVER", "PROCEDURE", "PROFILE", "ROUTINE", "OPERATOR", "TRIGGER", "CONSTRAINT", "DOMAIN", "LARGE OBJECT", "TABLESPACE", "TEXT SEARCH", "ROLE"); @@ -2561,6 +2597,10 @@ psql_completion(const char *text, int start, int end) else if (TailMatches("CREATE", "UNIQUE")) COMPLETE_WITH("INDEX"); + /* CREATE STORAGE */ + else if (Matches("CREATE", "STORAGE")) + COMPLETE_WITH("SERVER", "USER MAPPING"); + /* * If we have CREATE|UNIQUE INDEX, then add "ON", "CONCURRENTLY", and * existing indexes @@ -2761,6 +2801,10 @@ psql_completion(const char *text, int start, int end) else if (Matches("CREATE", "SERVER", MatchAny)) COMPLETE_WITH("TYPE", "VERSION", "FOREIGN DATA WRAPPER"); +/* CREATE STORAGE SERVER */ + else if (Matches("CREATE", "STORAGE", "SERVER", MatchAny)) + COMPLETE_WITH("OPTIONS"); + /* CREATE STATISTICS */ else if (Matches("CREATE", "STATISTICS", MatchAny)) COMPLETE_WITH("(", "ON"); @@ -3230,6 +3274,7 @@ psql_completion(const char *text, int start, int end) Matches("DROP", "EVENT", "TRIGGER", MatchAny) || Matches("DROP", "FOREIGN", "DATA", "WRAPPER", MatchAny) || Matches("DROP", "FOREIGN", "TABLE", MatchAny) || + Matches("DROP", "DIRECTORY", "TABLE", MatchAny) || Matches("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny)) COMPLETE_WITH("CASCADE", "RESTRICT"); @@ -3262,6 +3307,15 @@ psql_completion(const char *text, int start, int end) else if (Matches("DROP", "MATERIALIZED", "VIEW")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL); + /* DROP STORAGE */ + else if (Matches("DROP", "STORAGE")) + COMPLETE_WITH("SERVER", "USER MAPPING"); + /* DROP DIRECTORY TABLE */ + else if (Matches("DROP", "DIRECTORY")) + COMPLETE_WITH("TABLE"); + else if (Matches("DROP", "DIRECTORY", "TABLE")) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_directory_tables, NULL); + /* DROP OWNED BY */ else if (Matches("DROP", "OWNED")) COMPLETE_WITH("BY"); @@ -3423,6 +3477,10 @@ psql_completion(const char *text, int start, int end) else if (TailMatches("FOREIGN", "SERVER")) COMPLETE_WITH_QUERY(Query_for_list_of_servers); +/* STORAGE SERVER */ + else if (TailMatches("ALTER", "STORAGE", "SERVER")) + COMPLETE_WITH_QUERY(Query_for_list_of_storage_servers); + /* * GRANT and REVOKE are allowed inside CREATE SCHEMA and * ALTER DEFAULT PRIVILEGES, so use TailMatches @@ -3809,7 +3867,7 @@ psql_completion(const char *text, int start, int end) else if (Matches("SECURITY", "LABEL", "ON") || Matches("SECURITY", "LABEL", "FOR", MatchAny, "ON")) COMPLETE_WITH("TABLE", "COLUMN", "AGGREGATE", "DATABASE", "DOMAIN", - "EVENT TRIGGER", "FOREIGN TABLE", "FUNCTION", + "EVENT TRIGGER", "FOREIGN TABLE", "DIRECTORY TABLE", "FUNCTION", "LARGE OBJECT", "MATERIALIZED VIEW", "LANGUAGE", "PUBLICATION", "PROCEDURE", "ROLE", "ROUTINE", "SCHEMA", "SEQUENCE", "SUBSCRIPTION", "TABLESPACE", "TYPE", "VIEW"); @@ -4000,6 +4058,19 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH("SERVER"); else if (Matches("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny)) COMPLETE_WITH("OPTIONS"); +/* STORAGE USER MAPPING */ + else if (Matches("ALTER|CREATE|DROP", "STORAGE", "USER", "MAPPING")) + COMPLETE_WITH("FOR"); + else if (Matches("CREATE", "STORAGE", "USER", "MAPPING", "FOR")) + COMPLETE_WITH_QUERY(Query_for_list_of_roles + " UNION SELECT 'CURRENT_ROLE'" + " UNION SELECT 'CURRENT_USER'" + " UNION SELECT 'PUBLIC'" + " UNION SELECT 'USER'"); + else if (Matches("CREATE|ALTER|DROP", "STORAGE", "USER", "MAPPING", "FOR", MatchAny)) + COMPLETE_WITH("STORAGE SERVER"); + else if (Matches("CREATE|ALTER", "STORAGE", "USER", "MAPPING", "FOR", MatchAny, "STORAGE", "SERVER", MatchAny)) + COMPLETE_WITH("OPTIONS"); /* * VACUUM [ ( option [, ...] ) ] [ table_and_columns [, ...] ] @@ -4157,6 +4228,8 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL); else if (TailMatchesCS("\\dE*")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL); + else if (TailMatchesCS("\\dY*")) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_directory_tables, NULL); else if (TailMatchesCS("\\dy*")) COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers); @@ -4195,6 +4268,8 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH("TRIGGER"); else if (TailMatches("CREATE|ALTER|DROP", "FOREIGN")) COMPLETE_WITH("DATA WRAPPER", "TABLE"); + else if (TailMatches("CREATE|ALTER|DROP", "DIRECTORY")) + COMPLETE_WITH("TABLE"); else if (TailMatches("ALTER", "LARGE")) COMPLETE_WITH("OBJECT"); else if (TailMatches("CREATE|ALTER|DROP", "MATERIALIZED")) @@ -4203,6 +4278,8 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH("SEARCH"); else if (TailMatches("CREATE|ALTER|DROP", "USER")) COMPLETE_WITH("MAPPING FOR"); + else if (TailMatches("CREATE|ALTER|DROP", "STORAGE", "USER")) + COMPLETE_WITH("MAPPING FOR"); } else if (TailMatchesCS("\\h|\\help", MatchAny, MatchAny, MatchAny)) { @@ -4212,6 +4289,8 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE"); else if (TailMatches("CREATE|ALTER|DROP", "USER", "MAPPING")) COMPLETE_WITH("FOR"); + else if (TailMatches("CREATE|ALTER|DROP", "STORAGE", "USER", "MAPPING")) + COMPLETE_WITH("FOR"); } else if (TailMatchesCS("\\l*") && !TailMatchesCS("\\lo*")) COMPLETE_WITH_QUERY(Query_for_list_of_databases); diff --git a/src/bin/scripts/reindexdb.c b/src/bin/scripts/reindexdb.c index 7638b01fbdd..22355d38974 100644 --- a/src/bin/scripts/reindexdb.c +++ b/src/bin/scripts/reindexdb.c @@ -669,6 +669,7 @@ get_parallel_object_list(PGconn *conn, ReindexType type, " WHERE ns.nspname != 'pg_catalog'\n" " AND c.relkind IN (" CppAsString2(RELKIND_RELATION) ", " + CppAsString2(RELKIND_DIRECTORY_TABLE) ", " CppAsString2(RELKIND_MATVIEW) ")\n" " ORDER BY c.relpages DESC;"); break; @@ -691,6 +692,7 @@ get_parallel_object_list(PGconn *conn, ReindexType type, " ON c.relnamespace = ns.oid\n" " WHERE c.relkind IN (" CppAsString2(RELKIND_RELATION) ", " + CppAsString2(RELKIND_DIRECTORY_TABLE) ", " CppAsString2(RELKIND_MATVIEW) ")\n" " AND ns.nspname IN ("); diff --git a/src/bin/scripts/vacuumdb.c b/src/bin/scripts/vacuumdb.c index a85919c5c19..04a7273b0a0 100644 --- a/src/bin/scripts/vacuumdb.c +++ b/src/bin/scripts/vacuumdb.c @@ -627,6 +627,7 @@ vacuum_one_database(ConnParams *cparams, { appendPQExpBufferStr(&catalog_query, " WHERE c.relkind OPERATOR(pg_catalog.=) ANY (array[" CppAsString2(RELKIND_RELATION) ", " + CppAsString2(RELKIND_DIRECTORY_TABLE) ", " CppAsString2(RELKIND_MATVIEW) "])\n"); has_where = true; } diff --git a/src/common/md5_common.c b/src/common/md5_common.c index 2114890effe..2e03f893999 100644 --- a/src/common/md5_common.c +++ b/src/common/md5_common.c @@ -24,7 +24,7 @@ #include "common/cryptohash.h" #include "common/md5.h" -static void +void bytesToHex(uint8 b[16], char *s) { static const char *hex = "0123456789abcdef"; diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index fce6ebfd8ee..da23a4c701f 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -56,6 +56,6 @@ */ /* 3yyymmddN */ -#define CATALOG_VERSION_NO 302206171 +#define CATALOG_VERSION_NO 302402231 #endif diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h index a4090f0d2fa..c39c0edfa58 100644 --- a/src/include/catalog/dependency.h +++ b/src/include/catalog/dependency.h @@ -78,6 +78,10 @@ typedef enum DependencyType * is a profile mentioned in a role object. The referenced object must be * a pg_profile entry. * + * (g) a SHARED_DEPENDENCY_STORAGE_SERVER entry means that the referenced + * object is a storage server mentioned in a storage user mapping object. + * The referenced object must be a gp_storage_server entry. + * * SHARED_DEPENDENCY_INVALID is a value used as a parameter in internal * routines, and is not valid in the catalog itself. */ @@ -89,6 +93,7 @@ typedef enum SharedDependencyType SHARED_DEPENDENCY_POLICY = 'r', SHARED_DEPENDENCY_TABLESPACE = 't', SHARED_DEPENDENCY_PROFILE = 'f', + SHARED_DEPENDENCY_STORAGE_SERVER = 's', SHARED_DEPENDENCY_INVALID = 0 } SharedDependencyType; @@ -143,6 +148,9 @@ typedef enum ObjectClass /* GPDB additions */ OCLASS_PROFILE, /* pg_profile */ OCLASS_PASSWORDHISTORY, /* pg_password_history */ + OCLASS_DIRTABLE, /* pg_directory_table */ + OCLASS_STORAGE_SERVER, /* gp_storage_server */ + OCLASS_STORAGE_USER_MAPPING, /* gp_storage_user_mapping */ OCLASS_EXTPROTOCOL, /* pg_extprotocol */ OCLASS_TASK, /* pg_task */ } ObjectClass; @@ -290,6 +298,8 @@ extern void recordProfileDependency(Oid roleId, Oid profileId); extern void changeProfileDependency(Oid roleId, Oid profileId); +extern void recordStorageServerDependency(Oid classId, Oid objectId, Oid srvId); + /* Custom object class */ struct StringInfoData; struct CustomObjectClass { diff --git a/src/include/catalog/gp_storage_server.h b/src/include/catalog/gp_storage_server.h new file mode 100644 index 00000000000..391791ae36d --- /dev/null +++ b/src/include/catalog/gp_storage_server.h @@ -0,0 +1,51 @@ +/*------------------------------------------------------------------------- + * + * gp_storage_server.h + * + * Portions Copyright (c) 2024, HashData Technology Limited. + * + * IDENTIFICATION + * src/include/catalog/gp_storage_server.h + * + *------------------------------------------------------------------------- + */ +#ifndef GP_STORAGE_SERVER_H +#define GP_STORAGE_SERVER_H + +#include "catalog/genbki.h" +#include "catalog/gp_storage_server_d.h" + +/* ---------------- + * gp_storage_server definition. cpp turns this into + * typedef struct FormData_gp_storage_server + * ---------------- + */ +CATALOG(gp_storage_server,6015,StorageServerRelationId) BKI_SHARED_RELATION +{ + Oid oid; /* oid */ + NameData srvname; /* storage server name */ + Oid srvowner BKI_LOOKUP(pg_authid); /* server owner */ + +#ifdef CATALOG_VARLEN /* variable-length fields start here */ + aclitem srvacl[1]; /* access permissions */ + text srvoptions[1]; /* FDW-specific options */ +#endif +} FormData_gp_storage_server; + +/* ---------------- + * Form_gp_storage_server corresponds to a pointer to a tuple with + * the format of gp_storage_server relation. + * ---------------- + */ +typedef FormData_gp_storage_server *Form_gp_storage_server; + +DECLARE_TOAST(gp_storage_server, 6016, 6017); +#define GpStorageServerToastTable 6016 +#define GpStorageServerToastIndex 6017 + +DECLARE_UNIQUE_INDEX_PKEY(gp_storage_server_oid_index, 6018, on gp_storage_server using btree(oid oid_ops)); +#define StorageServerOidIndexId 6018 +DECLARE_UNIQUE_INDEX(gp_storage_server_name_index, 6019, on gp_storage_server using btree(srvname name_ops)); +#define StorageServerNameIndexId 6019 + +#endif //GP_STORAGE_SERVER_H diff --git a/src/include/catalog/gp_storage_user_mapping.h b/src/include/catalog/gp_storage_user_mapping.h new file mode 100644 index 00000000000..a9a18ec1eae --- /dev/null +++ b/src/include/catalog/gp_storage_user_mapping.h @@ -0,0 +1,54 @@ +/*------------------------------------------------------------------------- + * + * gp_storage_user_mapping.h + * + * Portions Copyright (c) 2024, HashData Technology Limited. + * + * IDENTIFICATION + * src/include/catalog/gp_storage_user_mapping.h + * + *------------------------------------------------------------------------- + */ +#ifndef GP_STORAGE_USER_MAPPING_H +#define GP_STORAGE_USER_MAPPING_H + +#include "catalog/genbki.h" +#include "catalog/gp_storage_user_mapping_d.h" + +/* ---------------- + * gp_storage_user_mapping definition. cpp turns this into + * typedef struct FormData_gp_storage_user_mapping + * ---------------- + */ +CATALOG(gp_storage_user_mapping,6131,StorageUserMappingRelationId) BKI_SHARED_RELATION +{ + Oid oid; /* oid */ + + Oid umuser BKI_LOOKUP_OPT(pg_authid); /* Id of the user, + * InvalidOid if PUBLIC is + * wanted */ + Oid umserver BKI_LOOKUP(gp_storage_server); /* server of this + * mapping */ + +#ifdef CATALOG_VARLEN /* variable-length fields start here */ + text umoptions[1]; /* user mapping options */ +#endif +} FormData_gp_storage_user_mapping; + +/* ---------------- + * Form_gp_storage_user_mapping corresponds to a pointer to a tuple with + * the format of gp_storage_user_mapping relation. + * ---------------- + */ +typedef FormData_gp_storage_user_mapping *Form_gp_storage_user_mapping; + +DECLARE_TOAST(gp_storage_user_mapping, 6132, 6133); +#define GpStorageUserMappingToastTable 6132 +#define GpStorageUserMappingToastIndex 6133 + +DECLARE_UNIQUE_INDEX_PKEY(gp_storage_user_mapping_oid_index, 6134, on gp_storage_user_mapping using btree(oid oid_ops)); +#define StorageUserMappingOidIndexId 6134 +DECLARE_UNIQUE_INDEX(gp_storage_user_mapping_server_index, 6135, on gp_storage_user_mapping using btree(umuser oid_ops, umserver oid_ops)); +#define StorageUserMappingServerIndexId 6135 + +#endif //GP_STORAGE_USER_MAPPING_H diff --git a/src/include/catalog/oid_dispatch.h b/src/include/catalog/oid_dispatch.h index bd2fbc261fe..90cc813c6a5 100644 --- a/src/include/catalog/oid_dispatch.h +++ b/src/include/catalog/oid_dispatch.h @@ -63,6 +63,8 @@ extern Oid GetNewOidForForeignDataWrapper(Relation relation, Oid indexId, AttrNu char *fdwname); extern Oid GetNewOidForForeignServer(Relation relation, Oid indexId, AttrNumber oidcolumn, char *srvname); +extern Oid GetNewOidForStorageServer(Relation relation, Oid indexId, AttrNumber oidcolumn, + char *srvname); extern Oid GetNewOidForLanguage(Relation relation, Oid indexId, AttrNumber oidcolumn, char *lanname); extern Oid GetNewOidForNamespace(Relation relation, Oid indexId, AttrNumber oidcolumn, @@ -107,6 +109,8 @@ extern Oid GetNewOidForResGroup(Relation relation, Oid indexId, AttrNumber oidco char *rsgname); extern Oid GetNewOidForUserMapping(Relation relation, Oid indexId, AttrNumber oidcolumn, Oid umuser, Oid umserver); +extern Oid GetNewOidForStorageUserMapping(Relation relation, Oid indexId, AttrNumber oidcolumn, + Oid umuser, Oid umserver); extern Oid GetNewOidForPublication(Relation relation, Oid indexId, AttrNumber oidcolumn, char *pubname); extern Oid GetNewOidForPublicationRel(Relation relation, Oid indexId, AttrNumber oidcolumn, diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h index 813d47fee83..ec525930d57 100644 --- a/src/include/catalog/pg_class.h +++ b/src/include/catalog/pg_class.h @@ -185,6 +185,7 @@ DECLARE_INDEX(pg_class_tblspc_relfilenode_index, 3455, on pg_class using btree(r #define RELKIND_AOSEGMENTS 'o' /* AO segment files and eof's */ #define RELKIND_AOBLOCKDIR 'b' /* AO block directory */ #define RELKIND_AOVISIMAP 'M' /* AO visibility map */ +#define RELKIND_DIRECTORY_TABLE 'd' /* directory table */ #define RELPERSISTENCE_PERMANENT 'p' /* regular table */ #define RELPERSISTENCE_UNLOGGED 'u' /* unlogged permanent table */ @@ -210,6 +211,7 @@ DECLARE_INDEX(pg_class_tblspc_relfilenode_index, 3455, on pg_class using btree(r */ #define RELKIND_HAS_STORAGE(relkind) \ ((relkind) == RELKIND_RELATION || \ + (relkind) == RELKIND_DIRECTORY_TABLE || \ (relkind) == RELKIND_INDEX || \ (relkind) == RELKIND_SEQUENCE || \ (relkind) == RELKIND_TOASTVALUE || \ diff --git a/src/include/catalog/pg_directory_table.h b/src/include/catalog/pg_directory_table.h new file mode 100644 index 00000000000..fb8c33d1711 --- /dev/null +++ b/src/include/catalog/pg_directory_table.h @@ -0,0 +1,72 @@ +/*------------------------------------------------------------------------- + * + * pg_directory_table.h + * definition of the "directory table" system catalog (pg_directory_table) + * + * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/catalog/pg_directory_table.h + * + * NOTES + * The Catalog.pm module reads this file and derives schema + * information. + * + *------------------------------------------------------------------------- + */ +#ifndef PG_DIRECTORY_TABLE_H +#define PG_DIRECTORY_TABLE_H + +#include "access/table.h" +#include "catalog/genbki.h" +#include "catalog/pg_directory_table_d.h" +#include "nodes/parsenodes.h" +#include "storage/ufile.h" + +/* ---------------- + * pg_directory_table definition. cpp turns this into + * typedef struct FormData_pg_directory_table + * ---------------- + */ +CATALOG(pg_directory_table,8545,DirectoryTableRelationId) +{ + /* OID of directory table */ + Oid dtrelid BKI_LOOKUP(pg_class); + + /* identifier of table space for relation (0 means default for database) */ + Oid dttablespace BKI_DEFAULT(0) BKI_LOOKUP_OPT(pg_tablespace); +#ifdef CATALOG_VARLEN /* variable-length fields start here */ + text dtlocation; /* directory table location */ +#endif +} FormData_pg_directory_table; + +/* ---------------- + * Form_pg_directory_table corresponds to a pointer to a tuple with + * the format of pg_directory_table relation. + * ---------------- + */ +typedef FormData_pg_directory_table *Form_pg_directory_table; + +DECLARE_TOAST(pg_directory_table, 8546, 8547); + +DECLARE_UNIQUE_INDEX_PKEY(pg_directory_table_relid_index, 8548, on pg_directory_table using btree(dtrelid oid_ops)); +#define DirectoryTableRelidIndexId 8548 + +typedef struct DirectoryTable +{ + Oid relId; /* relation Oid */ + Oid spcId; /* tablespace Oid */ + char *location; /* location */ +} DirectoryTable; + +#define DIRECTORY_TABLE_TAG_COLUMN_ATTNUM 5 + +extern DirectoryTable *GetDirectoryTable(Oid relId); +extern bool RelationIsDirectoryTable(Oid relId); +extern List *GetDirectoryTableSchema(void); +extern DistributedBy *GetDirectoryTableDistributedBy(void); +extern Oid CreateDirectoryTableIndex(Relation rel); +extern void RemoveDirectoryTableEntry(Oid relId); +extern FileAm *GetTablespaceFileHandler(Oid spcId); + +#endif /* PG_DIRECTORY_TABLE_H */ diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index d0f32a6f433..67c37b223fd 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -7375,6 +7375,12 @@ { oid => '3117', descr => 'I/O', proname => 'fdw_handler_out', prorettype => 'cstring', proargtypes => 'fdw_handler', prosrc => 'fdw_handler_out' }, +{ oid => '6451', descr => 'I/O', + proname => 'tblspc_handler_in', proisstrict => 'f', prorettype => 'tblspc_handler', + proargtypes => 'cstring', prosrc => 'tblspc_handler_in' }, +{ oid => '6452', descr => 'I/O', + proname => 'tblspc_handler_out', prorettype => 'cstring', + proargtypes => 'tblspc_handler', prosrc => 'tblspc_handler_out'}, { oid => '326', descr => 'I/O', proname => 'index_am_handler_in', proisstrict => 'f', prorettype => 'index_am_handler', proargtypes => 'cstring', @@ -11968,6 +11974,14 @@ { oid => 7050, descr => 'bitmap(internal)', proname => 'bmhandler', provolatile => 'v', prorettype => 'index_am_handler', proargtypes => 'internal', prosrc => 'bmhandler' }, +{ oid => 8644, descr => 'table function for directory table', + proname => 'directory_table', prorows => '1000', proretset => 't', provolatile => 'v', proparallel => 'u', prorettype => 'record', proargtypes => 'regclass', proallargtypes => '{regclass,text,text,text,int8,timestamptz,text,bytea}', proargmodes => '{i,o,o,o,o,o,o,o}', proargnames => '{relid,scoped_file_url,relative_path,tag,size,last_modified,md5,content}', prosrc => 'directory_table', proexeclocation => 's' }, + +{ oid => 8996, descr => 'delete a file in a directory table', + proname => 'remove_file', provolatile => 'v', prorettype => 'bool', proargtypes => 'regclass cstring', prosrc => 'remove_file' }, + +{ oid => 9109, descr => 'delete a file in a directory table on segment', + proname => 'remove_file_segment', provolatile => 'v', prorettype => 'bool', proargtypes => 'regclass cstring', prosrc => 'remove_file_segment', proexeclocation => 's' }, # AOCS functions. { oid => 9900, descr => 'decode internal AOCSVPInfo struct', diff --git a/src/include/catalog/pg_tablespace.h b/src/include/catalog/pg_tablespace.h index 6791bf536fd..81545837c57 100644 --- a/src/include/catalog/pg_tablespace.h +++ b/src/include/catalog/pg_tablespace.h @@ -37,6 +37,8 @@ CATALOG(pg_tablespace,1213,TableSpaceRelationId) BKI_SHARED_RELATION #ifdef CATALOG_VARLEN /* variable-length fields start here */ aclitem spcacl[1]; /* access permissions */ text spcoptions[1]; /* per-tablespace options */ + text spcfilehandlersrc BKI_DEFAULT(_null_); /* handler function src path */ + text spcfilehandlerbin BKI_DEFAULT(_null_); /* handler function bin path */ #endif } FormData_pg_tablespace; diff --git a/src/include/catalog/pg_type.dat b/src/include/catalog/pg_type.dat index c762c59e16a..ba1afca03e3 100644 --- a/src/include/catalog/pg_type.dat +++ b/src/include/catalog/pg_type.dat @@ -620,6 +620,13 @@ typcategory => 'P', typinput => 'fdw_handler_in', typoutput => 'fdw_handler_out', typreceive => '-', typsend => '-', typalign => 'i' }, +{ + oid => '5102', + descr => 'pseudo-type for the result of a table space handler function', + typname => 'tblspc_handler', typlen => '4', typbyval => 't', typtype => 'p', + typcategory => 'P', typinput => 'tblspc_handler_in', + typoutput => 'tblspc_handler_out', typreceive => '-', typsend => '-', + typalign => 'i' }, { oid => '325', descr => 'pseudo-type for the result of an index AM handler function', typname => 'index_am_handler', typlen => '4', typbyval => 't', typtype => 'p', diff --git a/src/include/catalog/storage_directory_table.h b/src/include/catalog/storage_directory_table.h new file mode 100644 index 00000000000..a73cd8de75d --- /dev/null +++ b/src/include/catalog/storage_directory_table.h @@ -0,0 +1,25 @@ +/*------------------------------------------------------------------------- + * + * Storage manipulation for directory table. + * + * Copyright (c) 2016-Present Hashdata, Inc. + * + * src/include/catalog/storage_directory_table.h + * + *------------------------------------------------------------------------- + */ + +#ifndef STORAGE_DIRECTORY_TABLE_H +#define STORAGE_DIRECTORY_TABLE_H + +#include "utils/relcache.h" + +extern void UFileAddCreatePendingEntry(Relation rel, Oid spcId, char *relativePath); +extern void UFileAddDeletePendingEntry(Relation rel, Oid spcId, char *relativePath); + +extern void UFileDoDeletesActions(bool isCommit); +extern void UFileAtSubCommitSmgr(void); +extern void UFileAtSubAbortSmgr(void); +extern void DirectoryTableDropStorage(Relation rel); + +#endif //STORAGE_DIRECTORY_TABLE_H diff --git a/src/include/commands/copy.h b/src/include/commands/copy.h index d2b51c6ce70..fb278d1329a 100644 --- a/src/include/commands/copy.h +++ b/src/include/commands/copy.h @@ -119,6 +119,7 @@ typedef struct CopyFormatOptions bool delim_off; /* delimiter is set to OFF? */ EolType eol_type; /* EOL type of input */ char *eol_str; /* optional NEWLINE from command. before eol_type is defined */ + char *tags; /* directory table */ SingleRowErrorDesc *sreh; /* end Cloudberry Database specific variables */ } CopyFormatOptions; @@ -143,6 +144,7 @@ extern void DoCopy(ParseState *state, const CopyStmt *stmt, uint64 *processed); extern void ProcessCopyOptions(ParseState *pstate, CopyFormatOptions *ops_out, bool is_from, List *options, Oid rel_oid); +extern void ProcessCopyDirectoryTableOptions(ParseState *pstate, CopyFormatOptions *ops_out, bool is_from, List *options, Oid rel_oid); extern CopyFromState BeginCopyFrom(ParseState *pstate, Relation rel, Node *whereClause, const char *filename, bool is_program, copy_data_source_cb data_source_cb, diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h index 949f8fa0375..f632b4291d1 100644 --- a/src/include/commands/defrem.h +++ b/src/include/commands/defrem.h @@ -131,9 +131,15 @@ extern ObjectAddress CreateForeignDataWrapper(CreateFdwStmt *stmt); extern ObjectAddress AlterForeignDataWrapper(AlterFdwStmt *stmt); extern ObjectAddress CreateForeignServer(CreateForeignServerStmt *stmt); extern ObjectAddress AlterForeignServer(AlterForeignServerStmt *stmt); +extern ObjectAddress CreateStorageServer(CreateStorageServerStmt *stmt); +extern ObjectAddress AlterStorageServer(AlterStorageServerStmt *stmt); +extern Oid RemoveStorageServer(DropStorageServerStmt *stmt); extern ObjectAddress CreateUserMapping(CreateUserMappingStmt *stmt); extern ObjectAddress AlterUserMapping(AlterUserMappingStmt *stmt); extern Oid RemoveUserMapping(DropUserMappingStmt *stmt); +extern ObjectAddress CreateStorageUserMapping(CreateStorageUserMappingStmt *stmt); +extern ObjectAddress AlterStorageUserMapping(AlterStorageUserMappingStmt *stmt); +extern Oid RemoveStorageUserMapping(DropStorageUserMappingStmt *stmt); extern void CreateForeignTable(CreateForeignTableStmt *stmt, Oid relid, bool skip_permission_check); extern void ImportForeignSchema(ImportForeignSchemaStmt *stmt); extern Datum transformGenericOptions(Oid catalogId, diff --git a/src/include/commands/dirtablecmds.h b/src/include/commands/dirtablecmds.h new file mode 100644 index 00000000000..b26043db867 --- /dev/null +++ b/src/include/commands/dirtablecmds.h @@ -0,0 +1,24 @@ +/*------------------------------------------------------------------------- + * + * dirtablecmds.h + * prototypes for dirtablecmds.c. + * + * + * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/commands/dirtablecmds.h + * + *------------------------------------------------------------------------- + */ + +#ifndef DIRTABLECMDS_H +#define DIRTABLECMDS_H + +#include "catalog/objectaddress.h" +#include "nodes/params.h" +#include "parser/parse_node.h" + +void CreateDirectoryTable(CreateDirectoryTableStmt *stmt, Oid relId); + +#endif //DIRTABLECMDS_H diff --git a/src/include/commands/storagecmds.h b/src/include/commands/storagecmds.h new file mode 100644 index 00000000000..6bfd93d3327 --- /dev/null +++ b/src/include/commands/storagecmds.h @@ -0,0 +1,52 @@ +/*------------------------------------------------------------------------- + * + * storagecmds.h + * storage server/user_mapping creation/manipulation commands + * + * Copyright (c) 2016-Present Hashdata, Inc. + * + * + * IDENTIFICATION + * src/include/commands/storagecmds.h + * + *------------------------------------------------------------------------- + */ + +#ifndef STORAGECMDS_H +#define STORAGECMDS_H + +#include "catalog/objectaddress.h" +#include "nodes/parsenodes.h" + + +/* Flags for GetStorageServerExtended */ +#define SSV_MISSING_OK 0x01 + +/* Helper for obtaining username for user mapping */ +#define StorageMappingUserName(userid) \ + (OidIsValid(userid) ? GetUserNameFromId(userid, false) : "public") + +typedef struct StorageServer +{ + Oid serverid; /* storage server Oid */ + Oid owner; /* storage server owner user Oid */ + char *servername; /* name of the storage server */ + List *options; /* srvoptions as DefElem list */ +} StorageServer; + +typedef struct StorageUserMapping +{ + Oid umid; /* Oid of storage user mapping */ + Oid userid; /* local user Oid */ + Oid serverid; /* storage server Oid */ + List *options; /* useoptions as DefElem list */ +} StorageUserMapping; + +extern Oid get_storage_server_oid(const char *servername, bool missing_ok); +extern StorageServer *GetStorageServerExtended(Oid serverid, bits16 flags); +extern StorageServer *GetStorageServer(Oid serverid); +extern StorageServer *GetStorageServerByName(const char *srvname, bool missing_ok); +extern StorageUserMapping *GetStorageUserMapping(Oid userid, Oid serverid); +extern Datum transformStorageGenericOptions(Oid catalogId, Datum oldOptions, List *options); + +#endif //STORAGECMDS_H diff --git a/src/include/commands/tablespace.h b/src/include/commands/tablespace.h index 830c1f1c0c6..1f41964cf75 100644 --- a/src/include/commands/tablespace.h +++ b/src/include/commands/tablespace.h @@ -43,6 +43,9 @@ typedef struct TableSpaceOpts float8 seq_page_cost; int effective_io_concurrency; int maintenance_io_concurrency; + bool stage; + int serverOffset; + int pathOffset; } TableSpaceOpts; extern Oid CreateTableSpace(CreateTableSpaceStmt *stmt); diff --git a/src/include/common/md5.h b/src/include/common/md5.h index 62a31e6ed4e..9ef0b123c6d 100644 --- a/src/include/common/md5.h +++ b/src/include/common/md5.h @@ -30,5 +30,6 @@ extern bool pg_md5_hash(const void *buff, size_t len, char *hexsum); extern bool pg_md5_binary(const void *buff, size_t len, void *outbuf); extern bool pg_md5_encrypt(const char *passwd, const char *salt, size_t salt_len, char *buf); +extern void bytesToHex(uint8 b[16], char *s); #endif /* PG_MD5_H */ diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index 5181b66746d..331c4e7444f 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -217,7 +217,7 @@ extern void ExecutorEnd(QueryDesc *queryDesc); extern void standard_ExecutorEnd(QueryDesc *queryDesc); extern void ExecutorRewind(QueryDesc *queryDesc); extern bool ExecCheckRTPerms(List *rangeTable, bool ereport_on_violation); -extern void CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation); +extern void CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation, ModifyTableState *mtstate); extern void InitResultRelInfo(ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index 371beaf89b7..8496472faa8 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -490,9 +490,15 @@ typedef enum NodeTag T_AlterFdwStmt, T_CreateForeignServerStmt, T_AlterForeignServerStmt, + T_CreateStorageServerStmt, + T_AlterStorageServerStmt, + T_DropStorageServerStmt, T_CreateUserMappingStmt, T_AlterUserMappingStmt, T_DropUserMappingStmt, + T_CreateStorageUserMappingStmt, + T_AlterStorageUserMappingStmt, + T_DropStorageUserMappingStmt, T_AlterTableSpaceOptionsStmt, T_AlterTableMoveAllStmt, T_SecLabelStmt, @@ -527,6 +533,7 @@ typedef enum NodeTag T_PartitionBy, T_PartitionRangeItem, T_PartitionValuesSpec, + T_CreateDirectoryTableStmt, T_CreateFileSpaceStmt, T_FileSpaceEntry, T_DropFileSpaceStmt, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index d9a278ede94..7ee9e7661ea 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1921,6 +1921,7 @@ typedef enum ObjectType OBJECT_EXTENSION, OBJECT_FDW, OBJECT_FOREIGN_SERVER, + OBJECT_STORAGE_SERVER, OBJECT_FOREIGN_TABLE, OBJECT_FUNCTION, OBJECT_INDEX, @@ -1954,9 +1955,11 @@ typedef enum ObjectType OBJECT_TSTEMPLATE, OBJECT_TYPE, OBJECT_USER_MAPPING, + OBJECT_STORAGE_USER_MAPPING, OBJECT_VIEW, OBJECT_RESQUEUE, - OBJECT_RESGROUP + OBJECT_RESGROUP, + OBJECT_DIRECTORY_TABLE } ObjectType; /* Event triggers and extended statistics are only stored on the QD node.*/ @@ -2384,6 +2387,8 @@ typedef struct CopyStmt bool is_from; /* TO or FROM */ bool is_program; /* is 'filename' a program to popen? */ char *filename; /* filename, or NULL for STDIN/STDOUT */ + char *dirfilename; /* dirtable filename */ + List *options; /* List of DefElem nodes */ Node *whereClause; /* WHERE condition (or NULL) */ @@ -2711,6 +2716,7 @@ typedef struct CreateTableSpaceStmt RoleSpec *owner; char *location; List *options; + char *filehandler; } CreateTableSpaceStmt; typedef struct DropTableSpaceStmt @@ -2860,6 +2866,32 @@ typedef struct AlterForeignServerStmt bool has_version; /* version specified */ } AlterForeignServerStmt; +/* ---------------------- + * Create/Alter/Drop STORAGE SERVER Statements + * ---------------------- + */ +typedef struct CreateStorageServerStmt +{ + NodeTag type; + char *servername; /* server name */ + bool if_not_exists; /* just do nothing if it already exists? */ + List *options; /* generic options to server */ +} CreateStorageServerStmt; + +typedef struct AlterStorageServerStmt +{ + NodeTag type; + char *servername; /* server name */ + List *options; /* generic options to server */ +} AlterStorageServerStmt; + +typedef struct DropStorageServerStmt +{ + NodeTag type; + char *servername; /* server name */ + bool missing_ok; /* ignore missing storage server */ +} DropStorageServerStmt; + /* ---------------------- * Create FOREIGN TABLE Statement * ---------------------- @@ -2903,6 +2935,36 @@ typedef struct DropUserMappingStmt bool missing_ok; /* ignore missing mappings */ } DropUserMappingStmt; +/* ---------------------- + * Create/Drop STORAGE USER MAPPING Statements + * ---------------------- + */ + +typedef struct CreateStorageUserMappingStmt +{ + NodeTag type; + RoleSpec *user; /* user role */ + char *servername; /* server name */ + bool if_not_exists; /* just do nothing if it already exists? */ + List *options; /* generic options to server */ +} CreateStorageUserMappingStmt; + +typedef struct AlterStorageUserMappingStmt +{ + NodeTag type; + RoleSpec *user; /* user role */ + char *servername; /* server name */ + List *options; /* generic options to server */ +} AlterStorageUserMappingStmt; + +typedef struct DropStorageUserMappingStmt +{ + NodeTag type; + RoleSpec *user; /* user role */ + char *servername; /* server name */ + bool missing_ok; /* ignore missing mappings */ +} DropStorageUserMappingStmt; + /* ---------------------- * Import Foreign Schema Statement * ---------------------- @@ -3279,6 +3341,17 @@ typedef struct AlterOpFamilyStmt List *items; /* List of CreateOpClassItem nodes */ } AlterOpFamilyStmt; +/* ---------------------- + * Create/Alter Directory Table Statements + * ---------------------- + */ +typedef struct CreateDirectoryTableStmt +{ + CreateStmt base; + char *tablespacename; +} CreateDirectoryTableStmt; + + /* ---------------------- * DROP Statement, applies to: * Table, External Table, Sequence, View, Index, Type, Domain, diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h index d8aca8f4a43..f29ac9b900c 100644 --- a/src/include/parser/kwlist.h +++ b/src/include/parser/kwlist.h @@ -146,6 +146,7 @@ PG_KEYWORD("depth", DEPTH, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("desc", DESC, RESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("detach", DETACH, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("dictionary", DICTIONARY, UNRESERVED_KEYWORD, BARE_LABEL) +PG_KEYWORD("directory", DIRECTORY, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("disable", DISABLE_P, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("discard", DISCARD, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("distinct", DISTINCT, RESERVED_KEYWORD, BARE_LABEL) @@ -476,6 +477,7 @@ PG_KEYWORD("table", TABLE, RESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("tables", TABLES, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("tablesample", TABLESAMPLE, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL) PG_KEYWORD("tablespace", TABLESPACE, UNRESERVED_KEYWORD, BARE_LABEL) +PG_KEYWORD("tag", TAG, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("task", TASK, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("temp", TEMP, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("template", TEMPLATE, UNRESERVED_KEYWORD, BARE_LABEL) diff --git a/src/include/storage/ufile.h b/src/include/storage/ufile.h new file mode 100644 index 00000000000..8a76957eaf5 --- /dev/null +++ b/src/include/storage/ufile.h @@ -0,0 +1,68 @@ +/*------------------------------------------------------------------------- + * + * Unified file abstraction and manipulation. + * + * Copyright (c) 2016-Present Hashdata, Inc. + * + * src/include/storage/ufile.h + * + *------------------------------------------------------------------------- + */ + +#ifndef UFILE_H +#define UFILE_H + +#include "storage/relfilenode.h" + +#define UFILE_ERROR_SIZE 1024 + +struct UFile; + +typedef struct FileAm +{ + struct UFile* (*open) (Oid spcId, const char *fileName, int fileFlags, + char *errorMessage, int errorMessageSize); + void (*close) (struct UFile *file); + int (*sync) (struct UFile *file); + int (*read) (struct UFile *file, char *buffer, int amount); + int (*write) (struct UFile *file, char *buffer, int amount); + int64_t (*size) (struct UFile *file); + void (*unlink) (Oid spcId, const char *fileName); + char* (*formatPathName) (RelFileNode *relFileNode); + bool (*ensurePath) (Oid spcId, const char *pathName); + bool (*exists) (Oid spcId, const char *fileName); + const char *(*name) (struct UFile *file); + const char *(*getLastError) (void); + void (*getConnection) (Oid spcId); +} FileAm; + +typedef struct UFile +{ + FileAm *methods; +} UFile; + +extern UFile *UFileOpen(Oid spcId, + const char *fileName, + int fileFlags, + char *errorMessage, + int errorMessageSize); +extern void UFileClose(UFile *file); +extern int UFileSync(UFile *fiLe); + +extern int UFileRead(UFile *file, char *buffer, int amount); +extern int UFileWrite(UFile *file, char *buffer, int amount); + +extern off_t UFileSize(UFile *file); +extern const char *UFileName(UFile *file); + +extern void UFileUnlink(Oid spcId, const char *fileName); +extern char* UFileFormatPathName(RelFileNode *relFileNode); +extern bool UFileEnsurePath(Oid spcId, const char *pathName); +extern bool UFileExists(Oid spcId, const char *fileName); + +extern const char *UFileGetLastError(UFile *file); +extern void forceCacheUFileResource(Oid id); + +extern struct FileAm localFileAm; + +#endif //UFILE_H diff --git a/src/include/tcop/cmdtaglist.h b/src/include/tcop/cmdtaglist.h index 74285522d99..c97011262df 100644 --- a/src/include/tcop/cmdtaglist.h +++ b/src/include/tcop/cmdtaglist.h @@ -34,6 +34,7 @@ PG_CMDTAG(CMDTAG_ALTER_CONSTRAINT, "ALTER CONSTRAINT", true, false, false) PG_CMDTAG(CMDTAG_ALTER_CONVERSION, "ALTER CONVERSION", true, false, false) PG_CMDTAG(CMDTAG_ALTER_DATABASE, "ALTER DATABASE", false, false, false) PG_CMDTAG(CMDTAG_ALTER_DEFAULT_PRIVILEGES, "ALTER DEFAULT PRIVILEGES", true, false, false) +PG_CMDTAG(CMDTAG_ALTER_DIRECTORY_TABLE, "ALTER DIRECTORY TABLE", true, false, false) PG_CMDTAG(CMDTAG_ALTER_DOMAIN, "ALTER DOMAIN", true, false, false) PG_CMDTAG(CMDTAG_ALTER_EVENT_TRIGGER, "ALTER EVENT TRIGGER", false, false, false) PG_CMDTAG(CMDTAG_ALTER_EXTENSION, "ALTER EXTENSION", true, false, false) @@ -61,6 +62,8 @@ PG_CMDTAG(CMDTAG_ALTER_SCHEMA, "ALTER SCHEMA", true, false, false) PG_CMDTAG(CMDTAG_ALTER_SEQUENCE, "ALTER SEQUENCE", true, false, false) PG_CMDTAG(CMDTAG_ALTER_SERVER, "ALTER SERVER", true, false, false) PG_CMDTAG(CMDTAG_ALTER_STATISTICS, "ALTER STATISTICS", true, false, false) +PG_CMDTAG(CMDTAG_ALTER_STORAGE_SERVER, "ALTER STORAGE SERVER", true, false, false) +PG_CMDTAG(CMDTAG_ALTER_STORAGE_USER_MAPPING, "ALTER STORAGE USER MAPPING", true, false, false) PG_CMDTAG(CMDTAG_ALTER_SUBSCRIPTION, "ALTER SUBSCRIPTION", true, false, false) PG_CMDTAG(CMDTAG_ALTER_SYSTEM, "ALTER SYSTEM", false, false, false) PG_CMDTAG(CMDTAG_ALTER_TABLE, "ALTER TABLE", true, true, false) @@ -96,6 +99,7 @@ PG_CMDTAG(CMDTAG_CREATE_COLLATION, "CREATE COLLATION", true, false, false) PG_CMDTAG(CMDTAG_CREATE_CONSTRAINT, "CREATE CONSTRAINT", true, false, false) PG_CMDTAG(CMDTAG_CREATE_CONVERSION, "CREATE CONVERSION", true, false, false) PG_CMDTAG(CMDTAG_CREATE_DATABASE, "CREATE DATABASE", false, false, false) +PG_CMDTAG(CMDTAG_CREATE_DIRECTORY_TABLE, "CREATE DIRECTORY TABLE", true, false, false) PG_CMDTAG(CMDTAG_CREATE_DOMAIN, "CREATE DOMAIN", true, false, false) PG_CMDTAG(CMDTAG_CREATE_EVENT_TRIGGER, "CREATE EVENT TRIGGER", false, false, false) PG_CMDTAG(CMDTAG_CREATE_EXTENSION, "CREATE EXTENSION", true, false, false) @@ -123,6 +127,8 @@ PG_CMDTAG(CMDTAG_CREATE_SCHEMA, "CREATE SCHEMA", true, false, false) PG_CMDTAG(CMDTAG_CREATE_SEQUENCE, "CREATE SEQUENCE", true, false, false) PG_CMDTAG(CMDTAG_CREATE_SERVER, "CREATE SERVER", true, false, false) PG_CMDTAG(CMDTAG_CREATE_STATISTICS, "CREATE STATISTICS", true, false, false) +PG_CMDTAG(CMDTAG_CREATE_STORAGE_SERVER, "CREATE STORAGE SERVER", true, false, false) +PG_CMDTAG(CMDTAG_CREATE_STORAGE_USER_MAPPING, "CREATE STORAGE USER MAPPING", true, false, false) PG_CMDTAG(CMDTAG_CREATE_SUBSCRIPTION, "CREATE SUBSCRIPTION", true, false, false) PG_CMDTAG(CMDTAG_CREATE_TABLE, "CREATE TABLE", true, false, false) PG_CMDTAG(CMDTAG_CREATE_TABLE_AS, "CREATE TABLE AS", true, false, false) @@ -162,6 +168,7 @@ PG_CMDTAG(CMDTAG_DROP_COLLATION, "DROP COLLATION", true, false, false) PG_CMDTAG(CMDTAG_DROP_CONSTRAINT, "DROP CONSTRAINT", true, false, false) PG_CMDTAG(CMDTAG_DROP_CONVERSION, "DROP CONVERSION", true, false, false) PG_CMDTAG(CMDTAG_DROP_DATABASE, "DROP DATABASE", false, false, false) +PG_CMDTAG(CMDTAG_DROP_DIRECTORY_TABLE, "DROP DIRECTORY TABLE", true, false, false) PG_CMDTAG(CMDTAG_DROP_DOMAIN, "DROP DOMAIN", true, false, false) PG_CMDTAG(CMDTAG_DROP_EVENT_TRIGGER, "DROP EVENT TRIGGER", false, false, false) PG_CMDTAG(CMDTAG_DROP_EXTENSION, "DROP EXTENSION", true, false, false) @@ -192,6 +199,8 @@ PG_CMDTAG(CMDTAG_DROP_SCHEMA, "DROP SCHEMA", true, false, false) PG_CMDTAG(CMDTAG_DROP_SEQUENCE, "DROP SEQUENCE", true, false, false) PG_CMDTAG(CMDTAG_DROP_SERVER, "DROP SERVER", true, false, false) PG_CMDTAG(CMDTAG_DROP_STATISTICS, "DROP STATISTICS", true, false, false) +PG_CMDTAG(CMDTAG_DROP_STORAGE_SERVER, "DROP STORAGE SERVER", true, false, false) +PG_CMDTAG(CMDTAG_DROP_STORAGE_USER_MAPPING, "DROP STORAGE USER MAPPING", true, false, false) PG_CMDTAG(CMDTAG_DROP_SUBSCRIPTION, "DROP SUBSCRIPTION", true, false, false) PG_CMDTAG(CMDTAG_DROP_TABLE, "DROP TABLE", true, false, false) PG_CMDTAG(CMDTAG_DROP_TABLESPACE, "DROP TABLESPACE", false, false, false) diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h index 6c42441aab8..bf47cd0a592 100644 --- a/src/include/utils/acl.h +++ b/src/include/utils/acl.h @@ -160,6 +160,7 @@ typedef struct ArrayType Acl; #define ACL_ALL_RIGHTS_EXTPROTOCOL (ACL_INSERT|ACL_SELECT) #define ACL_ALL_RIGHTS_FDW (ACL_USAGE) #define ACL_ALL_RIGHTS_FOREIGN_SERVER (ACL_USAGE) +#define ACL_ALL_RIGHTS_STORAGE_SERVER (ACL_USAGE) #define ACL_ALL_RIGHTS_FUNCTION (ACL_EXECUTE) #define ACL_ALL_RIGHTS_LANGUAGE (ACL_USAGE) #define ACL_ALL_RIGHTS_LARGEOBJECT (ACL_SELECT|ACL_UPDATE) @@ -260,6 +261,8 @@ extern AclMode pg_foreign_data_wrapper_aclmask(Oid fdw_oid, Oid roleid, AclMode mask, AclMaskHow how); extern AclMode pg_foreign_server_aclmask(Oid srv_oid, Oid roleid, AclMode mask, AclMaskHow how); +extern AclMode gp_storage_server_aclmask(Oid srv_oid, Oid roleid, + AclMode mask, AclMaskHow how); extern AclMode pg_extprotocol_aclmask(Oid ptc_oid, Oid roleid, AclMode mask, AclMaskHow how); extern AclMode pg_type_aclmask(Oid type_oid, Oid roleid, @@ -284,6 +287,7 @@ extern AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode); extern AclResult pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode); extern AclResult pg_foreign_data_wrapper_aclcheck(Oid fdw_oid, Oid roleid, AclMode mode); extern AclResult pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mode); +extern AclResult gp_storage_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mode); extern AclResult pg_extprotocol_aclcheck(Oid ptc_oid, Oid roleid, AclMode mode); extern AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode); @@ -318,6 +322,7 @@ extern bool pg_ts_dict_ownercheck(Oid dict_oid, Oid roleid); extern bool pg_ts_config_ownercheck(Oid cfg_oid, Oid roleid); extern bool pg_foreign_data_wrapper_ownercheck(Oid srv_oid, Oid roleid); extern bool pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid); +extern bool gp_storage_server_ownercheck(Oid srv_oid, Oid roleid); extern bool pg_event_trigger_ownercheck(Oid et_oid, Oid roleid); extern bool pg_extension_ownercheck(Oid ext_oid, Oid roleid); extern bool pg_publication_ownercheck(Oid pub_oid, Oid roleid); diff --git a/src/include/utils/spccache.h b/src/include/utils/spccache.h index 26ac680ff7a..47d733d742d 100644 --- a/src/include/utils/spccache.h +++ b/src/include/utils/spccache.h @@ -13,9 +13,19 @@ #ifndef SPCCACHE_H #define SPCCACHE_H +#include "commands/tablespace.h" + +typedef struct +{ + Oid oid; /* lookup key - must be first */ + TableSpaceOpts *opts; /* options, or NULL if none */ +} TableSpaceCacheEntry; + void get_tablespace_page_costs(Oid spcid, float8 *spc_random_page_cost, float8 *spc_seq_page_cost); int get_tablespace_io_concurrency(Oid spcid); int get_tablespace_maintenance_io_concurrency(Oid spcid); +extern TableSpaceCacheEntry *get_tablespace(Oid spcid); + #endif /* SPCCACHE_H */ diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h index 67415775582..62f6b2a46e2 100644 --- a/src/include/utils/syscache.h +++ b/src/include/utils/syscache.h @@ -65,6 +65,8 @@ enum SysCacheIdentifier FOREIGNDATAWRAPPEROID, FOREIGNSERVERNAME, FOREIGNSERVEROID, + STORAGESERVERNAME, + STORAGESERVEROID, FOREIGNTABLEREL, GPPOLICYID, AORELID, @@ -117,6 +119,9 @@ enum SysCacheIdentifier TSTEMPLATEOID, TYPENAMENSP, TYPEOID, + DIRECTORYTABLEREL, + STORAGEUSERMAPPINGOID, + STORAGEUSERMAPPINGUSERSERVER, USERMAPPINGOID, USERMAPPINGUSERSERVER diff --git a/src/interfaces/ecpg/preproc/ecpg.addons b/src/interfaces/ecpg/preproc/ecpg.addons index a87886a2640..03fbe642b6f 100644 --- a/src/interfaces/ecpg/preproc/ecpg.addons +++ b/src/interfaces/ecpg/preproc/ecpg.addons @@ -247,7 +247,7 @@ ECPG: where_or_current_clauseWHERECURRENT_POFcursor_name block char *cursor_marker = $4[0] == ':' ? mm_strdup("$0") : $4; $$ = cat_str(2,mm_strdup("where current of"), cursor_marker); } -ECPG: CopyStmtCOPYopt_binaryqualified_nameopt_column_listcopy_fromopt_programcopy_file_namecopy_delimiteropt_withcopy_optionswhere_clauseOptSingleRowErrorHandling addon +ECPG: CopyStmtCOPYopt_binaryqualified_nameopt_column_listcopy_fromopt_programcopy_file_nameopt_file_namecopy_delimiteropt_withcopy_optionswhere_clauseOptSingleRowErrorHandling addon if (strcmp($6, "from") == 0 && (strcmp($7, "stdin") == 0 || strcmp($7, "stdout") == 0)) mmerror(PARSE_ERROR, ET_WARNING, "COPY FROM STDIN is not implemented"); diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c index a65c15ee688..76ea85d8be6 100644 --- a/src/pl/plpgsql/src/pl_comp.c +++ b/src/pl/plpgsql/src/pl_comp.c @@ -1772,7 +1772,8 @@ plpgsql_parse_cwordtype(List *idents) classStruct->relkind != RELKIND_MATVIEW && classStruct->relkind != RELKIND_COMPOSITE_TYPE && classStruct->relkind != RELKIND_FOREIGN_TABLE && - classStruct->relkind != RELKIND_PARTITIONED_TABLE) + classStruct->relkind != RELKIND_PARTITIONED_TABLE && + classStruct->relkind != RELKIND_DIRECTORY_TABLE) goto done; /* diff --git a/src/test/isolation2/input/local_directory_table_mixed.source b/src/test/isolation2/input/local_directory_table_mixed.source new file mode 100644 index 00000000000..90bbc62f03c --- /dev/null +++ b/src/test/isolation2/input/local_directory_table_mixed.source @@ -0,0 +1,131 @@ +-- Mixed test for local directory table +-- setup for temp tablespace +! rm -rf '@testtablespace@'; +! mkdir -p '@testtablespace@'; +CREATE TABLESPACE directory_tblspc LOCATION '@testtablespace@'; + +CREATE EXTENSION IF NOT EXISTS gp_inject_fault; + +-- Test create directory table and create directory table +1: BEGIN; +2: BEGIN; +1: CREATE DIRECTORY TABLE dir_table1 TABLESPACE directory_tblspc; +2: CREATE DIRECTORY TABLE dir_table2 TABLESPACE directory_tblspc; +1: COMMIT; +2: COMMIT; + +1: COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation1'; +2: COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation2'; +3: COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation3'; +4: COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation4'; + +-- Test copy binary from the same directory table in parallel session is allowed +1: BEGIN; +2: BEGIN; +1: COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation5'; +2: COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation6'; +1: COMMIT; +2: COMMIT; + +-- Test copy binary from and select directory table +1: BEGIN; +2: BEGIN; +1: COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation5'; +2: SELECT relative_path, size, tag, md5 FROM dir_table2 ORDER BY 1; +1: COMMIT; +2: COMMIT; + +1: BEGIN; +2: BEGIN; +1: COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation6'; +2: SELECT relative_path, size, tag, md5, content FROM directory_table('dir_table2') ORDER BY 1; +1: COMMIT; +2: COMMIT; + +-- Test copy binary from and remove_file() +1: BEGIN; +2: BEGIN; +1: COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation7'; +2&: SELECT remove_file('dir_table1', 'nation6'); +1: COMMIT; +2<: +2: COMMIT; + +-- Test select and select +1: BEGIN; +2: BEGIN; +1: SELECT relative_path, size, tag, md5 FROM dir_table1 ORDER BY 1; +2: SELECT relative_path, size, tag, md5, content FROM directory_table('dir_table2') ORDER BY 1; +1: SELECT relative_path, size, tag, md5, content FROM directory_table('dir_table2') ORDER BY 1; +2: SELECT relative_path, size, tag, md5 FROM dir_table1 ORDER BY 1; +2: COMMIT; +1: COMMIT; + +-- Test select and remove_file() +1: BEGIN; +2: BEGIN; +1: SELECT gp_inject_fault('directory_table_inject', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; +1&: SELECT relative_path, size, tag, md5, content FROM directory_table('dir_table1') ORDER BY 1; +2&: SELECT remove_file('dir_table1', 'nation7'); +3: SELECT gp_wait_until_triggered_fault('directory_table_inject', 1, dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; +3: SELECT gp_inject_fault('directory_table_inject', 'resume', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; +1<: +1: COMMIT; +2<: +2: COMMIT; + +1: SELECT gp_inject_fault('directory_table_inject', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; + +1: BEGIN; +2: BEGIN; +1: SELECT gp_inject_fault('remove_file_inject', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; +1&: SELECT remove_file('dir_table1', 'nation5'); +2&: SELECT relative_path, size, tag, md5 FROM dir_table1 ORDER BY 1; +3: SELECT gp_wait_until_triggered_fault('remove_file_inject', 1, dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; +3: SELECT gp_inject_fault('remove_file_inject', 'resume', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; +1<: +1: COMMIT; +2<: +2: COMMIT; + +1: SELECT gp_inject_fault('remove_file_inject', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; + +1: BEGIN; +2: BEGIN; +1: SELECT gp_inject_fault('remove_file_inject', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; +1&: SELECT remove_file('dir_table2', 'nation6'); +2&: SELECT relative_path, size, tag, md5, content FROM directory_table('dir_table2') ORDER BY 1; +3: SELECT gp_wait_until_triggered_fault('remove_file_inject', 1, dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; +3: SELECT gp_inject_fault('remove_file_inject', 'resume', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; +1<: +1: COMMIT; +2<: +2: COMMIT; + +1: SELECT gp_inject_fault('remove_file_inject', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; + +1: BEGIN; +2: BEGIN; +1: SELECT gp_inject_fault('directory_table_inject', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; +1&: SELECT relative_path, size, tag, md5, content FROM directory_table('dir_table2') ORDER BY 1; +2&: SELECT remove_file('dir_table2', 'nation5'); +3: SELECT gp_wait_until_triggered_fault('directory_table_inject', 1, dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; +3: SELECT gp_inject_fault('directory_table_inject', 'resume', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; +1<: +1: COMMIT; +2<: +2: COMMIT; + +1: SELECT gp_inject_fault('directory_table_inject', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; + +-- Test create directory table and drop directory table +1: BEGIN; +2: BEGIN; +1: CREATE DIRECTORY TABLE dir_table3 TABLESPACE directory_tblspc; +2: DROP DIRECTORY TABLE dir_table2; +2: CREATE DIRECTORY TABLE dir_table2 TABLESPACE directory_tblspc; +1: COMMIT; +2: COMMIT; + +! rm -rf '@testtablespace@'; +DROP TABLESPACE directory_tblspc; \ No newline at end of file diff --git a/src/test/isolation2/isolation2_schedule b/src/test/isolation2/isolation2_schedule index 3785ea21bea..806c62a4d7f 100644 --- a/src/test/isolation2/isolation2_schedule +++ b/src/test/isolation2/isolation2_schedule @@ -308,3 +308,5 @@ test: ao_unique_index test: aocs_unique_index test: uao/ao_unique_index_vacuum_row test: uao/ao_unique_index_vacuum_column + +test: local_directory_table_mixed \ No newline at end of file diff --git a/src/test/isolation2/output/local_directory_table_mixed.source b/src/test/isolation2/output/local_directory_table_mixed.source new file mode 100644 index 00000000000..f8f2994bfa6 --- /dev/null +++ b/src/test/isolation2/output/local_directory_table_mixed.source @@ -0,0 +1,374 @@ +-- Mixed test for local directory table +-- setup for temp tablespace +! rm -rf '@testtablespace@'; + +! mkdir -p '@testtablespace@'; + +CREATE TABLESPACE directory_tblspc LOCATION '@testtablespace@'; +CREATE + +CREATE EXTENSION IF NOT EXISTS gp_inject_fault; +CREATE + +-- Test create directory table and create directory table +1: BEGIN; +BEGIN +2: BEGIN; +BEGIN +1: CREATE DIRECTORY TABLE dir_table1 TABLESPACE directory_tblspc; +CREATE +2: CREATE DIRECTORY TABLE dir_table2 TABLESPACE directory_tblspc; +CREATE +1: COMMIT; +COMMIT +2: COMMIT; +COMMIT + +1: COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation1'; +COPY 1 +2: COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation2'; +COPY 1 +3: COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation3'; +COPY 1 +4: COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation4'; +COPY 1 + +-- Test copy binary from the same directory table in parallel session is allowed +1: BEGIN; +BEGIN +2: BEGIN; +BEGIN +1: COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation5'; +COPY 1 +2: COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation6'; +COPY 1 +1: COMMIT; +COMMIT +2: COMMIT; +COMMIT + +-- Test copy binary from and select directory table +1: BEGIN; +BEGIN +2: BEGIN; +BEGIN +1: COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation5'; +COPY 1 +2: SELECT relative_path, size, tag, md5 FROM dir_table2 ORDER BY 1; + relative_path | size | tag | md5 +---------------+------+-----+---------------------------------- + nation2 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 + nation4 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 +(2 rows) +1: COMMIT; +COMMIT +2: COMMIT; +COMMIT + +1: BEGIN; +BEGIN +2: BEGIN; +BEGIN +1: COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation6'; +COPY 1 +2: SELECT relative_path, size, tag, md5, content FROM directory_table('dir_table2') ORDER BY 1; + relative_path | size | tag | md5 | content +---------------+------+-----+----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + nation2 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 | b'0|ALGERIA|0| haggle. carefully final deposits detect slyly agai\n1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon\n2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special \n3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold\n4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d\n5|ETHIOPIA|0|ven packages wake quickly. regu\n6|FRANCE|3|refully final requests. regular, ironi\n7|GERMANY|3|l platelets. regular accounts x-ray: unusual, regular acco\n8|INDIA|2|ss excuses cajole slyly across the packages. deposits print aroun\n9|INDONESIA|2| slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull\n10|IRAN|4|efully alongside of the slyly final dependencies. \n11|IRAQ|4|nic deposits boost atop the quickly final requests? quickly regula\n12|JAPAN|2|ously. final, express gifts cajole a\n13|JORDAN|4|ic deposits are blithely about the carefully regular pa\n14|KENYA|0| pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t\n15|MOROCCO|0|rns. blithely bold courts among the closely regular packages use furiously bold platelets?\n16|MOZAMBIQUE|0|s. ironic, unusual asymptotes wake blithely r\n17|PERU|1|platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun\n18|CHINA|2|c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos\n19|ROMANIA|3|ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account\n20|SAUDI ARABIA|4|ts. silent requests haggle. closely express packages sleep across the blithely\n21|VIETNAM|2|hely enticingly express accounts. even, final \n22|RUSSIA|3| requests against the platelets use never according to the quickly regular pint\n23|UNITED KINGDOM|3|eans boost carefully special requests. accounts are. carefull\n24|UNITED STATES|1|y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be\n' + nation4 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 | b'0|ALGERIA|0| haggle. carefully final deposits detect slyly agai\n1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon\n2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special \n3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold\n4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d\n5|ETHIOPIA|0|ven packages wake quickly. regu\n6|FRANCE|3|refully final requests. regular, ironi\n7|GERMANY|3|l platelets. regular accounts x-ray: unusual, regular acco\n8|INDIA|2|ss excuses cajole slyly across the packages. deposits print aroun\n9|INDONESIA|2| slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull\n10|IRAN|4|efully alongside of the slyly final dependencies. \n11|IRAQ|4|nic deposits boost atop the quickly final requests? quickly regula\n12|JAPAN|2|ously. final, express gifts cajole a\n13|JORDAN|4|ic deposits are blithely about the carefully regular pa\n14|KENYA|0| pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t\n15|MOROCCO|0|rns. blithely bold courts among the closely regular packages use furiously bold platelets?\n16|MOZAMBIQUE|0|s. ironic, unusual asymptotes wake blithely r\n17|PERU|1|platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun\n18|CHINA|2|c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos\n19|ROMANIA|3|ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account\n20|SAUDI ARABIA|4|ts. silent requests haggle. closely express packages sleep across the blithely\n21|VIETNAM|2|hely enticingly express accounts. even, final \n22|RUSSIA|3| requests against the platelets use never according to the quickly regular pint\n23|UNITED KINGDOM|3|eans boost carefully special requests. accounts are. carefull\n24|UNITED STATES|1|y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be\n' + nation5 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 | b'0|ALGERIA|0| haggle. carefully final deposits detect slyly agai\n1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon\n2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special \n3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold\n4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d\n5|ETHIOPIA|0|ven packages wake quickly. regu\n6|FRANCE|3|refully final requests. regular, ironi\n7|GERMANY|3|l platelets. regular accounts x-ray: unusual, regular acco\n8|INDIA|2|ss excuses cajole slyly across the packages. deposits print aroun\n9|INDONESIA|2| slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull\n10|IRAN|4|efully alongside of the slyly final dependencies. \n11|IRAQ|4|nic deposits boost atop the quickly final requests? quickly regula\n12|JAPAN|2|ously. final, express gifts cajole a\n13|JORDAN|4|ic deposits are blithely about the carefully regular pa\n14|KENYA|0| pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t\n15|MOROCCO|0|rns. blithely bold courts among the closely regular packages use furiously bold platelets?\n16|MOZAMBIQUE|0|s. ironic, unusual asymptotes wake blithely r\n17|PERU|1|platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun\n18|CHINA|2|c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos\n19|ROMANIA|3|ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account\n20|SAUDI ARABIA|4|ts. silent requests haggle. closely express packages sleep across the blithely\n21|VIETNAM|2|hely enticingly express accounts. even, final \n22|RUSSIA|3| requests against the platelets use never according to the quickly regular pint\n23|UNITED KINGDOM|3|eans boost carefully special requests. accounts are. carefull\n24|UNITED STATES|1|y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be\n' +(3 rows) +1: COMMIT; +COMMIT +2: COMMIT; +COMMIT + +-- Test copy binary from and remove_file() +1: BEGIN; +BEGIN +2: BEGIN; +BEGIN +1: COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation7'; +COPY 1 +2&: SELECT remove_file('dir_table1', 'nation6'); +1: COMMIT; +COMMIT +2<: <... completed> + remove_file +------------- + t +(1 row) +2: COMMIT; +COMMIT + +-- Test select and select +1: BEGIN; +BEGIN +2: BEGIN; +BEGIN +1: SELECT relative_path, size, tag, md5 FROM dir_table1 ORDER BY 1; + relative_path | size | tag | md5 +---------------+------+-----+---------------------------------- + nation1 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 + nation3 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 + nation5 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 + nation7 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 +(4 rows) +2: SELECT relative_path, size, tag, md5, content FROM directory_table('dir_table2') ORDER BY 1; + relative_path | size | tag | md5 | content +---------------+------+-----+----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + nation2 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 | b'0|ALGERIA|0| haggle. carefully final deposits detect slyly agai\n1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon\n2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special \n3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold\n4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d\n5|ETHIOPIA|0|ven packages wake quickly. regu\n6|FRANCE|3|refully final requests. regular, ironi\n7|GERMANY|3|l platelets. regular accounts x-ray: unusual, regular acco\n8|INDIA|2|ss excuses cajole slyly across the packages. deposits print aroun\n9|INDONESIA|2| slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull\n10|IRAN|4|efully alongside of the slyly final dependencies. \n11|IRAQ|4|nic deposits boost atop the quickly final requests? quickly regula\n12|JAPAN|2|ously. final, express gifts cajole a\n13|JORDAN|4|ic deposits are blithely about the carefully regular pa\n14|KENYA|0| pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t\n15|MOROCCO|0|rns. blithely bold courts among the closely regular packages use furiously bold platelets?\n16|MOZAMBIQUE|0|s. ironic, unusual asymptotes wake blithely r\n17|PERU|1|platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun\n18|CHINA|2|c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos\n19|ROMANIA|3|ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account\n20|SAUDI ARABIA|4|ts. silent requests haggle. closely express packages sleep across the blithely\n21|VIETNAM|2|hely enticingly express accounts. even, final \n22|RUSSIA|3| requests against the platelets use never according to the quickly regular pint\n23|UNITED KINGDOM|3|eans boost carefully special requests. accounts are. carefull\n24|UNITED STATES|1|y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be\n' + nation4 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 | b'0|ALGERIA|0| haggle. carefully final deposits detect slyly agai\n1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon\n2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special \n3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold\n4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d\n5|ETHIOPIA|0|ven packages wake quickly. regu\n6|FRANCE|3|refully final requests. regular, ironi\n7|GERMANY|3|l platelets. regular accounts x-ray: unusual, regular acco\n8|INDIA|2|ss excuses cajole slyly across the packages. deposits print aroun\n9|INDONESIA|2| slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull\n10|IRAN|4|efully alongside of the slyly final dependencies. \n11|IRAQ|4|nic deposits boost atop the quickly final requests? quickly regula\n12|JAPAN|2|ously. final, express gifts cajole a\n13|JORDAN|4|ic deposits are blithely about the carefully regular pa\n14|KENYA|0| pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t\n15|MOROCCO|0|rns. blithely bold courts among the closely regular packages use furiously bold platelets?\n16|MOZAMBIQUE|0|s. ironic, unusual asymptotes wake blithely r\n17|PERU|1|platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun\n18|CHINA|2|c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos\n19|ROMANIA|3|ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account\n20|SAUDI ARABIA|4|ts. silent requests haggle. closely express packages sleep across the blithely\n21|VIETNAM|2|hely enticingly express accounts. even, final \n22|RUSSIA|3| requests against the platelets use never according to the quickly regular pint\n23|UNITED KINGDOM|3|eans boost carefully special requests. accounts are. carefull\n24|UNITED STATES|1|y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be\n' + nation5 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 | b'0|ALGERIA|0| haggle. carefully final deposits detect slyly agai\n1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon\n2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special \n3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold\n4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d\n5|ETHIOPIA|0|ven packages wake quickly. regu\n6|FRANCE|3|refully final requests. regular, ironi\n7|GERMANY|3|l platelets. regular accounts x-ray: unusual, regular acco\n8|INDIA|2|ss excuses cajole slyly across the packages. deposits print aroun\n9|INDONESIA|2| slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull\n10|IRAN|4|efully alongside of the slyly final dependencies. \n11|IRAQ|4|nic deposits boost atop the quickly final requests? quickly regula\n12|JAPAN|2|ously. final, express gifts cajole a\n13|JORDAN|4|ic deposits are blithely about the carefully regular pa\n14|KENYA|0| pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t\n15|MOROCCO|0|rns. blithely bold courts among the closely regular packages use furiously bold platelets?\n16|MOZAMBIQUE|0|s. ironic, unusual asymptotes wake blithely r\n17|PERU|1|platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun\n18|CHINA|2|c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos\n19|ROMANIA|3|ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account\n20|SAUDI ARABIA|4|ts. silent requests haggle. closely express packages sleep across the blithely\n21|VIETNAM|2|hely enticingly express accounts. even, final \n22|RUSSIA|3| requests against the platelets use never according to the quickly regular pint\n23|UNITED KINGDOM|3|eans boost carefully special requests. accounts are. carefull\n24|UNITED STATES|1|y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be\n' + nation6 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 | b'0|ALGERIA|0| haggle. carefully final deposits detect slyly agai\n1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon\n2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special \n3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold\n4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d\n5|ETHIOPIA|0|ven packages wake quickly. regu\n6|FRANCE|3|refully final requests. regular, ironi\n7|GERMANY|3|l platelets. regular accounts x-ray: unusual, regular acco\n8|INDIA|2|ss excuses cajole slyly across the packages. deposits print aroun\n9|INDONESIA|2| slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull\n10|IRAN|4|efully alongside of the slyly final dependencies. \n11|IRAQ|4|nic deposits boost atop the quickly final requests? quickly regula\n12|JAPAN|2|ously. final, express gifts cajole a\n13|JORDAN|4|ic deposits are blithely about the carefully regular pa\n14|KENYA|0| pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t\n15|MOROCCO|0|rns. blithely bold courts among the closely regular packages use furiously bold platelets?\n16|MOZAMBIQUE|0|s. ironic, unusual asymptotes wake blithely r\n17|PERU|1|platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun\n18|CHINA|2|c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos\n19|ROMANIA|3|ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account\n20|SAUDI ARABIA|4|ts. silent requests haggle. closely express packages sleep across the blithely\n21|VIETNAM|2|hely enticingly express accounts. even, final \n22|RUSSIA|3| requests against the platelets use never according to the quickly regular pint\n23|UNITED KINGDOM|3|eans boost carefully special requests. accounts are. carefull\n24|UNITED STATES|1|y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be\n' +(4 rows) +1: SELECT relative_path, size, tag, md5, content FROM directory_table('dir_table2') ORDER BY 1; + relative_path | size | tag | md5 | content +---------------+------+-----+----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + nation2 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 | b'0|ALGERIA|0| haggle. carefully final deposits detect slyly agai\n1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon\n2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special \n3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold\n4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d\n5|ETHIOPIA|0|ven packages wake quickly. regu\n6|FRANCE|3|refully final requests. regular, ironi\n7|GERMANY|3|l platelets. regular accounts x-ray: unusual, regular acco\n8|INDIA|2|ss excuses cajole slyly across the packages. deposits print aroun\n9|INDONESIA|2| slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull\n10|IRAN|4|efully alongside of the slyly final dependencies. \n11|IRAQ|4|nic deposits boost atop the quickly final requests? quickly regula\n12|JAPAN|2|ously. final, express gifts cajole a\n13|JORDAN|4|ic deposits are blithely about the carefully regular pa\n14|KENYA|0| pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t\n15|MOROCCO|0|rns. blithely bold courts among the closely regular packages use furiously bold platelets?\n16|MOZAMBIQUE|0|s. ironic, unusual asymptotes wake blithely r\n17|PERU|1|platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun\n18|CHINA|2|c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos\n19|ROMANIA|3|ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account\n20|SAUDI ARABIA|4|ts. silent requests haggle. closely express packages sleep across the blithely\n21|VIETNAM|2|hely enticingly express accounts. even, final \n22|RUSSIA|3| requests against the platelets use never according to the quickly regular pint\n23|UNITED KINGDOM|3|eans boost carefully special requests. accounts are. carefull\n24|UNITED STATES|1|y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be\n' + nation4 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 | b'0|ALGERIA|0| haggle. carefully final deposits detect slyly agai\n1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon\n2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special \n3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold\n4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d\n5|ETHIOPIA|0|ven packages wake quickly. regu\n6|FRANCE|3|refully final requests. regular, ironi\n7|GERMANY|3|l platelets. regular accounts x-ray: unusual, regular acco\n8|INDIA|2|ss excuses cajole slyly across the packages. deposits print aroun\n9|INDONESIA|2| slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull\n10|IRAN|4|efully alongside of the slyly final dependencies. \n11|IRAQ|4|nic deposits boost atop the quickly final requests? quickly regula\n12|JAPAN|2|ously. final, express gifts cajole a\n13|JORDAN|4|ic deposits are blithely about the carefully regular pa\n14|KENYA|0| pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t\n15|MOROCCO|0|rns. blithely bold courts among the closely regular packages use furiously bold platelets?\n16|MOZAMBIQUE|0|s. ironic, unusual asymptotes wake blithely r\n17|PERU|1|platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun\n18|CHINA|2|c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos\n19|ROMANIA|3|ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account\n20|SAUDI ARABIA|4|ts. silent requests haggle. closely express packages sleep across the blithely\n21|VIETNAM|2|hely enticingly express accounts. even, final \n22|RUSSIA|3| requests against the platelets use never according to the quickly regular pint\n23|UNITED KINGDOM|3|eans boost carefully special requests. accounts are. carefull\n24|UNITED STATES|1|y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be\n' + nation5 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 | b'0|ALGERIA|0| haggle. carefully final deposits detect slyly agai\n1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon\n2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special \n3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold\n4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d\n5|ETHIOPIA|0|ven packages wake quickly. regu\n6|FRANCE|3|refully final requests. regular, ironi\n7|GERMANY|3|l platelets. regular accounts x-ray: unusual, regular acco\n8|INDIA|2|ss excuses cajole slyly across the packages. deposits print aroun\n9|INDONESIA|2| slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull\n10|IRAN|4|efully alongside of the slyly final dependencies. \n11|IRAQ|4|nic deposits boost atop the quickly final requests? quickly regula\n12|JAPAN|2|ously. final, express gifts cajole a\n13|JORDAN|4|ic deposits are blithely about the carefully regular pa\n14|KENYA|0| pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t\n15|MOROCCO|0|rns. blithely bold courts among the closely regular packages use furiously bold platelets?\n16|MOZAMBIQUE|0|s. ironic, unusual asymptotes wake blithely r\n17|PERU|1|platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun\n18|CHINA|2|c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos\n19|ROMANIA|3|ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account\n20|SAUDI ARABIA|4|ts. silent requests haggle. closely express packages sleep across the blithely\n21|VIETNAM|2|hely enticingly express accounts. even, final \n22|RUSSIA|3| requests against the platelets use never according to the quickly regular pint\n23|UNITED KINGDOM|3|eans boost carefully special requests. accounts are. carefull\n24|UNITED STATES|1|y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be\n' + nation6 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 | b'0|ALGERIA|0| haggle. carefully final deposits detect slyly agai\n1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon\n2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special \n3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold\n4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d\n5|ETHIOPIA|0|ven packages wake quickly. regu\n6|FRANCE|3|refully final requests. regular, ironi\n7|GERMANY|3|l platelets. regular accounts x-ray: unusual, regular acco\n8|INDIA|2|ss excuses cajole slyly across the packages. deposits print aroun\n9|INDONESIA|2| slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull\n10|IRAN|4|efully alongside of the slyly final dependencies. \n11|IRAQ|4|nic deposits boost atop the quickly final requests? quickly regula\n12|JAPAN|2|ously. final, express gifts cajole a\n13|JORDAN|4|ic deposits are blithely about the carefully regular pa\n14|KENYA|0| pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t\n15|MOROCCO|0|rns. blithely bold courts among the closely regular packages use furiously bold platelets?\n16|MOZAMBIQUE|0|s. ironic, unusual asymptotes wake blithely r\n17|PERU|1|platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun\n18|CHINA|2|c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos\n19|ROMANIA|3|ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account\n20|SAUDI ARABIA|4|ts. silent requests haggle. closely express packages sleep across the blithely\n21|VIETNAM|2|hely enticingly express accounts. even, final \n22|RUSSIA|3| requests against the platelets use never according to the quickly regular pint\n23|UNITED KINGDOM|3|eans boost carefully special requests. accounts are. carefull\n24|UNITED STATES|1|y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be\n' +(4 rows) +2: SELECT relative_path, size, tag, md5 FROM dir_table1 ORDER BY 1; + relative_path | size | tag | md5 +---------------+------+-----+---------------------------------- + nation1 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 + nation3 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 + nation5 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 + nation7 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 +(4 rows) +2: COMMIT; +COMMIT +1: COMMIT; +COMMIT + +-- Test select and remove_file() +1: BEGIN; +BEGIN +2: BEGIN; +BEGIN +1: SELECT gp_inject_fault('directory_table_inject', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; + gp_inject_fault +----------------- + Success: + Success: + Success: +(3 rows) +1&: SELECT relative_path, size, tag, md5, content FROM directory_table('dir_table1') ORDER BY 1; +2&: SELECT remove_file('dir_table1', 'nation7'); +3: SELECT gp_wait_until_triggered_fault('directory_table_inject', 1, dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; + gp_wait_until_triggered_fault +------------------------------- + Success: + Success: + Success: +(3 rows) +3: SELECT gp_inject_fault('directory_table_inject', 'resume', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; + gp_inject_fault +----------------- + Success: + Success: + Success: +(3 rows) +1<: <... completed> + relative_path | size | tag | md5 | content +---------------+------+-----+----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + nation1 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 | b'0|ALGERIA|0| haggle. carefully final deposits detect slyly agai\n1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon\n2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special \n3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold\n4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d\n5|ETHIOPIA|0|ven packages wake quickly. regu\n6|FRANCE|3|refully final requests. regular, ironi\n7|GERMANY|3|l platelets. regular accounts x-ray: unusual, regular acco\n8|INDIA|2|ss excuses cajole slyly across the packages. deposits print aroun\n9|INDONESIA|2| slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull\n10|IRAN|4|efully alongside of the slyly final dependencies. \n11|IRAQ|4|nic deposits boost atop the quickly final requests? quickly regula\n12|JAPAN|2|ously. final, express gifts cajole a\n13|JORDAN|4|ic deposits are blithely about the carefully regular pa\n14|KENYA|0| pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t\n15|MOROCCO|0|rns. blithely bold courts among the closely regular packages use furiously bold platelets?\n16|MOZAMBIQUE|0|s. ironic, unusual asymptotes wake blithely r\n17|PERU|1|platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun\n18|CHINA|2|c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos\n19|ROMANIA|3|ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account\n20|SAUDI ARABIA|4|ts. silent requests haggle. closely express packages sleep across the blithely\n21|VIETNAM|2|hely enticingly express accounts. even, final \n22|RUSSIA|3| requests against the platelets use never according to the quickly regular pint\n23|UNITED KINGDOM|3|eans boost carefully special requests. accounts are. carefull\n24|UNITED STATES|1|y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be\n' + nation3 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 | b'0|ALGERIA|0| haggle. carefully final deposits detect slyly agai\n1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon\n2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special \n3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold\n4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d\n5|ETHIOPIA|0|ven packages wake quickly. regu\n6|FRANCE|3|refully final requests. regular, ironi\n7|GERMANY|3|l platelets. regular accounts x-ray: unusual, regular acco\n8|INDIA|2|ss excuses cajole slyly across the packages. deposits print aroun\n9|INDONESIA|2| slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull\n10|IRAN|4|efully alongside of the slyly final dependencies. \n11|IRAQ|4|nic deposits boost atop the quickly final requests? quickly regula\n12|JAPAN|2|ously. final, express gifts cajole a\n13|JORDAN|4|ic deposits are blithely about the carefully regular pa\n14|KENYA|0| pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t\n15|MOROCCO|0|rns. blithely bold courts among the closely regular packages use furiously bold platelets?\n16|MOZAMBIQUE|0|s. ironic, unusual asymptotes wake blithely r\n17|PERU|1|platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun\n18|CHINA|2|c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos\n19|ROMANIA|3|ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account\n20|SAUDI ARABIA|4|ts. silent requests haggle. closely express packages sleep across the blithely\n21|VIETNAM|2|hely enticingly express accounts. even, final \n22|RUSSIA|3| requests against the platelets use never according to the quickly regular pint\n23|UNITED KINGDOM|3|eans boost carefully special requests. accounts are. carefull\n24|UNITED STATES|1|y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be\n' + nation5 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 | b'0|ALGERIA|0| haggle. carefully final deposits detect slyly agai\n1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon\n2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special \n3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold\n4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d\n5|ETHIOPIA|0|ven packages wake quickly. regu\n6|FRANCE|3|refully final requests. regular, ironi\n7|GERMANY|3|l platelets. regular accounts x-ray: unusual, regular acco\n8|INDIA|2|ss excuses cajole slyly across the packages. deposits print aroun\n9|INDONESIA|2| slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull\n10|IRAN|4|efully alongside of the slyly final dependencies. \n11|IRAQ|4|nic deposits boost atop the quickly final requests? quickly regula\n12|JAPAN|2|ously. final, express gifts cajole a\n13|JORDAN|4|ic deposits are blithely about the carefully regular pa\n14|KENYA|0| pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t\n15|MOROCCO|0|rns. blithely bold courts among the closely regular packages use furiously bold platelets?\n16|MOZAMBIQUE|0|s. ironic, unusual asymptotes wake blithely r\n17|PERU|1|platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun\n18|CHINA|2|c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos\n19|ROMANIA|3|ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account\n20|SAUDI ARABIA|4|ts. silent requests haggle. closely express packages sleep across the blithely\n21|VIETNAM|2|hely enticingly express accounts. even, final \n22|RUSSIA|3| requests against the platelets use never according to the quickly regular pint\n23|UNITED KINGDOM|3|eans boost carefully special requests. accounts are. carefull\n24|UNITED STATES|1|y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be\n' + nation7 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 | b'0|ALGERIA|0| haggle. carefully final deposits detect slyly agai\n1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon\n2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special \n3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold\n4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d\n5|ETHIOPIA|0|ven packages wake quickly. regu\n6|FRANCE|3|refully final requests. regular, ironi\n7|GERMANY|3|l platelets. regular accounts x-ray: unusual, regular acco\n8|INDIA|2|ss excuses cajole slyly across the packages. deposits print aroun\n9|INDONESIA|2| slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull\n10|IRAN|4|efully alongside of the slyly final dependencies. \n11|IRAQ|4|nic deposits boost atop the quickly final requests? quickly regula\n12|JAPAN|2|ously. final, express gifts cajole a\n13|JORDAN|4|ic deposits are blithely about the carefully regular pa\n14|KENYA|0| pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t\n15|MOROCCO|0|rns. blithely bold courts among the closely regular packages use furiously bold platelets?\n16|MOZAMBIQUE|0|s. ironic, unusual asymptotes wake blithely r\n17|PERU|1|platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun\n18|CHINA|2|c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos\n19|ROMANIA|3|ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account\n20|SAUDI ARABIA|4|ts. silent requests haggle. closely express packages sleep across the blithely\n21|VIETNAM|2|hely enticingly express accounts. even, final \n22|RUSSIA|3| requests against the platelets use never according to the quickly regular pint\n23|UNITED KINGDOM|3|eans boost carefully special requests. accounts are. carefull\n24|UNITED STATES|1|y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be\n' +(4 rows) +1: COMMIT; +COMMIT +2<: <... completed> + remove_file +------------- + t +(1 row) +2: COMMIT; +COMMIT + +1: SELECT gp_inject_fault('directory_table_inject', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; + gp_inject_fault +----------------- + Success: + Success: + Success: +(3 rows) + +1: BEGIN; +BEGIN +2: BEGIN; +BEGIN +1: SELECT gp_inject_fault('remove_file_inject', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; + gp_inject_fault +----------------- + Success: + Success: + Success: +(3 rows) +1&: SELECT remove_file('dir_table1', 'nation5'); +2&: SELECT relative_path, size, tag, md5 FROM dir_table1 ORDER BY 1; +3: SELECT gp_wait_until_triggered_fault('remove_file_inject', 1, dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; + gp_wait_until_triggered_fault +------------------------------- + Success: + Success: + Success: +(3 rows) +3: SELECT gp_inject_fault('remove_file_inject', 'resume', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; + gp_inject_fault +----------------- + Success: + Success: + Success: +(3 rows) +1<: <... completed> + remove_file +------------- + t +(1 row) +1: COMMIT; +COMMIT +2<: <... completed> + relative_path | size | tag | md5 +---------------+------+-----+---------------------------------- + nation1 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 + nation3 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 +(2 rows) +2: COMMIT; +COMMIT + +1: SELECT gp_inject_fault('remove_file_inject', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; + gp_inject_fault +----------------- + Success: + Success: + Success: +(3 rows) + +1: BEGIN; +BEGIN +2: BEGIN; +BEGIN +1: SELECT gp_inject_fault('remove_file_inject', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; + gp_inject_fault +----------------- + Success: + Success: + Success: +(3 rows) +1&: SELECT remove_file('dir_table2', 'nation6'); +2&: SELECT relative_path, size, tag, md5, content FROM directory_table('dir_table2') ORDER BY 1; +3: SELECT gp_wait_until_triggered_fault('remove_file_inject', 1, dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; + gp_wait_until_triggered_fault +------------------------------- + Success: + Success: + Success: +(3 rows) +3: SELECT gp_inject_fault('remove_file_inject', 'resume', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; + gp_inject_fault +----------------- + Success: + Success: + Success: +(3 rows) +1<: <... completed> + remove_file +------------- + t +(1 row) +1: COMMIT; +COMMIT +2<: <... completed> + relative_path | size | tag | md5 | content +---------------+------+-----+----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + nation2 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 | b'0|ALGERIA|0| haggle. carefully final deposits detect slyly agai\n1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon\n2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special \n3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold\n4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d\n5|ETHIOPIA|0|ven packages wake quickly. regu\n6|FRANCE|3|refully final requests. regular, ironi\n7|GERMANY|3|l platelets. regular accounts x-ray: unusual, regular acco\n8|INDIA|2|ss excuses cajole slyly across the packages. deposits print aroun\n9|INDONESIA|2| slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull\n10|IRAN|4|efully alongside of the slyly final dependencies. \n11|IRAQ|4|nic deposits boost atop the quickly final requests? quickly regula\n12|JAPAN|2|ously. final, express gifts cajole a\n13|JORDAN|4|ic deposits are blithely about the carefully regular pa\n14|KENYA|0| pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t\n15|MOROCCO|0|rns. blithely bold courts among the closely regular packages use furiously bold platelets?\n16|MOZAMBIQUE|0|s. ironic, unusual asymptotes wake blithely r\n17|PERU|1|platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun\n18|CHINA|2|c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos\n19|ROMANIA|3|ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account\n20|SAUDI ARABIA|4|ts. silent requests haggle. closely express packages sleep across the blithely\n21|VIETNAM|2|hely enticingly express accounts. even, final \n22|RUSSIA|3| requests against the platelets use never according to the quickly regular pint\n23|UNITED KINGDOM|3|eans boost carefully special requests. accounts are. carefull\n24|UNITED STATES|1|y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be\n' + nation4 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 | b'0|ALGERIA|0| haggle. carefully final deposits detect slyly agai\n1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon\n2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special \n3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold\n4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d\n5|ETHIOPIA|0|ven packages wake quickly. regu\n6|FRANCE|3|refully final requests. regular, ironi\n7|GERMANY|3|l platelets. regular accounts x-ray: unusual, regular acco\n8|INDIA|2|ss excuses cajole slyly across the packages. deposits print aroun\n9|INDONESIA|2| slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull\n10|IRAN|4|efully alongside of the slyly final dependencies. \n11|IRAQ|4|nic deposits boost atop the quickly final requests? quickly regula\n12|JAPAN|2|ously. final, express gifts cajole a\n13|JORDAN|4|ic deposits are blithely about the carefully regular pa\n14|KENYA|0| pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t\n15|MOROCCO|0|rns. blithely bold courts among the closely regular packages use furiously bold platelets?\n16|MOZAMBIQUE|0|s. ironic, unusual asymptotes wake blithely r\n17|PERU|1|platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun\n18|CHINA|2|c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos\n19|ROMANIA|3|ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account\n20|SAUDI ARABIA|4|ts. silent requests haggle. closely express packages sleep across the blithely\n21|VIETNAM|2|hely enticingly express accounts. even, final \n22|RUSSIA|3| requests against the platelets use never according to the quickly regular pint\n23|UNITED KINGDOM|3|eans boost carefully special requests. accounts are. carefull\n24|UNITED STATES|1|y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be\n' + nation5 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 | b'0|ALGERIA|0| haggle. carefully final deposits detect slyly agai\n1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon\n2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special \n3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold\n4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d\n5|ETHIOPIA|0|ven packages wake quickly. regu\n6|FRANCE|3|refully final requests. regular, ironi\n7|GERMANY|3|l platelets. regular accounts x-ray: unusual, regular acco\n8|INDIA|2|ss excuses cajole slyly across the packages. deposits print aroun\n9|INDONESIA|2| slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull\n10|IRAN|4|efully alongside of the slyly final dependencies. \n11|IRAQ|4|nic deposits boost atop the quickly final requests? quickly regula\n12|JAPAN|2|ously. final, express gifts cajole a\n13|JORDAN|4|ic deposits are blithely about the carefully regular pa\n14|KENYA|0| pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t\n15|MOROCCO|0|rns. blithely bold courts among the closely regular packages use furiously bold platelets?\n16|MOZAMBIQUE|0|s. ironic, unusual asymptotes wake blithely r\n17|PERU|1|platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun\n18|CHINA|2|c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos\n19|ROMANIA|3|ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account\n20|SAUDI ARABIA|4|ts. silent requests haggle. closely express packages sleep across the blithely\n21|VIETNAM|2|hely enticingly express accounts. even, final \n22|RUSSIA|3| requests against the platelets use never according to the quickly regular pint\n23|UNITED KINGDOM|3|eans boost carefully special requests. accounts are. carefull\n24|UNITED STATES|1|y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be\n' +(3 rows) +2: COMMIT; +COMMIT + +1: SELECT gp_inject_fault('remove_file_inject', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; + gp_inject_fault +----------------- + Success: + Success: + Success: +(3 rows) + +1: BEGIN; +BEGIN +2: BEGIN; +BEGIN +1: SELECT gp_inject_fault('directory_table_inject', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; + gp_inject_fault +----------------- + Success: + Success: + Success: +(3 rows) +1&: SELECT relative_path, size, tag, md5, content FROM directory_table('dir_table2') ORDER BY 1; +2&: SELECT remove_file('dir_table2', 'nation5'); +3: SELECT gp_wait_until_triggered_fault('directory_table_inject', 1, dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; + gp_wait_until_triggered_fault +------------------------------- + Success: + Success: + Success: +(3 rows) +3: SELECT gp_inject_fault('directory_table_inject', 'resume', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; + gp_inject_fault +----------------- + Success: + Success: + Success: +(3 rows) +1<: <... completed> + relative_path | size | tag | md5 | content +---------------+------+-----+----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + nation2 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 | b'0|ALGERIA|0| haggle. carefully final deposits detect slyly agai\n1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon\n2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special \n3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold\n4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d\n5|ETHIOPIA|0|ven packages wake quickly. regu\n6|FRANCE|3|refully final requests. regular, ironi\n7|GERMANY|3|l platelets. regular accounts x-ray: unusual, regular acco\n8|INDIA|2|ss excuses cajole slyly across the packages. deposits print aroun\n9|INDONESIA|2| slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull\n10|IRAN|4|efully alongside of the slyly final dependencies. \n11|IRAQ|4|nic deposits boost atop the quickly final requests? quickly regula\n12|JAPAN|2|ously. final, express gifts cajole a\n13|JORDAN|4|ic deposits are blithely about the carefully regular pa\n14|KENYA|0| pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t\n15|MOROCCO|0|rns. blithely bold courts among the closely regular packages use furiously bold platelets?\n16|MOZAMBIQUE|0|s. ironic, unusual asymptotes wake blithely r\n17|PERU|1|platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun\n18|CHINA|2|c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos\n19|ROMANIA|3|ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account\n20|SAUDI ARABIA|4|ts. silent requests haggle. closely express packages sleep across the blithely\n21|VIETNAM|2|hely enticingly express accounts. even, final \n22|RUSSIA|3| requests against the platelets use never according to the quickly regular pint\n23|UNITED KINGDOM|3|eans boost carefully special requests. accounts are. carefull\n24|UNITED STATES|1|y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be\n' + nation4 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 | b'0|ALGERIA|0| haggle. carefully final deposits detect slyly agai\n1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon\n2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special \n3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold\n4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d\n5|ETHIOPIA|0|ven packages wake quickly. regu\n6|FRANCE|3|refully final requests. regular, ironi\n7|GERMANY|3|l platelets. regular accounts x-ray: unusual, regular acco\n8|INDIA|2|ss excuses cajole slyly across the packages. deposits print aroun\n9|INDONESIA|2| slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull\n10|IRAN|4|efully alongside of the slyly final dependencies. \n11|IRAQ|4|nic deposits boost atop the quickly final requests? quickly regula\n12|JAPAN|2|ously. final, express gifts cajole a\n13|JORDAN|4|ic deposits are blithely about the carefully regular pa\n14|KENYA|0| pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t\n15|MOROCCO|0|rns. blithely bold courts among the closely regular packages use furiously bold platelets?\n16|MOZAMBIQUE|0|s. ironic, unusual asymptotes wake blithely r\n17|PERU|1|platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun\n18|CHINA|2|c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos\n19|ROMANIA|3|ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account\n20|SAUDI ARABIA|4|ts. silent requests haggle. closely express packages sleep across the blithely\n21|VIETNAM|2|hely enticingly express accounts. even, final \n22|RUSSIA|3| requests against the platelets use never according to the quickly regular pint\n23|UNITED KINGDOM|3|eans boost carefully special requests. accounts are. carefull\n24|UNITED STATES|1|y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be\n' + nation5 | 2199 | | 01ab9bc150261c9918ce9636be80ea15 | b'0|ALGERIA|0| haggle. carefully final deposits detect slyly agai\n1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon\n2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special \n3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold\n4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d\n5|ETHIOPIA|0|ven packages wake quickly. regu\n6|FRANCE|3|refully final requests. regular, ironi\n7|GERMANY|3|l platelets. regular accounts x-ray: unusual, regular acco\n8|INDIA|2|ss excuses cajole slyly across the packages. deposits print aroun\n9|INDONESIA|2| slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull\n10|IRAN|4|efully alongside of the slyly final dependencies. \n11|IRAQ|4|nic deposits boost atop the quickly final requests? quickly regula\n12|JAPAN|2|ously. final, express gifts cajole a\n13|JORDAN|4|ic deposits are blithely about the carefully regular pa\n14|KENYA|0| pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t\n15|MOROCCO|0|rns. blithely bold courts among the closely regular packages use furiously bold platelets?\n16|MOZAMBIQUE|0|s. ironic, unusual asymptotes wake blithely r\n17|PERU|1|platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun\n18|CHINA|2|c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos\n19|ROMANIA|3|ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account\n20|SAUDI ARABIA|4|ts. silent requests haggle. closely express packages sleep across the blithely\n21|VIETNAM|2|hely enticingly express accounts. even, final \n22|RUSSIA|3| requests against the platelets use never according to the quickly regular pint\n23|UNITED KINGDOM|3|eans boost carefully special requests. accounts are. carefull\n24|UNITED STATES|1|y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be\n' +(3 rows) +1: COMMIT; +COMMIT +2<: <... completed> + remove_file +------------- + t +(1 row) +2: COMMIT; +COMMIT + +1: SELECT gp_inject_fault('directory_table_inject', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' and content >= 0; + gp_inject_fault +----------------- + Success: + Success: + Success: +(3 rows) + +-- Test create directory table and drop directory table +1: BEGIN; +BEGIN +2: BEGIN; +BEGIN +1: CREATE DIRECTORY TABLE dir_table3 TABLESPACE directory_tblspc; +CREATE +2: DROP DIRECTORY TABLE dir_table2; +DROP +2: CREATE DIRECTORY TABLE dir_table2 TABLESPACE directory_tblspc; +CREATE +1: COMMIT; +COMMIT +2: COMMIT; +COMMIT + +! rm -rf '@testtablespace@'; + +DROP TABLESPACE directory_tblspc; +DROP diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out index 8b77a2dbf51..4774b14722c 100644 --- a/src/test/regress/expected/create_index.out +++ b/src/test/regress/expected/create_index.out @@ -2530,14 +2530,14 @@ SELECT relid, parentrelid, level FROM pg_partition_tree('concur_reindex_part_ind -- REINDEX TABLE fails for partitioned indexes -- Top-most parent index REINDEX TABLE concur_reindex_part_index; -- error -ERROR: "concur_reindex_part_index" is not a table or materialized view +ERROR: "concur_reindex_part_index" is not a table, directory table or materialized view REINDEX TABLE concur_reindex_part_index; -- error -ERROR: "concur_reindex_part_index" is not a table or materialized view +ERROR: "concur_reindex_part_index" is not a table, directory table or materialized view -- Partitioned index with no leaves REINDEX TABLE concur_reindex_part_index_10; -- error -ERROR: "concur_reindex_part_index_10" is not a table or materialized view +ERROR: "concur_reindex_part_index_10" is not a table, directory table or materialized view REINDEX TABLE concur_reindex_part_index_10; -- error -ERROR: "concur_reindex_part_index_10" is not a table or materialized view +ERROR: "concur_reindex_part_index_10" is not a table, directory table or materialized view -- Cannot run in a transaction block BEGIN; REINDEX INDEX concur_reindex_part_index; diff --git a/src/test/regress/expected/create_index_optimizer.out b/src/test/regress/expected/create_index_optimizer.out index 385b3aeb9e1..c0a9e4b98c0 100644 --- a/src/test/regress/expected/create_index_optimizer.out +++ b/src/test/regress/expected/create_index_optimizer.out @@ -2569,14 +2569,14 @@ SELECT relid, parentrelid, level FROM pg_partition_tree('concur_reindex_part_ind -- REINDEX TABLE fails for partitioned indexes -- Top-most parent index REINDEX TABLE concur_reindex_part_index; -- error -ERROR: "concur_reindex_part_index" is not a table or materialized view +ERROR: "concur_reindex_part_index" is not a table, directory table or materialized view REINDEX TABLE concur_reindex_part_index; -- error -ERROR: "concur_reindex_part_index" is not a table or materialized view +ERROR: "concur_reindex_part_index" is not a table, directory table or materialized view -- Partitioned index with no leaves REINDEX TABLE concur_reindex_part_index_10; -- error -ERROR: "concur_reindex_part_index_10" is not a table or materialized view +ERROR: "concur_reindex_part_index_10" is not a table, directory table or materialized view REINDEX TABLE concur_reindex_part_index_10; -- error -ERROR: "concur_reindex_part_index_10" is not a table or materialized view +ERROR: "concur_reindex_part_index_10" is not a table, directory table or materialized view -- Cannot run in a transaction block BEGIN; REINDEX INDEX concur_reindex_part_index; diff --git a/src/test/regress/expected/create_table_like.out b/src/test/regress/expected/create_table_like.out index d8d973b2fd0..0018b38650b 100644 --- a/src/test/regress/expected/create_table_like.out +++ b/src/test/regress/expected/create_table_like.out @@ -517,7 +517,7 @@ DROP TABLE noinh_con_copy, noinh_con_copy1; CREATE TABLE ctlt4 (a int, b text); CREATE SEQUENCE ctlseq1; CREATE TABLE ctlt10 (LIKE ctlseq1); -- fail -ERROR: "ctlseq1" is not a table, view, materialized view, composite type, or foreign table +ERROR: "ctlseq1" is not a table, directory table, view, materialized view, composite type, or foreign table LINE 1: CREATE TABLE ctlt10 (LIKE ctlseq1); ^ CREATE VIEW ctlv1 AS SELECT * FROM ctlt4; diff --git a/src/test/regress/expected/minirepro.out b/src/test/regress/expected/minirepro.out index 32fb6aab6da..79d67481f91 100644 --- a/src/test/regress/expected/minirepro.out +++ b/src/test/regress/expected/minirepro.out @@ -283,10 +283,10 @@ SET SET SET SET -psql:data/minirepro.sql:44: ERROR: only shared relations can be placed in pg_global tablespace -psql:data/minirepro.sql:46: ERROR: permission denied: "pg_tablespace" is a system catalog -psql:data/minirepro.sql:54: ERROR: permission denied: "pg_tablespace" is a system catalog -psql:data/minirepro.sql:62: ERROR: permission denied: "pg_tablespace" is a system catalog +psql:data/minirepro.sql:46: ERROR: only shared relations can be placed in pg_global tablespace +psql:data/minirepro.sql:48: ERROR: permission denied: "pg_tablespace" is a system catalog +psql:data/minirepro.sql:56: ERROR: permission denied: "pg_tablespace" is a system catalog +psql:data/minirepro.sql:64: ERROR: permission denied: "pg_tablespace" is a system catalog SET UPDATE 1 DELETE 1 @@ -299,6 +299,10 @@ DELETE 1 INSERT 0 1 DELETE 1 INSERT 0 1 +DELETE 1 +INSERT 0 1 +DELETE 1 +INSERT 0 1 select staattnum, stainherit, @@ -338,6 +342,8 @@ from pg_statistic where starelid='pg_tablespace'::regclass; 3 | f | 0 | 4 | -0.5 | 1 | 3 | 0 | 0 | 0 | 607 | 609 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | {1} | {1} | | | | {10} | | | | 4 | f | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | | | | | | | | | 5 | f | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | | | | | | | | | -(5 rows) + 6 | f | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | | | | | | | | | + 7 | f | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | | | | | | | | | +(7 rows) \! rm data/minirepro_q.sql diff --git a/src/test/regress/expected/oidjoins.out b/src/test/regress/expected/oidjoins.out index 8ef30c843c7..4d6ad39fbb8 100644 --- a/src/test/regress/expected/oidjoins.out +++ b/src/test/regress/expected/oidjoins.out @@ -142,6 +142,9 @@ NOTICE: checking pg_largeobject {loid} => pg_largeobject_metadata {oid} NOTICE: checking pg_aggregate {aggfnoid} => pg_proc {oid} NOTICE: checking pg_aggregate {aggtransfn} => pg_proc {oid} NOTICE: checking pg_aggregate {aggfinalfn} => pg_proc {oid} +NOTICE: checking gp_storage_server {srvowner} => pg_authid {oid} +NOTICE: checking gp_storage_user_mapping {umserver} => gp_storage_server {oid} +NOTICE: checking gp_storage_user_mapping {umuser} => pg_authid {oid} NOTICE: checking pg_aggregate {aggcombinefn} => pg_proc {oid} NOTICE: checking pg_aggregate {aggserialfn} => pg_proc {oid} NOTICE: checking pg_aggregate {aggdeserialfn} => pg_proc {oid} @@ -179,6 +182,8 @@ NOTICE: checking pg_trigger {tgrelid,tgattr} => pg_attribute {attrelid,attnum} NOTICE: checking pg_event_trigger {evtowner} => pg_authid {oid} NOTICE: checking pg_event_trigger {evtfoid} => pg_proc {oid} NOTICE: checking pg_description {classoid} => pg_class {oid} +NOTICE: checking pg_directory_table {dtrelid} => pg_class {oid} +NOTICE: checking pg_directory_table {dttablespace} => pg_tablespace {oid} NOTICE: checking pg_cast {castsource} => pg_type {oid} NOTICE: checking pg_cast {casttarget} => pg_type {oid} NOTICE: checking pg_cast {castfunc} => pg_proc {oid} diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out index fbac24e2306..85b3ce33312 100644 --- a/src/test/regress/expected/opr_sanity.out +++ b/src/test/regress/expected/opr_sanity.out @@ -402,12 +402,14 @@ WHERE 'cstring'::regtype = ANY (p1.proargtypes) AND NOT EXISTS(SELECT 1 FROM pg_conversion WHERE conproc = p1.oid) AND p1.oid != 'shell_in(cstring)'::regprocedure ORDER BY 1; - oid | proname -------+----------------- + oid | proname +------+--------------------- 2293 | cstring_out 2501 | cstring_send 7060 | get_role_status -(3 rows) + 8996 | remove_file + 9109 | remove_file_segment +(5 rows) -- Likewise, look for functions that return cstring and aren't datatype output -- functions nor typmod output functions. diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out index e70e4f17fa8..ca4b1db5320 100644 --- a/src/test/regress/expected/sanity_check.out +++ b/src/test/regress/expected/sanity_check.out @@ -128,6 +128,7 @@ pg_db_role_setting|t pg_default_acl|t pg_depend|t pg_description|t +pg_directory_table|t pg_enum|t pg_event_trigger|t pg_extension|t diff --git a/src/test/regress/greenplum_schedule b/src/test/regress/greenplum_schedule index 58fda7b5803..79ae4d04baa 100755 --- a/src/test/regress/greenplum_schedule +++ b/src/test/regress/greenplum_schedule @@ -313,4 +313,7 @@ test: aqumv # test access method with encoding options test: am_encoding +# tests of directory table +test: directory_table + # end of tests diff --git a/src/test/regress/input/directory_table.source b/src/test/regress/input/directory_table.source new file mode 100644 index 00000000000..089c3177310 --- /dev/null +++ b/src/test/regress/input/directory_table.source @@ -0,0 +1,647 @@ +-- +-- Test for directory table +-- + +-- Display pg_tablespace, pg_directory_table, gp_storage_server, gp_storage_user_mapping catalog +\d+ pg_tablespace; +\d+ pg_directory_table; +\d+ gp_storage_server; +\d+ gp_storage_user_mapping; + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname = 'pg_directory_table'; +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname = 'gp_storage_server'; +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname = 'gp_storage_user_mapping'; + +-- CREATE TABLESPACE +CREATE TABLESPACE directory_tblspc LOCATION '@testtablespace@'; + +-- CREATE DATABASE +CREATE DATABASE dirtable_db; +\c dirtable_db +\d+ pg_directory_table; +\d+ gp_storage_server; +\d+ gp_storage_user_mapping; + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname = 'pg_directory_table'; +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname = 'gp_storage_server'; +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname = 'gp_storage_user_mapping'; +\c regression + +-- CREATE USER for directory table +CREATE USER test_dirtable1; +CREATE USER test_dirtable2; +CREATE USER test_dirtable3; +CREATE USER test_dirtable4; + +-- Test CREATE STORAGE SERVER +SELECT srvname, srvacl, srvoptions from gp_storage_server ORDER BY 1; +CREATE STORAGE SERVER oss_server1; +CREATE STORAGE SERVER oss_server2 OPTIONS(protocal 'localhost'); +CREATE STORAGE SERVER oss_server3 OPTIONS(endpoint '127.0.0.1:9000'); +CREATE STORAGE SERVER oss_server4 OPTIONS(https 'true'); +CREATE STORAGE SERVER oss_server5 OPTIONS(virtual_host 'false'); +CREATE STORAGE SERVER oss_server6 OPTIONS(protocol 'qingstor', endpoint 'pek3b,qingstor.com'); +CREATE STORAGE SERVER oss_server7 OPTIONS(https 'false', virtual_host 'true'); +CREATE STORAGE SERVER oss_server8 OPTIONS(protocol 'hdfs', namenode '127.0.0.1:8020'); +CREATE STORAGE SERVER oss_server9 OWNER TO postgres; -- fail +CREATE STORAGE SERVER IF NOT EXISTS oss_server10; +CREATE STORAGE SERVER IF NOT EXISTS oss_server11 OPTIONS(protocol 's3av2'); +CREATE STORAGE SERVER IF NOT EXISTS oss_server12 OPTIONS(protocol 's3av2', endpoint '127.0.0.1:9000', https 'false'); +CREATE STORAGE SERVER IF NOT EXISTS oss_server13 OWNER TO postgres; -- fail + +SELECT srvname, srvacl, srvoptions from gp_storage_server ORDER BY 1; +\c dirtable_db +SELECT srvname, srvacl, srvoptions from gp_storage_server ORDER BY 1; +\c regression + +-- Test ALTER STORAGE SERVER +ALTER STORAGE SERVER oss_server1 OPTIONS(protocol 'aws'); +ALTER STORAGE SERVER oss_server1 OPTIONS(protocol 'test'); -- fail +ALTER STORAGE SERVER oss_server2 OPTIONS(https 'true'); +ALTER STORAGE SERVER oss_server2 OPTIONS(https 'false', virtual_host 'true'); -- fail +ALTER STORAGE SERVER oss_server2 OPTIONS(virtual_host 'true'); +ALTER STORAGE SERVER oss_server3 OPTIONS(endpoint '192.168.0.1'); -- fail +ALTER STORAGE SERVER oss_server4 OPTIONS(protocol 'localhost', virtual_host 'true'); +ALTER STORAGE SERVER oss_server4 OPTIONS(protocol 'qingstor'); -- fail +ALTER STORAGE SERVER oss_server5; -- fail +ALTER STORAGE SERVER oss_server6 OWNER TO postgres; -- fail +ALTER STORAGE SERVER IF EXISTS oss_server7 OPTIONS(endpoint '127.0.0.1:6555'); -- fail +ALTER STORAGE SERVER IF NOT EXISTS oss_server8 OPTIONS(virtual_host 'true'); -- fail + +SELECT srvname, srvacl, srvoptions from gp_storage_server ORDER BY 1; +\c dirtable_db +SELECT srvname, srvacl, srvoptions from gp_storage_server ORDER BY 1; +\c regression + +-- Test CREATE STORAGE USER MAPPING +CREATE STORAGE USER MAPPING FOR CURRENT_USER; -- fail + +CREATE STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server1; + +CREATE STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server1 +OPTIONS (accesskey 'KGFQWEFQQEFXVAEAWLLC', secretkey '0SJIWiIATh6jOlmAKr8DGq6hOAGBI1BnsnvgJmTs'); -- fail + +CREATE STORAGE USER MAPPING IF NOT EXISTS FOR CURRENT_USER STORAGE SERVER oss_server1; + +CREATE STORAGE USER MAPPING IF NOT EXISTS FOR CURRENT_USER STORAGE SERVER oss_server1 +OPTIONS (auth_method 'simple'); + +CREATE STORAGE USER MAPPING FOR CURRENT_ROLE STORAGE SERVER oss_server2 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE'); + +CREATE STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server2 +OPTIONS (accesskey 'KGFQWEFQQEFXVAEAWLLC', secretkey '0SJIWiIATh6jOlmAKr8DGq6hOAGBI1BnsnvgJmTs'); -- fail + +CREATE STORAGE USER MAPPING FOR CURRENT_ROLE STORAGE SERVER oss_server3 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE'); + +CREATE STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_not_exits; -- fail + +CREATE STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_not_exits +OPTIONS (accesskey 'KGFQWEFQQEFXVAEAWLLC', secretkey '0SJIWiIATh6jOlmAKr8DGq6hOAGBI1BnsnvgJmTs'); -- fail + +CREATE STORAGE USER MAPPING FOR test_dirtable1 STORAGE SERVER oss_server1; + +CREATE STORAGE USER MAPPING FOR test_dirtable1 STORAGE SERVER oss_server1 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H'); -- fail + +CREATE STORAGE USER MAPPING FOR test_dirtable1 STORAGE SERVER oss_server2 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H'); + +CREATE STORAGE USER MAPPING FOR test_dirtable1 STORAGE SERVER oss_server3 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H'); + +CREATE STORAGE USER MAPPING FOR no_exist_user STORAGE SERVER oss_server1; -- fail + +CREATE STORAGE USER MAPPING FOR no_exist_user STORAGE SERVER oss_server1 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H'); -- fail + +CREATE STORAGE USER MAPPING IF NOT EXISTS FOR CURRENT_USER STORAGE SERVER oss_server1 +OPTIONS (accesskey 'KGFQWEFQQEFXVAEAWLLC', secretkey '0SJIWiIATh6jOlmAKr8DGq6hOAGBI1BnsnvgJmTs'); -- skip + +CREATE STORAGE USER MAPPING IF NOT EXISTS FOR test_dirtable2 STORAGE SERVER oss_server3 +OPTIONS (endpoint '127.0.0.1:6555'); + +CREATE STORAGE USER MAPPING IF NOT EXISTS FOR test_dirtable3 STORAGE SERVER oss_server8 +OPTIONS (auth_method 'simple'); + +CREATE STORAGE USER MAPPING IF NOT EXISTS FOR no_exist_user STORAGE SERVER oss_server1; -- fail + +SELECT umoptions FROM gp_storage_user_mapping ORDER BY 1; +\c dirtable_db +SELECT umoptions FROM gp_storage_user_mapping ORDER BY 1; +\c regression + +-- Test ALTER STORAGE USER MAPPING +ALTER STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server1; -- fail + +ALTER STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server1 +OPTIONS (accesskey 'KGFQWEFQQEFXVAEAWLLC', secretkey '0SJIWiIATh6jOlmAKr8DGq6hOAGBI1BnsnvgJmTs'); + +ALTER STORAGE USER MAPPING FOR CURRENT_ROLE STORAGE SERVER oss_server1 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ'); -- fail + +ALTER STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server1 +OPTIONS (auth_method 'simple'); + +ALTER STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server2 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE'); -- fail + +ALTER STORAGE USER MAPPING IF EXISTS FOR CURRENT_USER STORAGE SERVER server_not_exists +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE'); -- fail + +ALTER STORAGE USER MAPPING IF EXISTS FOR no_exist_user STORAGE SERVER oss_server1 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE'); -- fail + +ALTER STORAGE USER MAPPING IF NOT EXISTS FOR test_dirtable1 STORAGE SERVER oss_server3 +OPTIONS (auth_method 'simple'); -- fail + +SELECT umoptions FROM gp_storage_user_mapping ORDER BY 1; +\c dirtable_db +SELECT umoptions FROM gp_storage_user_mapping ORDER BY 1; +\c regression + +-- Test DROP STORAGE USER MAPPING +DROP STORAGE USER MAPPING FOR CURRENT_USER; -- fail +DROP STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server2; +DROP STORAGE USER MAPPING IF EXISTS FOR test_dirtable1 STORAGE SERVER oss_server1; +DROP STORAGE USER MAPPING IF EXISTS FOR test_dirtable2 STORAGE SERVER no_exist_server; +DROP STORAGE USER MAPPING FOR test_dirtable3 STORAGE SERVER no_exist_server; -- fail +DROP STORAGE USER MAPPING FOR no_exist_user STORAGE SERVER oss_server1; -- fail +DROP STORAGE USER MAPPING IF EXISTS FOR no_exist_user STORAGE SERVER oss_server1; -- skip + +SELECT umoptions FROM gp_storage_user_mapping ORDER BY 1; +\c dirtable_db +SELECT umoptions FROM gp_storage_user_mapping ORDER BY 1; +\c regression + +-- Test DROP STOARGE SERVER +DROP STORAGE SERVER oss_server1; -- fail +DROP STORAGE SERVER oss_server2; -- fail +DROP STORAGE SERVER oss_server3; -- fail +DROP STORAGE SERVER oss_server4; -- fail +DROP STORAGE SERVER oss_server8; -- fail +DROP STORAGE SERVER oss_server9; -- fail +DROP STAROGE SERVER IF EXISTS oss_server9; -- fail +DROP STORAGE SERVER IF NOT EXISTS oss_server9; --fail +DROP STORAGE SERVER IF EXISTS oss_server10; + +SELECT srvname, srvacl, srvoptions from gp_storage_server ORDER BY 1; +\c dirtable_db +SELECT srvname, srvacl, srvoptions from gp_storage_server ORDER BY 1; +\c regression + +-- Test directory table +-- Test CREATE DIRECTORY TABLE +SELECT count(*) FROM pg_directory_table; +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname like '%dir_table%' ORDER BY 1; + +CREATE DIRECTORY TABLE dir_table1; +CREATE DIRECTORY TABLE dir_table2 TABLESPACE directory_tblspc; +CREATE DIRECTORY TABLE dir_table3 TABLESPACE directory_tblspc DISTRIBUTED BY(relative_path); -- fail +CREATE DIRECTORY TABLE dir_table3 TABLESPACE directory_tblspc DISTRIBUTED RANDOMLY; -- fail +CREATE DIRECTORY TABLE dir_table3 TABLESPACE directory_tblspc DISTRIBUTED REPLICATED; -- fail +CREATE DIRECTORY TABLE dir_table3 TABLESPACE directory_tblspc; +CREATE DIRECTORY TABLE IF NOT EXISTS dir_table4 TABLESPACE directory_tblspc; +CREATE DIRECTORY TABLE IF NOT EXISTS dir_table2 TABLESPACE directory_tblspc; -- fail +CREATE DIRECTORY TABLE dir_table5 TABLESPACE directory_tblspc; +CREATE DIRECTORY TABLE dir_table6 TABLESPACE pg_default; + +\dY +SELECT count(*) FROM pg_directory_table; +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname like '%dir_table%' ORDER BY 1; +\d+ dir_table1; +\d+ dir_table2; +\d+ dir_table3; +\c dirtable_db +\dY +SELECT count(*) FROM pg_directory_table; +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname like '%dir_table%' ORDER BY 1; +\c regression + +-- Test create table inherits directory table +CREATE TABLE test_inherits1 INHERITS(dir_table1); -- fail +CREATE TABLE test_inherits2(a int) INHERITS(dir_table2); -- fail +CREATE TABLE test_inherits3 INHERITS(dir_table2, dir_table3); -- fail +CREATE TABLE test_inherits4(b text) INHERITS(dir_table1, dir_table2); -- fail + +-- Test DROP DIRECTORY TABLE +DROP DIRECTORY TABLE dir_table4; +DROP DIRECTORY TABLE dir_table4; -- fail +DROP DIRECTORY TABLE IF EXISTS dir_table5; +DROP DIRECTORY TABLE IF EXISTS dir_table5; -- skip + +\dY +SELECT count(*) FROM pg_directory_table; +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname like '%dir_table%' ORDER BY 1; +\c dirtable_db +\dY +SELECT count(*) FROM pg_directory_table; +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname like '%dir_table%' ORDER BY 1; +\c regression + +-- Test CREATE/DROP/REINDEX on DIRECTORY SCHEMA TABLE +-- Test CREATE INDEX on DIRECTORY SCHEMA TABLE +CREATE INDEX dirtable1_relative_path_idx on dir_table1(relative_path); -- fail +CREATE INDEX dirtable1_size_idx on dir_table1(size); -- fail +CREATE INDEX dirtable1_last_modified_idx on dir_table1(last_modified); -- fail +CREATE INDEX dirtable1_md5_idx on dir_table1(md5); -- fail +CREATE INDEX dirtable1_tag_idx on dir_table1(tag); -- fail +\d+ dir_table1; + +-- Test DROP INDEX on DIRECTORY SCHEMA TABLE +DROP INDEX dir_table1_pkey; -- fail +DROP INDEX dir_table2_pkey; -- fail +DROP INDEX dir_table3_pkey; -- fail +DROP INDEX dir_table4_pkey; -- fail +DROP INDEX dir_table5_pkey; -- fail +DROP INDEX dir_table6_pkey; -- fail + +-- Test REINDEX on DIRECTORY SCHEMA TABLE +REINDEX INDEX dir_table1_pkey; +REINDEX INDEX dir_table2_pkey; +REINDEX INDEX dir_table3_pkey; +REINDEX INDEX dir_table4_pkey; +REINDEX INDEX dir_table5_pkey; +REINDEX INDEX dir_table6_pkey; + +REINDEX TABLE dir_table1; +REINDEX TABLE dir_table2; +REINDEX TABLE dir_table3; +REINDEX TABLE dir_table4; +REINDEX TABLE dir_table5; +REINDEX TABLE dir_table6; + +-- Test triggers +DROP FUNCTION IF EXISTS trigtest; +create function trigtest() returns trigger as $$ +begin + raise notice '% % % %', TG_TABLE_NAME, TG_OP, TG_WHEN, TG_LEVEL; + return new; +end;$$ language plpgsql; + +create trigger trigtest_b_row_tg_dirtable_1 before insert or update or delete on dir_table1 +for each row execute procedure trigtest(); +create trigger trigtest_a_row_tg_dirtable_1 after insert or update or delete on dir_table1 +for each row execute procedure trigtest(); +create trigger trigtest_b_stmt_tg_dirtable_1 before insert or update or delete on dir_table1 +for each statement execute procedure trigtest(); +create trigger trigtest_a_stmt_tg_dirtable_1 after insert or update or delete on dir_table1 +for each statement execute procedure trigtest(); + +-- Test COPY DIRECTORY TABLE syntax +SELECT relative_path, size, tag FROM dir_table1 ORDER BY 1; +SELECT relative_path, size, tag FROM dir_table2 ORDER BY 1; + +\COPY dir_table1 FROM '@abs_srcdir@/data/nation.csv'; -- fail +\COPY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation'; -- fail +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv'; -- fail +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation1'; +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation1'; -- fail +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation2' 'nation2'; -- fail +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation2'; +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation3' WITH TAG 'nation'; +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation3' WITH TAG 'nation'; -- fail +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation3' WITH TAG 'nation2'; -- fail +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation4' WITH TAG 'nation'; +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation5' WITH TAG 'nation' WITH TAG 'nation2'; -- fail +SELECT relative_path, size, tag FROM dir_table1 ORDER BY 1; +SELECT relative_path, content FROM directory_table('dir_table1') ORDER BY 1; + +COPY dir_table2 FROM '@abs_srcdir@/data/nation.csv'; -- fail +COPY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation'; -- fail +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv'; -- fail +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation1'; +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation1'; -- fail +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation2'; +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation3' WITH TAG 'nation'; +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation3' WITH TAG 'nation'; -- fail +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation3' WITH TAG 'nation2'; -- fail +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation4' WITH TAG 'nation'; +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation5' WITH TAG 'nation' WITH TAG 'nation2'; -- fail +SELECT relative_path, size, tag FROM dir_table2 ORDER BY 1; +SELECT relative_path, content FROM directory_table('dir_table2') ORDER BY 1; + +-- Test copy binary from directory table +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (format CSV); +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (freeze off); +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (freeze on); +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (delimiter ','); +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (null ' '); +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (header off); +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (header on); +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (quote ':'); +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (escape ':'); +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_quote (a)); +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_quote *); +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_not_null (a)); +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_null (a)); +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (convert_selectively (a)); +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (encoding 'sql_ascii'); + +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (format CSV); +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (freeze off); +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (freeze on); +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (delimiter ','); +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (null ' '); +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (header off); +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (header on); +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (quote ':'); +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (escape ':'); +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_quote (a)); +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_quote *); +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_not_null (a)); +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_null (a)); +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (convert_selectively (a)); +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (encoding 'sql_ascii'); + +-- Test copy file content md5 +CREATE OR REPLACE FUNCTION file_content(text, text) RETURNS BYTEA LANGUAGE SQL AS +'select content from directory_table($1) where relative_path = $2'; + +CREATE OR REPLACE FUNCTION file_md5(text, text) RETURNS TEXT LANGUAGE SQL AS +'select md5 from directory_table($1) where relative_path = $2'; + +CREATE OR REPLACE FUNCTION md5_equal(text, text) RETURNS BOOL LANGUAGE SQL AS +'SELECT md5(file_content($1, $2)) = (SELECT file_md5($1, $2))'; + +SELECT md5_equal('dir_table1', 'nation1'); +SELECT md5_equal('dir_table1', 'nation2'); +SELECT md5_equal('dir_table1', 'nation3'); +SELECT md5_equal('dir_table1', 'nation4'); + +SELECT md5_equal('dir_table2', 'nation1'); +SELECT md5_equal('dir_table2', 'nation2'); +SELECT md5_equal('dir_table2', 'nation3'); +SELECT md5_equal('dir_table2', 'nation4'); + +-- Does not support copy to +\COPY dir_table1 TO '@abs_srcdir@/data/dir_table1'; -- fail +\COPY BINARY dir_table1 TO '@abs_srcdir@/data/dir_table1'; -- fail +COPY dir_table1 TO '@abs_srcdir@/data/dir_table1'; -- fail +COPY BINARY dir_table1 TO '@abs_srcdir@/data/dir_table1'; -- fail +\COPY dir_table2 TO '@abs_srcdir@/data/dir_table2'; -- fail +\COPY BINARY dir_table2 TO '@abs_srcdir@/data/dir_table2'; -- fail +COPY dir_table2 TO '@abs_srcdir@/data/dir_table2'; -- fail +COPY BINARY dir_table2 TO '@abs_srcdir@/data/dir_table2'; -- fail +SELECT relative_path, size, tag FROM dir_table1 ORDER BY 1; +SELECT relative_path, size, tag FROM dir_table2 ORDER BY 1; + +-- Test join between two directory schema tables +ANALYZE dir_table1; +ANALYZE dir_table2; + +EXPLAIN (COSTS OFF) SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.relative_path = dir_table2.relative_path ORDER BY 1; +SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.relative_path = dir_table2.relative_path ORDER BY 1; + +EXPLAIN (COSTS OFF) SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.size = dir_table2.size ORDER BY 1 LIMIT 1; +SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.size = dir_table2.size ORDER BY 1 LIMIT 1; + +EXPLAIN (COSTS OFF) SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.md5 = dir_table2.md5 ORDER BY 1 LIMIT 1; +SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.md5 = dir_table2.md5 ORDER BY 1 LIMIT 1; + +EXPLAIN (COSTS OFF) SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.tag = dir_table2.tag ORDER BY 1; +SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.tag = dir_table2.tag ORDER BY 1; + +-- Test DML directory schema table, only allow to update tag +INSERT INTO dir_table1 VALUES('insert'); -- fail +INSERT INTO dir_table2 VALUES('insert', 512, '2000-03-21 17:13:27+08', '70f09140d1b83eb3ecf9a0e28494d2a4', 'insert'); -- fail +SELECT relative_path, size, tag FROM dir_table1 ORDER BY 1; +SELECT relative_path, size, tag FROM dir_table2 ORDER BY 1; + +DELETE FROM dir_table1; -- fail +DELETE FROM dir_table2 WHERE relative_path = 'nation1'; -- fail +SELECT relative_path, size, tag FROM dir_table1 ORDER BY 1; +SELECT relative_path, size, tag FROM dir_table2 ORDER BY 1; + +UPDATE dir_table1 SET relative_path = 'nation_updated'; -- fail +UPDATE dir_table2 SET relative_path = 'nation_updated' WHERE relative_path = 'nation2'; -- fail +UPDATE dir_table1 SET size = 512; -- fail +UPDATE dir_table2 SET size = 1024 WHERE relative_path = 'nation1'; -- fail +UPDATE dir_table1 SET last_modified = '2000-03-21 16:55:07+08'; -- fail +UPDATE dir_table2 SET last_modified = '2000-03-21 16:55:07+08' WHERE relative_path = 'nation3'; -- fail +UPDATE dir_table1 SET md5 = '70f09140d1b83eb3ecf9a0e28494d2a4'; -- fail +UPDATE dir_table2 SET md5 = '70f09140d1b83eb3ecf9a0e28494d2a4' WHERE relative_path = 'nation4'; -- fail +UPDATE dir_table1 SET tag = 'nation_new_tag'; -- ok +UPDATE dir_table1 SET tag = 'nation2_new_tag' WHERE relative_path = 'nation2'; -- ok +UPDATE dir_table2 SET tag = 'nation4_new_tag' WHERE relative_path = 'nation3'; -- ok +UPDATE dir_table1 SET tag = 'failed_tag' WHERE relative_path = 'not_exist_path'; +UPDATE dir_table2 SET tag = 'no_tag' WHERE relative_path = 'not_exist_path'; +SELECT relative_path, size, tag FROM dir_table1 ORDER BY 1; +SELECT relative_path, size, tag FROM dir_table2 ORDER BY 1; + +-- Test alter table directory schema table +ALTER TABLE dir_table1 ADD COLUMN a int; -- fail +ALTER DIRECTORY TABLE dir_table1 ADD COLUMN a int; -- fail +ALTER TABLE dir_table2 DROP COLUMN relative_path; -- fail +ALTER DIRECTORY TABLE dir_table2 DROP COLUMN relative_path; -- fail +ALTER TABLE dir_table1 RENAME TO dir_table_new; -- fail +ALTER DIRECTORY TABLE dir_table1 RENAME TO dir_table_new; -- fail +ALTER TABLE dir_table2 ADD CONSTRAINT dirtable_constraint UNIQUE (tag); -- fail +ALTER DIRECTORY TABLE dir_table2 ADD CONSTRAINT dirtable_constraint UNIQUE (tag); -- fail +ALTER TABLE dir_table1 DROP CONSTRAINT DROP CONSTRAINT test_pkey; -- fail +ALTER DIRECTORY TABLE dir_table1 DROP CONSTRAINT DROP CONSTRAINT test_pkey; -- fail + +-- Test remove_table +SELECT remove_file('dir_table1', 'nation5'); -- fail +SELECT remove_file('dir_table1', 'nation1'); +SELECT remove_file('dir_table2', 'nation1', 'nation2'); -- fail +SELECT remove_file('dir_table1', 'nation2'); +SELECT remove_file('dir_table3', 'nation1'); -- fail +SELECT remove_file('dir_table2', 'nation3'); +SELECT remove_file('dir_table1', 'nation1'); -- fail +SELECT relative_path, size, tag FROM dir_table1 ORDER BY 1; +SELECT relative_path, size, tag FROM dir_table2 ORDER BY 1; + +-- Test transaction commit of directory table manipulation +CREATE DIRECTORY TABLE dir_table4 TABLESPACE directory_tblspc; + +BEGIN; +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_commit'; +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_commit2' WITH TAG 'nation'; + +COMMIT; +SELECT relative_path, content FROM directory_table('dir_table4') ORDER BY 1; + +BEGIN; +SELECT remove_file('dir_table4', 'nation_commit'); +SELECT relative_path, content FROM directory_table('dir_table4') ORDER BY 1; +COMMIT; +SELECT relative_path, content FROM directory_table('dir_table4') ORDER BY 1; + +BEGIN; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +UPDATE dir_table4 SET tag = 'nation_updated' WHERE relative_path = 'nation_commit2'; +COMMIT; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + +-- Test transaction rollback of directory table manipulation + +BEGIN; +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_rollback'; +SELECT relative_path, content FROM directory_table('dir_table4') ORDER BY 1; +ROLLBACK; +SELECT relative_path, content FROM directory_table('dir_table4') ORDER BY 1; + +BEGIN; +SELECT remove_file('dir_table4', 'nation_commit2'); +SELECT relative_path, content FROM directory_table('dir_table4') ORDER BY 1; +ROLLBACK; +SELECT relative_path, content FROM directory_table('dir_table4') ORDER BY 1; + +BEGIN; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_rollback2' WITH TAG 'nation'; +UPDATE dir_table4 SET tag = 'nation_updated' WHERE relative_path = 'nation_rollback2'; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +ROLLBACK; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + +-- Test subtransaction commit of directory table manipulation +BEGIN; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subcommit' WITH TAG 'nation'; +SAVEPOINT s1; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subcommit2'; +SAVEPOINT s2; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subcommit3'; +RELEASE SAVEPOINT s1; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +COMMIT; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + +BEGIN; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +SELECT remove_file('dir_table4', 'nation_subcommit'); +SAVEPOINT s1; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subcommit'; +SAVEPOINT s2; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +RELEASE SAVEPOINT s1; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +COMMIT; + +BEGIN; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +SELECT remove_file('dir_table4', 'nation_subcommit'); +SAVEPOINT s1; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +SELECT remove_file('dir_table4', 'nation_subcommit2'); +SAVEPOINT s2; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +RELEASE SAVEPOINT s2; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +COMMIT; + +BEGIN; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +SELECT remove_file('dir_table4', 'nation_subcommit2'); +SAVEPOINT s1; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subcommit4'; +SAVEPOINT s2; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +ROLLBACK TO SAVEPOINT s1; +COMMIT; + +-- Test subtransaction rollback of directory table manipulation +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subrollback1'; +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subrollback2'; +BEGIN; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subrollback3'; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +SAVEPOINT s1; +SELECT remove_file('dir_table4', 'nation_subrollback1'); +SAVEPOINT s2; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +ROLLBACK; + +BEGIN; +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subrollback4'; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +SAVEPOINT s1; +SELECT remove_file('dir_table4', 'nation_subrollback4'); +SAVEPOINT s2; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +RELEASE SAVEPOINT s1; +ROLLBACK; + +BEGIN; +SELECT remove_file('dir_table4', 'nation_subrollback2'); +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subrollback5'; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +SAVEPOINT s1; +SELECT remove_file('dir_table4', 'nation_subrollback5'); +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +ROLLBACK TO SAVEPOINT s1; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subrollback6'; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; +SAVEPOINT s2; +ROLLBACK; + +-- clean up +DROP DIRECTORY TABLE IF EXISTS dir_table1; +DROP DIRECTORY TABLE IF EXISTS dir_table2; +DROP DIRECTORY TABLE IF EXISTS dir_table3; +DROP DIRECTORY TABLE IF EXISTS dir_table4; +DROP DIRECTORY TABLE IF EXISTS dir_table5; +DROP DIRECTORY TABLE IF EXISTS dir_table6; + +DROP FUNCTION IF EXISTS trigtest; + +DROP STORAGE USER MAPPING IF EXISTS FOR CURRENT_USER STORAGE SERVER oss_server1; +DROP STORAGE USER MAPPING IF EXISTS FOR CURRENT_USER STORAGE SERVER oss_server2; +DROP STORAGE USER MAPPING IF EXISTS FOR CURRENT_USER STORAGE SERVER oss_server3; +DROP STORAGE USER MAPPING IF EXISTS FOR CURRENT_USER STORAGE SERVER oss_server4; +DROP STORAGE USER MAPPING IF EXISTS FOR test_dirtable1 STORAGE SERVER oss_server1; +DROP STORAGE USER MAPPING IF EXISTS FOR test_dirtable1 STORAGE SERVER oss_server2; +DROP STORAGE USER MAPPING IF EXISTS FOR test_dirtable1 STORAGE SERVER oss_server3; +DROP STORAGE USER MAPPING IF EXISTS FOR test_dirtable2 STORAGE SERVER oss_server3; +DROP STORAGE USER MAPPING IF EXISTS FOR test_dirtable3 STORAGE SERVER oss_server8; + +DROP STORAGE SERVER IF EXISTS oss_server1; +DROP STORAGE SERVER IF EXISTS oss_server2; +DROP STORAGE SERVER IF EXISTS oss_server3; +DROP STORAGE SERVER IF EXISTS oss_server4; +DROP STORAGE SERVER IF EXISTS oss_server5; +DROP STORAGE SERVER IF EXISTS oss_server6; +DROP STORAGE SERVER IF EXISTS oss_server7; +DROP STORAGE SERVER IF EXISTS oss_server8; +DROP STORAGE SERVER IF EXISTS oss_server9; +DROP STORAGE SERVER IF EXISTS oss_server10; +DROP STORAGE SERVER IF EXISTS oss_server11; +DROP STORAGE SERVER IF EXISTS oss_server12; +DROP STORAGE SERVER IF EXISTS oss_server13; + +SELECT srvname, srvacl, srvoptions FROM gp_storage_server; + +DROP USER test_dirtable1; +DROP USER test_dirtable2; +DROP USER test_dirtable3; +DROP USER test_dirtable4; + +DROP FUNCTION IF EXISTS file_content; +DROP FUNCTION IF EXISTS file_md5; +DROP FUNCTION IF EXISTS md5_equal; + +DROP DATABASE dirtable_db; + +DROP TRIGGER IF EXISTS trigtest_b_row_tg_dirtable_1 ON dir_table1; +DROP TRIGGER IF EXISTS trigtest_a_row_tg_dirtable_1 ON dir_table1; +DROP TRIGGER IF EXISTS trigtest_b_stmt_tg_dirtable_1 ON dir_table1; +DROP TRIGGER IF EXISTS trigtest_a_stmt_tg_dirtable_1 ON dir_table1; + +DROP TABLESPACE directory_tblspc; diff --git a/src/test/regress/output/directory_table.source b/src/test/regress/output/directory_table.source new file mode 100644 index 00000000000..196bd87b6fd --- /dev/null +++ b/src/test/regress/output/directory_table.source @@ -0,0 +1,1847 @@ +-- +-- Test for directory table +-- +-- Display pg_tablespace, pg_directory_table, gp_storage_server, gp_storage_user_mapping catalog +\d+ pg_tablespace; + Table "pg_catalog.pg_tablespace" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +-------------------+-----------+-----------+----------+---------+----------+--------------+------------- + oid | oid | | not null | | plain | | + spcname | name | | not null | | plain | | + spcowner | oid | | not null | | plain | | + spcacl | aclitem[] | | | | extended | | + spcoptions | text[] | C | | | extended | | + spcfilehandlersrc | text | C | | | extended | | + spcfilehandlerbin | text | C | | | extended | | +Indexes: + "pg_tablespace_oid_index" PRIMARY KEY, btree (oid), tablespace "pg_global" + "pg_tablespace_spcname_index" UNIQUE CONSTRAINT, btree (spcname), tablespace "pg_global" +Tablespace: "pg_global" + +\d+ pg_directory_table; + Table "pg_catalog.pg_directory_table" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------------+------+-----------+----------+---------+----------+--------------+------------- + dtrelid | oid | | not null | | plain | | + dttablespace | oid | | not null | | plain | | + dtlocation | text | C | | | extended | | +Indexes: + "pg_directory_table_relid_index" PRIMARY KEY, btree (dtrelid) + +\d+ gp_storage_server; + Table "pg_catalog.gp_storage_server" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +------------+-----------+-----------+----------+---------+----------+--------------+------------- + oid | oid | | not null | | plain | | + srvname | name | | not null | | plain | | + srvowner | oid | | not null | | plain | | + srvacl | aclitem[] | | | | extended | | + srvoptions | text[] | C | | | extended | | +Indexes: + "gp_storage_server_oid_index" PRIMARY KEY, btree (oid), tablespace "pg_global" + "gp_storage_server_name_index" UNIQUE CONSTRAINT, btree (srvname), tablespace "pg_global" +Tablespace: "pg_global" + +\d+ gp_storage_user_mapping; + Table "pg_catalog.gp_storage_user_mapping" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +-----------+--------+-----------+----------+---------+----------+--------------+------------- + oid | oid | | not null | | plain | | + umuser | oid | | not null | | plain | | + umserver | oid | | not null | | plain | | + umoptions | text[] | C | | | extended | | +Indexes: + "gp_storage_user_mapping_oid_index" PRIMARY KEY, btree (oid), tablespace "pg_global" + "gp_storage_user_mapping_server_index" UNIQUE CONSTRAINT, btree (umuser, umserver), tablespace "pg_global" +Tablespace: "pg_global" + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname = 'pg_directory_table'; + relname | relisshared | relpersistence | relkind +--------------------+-------------+----------------+--------- + pg_directory_table | f | p | r +(1 row) + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname = 'gp_storage_server'; + relname | relisshared | relpersistence | relkind +-------------------+-------------+----------------+--------- + gp_storage_server | t | p | r +(1 row) + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname = 'gp_storage_user_mapping'; + relname | relisshared | relpersistence | relkind +-------------------------+-------------+----------------+--------- + gp_storage_user_mapping | t | p | r +(1 row) + +-- CREATE TABLESPACE +CREATE TABLESPACE directory_tblspc LOCATION '@testtablespace@'; +-- CREATE DATABASE +CREATE DATABASE dirtable_db; +\c dirtable_db +\d+ pg_directory_table; + Table "pg_catalog.pg_directory_table" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------------+------+-----------+----------+---------+----------+--------------+------------- + dtrelid | oid | | not null | | plain | | + dttablespace | oid | | not null | | plain | | + dtlocation | text | C | | | extended | | +Indexes: + "pg_directory_table_relid_index" PRIMARY KEY, btree (dtrelid) + +\d+ gp_storage_server; + Table "pg_catalog.gp_storage_server" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +------------+-----------+-----------+----------+---------+----------+--------------+------------- + oid | oid | | not null | | plain | | + srvname | name | | not null | | plain | | + srvowner | oid | | not null | | plain | | + srvacl | aclitem[] | | | | extended | | + srvoptions | text[] | C | | | extended | | +Indexes: + "gp_storage_server_oid_index" PRIMARY KEY, btree (oid), tablespace "pg_global" + "gp_storage_server_name_index" UNIQUE CONSTRAINT, btree (srvname), tablespace "pg_global" +Tablespace: "pg_global" + +\d+ gp_storage_user_mapping; + Table "pg_catalog.gp_storage_user_mapping" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +-----------+--------+-----------+----------+---------+----------+--------------+------------- + oid | oid | | not null | | plain | | + umuser | oid | | not null | | plain | | + umserver | oid | | not null | | plain | | + umoptions | text[] | C | | | extended | | +Indexes: + "gp_storage_user_mapping_oid_index" PRIMARY KEY, btree (oid), tablespace "pg_global" + "gp_storage_user_mapping_server_index" UNIQUE CONSTRAINT, btree (umuser, umserver), tablespace "pg_global" +Tablespace: "pg_global" + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname = 'pg_directory_table'; + relname | relisshared | relpersistence | relkind +--------------------+-------------+----------------+--------- + pg_directory_table | f | p | r +(1 row) + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname = 'gp_storage_server'; + relname | relisshared | relpersistence | relkind +-------------------+-------------+----------------+--------- + gp_storage_server | t | p | r +(1 row) + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname = 'gp_storage_user_mapping'; + relname | relisshared | relpersistence | relkind +-------------------------+-------------+----------------+--------- + gp_storage_user_mapping | t | p | r +(1 row) + +\c regression +-- CREATE USER for directory table +CREATE USER test_dirtable1; +NOTICE: resource queue required -- using default resource queue "pg_default" +CREATE USER test_dirtable2; +NOTICE: resource queue required -- using default resource queue "pg_default" +CREATE USER test_dirtable3; +NOTICE: resource queue required -- using default resource queue "pg_default" +CREATE USER test_dirtable4; +NOTICE: resource queue required -- using default resource queue "pg_default" +-- Test CREATE STORAGE SERVER +SELECT srvname, srvacl, srvoptions from gp_storage_server ORDER BY 1; + srvname | srvacl | srvoptions +---------+--------+------------ +(0 rows) + +CREATE STORAGE SERVER oss_server1; +CREATE STORAGE SERVER oss_server2 OPTIONS(protocal 'localhost'); +CREATE STORAGE SERVER oss_server3 OPTIONS(endpoint '127.0.0.1:9000'); +CREATE STORAGE SERVER oss_server4 OPTIONS(https 'true'); +CREATE STORAGE SERVER oss_server5 OPTIONS(virtual_host 'false'); +CREATE STORAGE SERVER oss_server6 OPTIONS(protocol 'qingstor', endpoint 'pek3b,qingstor.com'); +CREATE STORAGE SERVER oss_server7 OPTIONS(https 'false', virtual_host 'true'); +CREATE STORAGE SERVER oss_server8 OPTIONS(protocol 'hdfs', namenode '127.0.0.1:8020'); +CREATE STORAGE SERVER oss_server9 OWNER TO postgres; -- fail +ERROR: syntax error at or near "OWNER" +LINE 1: CREATE STORAGE SERVER oss_server9 OWNER TO postgres; + ^ +CREATE STORAGE SERVER IF NOT EXISTS oss_server10; +CREATE STORAGE SERVER IF NOT EXISTS oss_server11 OPTIONS(protocol 's3av2'); +CREATE STORAGE SERVER IF NOT EXISTS oss_server12 OPTIONS(protocol 's3av2', endpoint '127.0.0.1:9000', https 'false'); +CREATE STORAGE SERVER IF NOT EXISTS oss_server13 OWNER TO postgres; -- fail +ERROR: syntax error at or near "OWNER" +LINE 1: CREATE STORAGE SERVER IF NOT EXISTS oss_server13 OWNER TO po... + ^ +SELECT srvname, srvacl, srvoptions from gp_storage_server ORDER BY 1; + srvname | srvacl | srvoptions +--------------+--------+------------------------------------------------------ + oss_server1 | | + oss_server10 | | + oss_server11 | | {protocol=s3av2} + oss_server12 | | {protocol=s3av2,endpoint=127.0.0.1:9000,https=false} + oss_server2 | | {protocal=localhost} + oss_server3 | | {endpoint=127.0.0.1:9000} + oss_server4 | | {https=true} + oss_server5 | | {virtual_host=false} + oss_server6 | | {protocol=qingstor,"endpoint=pek3b,qingstor.com"} + oss_server7 | | {https=false,virtual_host=true} + oss_server8 | | {protocol=hdfs,namenode=127.0.0.1:8020} +(11 rows) + +\c dirtable_db +SELECT srvname, srvacl, srvoptions from gp_storage_server ORDER BY 1; + srvname | srvacl | srvoptions +--------------+--------+------------------------------------------------------ + oss_server1 | | + oss_server10 | | + oss_server11 | | {protocol=s3av2} + oss_server12 | | {protocol=s3av2,endpoint=127.0.0.1:9000,https=false} + oss_server2 | | {protocal=localhost} + oss_server3 | | {endpoint=127.0.0.1:9000} + oss_server4 | | {https=true} + oss_server5 | | {virtual_host=false} + oss_server6 | | {protocol=qingstor,"endpoint=pek3b,qingstor.com"} + oss_server7 | | {https=false,virtual_host=true} + oss_server8 | | {protocol=hdfs,namenode=127.0.0.1:8020} +(11 rows) + +\c regression +-- Test ALTER STORAGE SERVER +ALTER STORAGE SERVER oss_server1 OPTIONS(protocol 'aws'); +ALTER STORAGE SERVER oss_server1 OPTIONS(protocol 'test'); -- fail +ERROR: option "protocol" provided more than once +ALTER STORAGE SERVER oss_server2 OPTIONS(https 'true'); +ALTER STORAGE SERVER oss_server2 OPTIONS(https 'false', virtual_host 'true'); -- fail +ERROR: option "https" provided more than once +ALTER STORAGE SERVER oss_server2 OPTIONS(virtual_host 'true'); +ALTER STORAGE SERVER oss_server3 OPTIONS(endpoint '192.168.0.1'); -- fail +ERROR: option "endpoint" provided more than once +ALTER STORAGE SERVER oss_server4 OPTIONS(protocol 'localhost', virtual_host 'true'); +ALTER STORAGE SERVER oss_server4 OPTIONS(protocol 'qingstor'); -- fail +ERROR: option "protocol" provided more than once +ALTER STORAGE SERVER oss_server5; -- fail +ERROR: syntax error at or near ";" +LINE 1: ALTER STORAGE SERVER oss_server5; + ^ +ALTER STORAGE SERVER oss_server6 OWNER TO postgres; -- fail +ERROR: syntax error at or near "OWNER" +LINE 1: ALTER STORAGE SERVER oss_server6 OWNER TO postgres; + ^ +ALTER STORAGE SERVER IF EXISTS oss_server7 OPTIONS(endpoint '127.0.0.1:6555'); -- fail +ERROR: syntax error at or near "EXISTS" +LINE 1: ALTER STORAGE SERVER IF EXISTS oss_server7 OPTIONS(endpoint ... + ^ +ALTER STORAGE SERVER IF NOT EXISTS oss_server8 OPTIONS(virtual_host 'true'); -- fail +ERROR: syntax error at or near "NOT" +LINE 1: ALTER STORAGE SERVER IF NOT EXISTS oss_server8 OPTIONS(virtu... + ^ +SELECT srvname, srvacl, srvoptions from gp_storage_server ORDER BY 1; + srvname | srvacl | srvoptions +--------------+--------+------------------------------------------------------ + oss_server1 | | {protocol=aws} + oss_server10 | | + oss_server11 | | {protocol=s3av2} + oss_server12 | | {protocol=s3av2,endpoint=127.0.0.1:9000,https=false} + oss_server2 | | {protocal=localhost,https=true,virtual_host=true} + oss_server3 | | {endpoint=127.0.0.1:9000} + oss_server4 | | {https=true,protocol=localhost,virtual_host=true} + oss_server5 | | {virtual_host=false} + oss_server6 | | {protocol=qingstor,"endpoint=pek3b,qingstor.com"} + oss_server7 | | {https=false,virtual_host=true} + oss_server8 | | {protocol=hdfs,namenode=127.0.0.1:8020} +(11 rows) + +\c dirtable_db +SELECT srvname, srvacl, srvoptions from gp_storage_server ORDER BY 1; + srvname | srvacl | srvoptions +--------------+--------+------------------------------------------------------ + oss_server1 | | {protocol=aws} + oss_server10 | | + oss_server11 | | {protocol=s3av2} + oss_server12 | | {protocol=s3av2,endpoint=127.0.0.1:9000,https=false} + oss_server2 | | {protocal=localhost,https=true,virtual_host=true} + oss_server3 | | {endpoint=127.0.0.1:9000} + oss_server4 | | {https=true,protocol=localhost,virtual_host=true} + oss_server5 | | {virtual_host=false} + oss_server6 | | {protocol=qingstor,"endpoint=pek3b,qingstor.com"} + oss_server7 | | {https=false,virtual_host=true} + oss_server8 | | {protocol=hdfs,namenode=127.0.0.1:8020} +(11 rows) + +\c regression +-- Test CREATE STORAGE USER MAPPING +CREATE STORAGE USER MAPPING FOR CURRENT_USER; -- fail +ERROR: syntax error at or near ";" +LINE 1: CREATE STORAGE USER MAPPING FOR CURRENT_USER; + ^ +CREATE STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server1; +CREATE STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server1 +OPTIONS (accesskey 'KGFQWEFQQEFXVAEAWLLC', secretkey '0SJIWiIATh6jOlmAKr8DGq6hOAGBI1BnsnvgJmTs'); -- fail +ERROR: storage user mapping for "gpadmin" already exists for storage server "oss_server1" +CREATE STORAGE USER MAPPING IF NOT EXISTS FOR CURRENT_USER STORAGE SERVER oss_server1; +NOTICE: storage user mapping for "gpadmin" already exists for storage server "oss_server1", skipping +CREATE STORAGE USER MAPPING IF NOT EXISTS FOR CURRENT_USER STORAGE SERVER oss_server1 +OPTIONS (auth_method 'simple'); +NOTICE: storage user mapping for "gpadmin" already exists for storage server "oss_server1", skipping +CREATE STORAGE USER MAPPING FOR CURRENT_ROLE STORAGE SERVER oss_server2 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE'); +CREATE STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server2 +OPTIONS (accesskey 'KGFQWEFQQEFXVAEAWLLC', secretkey '0SJIWiIATh6jOlmAKr8DGq6hOAGBI1BnsnvgJmTs'); -- fail +ERROR: storage user mapping for "gpadmin" already exists for storage server "oss_server2" +CREATE STORAGE USER MAPPING FOR CURRENT_ROLE STORAGE SERVER oss_server3 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE'); +CREATE STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_not_exits; -- fail +ERROR: server "oss_not_exits" does not exist +CREATE STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_not_exits +OPTIONS (accesskey 'KGFQWEFQQEFXVAEAWLLC', secretkey '0SJIWiIATh6jOlmAKr8DGq6hOAGBI1BnsnvgJmTs'); -- fail +ERROR: server "oss_not_exits" does not exist +CREATE STORAGE USER MAPPING FOR test_dirtable1 STORAGE SERVER oss_server1; +CREATE STORAGE USER MAPPING FOR test_dirtable1 STORAGE SERVER oss_server1 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H'); -- fail +ERROR: storage user mapping for "test_dirtable1" already exists for storage server "oss_server1" +CREATE STORAGE USER MAPPING FOR test_dirtable1 STORAGE SERVER oss_server2 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H'); +CREATE STORAGE USER MAPPING FOR test_dirtable1 STORAGE SERVER oss_server3 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H'); +CREATE STORAGE USER MAPPING FOR no_exist_user STORAGE SERVER oss_server1; -- fail +ERROR: role "no_exist_user" does not exist +CREATE STORAGE USER MAPPING FOR no_exist_user STORAGE SERVER oss_server1 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H'); -- fail +ERROR: role "no_exist_user" does not exist +CREATE STORAGE USER MAPPING IF NOT EXISTS FOR CURRENT_USER STORAGE SERVER oss_server1 +OPTIONS (accesskey 'KGFQWEFQQEFXVAEAWLLC', secretkey '0SJIWiIATh6jOlmAKr8DGq6hOAGBI1BnsnvgJmTs'); -- skip +NOTICE: storage user mapping for "gpadmin" already exists for storage server "oss_server1", skipping +CREATE STORAGE USER MAPPING IF NOT EXISTS FOR test_dirtable2 STORAGE SERVER oss_server3 +OPTIONS (endpoint '127.0.0.1:6555'); +CREATE STORAGE USER MAPPING IF NOT EXISTS FOR test_dirtable3 STORAGE SERVER oss_server8 +OPTIONS (auth_method 'simple'); +CREATE STORAGE USER MAPPING IF NOT EXISTS FOR no_exist_user STORAGE SERVER oss_server1; -- fail +ERROR: role "no_exist_user" does not exist +SELECT umoptions FROM gp_storage_user_mapping ORDER BY 1; + umoptions +------------------------------------------------------------------------------------- + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {auth_method=simple} + {endpoint=127.0.0.1:6555} + + +(8 rows) + +\c dirtable_db +SELECT umoptions FROM gp_storage_user_mapping ORDER BY 1; + umoptions +------------------------------------------------------------------------------------- + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {auth_method=simple} + {endpoint=127.0.0.1:6555} + + +(8 rows) + +\c regression +-- Test ALTER STORAGE USER MAPPING +ALTER STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server1; -- fail +ERROR: syntax error at or near ";" +LINE 1: ...GE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server1; + ^ +ALTER STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server1 +OPTIONS (accesskey 'KGFQWEFQQEFXVAEAWLLC', secretkey '0SJIWiIATh6jOlmAKr8DGq6hOAGBI1BnsnvgJmTs'); +ALTER STORAGE USER MAPPING FOR CURRENT_ROLE STORAGE SERVER oss_server1 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ'); -- fail +ERROR: option "accesskey" provided more than once +ALTER STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server1 +OPTIONS (auth_method 'simple'); +ALTER STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server2 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE'); -- fail +ERROR: option "accesskey" provided more than once +ALTER STORAGE USER MAPPING IF EXISTS FOR CURRENT_USER STORAGE SERVER server_not_exists +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE'); -- fail +ERROR: syntax error at or near "IF" +LINE 1: ALTER STORAGE USER MAPPING IF EXISTS FOR CURRENT_USER STORAG... + ^ +ALTER STORAGE USER MAPPING IF EXISTS FOR no_exist_user STORAGE SERVER oss_server1 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE'); -- fail +ERROR: syntax error at or near "IF" +LINE 1: ALTER STORAGE USER MAPPING IF EXISTS FOR no_exist_user STORA... + ^ +ALTER STORAGE USER MAPPING IF NOT EXISTS FOR test_dirtable1 STORAGE SERVER oss_server3 +OPTIONS (auth_method 'simple'); -- fail +ERROR: syntax error at or near "IF" +LINE 1: ALTER STORAGE USER MAPPING IF NOT EXISTS FOR test_dirtable1 ... + ^ +SELECT umoptions FROM gp_storage_user_mapping ORDER BY 1; + umoptions +-------------------------------------------------------------------------------------------------------- + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {accesskey=KGFQWEFQQEFXVAEAWLLC,secretkey=0SJIWiIATh6jOlmAKr8DGq6hOAGBI1BnsnvgJmTs,auth_method=simple} + {auth_method=simple} + {endpoint=127.0.0.1:6555} + +(8 rows) + +\c dirtable_db +SELECT umoptions FROM gp_storage_user_mapping ORDER BY 1; + umoptions +-------------------------------------------------------------------------------------------------------- + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {accesskey=KGFQWEFQQEFXVAEAWLLC,secretkey=0SJIWiIATh6jOlmAKr8DGq6hOAGBI1BnsnvgJmTs,auth_method=simple} + {auth_method=simple} + {endpoint=127.0.0.1:6555} + +(8 rows) + +\c regression +-- Test DROP STORAGE USER MAPPING +DROP STORAGE USER MAPPING FOR CURRENT_USER; -- fail +ERROR: syntax error at or near ";" +LINE 1: DROP STORAGE USER MAPPING FOR CURRENT_USER; + ^ +DROP STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server2; +DROP STORAGE USER MAPPING IF EXISTS FOR test_dirtable1 STORAGE SERVER oss_server1; +DROP STORAGE USER MAPPING IF EXISTS FOR test_dirtable2 STORAGE SERVER no_exist_server; +NOTICE: storage server "no_exist_server" does not exist, skipping +DROP STORAGE USER MAPPING FOR test_dirtable3 STORAGE SERVER no_exist_server; -- fail +ERROR: storage server "no_exist_server" does not exist +DROP STORAGE USER MAPPING FOR no_exist_user STORAGE SERVER oss_server1; -- fail +ERROR: role "no_exist_user" does not exist +DROP STORAGE USER MAPPING IF EXISTS FOR no_exist_user STORAGE SERVER oss_server1; -- skip +NOTICE: role "no_exist_user" does not exist, skipping +SELECT umoptions FROM gp_storage_user_mapping ORDER BY 1; + umoptions +-------------------------------------------------------------------------------------------------------- + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {accesskey=KGFQWEFQQEFXVAEAWLLC,secretkey=0SJIWiIATh6jOlmAKr8DGq6hOAGBI1BnsnvgJmTs,auth_method=simple} + {auth_method=simple} + {endpoint=127.0.0.1:6555} +(6 rows) + +\c dirtable_db +SELECT umoptions FROM gp_storage_user_mapping ORDER BY 1; + umoptions +-------------------------------------------------------------------------------------------------------- + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {accesskey=KGFQWEFQQEFXVAEAWLLC,secretkey=0SJIWiIATh6jOlmAKr8DGq6hOAGBI1BnsnvgJmTs,auth_method=simple} + {auth_method=simple} + {endpoint=127.0.0.1:6555} +(6 rows) + +\c regression +-- Test DROP STOARGE SERVER +DROP STORAGE SERVER oss_server1; -- fail +ERROR: storage server "oss_server1" cannot be dropped because some objects depend on it +DETAIL: storage server of storage user mapping for gpadmin on storage server oss_server1 +DROP STORAGE SERVER oss_server2; -- fail +ERROR: storage server "oss_server2" cannot be dropped because some objects depend on it +DETAIL: storage server of storage user mapping for test_dirtable1 on storage server oss_server2 +DROP STORAGE SERVER oss_server3; -- fail +ERROR: storage server "oss_server3" cannot be dropped because some objects depend on it +DETAIL: storage server of storage user mapping for gpadmin on storage server oss_server3 +storage server of storage user mapping for test_dirtable1 on storage server oss_server3 +storage server of storage user mapping for test_dirtable2 on storage server oss_server3 +DROP STORAGE SERVER oss_server4; -- fail +DROP STORAGE SERVER oss_server8; -- fail +ERROR: storage server "oss_server8" cannot be dropped because some objects depend on it +DETAIL: storage server of storage user mapping for test_dirtable3 on storage server oss_server8 +DROP STORAGE SERVER oss_server9; -- fail +ERROR: storage server "oss_server9" not exists +DROP STAROGE SERVER IF EXISTS oss_server9; -- fail +ERROR: syntax error at or near "STAROGE" +LINE 1: DROP STAROGE SERVER IF EXISTS oss_server9; + ^ +DROP STORAGE SERVER IF NOT EXISTS oss_server9; --fail +ERROR: syntax error at or near "NOT" +LINE 1: DROP STORAGE SERVER IF NOT EXISTS oss_server9; + ^ +DROP STORAGE SERVER IF EXISTS oss_server10; +SELECT srvname, srvacl, srvoptions from gp_storage_server ORDER BY 1; + srvname | srvacl | srvoptions +--------------+--------+------------------------------------------------------ + oss_server1 | | {protocol=aws} + oss_server11 | | {protocol=s3av2} + oss_server12 | | {protocol=s3av2,endpoint=127.0.0.1:9000,https=false} + oss_server2 | | {protocal=localhost,https=true,virtual_host=true} + oss_server3 | | {endpoint=127.0.0.1:9000} + oss_server5 | | {virtual_host=false} + oss_server6 | | {protocol=qingstor,"endpoint=pek3b,qingstor.com"} + oss_server7 | | {https=false,virtual_host=true} + oss_server8 | | {protocol=hdfs,namenode=127.0.0.1:8020} +(9 rows) + +\c dirtable_db +SELECT srvname, srvacl, srvoptions from gp_storage_server ORDER BY 1; + srvname | srvacl | srvoptions +--------------+--------+------------------------------------------------------ + oss_server1 | | {protocol=aws} + oss_server11 | | {protocol=s3av2} + oss_server12 | | {protocol=s3av2,endpoint=127.0.0.1:9000,https=false} + oss_server2 | | {protocal=localhost,https=true,virtual_host=true} + oss_server3 | | {endpoint=127.0.0.1:9000} + oss_server5 | | {virtual_host=false} + oss_server6 | | {protocol=qingstor,"endpoint=pek3b,qingstor.com"} + oss_server7 | | {https=false,virtual_host=true} + oss_server8 | | {protocol=hdfs,namenode=127.0.0.1:8020} +(9 rows) + +\c regression +-- Test directory table +-- Test CREATE DIRECTORY TABLE +SELECT count(*) FROM pg_directory_table; + count +------- + 0 +(1 row) + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname like '%dir_table%' ORDER BY 1; + relname | relisshared | relpersistence | relkind +---------+-------------+----------------+--------- +(0 rows) + +CREATE DIRECTORY TABLE dir_table1; +CREATE DIRECTORY TABLE dir_table2 TABLESPACE directory_tblspc; +CREATE DIRECTORY TABLE dir_table3 TABLESPACE directory_tblspc DISTRIBUTED BY(relative_path); -- fail +ERROR: Create directory table is not allowed to set distributed by. +LINE 1: ...TORY TABLE dir_table3 TABLESPACE directory_tblspc DISTRIBUTE... + ^ +CREATE DIRECTORY TABLE dir_table3 TABLESPACE directory_tblspc DISTRIBUTED RANDOMLY; -- fail +ERROR: Create directory table is not allowed to set distributed by. +LINE 1: ...TORY TABLE dir_table3 TABLESPACE directory_tblspc DISTRIBUTE... + ^ +CREATE DIRECTORY TABLE dir_table3 TABLESPACE directory_tblspc DISTRIBUTED REPLICATED; -- fail +ERROR: Create directory table is not allowed to set distributed by. +LINE 1: ...TORY TABLE dir_table3 TABLESPACE directory_tblspc DISTRIBUTE... + ^ +CREATE DIRECTORY TABLE dir_table3 TABLESPACE directory_tblspc; +CREATE DIRECTORY TABLE IF NOT EXISTS dir_table4 TABLESPACE directory_tblspc; +CREATE DIRECTORY TABLE IF NOT EXISTS dir_table2 TABLESPACE directory_tblspc; -- fail +NOTICE: relation "dir_table2" already exists, skipping +CREATE DIRECTORY TABLE dir_table5 TABLESPACE directory_tblspc; +CREATE DIRECTORY TABLE dir_table6 TABLESPACE pg_default; +\dY + List of relations + Schema | Name | Type | Owner +--------+------------+-----------------+--------- + public | dir_table1 | directory table | gpadmin + public | dir_table2 | directory table | gpadmin + public | dir_table3 | directory table | gpadmin + public | dir_table4 | directory table | gpadmin + public | dir_table5 | directory table | gpadmin + public | dir_table6 | directory table | gpadmin +(6 rows) + +SELECT count(*) FROM pg_directory_table; + count +------- + 6 +(1 row) + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname like '%dir_table%' ORDER BY 1; + relname | relisshared | relpersistence | relkind +-----------------+-------------+----------------+--------- + dir_table1 | f | p | d + dir_table1_pkey | f | p | i + dir_table2 | f | p | d + dir_table2_pkey | f | p | i + dir_table3 | f | p | d + dir_table3_pkey | f | p | i + dir_table4 | f | p | d + dir_table4_pkey | f | p | i + dir_table5 | f | p | d + dir_table5_pkey | f | p | i + dir_table6 | f | p | d + dir_table6_pkey | f | p | i +(12 rows) + +\d+ dir_table1; + Directory able "public.dir_table1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +---------------+--------------------------+-----------+----------+---------+----------+--------------+------------- + relative_path | text | | | | extended | | + size | bigint | | | | plain | | + last_modified | timestamp with time zone | | | | plain | | + md5 | text | | | | extended | | + tag | text | | | | extended | | +Indexes: + "dir_table1_pkey" PRIMARY KEY, btree (relative_path) +Distributed by: (relative_path) + +\d+ dir_table2; + Directory able "public.dir_table2" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +---------------+--------------------------+-----------+----------+---------+----------+--------------+------------- + relative_path | text | | | | extended | | + size | bigint | | | | plain | | + last_modified | timestamp with time zone | | | | plain | | + md5 | text | | | | extended | | + tag | text | | | | extended | | +Indexes: + "dir_table2_pkey" PRIMARY KEY, btree (relative_path) +Distributed by: (relative_path) + +\d+ dir_table3; + Directory able "public.dir_table3" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +---------------+--------------------------+-----------+----------+---------+----------+--------------+------------- + relative_path | text | | | | extended | | + size | bigint | | | | plain | | + last_modified | timestamp with time zone | | | | plain | | + md5 | text | | | | extended | | + tag | text | | | | extended | | +Indexes: + "dir_table3_pkey" PRIMARY KEY, btree (relative_path) +Distributed by: (relative_path) + +\c dirtable_db +\dY + List of relations + Schema | Name | Type | Owner +--------+------+------+------- +(0 rows) + +SELECT count(*) FROM pg_directory_table; + count +------- + 0 +(1 row) + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname like '%dir_table%' ORDER BY 1; + relname | relisshared | relpersistence | relkind +---------+-------------+----------------+--------- +(0 rows) + +\c regression +-- Test create table inherits directory table +CREATE TABLE test_inherits1 INHERITS(dir_table1); -- fail +ERROR: syntax error at or near "INHERITS" +LINE 1: CREATE TABLE test_inherits1 INHERITS(dir_table1); + ^ +CREATE TABLE test_inherits2(a int) INHERITS(dir_table2); -- fail +NOTICE: table has parent, setting distribution columns to match parent table +ERROR: inherited relation "dir_table2" is not a table or foreign table +CREATE TABLE test_inherits3 INHERITS(dir_table2, dir_table3); -- fail +ERROR: syntax error at or near "INHERITS" +LINE 1: CREATE TABLE test_inherits3 INHERITS(dir_table2, dir_table3)... + ^ +CREATE TABLE test_inherits4(b text) INHERITS(dir_table1, dir_table2); -- fail +NOTICE: table has parent, setting distribution columns to match parent table +ERROR: inherited relation "dir_table1" is not a table or foreign table +-- Test DROP DIRECTORY TABLE +DROP DIRECTORY TABLE dir_table4; +DROP DIRECTORY TABLE dir_table4; -- fail +ERROR: directory table "dir_table4" does not exist +DROP DIRECTORY TABLE IF EXISTS dir_table5; +DROP DIRECTORY TABLE IF EXISTS dir_table5; -- skip +NOTICE: directory table "dir_table5" does not exist, skipping +\dY + List of relations + Schema | Name | Type | Owner +--------+------------+-----------------+--------- + public | dir_table1 | directory table | gpadmin + public | dir_table2 | directory table | gpadmin + public | dir_table3 | directory table | gpadmin + public | dir_table6 | directory table | gpadmin +(4 rows) + +SELECT count(*) FROM pg_directory_table; + count +------- + 4 +(1 row) + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname like '%dir_table%' ORDER BY 1; + relname | relisshared | relpersistence | relkind +-----------------+-------------+----------------+--------- + dir_table1 | f | p | d + dir_table1_pkey | f | p | i + dir_table2 | f | p | d + dir_table2_pkey | f | p | i + dir_table3 | f | p | d + dir_table3_pkey | f | p | i + dir_table6 | f | p | d + dir_table6_pkey | f | p | i +(8 rows) + +\c dirtable_db +\dY + List of relations + Schema | Name | Type | Owner +--------+------+------+------- +(0 rows) + +SELECT count(*) FROM pg_directory_table; + count +------- + 0 +(1 row) + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname like '%dir_table%' ORDER BY 1; + relname | relisshared | relpersistence | relkind +---------+-------------+----------------+--------- +(0 rows) + +\c regression +-- Test CREATE/DROP/REINDEX on DIRECTORY SCHEMA TABLE +-- Test CREATE INDEX on DIRECTORY SCHEMA TABLE +CREATE INDEX dirtable1_relative_path_idx on dir_table1(relative_path); -- fail +ERROR: Disallowed to create index on directory table "dir_table1". (indexcmds.c:709) +CREATE INDEX dirtable1_size_idx on dir_table1(size); -- fail +ERROR: Disallowed to create index on directory table "dir_table1". (indexcmds.c:709) +CREATE INDEX dirtable1_last_modified_idx on dir_table1(last_modified); -- fail +ERROR: Disallowed to create index on directory table "dir_table1". (indexcmds.c:709) +CREATE INDEX dirtable1_md5_idx on dir_table1(md5); -- fail +ERROR: Disallowed to create index on directory table "dir_table1". (indexcmds.c:709) +CREATE INDEX dirtable1_tag_idx on dir_table1(tag); -- fail +ERROR: Disallowed to create index on directory table "dir_table1". (indexcmds.c:709) +\d+ dir_table1; + Directory able "public.dir_table1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +---------------+--------------------------+-----------+----------+---------+----------+--------------+------------- + relative_path | text | | | | extended | | + size | bigint | | | | plain | | + last_modified | timestamp with time zone | | | | plain | | + md5 | text | | | | extended | | + tag | text | | | | extended | | +Indexes: + "dir_table1_pkey" PRIMARY KEY, btree (relative_path) +Distributed by: (relative_path) + +-- Test DROP INDEX on DIRECTORY SCHEMA TABLE +DROP INDEX dir_table1_pkey; -- fail +ERROR: Disallowed to drop index "dir_table1_pkey" on directory table "dir_table1" +DROP INDEX dir_table2_pkey; -- fail +ERROR: Disallowed to drop index "dir_table2_pkey" on directory table "dir_table2" +DROP INDEX dir_table3_pkey; -- fail +ERROR: Disallowed to drop index "dir_table3_pkey" on directory table "dir_table3" +DROP INDEX dir_table4_pkey; -- fail +ERROR: index "dir_table4_pkey" does not exist +DROP INDEX dir_table5_pkey; -- fail +ERROR: index "dir_table5_pkey" does not exist +DROP INDEX dir_table6_pkey; -- fail +ERROR: Disallowed to drop index "dir_table6_pkey" on directory table "dir_table6" +-- Test REINDEX on DIRECTORY SCHEMA TABLE +REINDEX INDEX dir_table1_pkey; +REINDEX INDEX dir_table2_pkey; +REINDEX INDEX dir_table3_pkey; +REINDEX INDEX dir_table4_pkey; +ERROR: relation "dir_table4_pkey" does not exist +REINDEX INDEX dir_table5_pkey; +ERROR: relation "dir_table5_pkey" does not exist +REINDEX INDEX dir_table6_pkey; +REINDEX TABLE dir_table1; +REINDEX TABLE dir_table2; +REINDEX TABLE dir_table3; +REINDEX TABLE dir_table4; +ERROR: relation "dir_table4" does not exist +REINDEX TABLE dir_table5; +ERROR: relation "dir_table5" does not exist +REINDEX TABLE dir_table6; +-- Test triggers +DROP FUNCTION IF EXISTS trigtest; +create function trigtest() returns trigger as $$ +begin + raise notice '% % % %', TG_TABLE_NAME, TG_OP, TG_WHEN, TG_LEVEL; + return new; +end;$$ language plpgsql; +create trigger trigtest_b_row_tg_dirtable_1 before insert or update or delete on dir_table1 +for each row execute procedure trigtest(); +create trigger trigtest_a_row_tg_dirtable_1 after insert or update or delete on dir_table1 +for each row execute procedure trigtest(); +create trigger trigtest_b_stmt_tg_dirtable_1 before insert or update or delete on dir_table1 +for each statement execute procedure trigtest(); +ERROR: Triggers for statements are not yet supported +create trigger trigtest_a_stmt_tg_dirtable_1 after insert or update or delete on dir_table1 +for each statement execute procedure trigtest(); +ERROR: Triggers for statements are not yet supported +-- Test COPY DIRECTORY TABLE syntax +SELECT relative_path, size, tag FROM dir_table1 ORDER BY 1; + relative_path | size | tag +---------------+------+----- +(0 rows) + +SELECT relative_path, size, tag FROM dir_table2 ORDER BY 1; + relative_path | size | tag +---------------+------+----- +(0 rows) + +\COPY dir_table1 FROM '@abs_srcdir@/data/nation.csv'; -- fail +ERROR: Copy from directory table file name can't be null. +\COPY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation'; -- fail +ERROR: Only support copy binary from directory table. +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv'; -- fail +ERROR: Copy from directory table file name can't be null. +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation1'; +NOTICE: dir_table1 INSERT AFTER ROW (seg1 127.0.1.1:7003 pid=15072) +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation1'; -- fail +ERROR: duplicate key value violates unique constraint "dir_table1_pkey" +DETAIL: Key (relative_path)=(nation1) already exists. +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation2' 'nation2'; -- fail +ERROR: syntax error at or near "'nation2'" +LINE 1: COPY BINARY dir_table1 FROM STDIN 'nation2' 'nation2'; -- fa... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation2'; +NOTICE: dir_table1 INSERT AFTER ROW (seg2 127.0.1.1:7004 pid=15073) +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation3' WITH TAG 'nation'; +NOTICE: dir_table1 INSERT AFTER ROW (seg1 127.0.1.1:7003 pid=15072) +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation3' WITH TAG 'nation'; -- fail +ERROR: duplicate key value violates unique constraint "dir_table1_pkey" +DETAIL: Key (relative_path)=(nation3) already exists. +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation3' WITH TAG 'nation2'; -- fail +ERROR: duplicate key value violates unique constraint "dir_table1_pkey" +DETAIL: Key (relative_path)=(nation3) already exists. +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation4' WITH TAG 'nation'; +NOTICE: dir_table1 INSERT AFTER ROW (seg2 127.0.1.1:7004 pid=15073) +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation5' WITH TAG 'nation' WITH TAG 'nation2'; -- fail +ERROR: syntax error at or near "WITH" +LINE 1: ...dir_table1 FROM STDIN 'nation5' WITH TAG 'nation' WITH TAG '... + ^ +SELECT relative_path, size, tag FROM dir_table1 ORDER BY 1; + relative_path | size | tag +---------------+------+-------- + nation1 | 2199 | + nation2 | 2199 | + nation3 | 2199 | nation + nation4 | 2199 | nation +(4 rows) + +SELECT relative_path, content FROM directory_table('dir_table1') ORDER BY 1; + relative_path | content +---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + nation1 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a + nation2 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a + nation3 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a + nation4 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a +(4 rows) + +COPY dir_table2 FROM '@abs_srcdir@/data/nation.csv'; -- fail +ERROR: Copy from directory table file name can't be null. +COPY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation'; -- fail +ERROR: Only support copy binary from directory table. +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv'; -- fail +ERROR: Copy from directory table file name can't be null. +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation1'; +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation1'; -- fail +ERROR: duplicate key value violates unique constraint "dir_table2_pkey" +DETAIL: Key (relative_path)=(nation1) already exists. +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation2'; +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation3' WITH TAG 'nation'; +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation3' WITH TAG 'nation'; -- fail +ERROR: duplicate key value violates unique constraint "dir_table2_pkey" +DETAIL: Key (relative_path)=(nation3) already exists. +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation3' WITH TAG 'nation2'; -- fail +ERROR: duplicate key value violates unique constraint "dir_table2_pkey" +DETAIL: Key (relative_path)=(nation3) already exists. +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation4' WITH TAG 'nation'; +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation5' WITH TAG 'nation' WITH TAG 'nation2'; -- fail +ERROR: syntax error at or near "WITH" +LINE 1: ...ress/data/nation.csv' 'nation5' WITH TAG 'nation' WITH TAG '... + ^ +SELECT relative_path, size, tag FROM dir_table2 ORDER BY 1; + relative_path | size | tag +---------------+------+-------- + nation1 | 2199 | + nation2 | 2199 | + nation3 | 2199 | nation + nation4 | 2199 | nation +(4 rows) + +SELECT relative_path, content FROM directory_table('dir_table2') ORDER BY 1; + relative_path | content +---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + nation1 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a + nation2 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a + nation3 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a + nation4 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a +(4 rows) + +-- Test copy binary from directory table +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (format CSV); +ERROR: conflicting or redundant options +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (format CSV... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (freeze off); +ERROR: option "freeze" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (freeze off... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (freeze on); +ERROR: option "freeze" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (freeze on)... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (delimiter ','); +ERROR: option "delimiter" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (delimiter ... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (null ' '); +ERROR: option "null" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (null ' '); + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (header off); +ERROR: option "header" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (header off... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (header on); +ERROR: option "header" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (header on)... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (quote ':'); +ERROR: option "quote" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (quote ':')... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (escape ':'); +ERROR: option "escape" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (escape ':'... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_quote (a)); +ERROR: option "force_quote" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (force_quot... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_quote *); +ERROR: option "force_quote" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (force_quot... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_not_null (a)); +ERROR: option "force_not_null" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (force_not_... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_null (a)); +ERROR: option "force_null" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (force_null... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (convert_selectively (a)); +ERROR: option "convert_selectively" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (convert_se... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (encoding 'sql_ascii'); +ERROR: option "encoding" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (encoding '... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (format CSV); +ERROR: conflicting or redundant options +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (format CSV... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (freeze off); +ERROR: option "freeze" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (freeze off... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (freeze on); +ERROR: option "freeze" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (freeze on)... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (delimiter ','); +ERROR: option "delimiter" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (delimiter ... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (null ' '); +ERROR: option "null" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (null ' '); + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (header off); +ERROR: option "header" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (header off... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (header on); +ERROR: option "header" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (header on)... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (quote ':'); +ERROR: option "quote" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (quote ':')... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (escape ':'); +ERROR: option "escape" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (escape ':'... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_quote (a)); +ERROR: option "force_quote" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (force_quot... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_quote *); +ERROR: option "force_quote" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (force_quot... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_not_null (a)); +ERROR: option "force_not_null" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (force_not_... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_null (a)); +ERROR: option "force_null" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (force_null... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (convert_selectively (a)); +ERROR: option "convert_selectively" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (convert_se... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (encoding 'sql_ascii'); +ERROR: option "encoding" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (encoding '... + ^ +-- Test copy file content md5 +CREATE OR REPLACE FUNCTION file_content(text, text) RETURNS BYTEA LANGUAGE SQL AS +'select content from directory_table($1) where relative_path = $2'; +CREATE OR REPLACE FUNCTION file_md5(text, text) RETURNS TEXT LANGUAGE SQL AS +'select md5 from directory_table($1) where relative_path = $2'; +CREATE OR REPLACE FUNCTION md5_equal(text, text) RETURNS BOOL LANGUAGE SQL AS +'SELECT md5(file_content($1, $2)) = (SELECT file_md5($1, $2))'; +SELECT md5_equal('dir_table1', 'nation1'); + md5_equal +----------- + t +(1 row) + +SELECT md5_equal('dir_table1', 'nation2'); + md5_equal +----------- + t +(1 row) + +SELECT md5_equal('dir_table1', 'nation3'); + md5_equal +----------- + t +(1 row) + +SELECT md5_equal('dir_table1', 'nation4'); + md5_equal +----------- + t +(1 row) + +SELECT md5_equal('dir_table2', 'nation1'); + md5_equal +----------- + t +(1 row) + +SELECT md5_equal('dir_table2', 'nation2'); + md5_equal +----------- + t +(1 row) + +SELECT md5_equal('dir_table2', 'nation3'); + md5_equal +----------- + t +(1 row) + +SELECT md5_equal('dir_table2', 'nation4'); + md5_equal +----------- + t +(1 row) + +-- Does not support copy to +\COPY dir_table1 TO '@abs_srcdir@/data/dir_table1'; -- fail +ERROR: cannot copy from non-table relation "dir_table1" +\COPY BINARY dir_table1 TO '@abs_srcdir@/data/dir_table1'; -- fail +ERROR: cannot copy from non-table relation "dir_table1" +COPY dir_table1 TO '@abs_srcdir@/data/dir_table1'; -- fail +ERROR: cannot copy from non-table relation "dir_table1" +COPY BINARY dir_table1 TO '@abs_srcdir@/data/dir_table1'; -- fail +ERROR: cannot copy from non-table relation "dir_table1" +\COPY dir_table2 TO '@abs_srcdir@/data/dir_table2'; -- fail +ERROR: cannot copy from non-table relation "dir_table2" +\COPY BINARY dir_table2 TO '@abs_srcdir@/data/dir_table2'; -- fail +ERROR: cannot copy from non-table relation "dir_table2" +COPY dir_table2 TO '@abs_srcdir@/data/dir_table2'; -- fail +ERROR: cannot copy from non-table relation "dir_table2" +COPY BINARY dir_table2 TO '@abs_srcdir@/data/dir_table2'; -- fail +ERROR: cannot copy from non-table relation "dir_table2" +SELECT relative_path, size, tag FROM dir_table1 ORDER BY 1; + relative_path | size | tag +---------------+------+-------- + nation1 | 2199 | + nation2 | 2199 | + nation3 | 2199 | nation + nation4 | 2199 | nation +(4 rows) + +SELECT relative_path, size, tag FROM dir_table2 ORDER BY 1; + relative_path | size | tag +---------------+------+-------- + nation1 | 2199 | + nation2 | 2199 | + nation3 | 2199 | nation + nation4 | 2199 | nation +(4 rows) + +-- Test join between two directory schema tables +ANALYZE dir_table1; +ANALYZE dir_table2; +EXPLAIN (COSTS OFF) SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.relative_path = dir_table2.relative_path ORDER BY 1; + QUERY PLAN +-------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Merge Key: dir_table1.relative_path + -> Sort + Sort Key: dir_table1.relative_path + -> Hash Join + Hash Cond: (dir_table1.relative_path = dir_table2.relative_path) + -> Seq Scan on dir_table1 + -> Hash + -> Seq Scan on dir_table2 + Optimizer: Postgres query optimizer +(10 rows) + +SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.relative_path = dir_table2.relative_path ORDER BY 1; + relative_path +--------------- + nation1 + nation2 + nation3 + nation4 +(4 rows) + +EXPLAIN (COSTS OFF) SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.size = dir_table2.size ORDER BY 1 LIMIT 1; + QUERY PLAN +------------------------------------------------------------------------------------ + Limit + -> Gather Motion 3:1 (slice1; segments: 3) + Merge Key: dir_table1.relative_path + -> Limit + -> Sort + Sort Key: dir_table1.relative_path + -> Hash Join + Hash Cond: (dir_table1.size = dir_table2.size) + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: dir_table1.size + -> Seq Scan on dir_table1 + -> Hash + -> Redistribute Motion 3:3 (slice3; segments: 3) + Hash Key: dir_table2.size + -> Seq Scan on dir_table2 + Optimizer: Postgres query optimizer +(16 rows) + +SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.size = dir_table2.size ORDER BY 1 LIMIT 1; + relative_path +--------------- + nation1 +(1 row) + +EXPLAIN (COSTS OFF) SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.md5 = dir_table2.md5 ORDER BY 1 LIMIT 1; + QUERY PLAN +------------------------------------------------------------------------------------ + Limit + -> Gather Motion 3:1 (slice1; segments: 3) + Merge Key: dir_table1.relative_path + -> Limit + -> Sort + Sort Key: dir_table1.relative_path + -> Hash Join + Hash Cond: (dir_table1.md5 = dir_table2.md5) + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: dir_table1.md5 + -> Seq Scan on dir_table1 + -> Hash + -> Redistribute Motion 3:3 (slice3; segments: 3) + Hash Key: dir_table2.md5 + -> Seq Scan on dir_table2 + Optimizer: Postgres query optimizer +(16 rows) + +SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.md5 = dir_table2.md5 ORDER BY 1 LIMIT 1; + relative_path +--------------- + nation1 +(1 row) + +EXPLAIN (COSTS OFF) SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.tag = dir_table2.tag ORDER BY 1; + QUERY PLAN +--------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Merge Key: dir_table1.relative_path + -> Sort + Sort Key: dir_table1.relative_path + -> Hash Join + Hash Cond: (dir_table2.tag = dir_table1.tag) + -> Broadcast Motion 3:3 (slice2; segments: 3) + -> Seq Scan on dir_table2 + -> Hash + -> Seq Scan on dir_table1 + Optimizer: Postgres query optimizer +(11 rows) + +SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.tag = dir_table2.tag ORDER BY 1; + relative_path +--------------- + nation3 + nation3 + nation4 + nation4 +(4 rows) + +-- Test DML directory schema table, only allow to update tag +INSERT INTO dir_table1 VALUES('insert'); -- fail +ERROR: cannot change directory table "dir_table1" +INSERT INTO dir_table2 VALUES('insert', 512, '2000-03-21 17:13:27+08', '70f09140d1b83eb3ecf9a0e28494d2a4', 'insert'); -- fail +ERROR: cannot change directory table "dir_table2" +SELECT relative_path, size, tag FROM dir_table1 ORDER BY 1; + relative_path | size | tag +---------------+------+-------- + nation1 | 2199 | + nation2 | 2199 | + nation3 | 2199 | nation + nation4 | 2199 | nation +(4 rows) + +SELECT relative_path, size, tag FROM dir_table2 ORDER BY 1; + relative_path | size | tag +---------------+------+-------- + nation1 | 2199 | + nation2 | 2199 | + nation3 | 2199 | nation + nation4 | 2199 | nation +(4 rows) + +DELETE FROM dir_table1; -- fail +ERROR: cannot change directory table "dir_table1" +DELETE FROM dir_table2 WHERE relative_path = 'nation1'; -- fail +ERROR: cannot change directory table "dir_table2" +SELECT relative_path, size, tag FROM dir_table1 ORDER BY 1; + relative_path | size | tag +---------------+------+-------- + nation1 | 2199 | + nation2 | 2199 | + nation3 | 2199 | nation + nation4 | 2199 | nation +(4 rows) + +SELECT relative_path, size, tag FROM dir_table2 ORDER BY 1; + relative_path | size | tag +---------------+------+-------- + nation1 | 2199 | + nation2 | 2199 | + nation3 | 2199 | nation + nation4 | 2199 | nation +(4 rows) + +UPDATE dir_table1 SET relative_path = 'nation_updated'; -- fail +ERROR: UPDATE on distributed key column not allowed on relation with update triggers +UPDATE dir_table2 SET relative_path = 'nation_updated' WHERE relative_path = 'nation2'; -- fail +ERROR: Only allow to update directory "tag" column. +UPDATE dir_table1 SET size = 512; -- fail +ERROR: Only allow to update directory "tag" column. +UPDATE dir_table2 SET size = 1024 WHERE relative_path = 'nation1'; -- fail +ERROR: Only allow to update directory "tag" column. +UPDATE dir_table1 SET last_modified = '2000-03-21 16:55:07+08'; -- fail +ERROR: Only allow to update directory "tag" column. +UPDATE dir_table2 SET last_modified = '2000-03-21 16:55:07+08' WHERE relative_path = 'nation3'; -- fail +ERROR: Only allow to update directory "tag" column. +UPDATE dir_table1 SET md5 = '70f09140d1b83eb3ecf9a0e28494d2a4'; -- fail +ERROR: Only allow to update directory "tag" column. +UPDATE dir_table2 SET md5 = '70f09140d1b83eb3ecf9a0e28494d2a4' WHERE relative_path = 'nation4'; -- fail +ERROR: Only allow to update directory "tag" column. +UPDATE dir_table1 SET tag = 'nation_new_tag'; -- ok +NOTICE: dir_table1 UPDATE BEFORE ROW (seg1 127.0.1.1:7003 pid=15072) +NOTICE: dir_table1 UPDATE BEFORE ROW (seg1 127.0.1.1:7003 pid=15072) +NOTICE: dir_table1 UPDATE BEFORE ROW (seg2 127.0.1.1:7004 pid=15073) +NOTICE: dir_table1 UPDATE AFTER ROW (seg1 127.0.1.1:7003 pid=15072) +NOTICE: dir_table1 UPDATE AFTER ROW (seg1 127.0.1.1:7003 pid=15072) +NOTICE: dir_table1 UPDATE BEFORE ROW (seg2 127.0.1.1:7004 pid=15073) +NOTICE: dir_table1 UPDATE AFTER ROW (seg2 127.0.1.1:7004 pid=15073) +NOTICE: dir_table1 UPDATE AFTER ROW (seg2 127.0.1.1:7004 pid=15073) +UPDATE dir_table1 SET tag = 'nation2_new_tag' WHERE relative_path = 'nation2'; -- ok +NOTICE: dir_table1 UPDATE BEFORE ROW (seg2 127.0.1.1:7004 pid=15073) +NOTICE: dir_table1 UPDATE AFTER ROW (seg2 127.0.1.1:7004 pid=15073) +UPDATE dir_table2 SET tag = 'nation4_new_tag' WHERE relative_path = 'nation3'; -- ok +UPDATE dir_table1 SET tag = 'failed_tag' WHERE relative_path = 'not_exist_path'; +UPDATE dir_table2 SET tag = 'no_tag' WHERE relative_path = 'not_exist_path'; +SELECT relative_path, size, tag FROM dir_table1 ORDER BY 1; + relative_path | size | tag +---------------+------+----------------- + nation1 | 2199 | nation_new_tag + nation2 | 2199 | nation2_new_tag + nation3 | 2199 | nation_new_tag + nation4 | 2199 | nation_new_tag +(4 rows) + +SELECT relative_path, size, tag FROM dir_table2 ORDER BY 1; + relative_path | size | tag +---------------+------+----------------- + nation1 | 2199 | + nation2 | 2199 | + nation3 | 2199 | nation4_new_tag + nation4 | 2199 | nation +(4 rows) + +-- Test alter table directory schema table +ALTER TABLE dir_table1 ADD COLUMN a int; -- fail +ERROR: "dir_table1" is not a table, composite type, or foreign table +ALTER DIRECTORY TABLE dir_table1 ADD COLUMN a int; -- fail +ERROR: syntax error at or near "DIRECTORY" +LINE 1: ALTER DIRECTORY TABLE dir_table1 ADD COLUMN a int; + ^ +ALTER TABLE dir_table2 DROP COLUMN relative_path; -- fail +ERROR: "dir_table2" is not a table, composite type, or foreign table +ALTER DIRECTORY TABLE dir_table2 DROP COLUMN relative_path; -- fail +ERROR: syntax error at or near "DIRECTORY" +LINE 1: ALTER DIRECTORY TABLE dir_table2 DROP COLUMN relative_path; + ^ +ALTER TABLE dir_table1 RENAME TO dir_table_new; -- fail +ERROR: Rename directory table is not allowed. +ALTER DIRECTORY TABLE dir_table1 RENAME TO dir_table_new; -- fail +ERROR: syntax error at or near "DIRECTORY" +LINE 1: ALTER DIRECTORY TABLE dir_table1 RENAME TO dir_table_new; + ^ +ALTER TABLE dir_table2 ADD CONSTRAINT dirtable_constraint UNIQUE (tag); -- fail +ERROR: "dir_table2" is not a table or foreign table +ALTER DIRECTORY TABLE dir_table2 ADD CONSTRAINT dirtable_constraint UNIQUE (tag); -- fail +ERROR: syntax error at or near "DIRECTORY" +LINE 1: ALTER DIRECTORY TABLE dir_table2 ADD CONSTRAINT dirtable_con... + ^ +ALTER TABLE dir_table1 DROP CONSTRAINT DROP CONSTRAINT test_pkey; -- fail +ERROR: syntax error at or near "CONSTRAINT" +LINE 1: ALTER TABLE dir_table1 DROP CONSTRAINT DROP CONSTRAINT test_... + ^ +ALTER DIRECTORY TABLE dir_table1 DROP CONSTRAINT DROP CONSTRAINT test_pkey; -- fail +ERROR: syntax error at or near "DIRECTORY" +LINE 1: ALTER DIRECTORY TABLE dir_table1 DROP CONSTRAINT DROP CONSTR... + ^ +-- Test remove_table +SELECT remove_file('dir_table1', 'nation5'); -- fail + remove_file +------------- + f +(1 row) + +SELECT remove_file('dir_table1', 'nation1'); + remove_file +------------- + t +(1 row) + +SELECT remove_file('dir_table2', 'nation1', 'nation2'); -- fail +ERROR: function remove_file(unknown, unknown, unknown) does not exist +LINE 1: SELECT remove_file('dir_table2', 'nation1', 'nation2'); + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +SELECT remove_file('dir_table1', 'nation2'); + remove_file +------------- + t +(1 row) + +SELECT remove_file('dir_table3', 'nation1'); -- fail + remove_file +------------- + f +(1 row) + +SELECT remove_file('dir_table2', 'nation3'); + remove_file +------------- + t +(1 row) + +SELECT remove_file('dir_table1', 'nation1'); -- fail + remove_file +------------- + f +(1 row) + +SELECT relative_path, size, tag FROM dir_table1 ORDER BY 1; + relative_path | size | tag +---------------+------+---------------- + nation3 | 2199 | nation_new_tag + nation4 | 2199 | nation_new_tag +(2 rows) + +SELECT relative_path, size, tag FROM dir_table2 ORDER BY 1; + relative_path | size | tag +---------------+------+-------- + nation1 | 2199 | + nation2 | 2199 | + nation4 | 2199 | nation +(3 rows) + +-- Test transaction commit of directory table manipulation +CREATE DIRECTORY TABLE dir_table4 TABLESPACE directory_tblspc; +BEGIN; +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_commit'; +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_commit2' WITH TAG 'nation'; +COMMIT; +SELECT relative_path, content FROM directory_table('dir_table4') ORDER BY 1; + relative_path | content +----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + nation_commit | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a + nation_commit2 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a +(2 rows) + +BEGIN; +SELECT remove_file('dir_table4', 'nation_commit'); + remove_file +------------- + t +(1 row) + +SELECT relative_path, content FROM directory_table('dir_table4') ORDER BY 1; + relative_path | content +----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + nation_commit2 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a +(1 row) + +COMMIT; +SELECT relative_path, content FROM directory_table('dir_table4') ORDER BY 1; + relative_path | content +----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + nation_commit2 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a +(1 row) + +BEGIN; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +----------------+-------- + nation_commit2 | nation +(1 row) + +UPDATE dir_table4 SET tag = 'nation_updated' WHERE relative_path = 'nation_commit2'; +COMMIT; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +----------------+---------------- + nation_commit2 | nation_updated +(1 row) + +-- Test transaction rollback of directory table manipulation +BEGIN; +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_rollback'; +SELECT relative_path, content FROM directory_table('dir_table4') ORDER BY 1; + relative_path | content +-----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + nation_commit2 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a + nation_rollback | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a +(2 rows) + +ROLLBACK; +SELECT relative_path, content FROM directory_table('dir_table4') ORDER BY 1; + relative_path | content +----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + nation_commit2 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a +(1 row) + +BEGIN; +SELECT remove_file('dir_table4', 'nation_commit2'); + remove_file +------------- + t +(1 row) + +SELECT relative_path, content FROM directory_table('dir_table4') ORDER BY 1; + relative_path | content +---------------+--------- +(0 rows) + +ROLLBACK; +SELECT relative_path, content FROM directory_table('dir_table4') ORDER BY 1; + relative_path | content +----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + nation_commit2 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a +(1 row) + +BEGIN; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +----------------+---------------- + nation_commit2 | nation_updated +(1 row) + +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_rollback2' WITH TAG 'nation'; +UPDATE dir_table4 SET tag = 'nation_updated' WHERE relative_path = 'nation_rollback2'; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +------------------+---------------- + nation_commit2 | nation_updated + nation_rollback2 | nation_updated +(2 rows) + +ROLLBACK; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +----------------+---------------- + nation_commit2 | nation_updated +(1 row) + +-- Test subtransaction commit of directory table manipulation +BEGIN; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +----------------+---------------- + nation_commit2 | nation_updated +(1 row) + +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subcommit' WITH TAG 'nation'; +SAVEPOINT s1; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit | nation +(2 rows) + +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subcommit2'; +SAVEPOINT s2; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit | nation + nation_subcommit2 | +(3 rows) + +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subcommit3'; +RELEASE SAVEPOINT s1; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit | nation + nation_subcommit2 | + nation_subcommit3 | +(4 rows) + +COMMIT; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit | nation + nation_subcommit2 | + nation_subcommit3 | +(4 rows) + +BEGIN; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit | nation + nation_subcommit2 | + nation_subcommit3 | +(4 rows) + +SELECT remove_file('dir_table4', 'nation_subcommit'); + remove_file +------------- + t +(1 row) + +SAVEPOINT s1; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit2 | + nation_subcommit3 | +(3 rows) + +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subcommit'; +SAVEPOINT s2; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit | + nation_subcommit2 | + nation_subcommit3 | +(4 rows) + +RELEASE SAVEPOINT s1; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit | + nation_subcommit2 | + nation_subcommit3 | +(4 rows) + +COMMIT; +BEGIN; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit | + nation_subcommit2 | + nation_subcommit3 | +(4 rows) + +SELECT remove_file('dir_table4', 'nation_subcommit'); + remove_file +------------- + t +(1 row) + +SAVEPOINT s1; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit2 | + nation_subcommit3 | +(3 rows) + +SELECT remove_file('dir_table4', 'nation_subcommit2'); + remove_file +------------- + t +(1 row) + +SAVEPOINT s2; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | +(2 rows) + +RELEASE SAVEPOINT s2; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | +(2 rows) + +COMMIT; +BEGIN; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | +(2 rows) + +SELECT remove_file('dir_table4', 'nation_subcommit2'); + remove_file +------------- + f +(1 row) + +SAVEPOINT s1; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | +(2 rows) + +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subcommit4'; +SAVEPOINT s2; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | + nation_subcommit4 | +(3 rows) + +ROLLBACK TO SAVEPOINT s1; +COMMIT; +-- Test subtransaction rollback of directory table manipulation +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subrollback1'; +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subrollback2'; +BEGIN; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +---------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | + nation_subrollback1 | + nation_subrollback2 | +(4 rows) + +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subrollback3'; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +---------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | + nation_subrollback1 | + nation_subrollback2 | + nation_subrollback3 | +(5 rows) + +SAVEPOINT s1; +SELECT remove_file('dir_table4', 'nation_subrollback1'); + remove_file +------------- + t +(1 row) + +SAVEPOINT s2; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +---------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | + nation_subrollback2 | + nation_subrollback3 | +(4 rows) + +ROLLBACK; +BEGIN; +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subrollback4'; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +---------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | + nation_subrollback1 | + nation_subrollback2 | + nation_subrollback4 | +(5 rows) + +SAVEPOINT s1; +SELECT remove_file('dir_table4', 'nation_subrollback4'); + remove_file +------------- + t +(1 row) + +SAVEPOINT s2; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +---------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | + nation_subrollback1 | + nation_subrollback2 | +(4 rows) + +RELEASE SAVEPOINT s1; +ROLLBACK; +BEGIN; +SELECT remove_file('dir_table4', 'nation_subrollback2'); + remove_file +------------- + t +(1 row) + +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subrollback5'; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +---------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | + nation_subrollback1 | + nation_subrollback5 | +(4 rows) + +SAVEPOINT s1; +SELECT remove_file('dir_table4', 'nation_subrollback5'); + remove_file +------------- + t +(1 row) + +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +---------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | + nation_subrollback1 | +(3 rows) + +ROLLBACK TO SAVEPOINT s1; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +---------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | + nation_subrollback1 | + nation_subrollback5 | +(4 rows) + +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subrollback6'; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +---------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | + nation_subrollback1 | + nation_subrollback5 | + nation_subrollback6 | +(5 rows) + +SAVEPOINT s2; +ROLLBACK; +-- clean up +DROP DIRECTORY TABLE IF EXISTS dir_table1; +DROP DIRECTORY TABLE IF EXISTS dir_table2; +DROP DIRECTORY TABLE IF EXISTS dir_table3; +DROP DIRECTORY TABLE IF EXISTS dir_table4; +DROP DIRECTORY TABLE IF EXISTS dir_table5; +NOTICE: directory table "dir_table5" does not exist, skipping +DROP DIRECTORY TABLE IF EXISTS dir_table6; +DROP FUNCTION IF EXISTS trigtest; +DROP STORAGE USER MAPPING IF EXISTS FOR CURRENT_USER STORAGE SERVER oss_server1; +DROP STORAGE USER MAPPING IF EXISTS FOR CURRENT_USER STORAGE SERVER oss_server2; +NOTICE: storage user mapping for "gpadmin" does not exist for storage server "oss_server2", skipping +DROP STORAGE USER MAPPING IF EXISTS FOR CURRENT_USER STORAGE SERVER oss_server3; +DROP STORAGE USER MAPPING IF EXISTS FOR CURRENT_USER STORAGE SERVER oss_server4; +NOTICE: storage server "oss_server4" does not exist, skipping +DROP STORAGE USER MAPPING IF EXISTS FOR test_dirtable1 STORAGE SERVER oss_server1; +NOTICE: storage user mapping for "test_dirtable1" does not exist for storage server "oss_server1", skipping +DROP STORAGE USER MAPPING IF EXISTS FOR test_dirtable1 STORAGE SERVER oss_server2; +DROP STORAGE USER MAPPING IF EXISTS FOR test_dirtable1 STORAGE SERVER oss_server3; +DROP STORAGE USER MAPPING IF EXISTS FOR test_dirtable2 STORAGE SERVER oss_server3; +DROP STORAGE USER MAPPING IF EXISTS FOR test_dirtable3 STORAGE SERVER oss_server8; +DROP STORAGE SERVER IF EXISTS oss_server1; +DROP STORAGE SERVER IF EXISTS oss_server2; +DROP STORAGE SERVER IF EXISTS oss_server3; +DROP STORAGE SERVER IF EXISTS oss_server4; +NOTICE: storage server "oss_server4" not exists, skipping +DROP STORAGE SERVER IF EXISTS oss_server5; +DROP STORAGE SERVER IF EXISTS oss_server6; +DROP STORAGE SERVER IF EXISTS oss_server7; +DROP STORAGE SERVER IF EXISTS oss_server8; +DROP STORAGE SERVER IF EXISTS oss_server9; +NOTICE: storage server "oss_server9" not exists, skipping +DROP STORAGE SERVER IF EXISTS oss_server10; +NOTICE: storage server "oss_server10" not exists, skipping +DROP STORAGE SERVER IF EXISTS oss_server11; +DROP STORAGE SERVER IF EXISTS oss_server12; +DROP STORAGE SERVER IF EXISTS oss_server13; +NOTICE: storage server "oss_server13" not exists, skipping +SELECT srvname, srvacl, srvoptions FROM gp_storage_server; + srvname | srvacl | srvoptions +---------+--------+------------ +(0 rows) + +DROP USER test_dirtable1; +DROP USER test_dirtable2; +DROP USER test_dirtable3; +DROP USER test_dirtable4; +DROP FUNCTION IF EXISTS file_content; +DROP FUNCTION IF EXISTS file_md5; +DROP FUNCTION IF EXISTS md5_equal; +DROP DATABASE dirtable_db; +DROP TRIGGER IF EXISTS trigtest_b_row_tg_dirtable_1 ON dir_table1; +NOTICE: relation "dir_table1" does not exist, skipping +DROP TRIGGER IF EXISTS trigtest_a_row_tg_dirtable_1 ON dir_table1; +NOTICE: relation "dir_table1" does not exist, skipping +DROP TRIGGER IF EXISTS trigtest_b_stmt_tg_dirtable_1 ON dir_table1; +NOTICE: relation "dir_table1" does not exist, skipping +DROP TRIGGER IF EXISTS trigtest_a_stmt_tg_dirtable_1 ON dir_table1; +NOTICE: relation "dir_table1" does not exist, skipping +DROP TABLESPACE directory_tblspc; diff --git a/src/test/regress/output/directory_table_optimizer.source b/src/test/regress/output/directory_table_optimizer.source new file mode 100644 index 00000000000..66fdb0a39cc --- /dev/null +++ b/src/test/regress/output/directory_table_optimizer.source @@ -0,0 +1,1842 @@ +-- +-- Test for directory table +-- +-- Display pg_tablespace, pg_directory_table, gp_storage_server, gp_storage_user_mapping catalog +\d+ pg_tablespace; + Table "pg_catalog.pg_tablespace" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +-------------------+-----------+-----------+----------+---------+----------+--------------+------------- + oid | oid | | not null | | plain | | + spcname | name | | not null | | plain | | + spcowner | oid | | not null | | plain | | + spcacl | aclitem[] | | | | extended | | + spcoptions | text[] | C | | | extended | | + spcfilehandlersrc | text | C | | | extended | | + spcfilehandlerbin | text | C | | | extended | | +Indexes: + "pg_tablespace_oid_index" PRIMARY KEY, btree (oid), tablespace "pg_global" + "pg_tablespace_spcname_index" UNIQUE CONSTRAINT, btree (spcname), tablespace "pg_global" +Tablespace: "pg_global" + +\d+ pg_directory_table; + Table "pg_catalog.pg_directory_table" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------------+------+-----------+----------+---------+----------+--------------+------------- + dtrelid | oid | | not null | | plain | | + dttablespace | oid | | not null | | plain | | + dtlocation | text | C | | | extended | | +Indexes: + "pg_directory_table_relid_index" PRIMARY KEY, btree (dtrelid) + +\d+ gp_storage_server; + Table "pg_catalog.gp_storage_server" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +------------+-----------+-----------+----------+---------+----------+--------------+------------- + oid | oid | | not null | | plain | | + srvname | name | | not null | | plain | | + srvowner | oid | | not null | | plain | | + srvacl | aclitem[] | | | | extended | | + srvoptions | text[] | C | | | extended | | +Indexes: + "gp_storage_server_oid_index" PRIMARY KEY, btree (oid), tablespace "pg_global" + "gp_storage_server_name_index" UNIQUE CONSTRAINT, btree (srvname), tablespace "pg_global" +Tablespace: "pg_global" + +\d+ gp_storage_user_mapping; + Table "pg_catalog.gp_storage_user_mapping" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +-----------+--------+-----------+----------+---------+----------+--------------+------------- + oid | oid | | not null | | plain | | + umuser | oid | | not null | | plain | | + umserver | oid | | not null | | plain | | + umoptions | text[] | C | | | extended | | +Indexes: + "gp_storage_user_mapping_oid_index" PRIMARY KEY, btree (oid), tablespace "pg_global" + "gp_storage_user_mapping_server_index" UNIQUE CONSTRAINT, btree (umuser, umserver), tablespace "pg_global" +Tablespace: "pg_global" + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname = 'pg_directory_table'; + relname | relisshared | relpersistence | relkind +--------------------+-------------+----------------+--------- + pg_directory_table | f | p | r +(1 row) + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname = 'gp_storage_server'; + relname | relisshared | relpersistence | relkind +-------------------+-------------+----------------+--------- + gp_storage_server | t | p | r +(1 row) + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname = 'gp_storage_user_mapping'; + relname | relisshared | relpersistence | relkind +-------------------------+-------------+----------------+--------- + gp_storage_user_mapping | t | p | r +(1 row) + +-- CREATE TABLESPACE +CREATE TABLESPACE directory_tblspc LOCATION '@testtablespace@'; +-- CREATE DATABASE +CREATE DATABASE dirtable_db; +\c dirtable_db +\d+ pg_directory_table; + Table "pg_catalog.pg_directory_table" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------------+------+-----------+----------+---------+----------+--------------+------------- + dtrelid | oid | | not null | | plain | | + dttablespace | oid | | not null | | plain | | + dtlocation | text | C | | | extended | | +Indexes: + "pg_directory_table_relid_index" PRIMARY KEY, btree (dtrelid) + +\d+ gp_storage_server; + Table "pg_catalog.gp_storage_server" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +------------+-----------+-----------+----------+---------+----------+--------------+------------- + oid | oid | | not null | | plain | | + srvname | name | | not null | | plain | | + srvowner | oid | | not null | | plain | | + srvacl | aclitem[] | | | | extended | | + srvoptions | text[] | C | | | extended | | +Indexes: + "gp_storage_server_oid_index" PRIMARY KEY, btree (oid), tablespace "pg_global" + "gp_storage_server_name_index" UNIQUE CONSTRAINT, btree (srvname), tablespace "pg_global" +Tablespace: "pg_global" + +\d+ gp_storage_user_mapping; + Table "pg_catalog.gp_storage_user_mapping" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +-----------+--------+-----------+----------+---------+----------+--------------+------------- + oid | oid | | not null | | plain | | + umuser | oid | | not null | | plain | | + umserver | oid | | not null | | plain | | + umoptions | text[] | C | | | extended | | +Indexes: + "gp_storage_user_mapping_oid_index" PRIMARY KEY, btree (oid), tablespace "pg_global" + "gp_storage_user_mapping_server_index" UNIQUE CONSTRAINT, btree (umuser, umserver), tablespace "pg_global" +Tablespace: "pg_global" + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname = 'pg_directory_table'; + relname | relisshared | relpersistence | relkind +--------------------+-------------+----------------+--------- + pg_directory_table | f | p | r +(1 row) + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname = 'gp_storage_server'; + relname | relisshared | relpersistence | relkind +-------------------+-------------+----------------+--------- + gp_storage_server | t | p | r +(1 row) + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname = 'gp_storage_user_mapping'; + relname | relisshared | relpersistence | relkind +-------------------------+-------------+----------------+--------- + gp_storage_user_mapping | t | p | r +(1 row) + +\c regression +-- CREATE USER for directory table +CREATE USER test_dirtable1; +NOTICE: resource queue required -- using default resource queue "pg_default" +CREATE USER test_dirtable2; +NOTICE: resource queue required -- using default resource queue "pg_default" +CREATE USER test_dirtable3; +NOTICE: resource queue required -- using default resource queue "pg_default" +CREATE USER test_dirtable4; +NOTICE: resource queue required -- using default resource queue "pg_default" +-- Test CREATE STORAGE SERVER +SELECT srvname, srvacl, srvoptions from gp_storage_server ORDER BY 1; + srvname | srvacl | srvoptions +---------+--------+------------ +(0 rows) + +CREATE STORAGE SERVER oss_server1; +CREATE STORAGE SERVER oss_server2 OPTIONS(protocal 'localhost'); +CREATE STORAGE SERVER oss_server3 OPTIONS(endpoint '127.0.0.1:9000'); +CREATE STORAGE SERVER oss_server4 OPTIONS(https 'true'); +CREATE STORAGE SERVER oss_server5 OPTIONS(virtual_host 'false'); +CREATE STORAGE SERVER oss_server6 OPTIONS(protocol 'qingstor', endpoint 'pek3b,qingstor.com'); +CREATE STORAGE SERVER oss_server7 OPTIONS(https 'false', virtual_host 'true'); +CREATE STORAGE SERVER oss_server8 OPTIONS(protocol 'hdfs', namenode '127.0.0.1:8020'); +CREATE STORAGE SERVER oss_server9 OWNER TO postgres; -- fail +ERROR: syntax error at or near "OWNER" +LINE 1: CREATE STORAGE SERVER oss_server9 OWNER TO postgres; + ^ +CREATE STORAGE SERVER IF NOT EXISTS oss_server10; +CREATE STORAGE SERVER IF NOT EXISTS oss_server11 OPTIONS(protocol 's3av2'); +CREATE STORAGE SERVER IF NOT EXISTS oss_server12 OPTIONS(protocol 's3av2', endpoint '127.0.0.1:9000', https 'false'); +CREATE STORAGE SERVER IF NOT EXISTS oss_server13 OWNER TO postgres; -- fail +ERROR: syntax error at or near "OWNER" +LINE 1: CREATE STORAGE SERVER IF NOT EXISTS oss_server13 OWNER TO po... + ^ +SELECT srvname, srvacl, srvoptions from gp_storage_server ORDER BY 1; + srvname | srvacl | srvoptions +--------------+--------+------------------------------------------------------ + oss_server1 | | + oss_server10 | | + oss_server11 | | {protocol=s3av2} + oss_server12 | | {protocol=s3av2,endpoint=127.0.0.1:9000,https=false} + oss_server2 | | {protocal=localhost} + oss_server3 | | {endpoint=127.0.0.1:9000} + oss_server4 | | {https=true} + oss_server5 | | {virtual_host=false} + oss_server6 | | {protocol=qingstor,"endpoint=pek3b,qingstor.com"} + oss_server7 | | {https=false,virtual_host=true} + oss_server8 | | {protocol=hdfs,namenode=127.0.0.1:8020} +(11 rows) + +\c dirtable_db +SELECT srvname, srvacl, srvoptions from gp_storage_server ORDER BY 1; + srvname | srvacl | srvoptions +--------------+--------+------------------------------------------------------ + oss_server1 | | + oss_server10 | | + oss_server11 | | {protocol=s3av2} + oss_server12 | | {protocol=s3av2,endpoint=127.0.0.1:9000,https=false} + oss_server2 | | {protocal=localhost} + oss_server3 | | {endpoint=127.0.0.1:9000} + oss_server4 | | {https=true} + oss_server5 | | {virtual_host=false} + oss_server6 | | {protocol=qingstor,"endpoint=pek3b,qingstor.com"} + oss_server7 | | {https=false,virtual_host=true} + oss_server8 | | {protocol=hdfs,namenode=127.0.0.1:8020} +(11 rows) + +\c regression +-- Test ALTER STORAGE SERVER +ALTER STORAGE SERVER oss_server1 OPTIONS(protocol 'aws'); +ALTER STORAGE SERVER oss_server1 OPTIONS(protocol 'test'); -- fail +ERROR: option "protocol" provided more than once +ALTER STORAGE SERVER oss_server2 OPTIONS(https 'true'); +ALTER STORAGE SERVER oss_server2 OPTIONS(https 'false', virtual_host 'true'); -- fail +ERROR: option "https" provided more than once +ALTER STORAGE SERVER oss_server2 OPTIONS(virtual_host 'true'); +ALTER STORAGE SERVER oss_server3 OPTIONS(endpoint '192.168.0.1'); -- fail +ERROR: option "endpoint" provided more than once +ALTER STORAGE SERVER oss_server4 OPTIONS(protocol 'localhost', virtual_host 'true'); +ALTER STORAGE SERVER oss_server4 OPTIONS(protocol 'qingstor'); -- fail +ERROR: option "protocol" provided more than once +ALTER STORAGE SERVER oss_server5; -- fail +ERROR: syntax error at or near ";" +LINE 1: ALTER STORAGE SERVER oss_server5; + ^ +ALTER STORAGE SERVER oss_server6 OWNER TO postgres; -- fail +ERROR: syntax error at or near "OWNER" +LINE 1: ALTER STORAGE SERVER oss_server6 OWNER TO postgres; + ^ +ALTER STORAGE SERVER IF EXISTS oss_server7 OPTIONS(endpoint '127.0.0.1:6555'); -- fail +ERROR: syntax error at or near "EXISTS" +LINE 1: ALTER STORAGE SERVER IF EXISTS oss_server7 OPTIONS(endpoint ... + ^ +ALTER STORAGE SERVER IF NOT EXISTS oss_server8 OPTIONS(virtual_host 'true'); -- fail +ERROR: syntax error at or near "NOT" +LINE 1: ALTER STORAGE SERVER IF NOT EXISTS oss_server8 OPTIONS(virtu... + ^ +SELECT srvname, srvacl, srvoptions from gp_storage_server ORDER BY 1; + srvname | srvacl | srvoptions +--------------+--------+------------------------------------------------------ + oss_server1 | | {protocol=aws} + oss_server10 | | + oss_server11 | | {protocol=s3av2} + oss_server12 | | {protocol=s3av2,endpoint=127.0.0.1:9000,https=false} + oss_server2 | | {protocal=localhost,https=true,virtual_host=true} + oss_server3 | | {endpoint=127.0.0.1:9000} + oss_server4 | | {https=true,protocol=localhost,virtual_host=true} + oss_server5 | | {virtual_host=false} + oss_server6 | | {protocol=qingstor,"endpoint=pek3b,qingstor.com"} + oss_server7 | | {https=false,virtual_host=true} + oss_server8 | | {protocol=hdfs,namenode=127.0.0.1:8020} +(11 rows) + +\c dirtable_db +SELECT srvname, srvacl, srvoptions from gp_storage_server ORDER BY 1; + srvname | srvacl | srvoptions +--------------+--------+------------------------------------------------------ + oss_server1 | | {protocol=aws} + oss_server10 | | + oss_server11 | | {protocol=s3av2} + oss_server12 | | {protocol=s3av2,endpoint=127.0.0.1:9000,https=false} + oss_server2 | | {protocal=localhost,https=true,virtual_host=true} + oss_server3 | | {endpoint=127.0.0.1:9000} + oss_server4 | | {https=true,protocol=localhost,virtual_host=true} + oss_server5 | | {virtual_host=false} + oss_server6 | | {protocol=qingstor,"endpoint=pek3b,qingstor.com"} + oss_server7 | | {https=false,virtual_host=true} + oss_server8 | | {protocol=hdfs,namenode=127.0.0.1:8020} +(11 rows) + +\c regression +-- Test CREATE STORAGE USER MAPPING +CREATE STORAGE USER MAPPING FOR CURRENT_USER; -- fail +ERROR: syntax error at or near ";" +LINE 1: CREATE STORAGE USER MAPPING FOR CURRENT_USER; + ^ +CREATE STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server1; +CREATE STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server1 +OPTIONS (accesskey 'KGFQWEFQQEFXVAEAWLLC', secretkey '0SJIWiIATh6jOlmAKr8DGq6hOAGBI1BnsnvgJmTs'); -- fail +ERROR: storage user mapping for "gpadmin" already exists for storage server "oss_server1" +CREATE STORAGE USER MAPPING IF NOT EXISTS FOR CURRENT_USER STORAGE SERVER oss_server1; +NOTICE: storage user mapping for "gpadmin" already exists for storage server "oss_server1", skipping +CREATE STORAGE USER MAPPING IF NOT EXISTS FOR CURRENT_USER STORAGE SERVER oss_server1 +OPTIONS (auth_method 'simple'); +NOTICE: storage user mapping for "gpadmin" already exists for storage server "oss_server1", skipping +CREATE STORAGE USER MAPPING FOR CURRENT_ROLE STORAGE SERVER oss_server2 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE'); +CREATE STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server2 +OPTIONS (accesskey 'KGFQWEFQQEFXVAEAWLLC', secretkey '0SJIWiIATh6jOlmAKr8DGq6hOAGBI1BnsnvgJmTs'); -- fail +ERROR: storage user mapping for "gpadmin" already exists for storage server "oss_server2" +CREATE STORAGE USER MAPPING FOR CURRENT_ROLE STORAGE SERVER oss_server3 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE'); +CREATE STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_not_exits; -- fail +ERROR: server "oss_not_exits" does not exist +CREATE STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_not_exits +OPTIONS (accesskey 'KGFQWEFQQEFXVAEAWLLC', secretkey '0SJIWiIATh6jOlmAKr8DGq6hOAGBI1BnsnvgJmTs'); -- fail +ERROR: server "oss_not_exits" does not exist +CREATE STORAGE USER MAPPING FOR test_dirtable1 STORAGE SERVER oss_server1; +CREATE STORAGE USER MAPPING FOR test_dirtable1 STORAGE SERVER oss_server1 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H'); -- fail +ERROR: storage user mapping for "test_dirtable1" already exists for storage server "oss_server1" +CREATE STORAGE USER MAPPING FOR test_dirtable1 STORAGE SERVER oss_server2 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H'); +CREATE STORAGE USER MAPPING FOR test_dirtable1 STORAGE SERVER oss_server3 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H'); +CREATE STORAGE USER MAPPING FOR no_exist_user STORAGE SERVER oss_server1; -- fail +ERROR: role "no_exist_user" does not exist +CREATE STORAGE USER MAPPING FOR no_exist_user STORAGE SERVER oss_server1 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H'); -- fail +ERROR: role "no_exist_user" does not exist +CREATE STORAGE USER MAPPING IF NOT EXISTS FOR CURRENT_USER STORAGE SERVER oss_server1 +OPTIONS (accesskey 'KGFQWEFQQEFXVAEAWLLC', secretkey '0SJIWiIATh6jOlmAKr8DGq6hOAGBI1BnsnvgJmTs'); -- skip +NOTICE: storage user mapping for "gpadmin" already exists for storage server "oss_server1", skipping +CREATE STORAGE USER MAPPING IF NOT EXISTS FOR test_dirtable2 STORAGE SERVER oss_server3 +OPTIONS (endpoint '127.0.0.1:6555'); +CREATE STORAGE USER MAPPING IF NOT EXISTS FOR test_dirtable3 STORAGE SERVER oss_server8 +OPTIONS (auth_method 'simple'); +CREATE STORAGE USER MAPPING IF NOT EXISTS FOR no_exist_user STORAGE SERVER oss_server1; -- fail +ERROR: role "no_exist_user" does not exist +SELECT umoptions FROM gp_storage_user_mapping ORDER BY 1; + umoptions +------------------------------------------------------------------------------------- + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {auth_method=simple} + {endpoint=127.0.0.1:6555} + + +(8 rows) + +\c dirtable_db +SELECT umoptions FROM gp_storage_user_mapping ORDER BY 1; + umoptions +------------------------------------------------------------------------------------- + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {auth_method=simple} + {endpoint=127.0.0.1:6555} + + +(8 rows) + +\c regression +-- Test ALTER STORAGE USER MAPPING +ALTER STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server1; -- fail +ERROR: syntax error at or near ";" +LINE 1: ...GE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server1; + ^ +ALTER STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server1 +OPTIONS (accesskey 'KGFQWEFQQEFXVAEAWLLC', secretkey '0SJIWiIATh6jOlmAKr8DGq6hOAGBI1BnsnvgJmTs'); +ALTER STORAGE USER MAPPING FOR CURRENT_ROLE STORAGE SERVER oss_server1 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ'); -- fail +ERROR: option "accesskey" provided more than once +ALTER STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server1 +OPTIONS (auth_method 'simple'); +ALTER STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server2 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE'); -- fail +ERROR: option "accesskey" provided more than once +ALTER STORAGE USER MAPPING IF EXISTS FOR CURRENT_USER STORAGE SERVER server_not_exists +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE'); -- fail +ERROR: syntax error at or near "IF" +LINE 1: ALTER STORAGE USER MAPPING IF EXISTS FOR CURRENT_USER STORAG... + ^ +ALTER STORAGE USER MAPPING IF EXISTS FOR no_exist_user STORAGE SERVER oss_server1 +OPTIONS (accesskey 'EQEJIOJFAKQWESQEJIWQ', secretkey '0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE'); -- fail +ERROR: syntax error at or near "IF" +LINE 1: ALTER STORAGE USER MAPPING IF EXISTS FOR no_exist_user STORA... + ^ +ALTER STORAGE USER MAPPING IF NOT EXISTS FOR test_dirtable1 STORAGE SERVER oss_server3 +OPTIONS (auth_method 'simple'); -- fail +ERROR: syntax error at or near "IF" +LINE 1: ALTER STORAGE USER MAPPING IF NOT EXISTS FOR test_dirtable1 ... + ^ +SELECT umoptions FROM gp_storage_user_mapping ORDER BY 1; + umoptions +-------------------------------------------------------------------------------------------------------- + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {accesskey=KGFQWEFQQEFXVAEAWLLC,secretkey=0SJIWiIATh6jOlmAKr8DGq6hOAGBI1BnsnvgJmTs,auth_method=simple} + {auth_method=simple} + {endpoint=127.0.0.1:6555} + +(8 rows) + +\c dirtable_db +SELECT umoptions FROM gp_storage_user_mapping ORDER BY 1; + umoptions +-------------------------------------------------------------------------------------------------------- + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {accesskey=KGFQWEFQQEFXVAEAWLLC,secretkey=0SJIWiIATh6jOlmAKr8DGq6hOAGBI1BnsnvgJmTs,auth_method=simple} + {auth_method=simple} + {endpoint=127.0.0.1:6555} + +(8 rows) + +\c regression +-- Test DROP STORAGE USER MAPPING +DROP STORAGE USER MAPPING FOR CURRENT_USER; -- fail +ERROR: syntax error at or near ";" +LINE 1: DROP STORAGE USER MAPPING FOR CURRENT_USER; + ^ +DROP STORAGE USER MAPPING FOR CURRENT_USER STORAGE SERVER oss_server2; +DROP STORAGE USER MAPPING IF EXISTS FOR test_dirtable1 STORAGE SERVER oss_server1; +DROP STORAGE USER MAPPING IF EXISTS FOR test_dirtable2 STORAGE SERVER no_exist_server; +NOTICE: storage server "no_exist_server" does not exist, skipping +DROP STORAGE USER MAPPING FOR test_dirtable3 STORAGE SERVER no_exist_server; -- fail +ERROR: storage server "no_exist_server" does not exist +DROP STORAGE USER MAPPING FOR no_exist_user STORAGE SERVER oss_server1; -- fail +ERROR: role "no_exist_user" does not exist +DROP STORAGE USER MAPPING IF EXISTS FOR no_exist_user STORAGE SERVER oss_server1; -- skip +NOTICE: role "no_exist_user" does not exist, skipping +SELECT umoptions FROM gp_storage_user_mapping ORDER BY 1; + umoptions +-------------------------------------------------------------------------------------------------------- + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {accesskey=KGFQWEFQQEFXVAEAWLLC,secretkey=0SJIWiIATh6jOlmAKr8DGq6hOAGBI1BnsnvgJmTs,auth_method=simple} + {auth_method=simple} + {endpoint=127.0.0.1:6555} +(6 rows) + +\c dirtable_db +SELECT umoptions FROM gp_storage_user_mapping ORDER BY 1; + umoptions +-------------------------------------------------------------------------------------------------------- + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=0ADQiAxcaUJ2lMHipis80hsUEhdiqui82JhduOKE} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {accesskey=EQEJIOJFAKQWESQEJIWQ,secretkey=7KieQKdu02jHEUEjsqUYE83mx9OE2kdj2SJ72h6H} + {accesskey=KGFQWEFQQEFXVAEAWLLC,secretkey=0SJIWiIATh6jOlmAKr8DGq6hOAGBI1BnsnvgJmTs,auth_method=simple} + {auth_method=simple} + {endpoint=127.0.0.1:6555} +(6 rows) + +\c regression +-- Test DROP STOARGE SERVER +DROP STORAGE SERVER oss_server1; -- fail +ERROR: storage server "oss_server1" cannot be dropped because some objects depend on it +DETAIL: storage server of storage user mapping for gpadmin on storage server oss_server1 +DROP STORAGE SERVER oss_server2; -- fail +ERROR: storage server "oss_server2" cannot be dropped because some objects depend on it +DETAIL: storage server of storage user mapping for test_dirtable1 on storage server oss_server2 +DROP STORAGE SERVER oss_server3; -- fail +ERROR: storage server "oss_server3" cannot be dropped because some objects depend on it +DETAIL: storage server of storage user mapping for gpadmin on storage server oss_server3 +storage server of storage user mapping for test_dirtable1 on storage server oss_server3 +storage server of storage user mapping for test_dirtable2 on storage server oss_server3 +DROP STORAGE SERVER oss_server4; -- fail +DROP STORAGE SERVER oss_server8; -- fail +ERROR: storage server "oss_server8" cannot be dropped because some objects depend on it +DETAIL: storage server of storage user mapping for test_dirtable3 on storage server oss_server8 +DROP STORAGE SERVER oss_server9; -- fail +ERROR: storage server "oss_server9" not exists +DROP STAROGE SERVER IF EXISTS oss_server9; -- fail +ERROR: syntax error at or near "STAROGE" +LINE 1: DROP STAROGE SERVER IF EXISTS oss_server9; + ^ +DROP STORAGE SERVER IF NOT EXISTS oss_server9; --fail +ERROR: syntax error at or near "NOT" +LINE 1: DROP STORAGE SERVER IF NOT EXISTS oss_server9; + ^ +DROP STORAGE SERVER IF EXISTS oss_server10; +SELECT srvname, srvacl, srvoptions from gp_storage_server ORDER BY 1; + srvname | srvacl | srvoptions +--------------+--------+------------------------------------------------------ + oss_server1 | | {protocol=aws} + oss_server11 | | {protocol=s3av2} + oss_server12 | | {protocol=s3av2,endpoint=127.0.0.1:9000,https=false} + oss_server2 | | {protocal=localhost,https=true,virtual_host=true} + oss_server3 | | {endpoint=127.0.0.1:9000} + oss_server5 | | {virtual_host=false} + oss_server6 | | {protocol=qingstor,"endpoint=pek3b,qingstor.com"} + oss_server7 | | {https=false,virtual_host=true} + oss_server8 | | {protocol=hdfs,namenode=127.0.0.1:8020} +(9 rows) + +\c dirtable_db +SELECT srvname, srvacl, srvoptions from gp_storage_server ORDER BY 1; + srvname | srvacl | srvoptions +--------------+--------+------------------------------------------------------ + oss_server1 | | {protocol=aws} + oss_server11 | | {protocol=s3av2} + oss_server12 | | {protocol=s3av2,endpoint=127.0.0.1:9000,https=false} + oss_server2 | | {protocal=localhost,https=true,virtual_host=true} + oss_server3 | | {endpoint=127.0.0.1:9000} + oss_server5 | | {virtual_host=false} + oss_server6 | | {protocol=qingstor,"endpoint=pek3b,qingstor.com"} + oss_server7 | | {https=false,virtual_host=true} + oss_server8 | | {protocol=hdfs,namenode=127.0.0.1:8020} +(9 rows) + +\c regression +-- Test directory table +-- Test CREATE DIRECTORY TABLE +SELECT count(*) FROM pg_directory_table; + count +------- + 0 +(1 row) + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname like '%dir_table%' ORDER BY 1; + relname | relisshared | relpersistence | relkind +---------+-------------+----------------+--------- +(0 rows) + +CREATE DIRECTORY TABLE dir_table1; +CREATE DIRECTORY TABLE dir_table2 TABLESPACE directory_tblspc; +CREATE DIRECTORY TABLE dir_table3 TABLESPACE directory_tblspc DISTRIBUTED BY(relative_path); -- fail +ERROR: Create directory table is not allowed to set distributed by. +LINE 1: ...TORY TABLE dir_table3 TABLESPACE directory_tblspc DISTRIBUTE... + ^ +CREATE DIRECTORY TABLE dir_table3 TABLESPACE directory_tblspc DISTRIBUTED RANDOMLY; -- fail +ERROR: Create directory table is not allowed to set distributed by. +LINE 1: ...TORY TABLE dir_table3 TABLESPACE directory_tblspc DISTRIBUTE... + ^ +CREATE DIRECTORY TABLE dir_table3 TABLESPACE directory_tblspc DISTRIBUTED REPLICATED; -- fail +ERROR: Create directory table is not allowed to set distributed by. +LINE 1: ...TORY TABLE dir_table3 TABLESPACE directory_tblspc DISTRIBUTE... + ^ +CREATE DIRECTORY TABLE dir_table3 TABLESPACE directory_tblspc; +CREATE DIRECTORY TABLE IF NOT EXISTS dir_table4 TABLESPACE directory_tblspc; +CREATE DIRECTORY TABLE IF NOT EXISTS dir_table2 TABLESPACE directory_tblspc; -- fail +NOTICE: relation "dir_table2" already exists, skipping +CREATE DIRECTORY TABLE dir_table5 TABLESPACE directory_tblspc; +CREATE DIRECTORY TABLE dir_table6 TABLESPACE pg_default; +\dY + List of relations + Schema | Name | Type | Owner +--------+------------+-----------------+--------- + public | dir_table1 | directory table | gpadmin + public | dir_table2 | directory table | gpadmin + public | dir_table3 | directory table | gpadmin + public | dir_table4 | directory table | gpadmin + public | dir_table5 | directory table | gpadmin + public | dir_table6 | directory table | gpadmin +(6 rows) + +SELECT count(*) FROM pg_directory_table; + count +------- + 6 +(1 row) + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname like '%dir_table%' ORDER BY 1; + relname | relisshared | relpersistence | relkind +-----------------+-------------+----------------+--------- + dir_table1 | f | p | d + dir_table1_pkey | f | p | i + dir_table2 | f | p | d + dir_table2_pkey | f | p | i + dir_table3 | f | p | d + dir_table3_pkey | f | p | i + dir_table4 | f | p | d + dir_table4_pkey | f | p | i + dir_table5 | f | p | d + dir_table5_pkey | f | p | i + dir_table6 | f | p | d + dir_table6_pkey | f | p | i +(12 rows) + +\d+ dir_table1; + Directory able "public.dir_table1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +---------------+--------------------------+-----------+----------+---------+----------+--------------+------------- + relative_path | text | | | | extended | | + size | bigint | | | | plain | | + last_modified | timestamp with time zone | | | | plain | | + md5 | text | | | | extended | | + tag | text | | | | extended | | +Indexes: + "dir_table1_pkey" PRIMARY KEY, btree (relative_path) +Distributed by: (relative_path) + +\d+ dir_table2; + Directory able "public.dir_table2" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +---------------+--------------------------+-----------+----------+---------+----------+--------------+------------- + relative_path | text | | | | extended | | + size | bigint | | | | plain | | + last_modified | timestamp with time zone | | | | plain | | + md5 | text | | | | extended | | + tag | text | | | | extended | | +Indexes: + "dir_table2_pkey" PRIMARY KEY, btree (relative_path) +Distributed by: (relative_path) + +\d+ dir_table3; + Directory able "public.dir_table3" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +---------------+--------------------------+-----------+----------+---------+----------+--------------+------------- + relative_path | text | | | | extended | | + size | bigint | | | | plain | | + last_modified | timestamp with time zone | | | | plain | | + md5 | text | | | | extended | | + tag | text | | | | extended | | +Indexes: + "dir_table3_pkey" PRIMARY KEY, btree (relative_path) +Distributed by: (relative_path) + +\c dirtable_db +\dY + List of relations + Schema | Name | Type | Owner +--------+------+------+------- +(0 rows) + +SELECT count(*) FROM pg_directory_table; + count +------- + 0 +(1 row) + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname like '%dir_table%' ORDER BY 1; + relname | relisshared | relpersistence | relkind +---------+-------------+----------------+--------- +(0 rows) + +\c regression +-- Test create table inherits directory table +CREATE TABLE test_inherits1 INHERITS(dir_table1); -- fail +ERROR: syntax error at or near "INHERITS" +LINE 1: CREATE TABLE test_inherits1 INHERITS(dir_table1); + ^ +CREATE TABLE test_inherits2(a int) INHERITS(dir_table2); -- fail +NOTICE: table has parent, setting distribution columns to match parent table +ERROR: inherited relation "dir_table2" is not a table or foreign table +CREATE TABLE test_inherits3 INHERITS(dir_table2, dir_table3); -- fail +ERROR: syntax error at or near "INHERITS" +LINE 1: CREATE TABLE test_inherits3 INHERITS(dir_table2, dir_table3)... + ^ +CREATE TABLE test_inherits4(b text) INHERITS(dir_table1, dir_table2); -- fail +NOTICE: table has parent, setting distribution columns to match parent table +ERROR: inherited relation "dir_table1" is not a table or foreign table +-- Test DROP DIRECTORY TABLE +DROP DIRECTORY TABLE dir_table4; +DROP DIRECTORY TABLE dir_table4; -- fail +ERROR: directory table "dir_table4" does not exist +DROP DIRECTORY TABLE IF EXISTS dir_table5; +DROP DIRECTORY TABLE IF EXISTS dir_table5; -- skip +NOTICE: directory table "dir_table5" does not exist, skipping +\dY + List of relations + Schema | Name | Type | Owner +--------+------------+-----------------+--------- + public | dir_table1 | directory table | gpadmin + public | dir_table2 | directory table | gpadmin + public | dir_table3 | directory table | gpadmin + public | dir_table6 | directory table | gpadmin +(4 rows) + +SELECT count(*) FROM pg_directory_table; + count +------- + 4 +(1 row) + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname like '%dir_table%' ORDER BY 1; + relname | relisshared | relpersistence | relkind +-----------------+-------------+----------------+--------- + dir_table1 | f | p | d + dir_table1_pkey | f | p | i + dir_table2 | f | p | d + dir_table2_pkey | f | p | i + dir_table3 | f | p | d + dir_table3_pkey | f | p | i + dir_table6 | f | p | d + dir_table6_pkey | f | p | i +(8 rows) + +\c dirtable_db +\dY + List of relations + Schema | Name | Type | Owner +--------+------+------+------- +(0 rows) + +SELECT count(*) FROM pg_directory_table; + count +------- + 0 +(1 row) + +SELECT relname, relisshared, relpersistence, relkind FROM pg_class WHERE relname like '%dir_table%' ORDER BY 1; + relname | relisshared | relpersistence | relkind +---------+-------------+----------------+--------- +(0 rows) + +\c regression +-- Test CREATE/DROP/REINDEX on DIRECTORY SCHEMA TABLE +-- Test CREATE INDEX on DIRECTORY SCHEMA TABLE +CREATE INDEX dirtable1_relative_path_idx on dir_table1(relative_path); -- fail +ERROR: Disallowed to create index on directory table "dir_table1". (indexcmds.c:709) +CREATE INDEX dirtable1_size_idx on dir_table1(size); -- fail +ERROR: Disallowed to create index on directory table "dir_table1". (indexcmds.c:709) +CREATE INDEX dirtable1_last_modified_idx on dir_table1(last_modified); -- fail +ERROR: Disallowed to create index on directory table "dir_table1". (indexcmds.c:709) +CREATE INDEX dirtable1_md5_idx on dir_table1(md5); -- fail +ERROR: Disallowed to create index on directory table "dir_table1". (indexcmds.c:709) +CREATE INDEX dirtable1_tag_idx on dir_table1(tag); -- fail +ERROR: Disallowed to create index on directory table "dir_table1". (indexcmds.c:709) +\d+ dir_table1; + Directory able "public.dir_table1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +---------------+--------------------------+-----------+----------+---------+----------+--------------+------------- + relative_path | text | | | | extended | | + size | bigint | | | | plain | | + last_modified | timestamp with time zone | | | | plain | | + md5 | text | | | | extended | | + tag | text | | | | extended | | +Indexes: + "dir_table1_pkey" PRIMARY KEY, btree (relative_path) +Distributed by: (relative_path) + +-- Test DROP INDEX on DIRECTORY SCHEMA TABLE +DROP INDEX dir_table1_pkey; -- fail +ERROR: Disallowed to drop index "dir_table1_pkey" on directory table "dir_table1" +DROP INDEX dir_table2_pkey; -- fail +ERROR: Disallowed to drop index "dir_table2_pkey" on directory table "dir_table2" +DROP INDEX dir_table3_pkey; -- fail +ERROR: Disallowed to drop index "dir_table3_pkey" on directory table "dir_table3" +DROP INDEX dir_table4_pkey; -- fail +ERROR: index "dir_table4_pkey" does not exist +DROP INDEX dir_table5_pkey; -- fail +ERROR: index "dir_table5_pkey" does not exist +DROP INDEX dir_table6_pkey; -- fail +ERROR: Disallowed to drop index "dir_table6_pkey" on directory table "dir_table6" +-- Test REINDEX on DIRECTORY SCHEMA TABLE +REINDEX INDEX dir_table1_pkey; +REINDEX INDEX dir_table2_pkey; +REINDEX INDEX dir_table3_pkey; +REINDEX INDEX dir_table4_pkey; +ERROR: relation "dir_table4_pkey" does not exist +REINDEX INDEX dir_table5_pkey; +ERROR: relation "dir_table5_pkey" does not exist +REINDEX INDEX dir_table6_pkey; +REINDEX TABLE dir_table1; +REINDEX TABLE dir_table2; +REINDEX TABLE dir_table3; +REINDEX TABLE dir_table4; +ERROR: relation "dir_table4" does not exist +REINDEX TABLE dir_table5; +ERROR: relation "dir_table5" does not exist +REINDEX TABLE dir_table6; +-- Test triggers +DROP FUNCTION IF EXISTS trigtest; +create function trigtest() returns trigger as $$ +begin + raise notice '% % % %', TG_TABLE_NAME, TG_OP, TG_WHEN, TG_LEVEL; + return new; +end;$$ language plpgsql; +create trigger trigtest_b_row_tg_dirtable_1 before insert or update or delete on dir_table1 +for each row execute procedure trigtest(); +create trigger trigtest_a_row_tg_dirtable_1 after insert or update or delete on dir_table1 +for each row execute procedure trigtest(); +create trigger trigtest_b_stmt_tg_dirtable_1 before insert or update or delete on dir_table1 +for each statement execute procedure trigtest(); +ERROR: Triggers for statements are not yet supported +create trigger trigtest_a_stmt_tg_dirtable_1 after insert or update or delete on dir_table1 +for each statement execute procedure trigtest(); +ERROR: Triggers for statements are not yet supported +-- Test COPY DIRECTORY TABLE syntax +SELECT relative_path, size, tag FROM dir_table1 ORDER BY 1; + relative_path | size | tag +---------------+------+----- +(0 rows) + +SELECT relative_path, size, tag FROM dir_table2 ORDER BY 1; + relative_path | size | tag +---------------+------+----- +(0 rows) + +\COPY dir_table1 FROM '@abs_srcdir@/data/nation.csv'; -- fail +ERROR: Copy from directory table file name can't be null. +\COPY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation'; -- fail +ERROR: Only support copy binary from directory table. +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv'; -- fail +ERROR: Copy from directory table file name can't be null. +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation1'; +NOTICE: dir_table1 INSERT AFTER ROW (seg1 127.0.1.1:7003 pid=31465) +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation1'; -- fail +ERROR: duplicate key value violates unique constraint "dir_table1_pkey" +DETAIL: Key (relative_path)=(nation1) already exists. +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation2' 'nation2'; -- fail +ERROR: syntax error at or near "'nation2'" +LINE 1: COPY BINARY dir_table1 FROM STDIN 'nation2' 'nation2'; -- fa... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation2'; +NOTICE: dir_table1 INSERT AFTER ROW (seg2 127.0.1.1:7004 pid=31466) +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation3' WITH TAG 'nation'; +NOTICE: dir_table1 INSERT AFTER ROW (seg1 127.0.1.1:7003 pid=31465) +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation3' WITH TAG 'nation'; -- fail +ERROR: duplicate key value violates unique constraint "dir_table1_pkey" +DETAIL: Key (relative_path)=(nation3) already exists. +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation3' WITH TAG 'nation2'; -- fail +ERROR: duplicate key value violates unique constraint "dir_table1_pkey" +DETAIL: Key (relative_path)=(nation3) already exists. +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation4' WITH TAG 'nation'; +NOTICE: dir_table1 INSERT AFTER ROW (seg2 127.0.1.1:7004 pid=31466) +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation5' WITH TAG 'nation' WITH TAG 'nation2'; -- fail +ERROR: syntax error at or near "WITH" +LINE 1: ...dir_table1 FROM STDIN 'nation5' WITH TAG 'nation' WITH TAG '... + ^ +SELECT relative_path, size, tag FROM dir_table1 ORDER BY 1; + relative_path | size | tag +---------------+------+-------- + nation1 | 2199 | + nation2 | 2199 | + nation3 | 2199 | nation + nation4 | 2199 | nation +(4 rows) + +SELECT relative_path, content FROM directory_table('dir_table1') ORDER BY 1; + relative_path | content +---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + nation1 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a + nation2 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a + nation3 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a + nation4 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a +(4 rows) + +COPY dir_table2 FROM '@abs_srcdir@/data/nation.csv'; -- fail +ERROR: Copy from directory table file name can't be null. +COPY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation'; -- fail +ERROR: Only support copy binary from directory table. +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv'; -- fail +ERROR: Copy from directory table file name can't be null. +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation1'; +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation1'; -- fail +ERROR: duplicate key value violates unique constraint "dir_table2_pkey" +DETAIL: Key (relative_path)=(nation1) already exists. +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation2'; +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation3' WITH TAG 'nation'; +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation3' WITH TAG 'nation'; -- fail +ERROR: duplicate key value violates unique constraint "dir_table2_pkey" +DETAIL: Key (relative_path)=(nation3) already exists. +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation3' WITH TAG 'nation2'; -- fail +ERROR: duplicate key value violates unique constraint "dir_table2_pkey" +DETAIL: Key (relative_path)=(nation3) already exists. +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation4' WITH TAG 'nation'; +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation5' WITH TAG 'nation' WITH TAG 'nation2'; -- fail +ERROR: syntax error at or near "WITH" +LINE 1: ...ress/data/nation.csv' 'nation5' WITH TAG 'nation' WITH TAG '... + ^ +SELECT relative_path, size, tag FROM dir_table2 ORDER BY 1; + relative_path | size | tag +---------------+------+-------- + nation1 | 2199 | + nation2 | 2199 | + nation3 | 2199 | nation + nation4 | 2199 | nation +(4 rows) + +SELECT relative_path, content FROM directory_table('dir_table2') ORDER BY 1; + relative_path | content +---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + nation1 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a + nation2 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a + nation3 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a + nation4 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a +(4 rows) + +-- Test copy binary from directory table +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (format CSV); +ERROR: conflicting or redundant options +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (format CSV... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (freeze off); +ERROR: option "freeze" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (freeze off... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (freeze on); +ERROR: option "freeze" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (freeze on)... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (delimiter ','); +ERROR: option "delimiter" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (delimiter ... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (null ' '); +ERROR: option "null" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (null ' '); + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (header off); +ERROR: option "header" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (header off... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (header on); +ERROR: option "header" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (header on)... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (quote ':'); +ERROR: option "quote" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (quote ':')... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (escape ':'); +ERROR: option "escape" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (escape ':'... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_quote (a)); +ERROR: option "force_quote" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (force_quot... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_quote *); +ERROR: option "force_quote" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (force_quot... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_not_null (a)); +ERROR: option "force_not_null" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (force_not_... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_null (a)); +ERROR: option "force_null" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (force_null... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (convert_selectively (a)); +ERROR: option "convert_selectively" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (convert_se... + ^ +\COPY BINARY dir_table1 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (encoding 'sql_ascii'); +ERROR: option "encoding" not recognized +LINE 1: ...OPY BINARY dir_table1 FROM STDIN 'nation_failed' (encoding '... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (format CSV); +ERROR: conflicting or redundant options +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (format CSV... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (freeze off); +ERROR: option "freeze" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (freeze off... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (freeze on); +ERROR: option "freeze" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (freeze on)... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (delimiter ','); +ERROR: option "delimiter" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (delimiter ... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (null ' '); +ERROR: option "null" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (null ' '); + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (header off); +ERROR: option "header" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (header off... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (header on); +ERROR: option "header" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (header on)... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (quote ':'); +ERROR: option "quote" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (quote ':')... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (escape ':'); +ERROR: option "escape" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (escape ':'... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_quote (a)); +ERROR: option "force_quote" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (force_quot... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_quote *); +ERROR: option "force_quote" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (force_quot... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_not_null (a)); +ERROR: option "force_not_null" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (force_not_... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (force_null (a)); +ERROR: option "force_null" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (force_null... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (convert_selectively (a)); +ERROR: option "convert_selectively" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (convert_se... + ^ +COPY BINARY dir_table2 FROM '@abs_srcdir@/data/nation.csv' 'nation_failed' (encoding 'sql_ascii'); +ERROR: option "encoding" not recognized +LINE 1: ...rc/test/regress/data/nation.csv' 'nation_failed' (encoding '... + ^ +-- Test copy file content md5 +CREATE OR REPLACE FUNCTION file_content(text, text) RETURNS BYTEA LANGUAGE SQL AS +'select content from directory_table($1) where relative_path = $2'; +CREATE OR REPLACE FUNCTION file_md5(text, text) RETURNS TEXT LANGUAGE SQL AS +'select md5 from directory_table($1) where relative_path = $2'; +CREATE OR REPLACE FUNCTION md5_equal(text, text) RETURNS BOOL LANGUAGE SQL AS +'SELECT md5(file_content($1, $2)) = (SELECT file_md5($1, $2))'; +SELECT md5_equal('dir_table1', 'nation1'); + md5_equal +----------- + t +(1 row) + +SELECT md5_equal('dir_table1', 'nation2'); + md5_equal +----------- + t +(1 row) + +SELECT md5_equal('dir_table1', 'nation3'); + md5_equal +----------- + t +(1 row) + +SELECT md5_equal('dir_table1', 'nation4'); + md5_equal +----------- + t +(1 row) + +SELECT md5_equal('dir_table2', 'nation1'); + md5_equal +----------- + t +(1 row) + +SELECT md5_equal('dir_table2', 'nation2'); + md5_equal +----------- + t +(1 row) + +SELECT md5_equal('dir_table2', 'nation3'); + md5_equal +----------- + t +(1 row) + +SELECT md5_equal('dir_table2', 'nation4'); + md5_equal +----------- + t +(1 row) + +-- Does not support copy to +\COPY dir_table1 TO '@abs_srcdir@/data/dir_table1'; -- fail +ERROR: cannot copy from non-table relation "dir_table1" +\COPY BINARY dir_table1 TO '@abs_srcdir@/data/dir_table1'; -- fail +ERROR: cannot copy from non-table relation "dir_table1" +COPY dir_table1 TO '@abs_srcdir@/data/dir_table1'; -- fail +ERROR: cannot copy from non-table relation "dir_table1" +COPY BINARY dir_table1 TO '@abs_srcdir@/data/dir_table1'; -- fail +ERROR: cannot copy from non-table relation "dir_table1" +\COPY dir_table2 TO '@abs_srcdir@/data/dir_table2'; -- fail +ERROR: cannot copy from non-table relation "dir_table2" +\COPY BINARY dir_table2 TO '@abs_srcdir@/data/dir_table2'; -- fail +ERROR: cannot copy from non-table relation "dir_table2" +COPY dir_table2 TO '@abs_srcdir@/data/dir_table2'; -- fail +ERROR: cannot copy from non-table relation "dir_table2" +COPY BINARY dir_table2 TO '@abs_srcdir@/data/dir_table2'; -- fail +ERROR: cannot copy from non-table relation "dir_table2" +SELECT relative_path, size, tag FROM dir_table1 ORDER BY 1; + relative_path | size | tag +---------------+------+-------- + nation1 | 2199 | + nation2 | 2199 | + nation3 | 2199 | nation + nation4 | 2199 | nation +(4 rows) + +SELECT relative_path, size, tag FROM dir_table2 ORDER BY 1; + relative_path | size | tag +---------------+------+-------- + nation1 | 2199 | + nation2 | 2199 | + nation3 | 2199 | nation + nation4 | 2199 | nation +(4 rows) + +-- Test join between two directory schema tables +ANALYZE dir_table1; +ANALYZE dir_table2; +EXPLAIN (COSTS OFF) SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.relative_path = dir_table2.relative_path ORDER BY 1; + QUERY PLAN +---------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Merge Key: dir_table1.relative_path + -> Sort + Sort Key: dir_table1.relative_path + -> Nested Loop + Join Filter: true + -> Seq Scan on dir_table1 + -> Index Scan using dir_table2_pkey on dir_table2 + Index Cond: (relative_path = dir_table1.relative_path) + Optimizer: Pivotal Optimizer (GPORCA) +(10 rows) + +SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.relative_path = dir_table2.relative_path ORDER BY 1; + relative_path +--------------- + nation1 + nation2 + nation3 + nation4 +(4 rows) + +EXPLAIN (COSTS OFF) SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.size = dir_table2.size ORDER BY 1 LIMIT 1; + QUERY PLAN +--------------------------------------------------------------------------------- + Limit + -> Gather Motion 3:1 (slice1; segments: 3) + Merge Key: dir_table1.relative_path + -> Limit + -> Sort + Sort Key: dir_table1.relative_path + -> Hash Join + Hash Cond: (dir_table1.size = dir_table2.size) + -> Seq Scan on dir_table1 + -> Hash + -> Broadcast Motion 3:3 (slice2; segments: 3) + -> Seq Scan on dir_table2 + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.size = dir_table2.size ORDER BY 1 LIMIT 1; + relative_path +--------------- + nation1 +(1 row) + +EXPLAIN (COSTS OFF) SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.md5 = dir_table2.md5 ORDER BY 1 LIMIT 1; + QUERY PLAN +------------------------------------------------------------------ + Limit + -> Sort + Sort Key: dir_table1.relative_path + -> Hash Join + Hash Cond: (dir_table1.md5 = dir_table2.md5) + -> Gather Motion 3:1 (slice1; segments: 3) + -> Seq Scan on dir_table1 + -> Hash + -> Gather Motion 3:1 (slice2; segments: 3) + -> Seq Scan on dir_table2 + Optimizer: Pivotal Optimizer (GPORCA) +(11 rows) + +SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.md5 = dir_table2.md5 ORDER BY 1 LIMIT 1; + relative_path +--------------- + nation1 +(1 row) + +EXPLAIN (COSTS OFF) SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.tag = dir_table2.tag ORDER BY 1; + QUERY PLAN +------------------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Merge Key: dir_table1.relative_path + -> Sort + Sort Key: dir_table1.relative_path + -> Hash Join + Hash Cond: (dir_table1.tag = dir_table2.tag) + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: dir_table1.tag + -> Seq Scan on dir_table1 + -> Hash + -> Redistribute Motion 3:3 (slice3; segments: 3) + Hash Key: dir_table2.tag + -> Seq Scan on dir_table2 + Optimizer: Pivotal Optimizer (GPORCA) +(14 rows) + +SELECT dir_table1.relative_path FROM dir_table1, dir_table2 +WHERE dir_table1.tag = dir_table2.tag ORDER BY 1; + relative_path +--------------- + nation3 + nation3 + nation4 + nation4 +(4 rows) + +-- Test DML directory schema table, only allow to update tag +INSERT INTO dir_table1 VALUES('insert'); -- fail +ERROR: cannot change directory table "dir_table1" +INSERT INTO dir_table2 VALUES('insert', 512, '2000-03-21 17:13:27+08', '70f09140d1b83eb3ecf9a0e28494d2a4', 'insert'); -- fail +ERROR: cannot change directory table "dir_table2" +SELECT relative_path, size, tag FROM dir_table1 ORDER BY 1; + relative_path | size | tag +---------------+------+-------- + nation1 | 2199 | + nation2 | 2199 | + nation3 | 2199 | nation + nation4 | 2199 | nation +(4 rows) + +SELECT relative_path, size, tag FROM dir_table2 ORDER BY 1; + relative_path | size | tag +---------------+------+-------- + nation1 | 2199 | + nation2 | 2199 | + nation3 | 2199 | nation + nation4 | 2199 | nation +(4 rows) + +DELETE FROM dir_table1; -- fail +ERROR: cannot change directory table "dir_table1" +DELETE FROM dir_table2 WHERE relative_path = 'nation1'; -- fail +ERROR: cannot change directory table "dir_table2" +SELECT relative_path, size, tag FROM dir_table1 ORDER BY 1; + relative_path | size | tag +---------------+------+-------- + nation1 | 2199 | + nation2 | 2199 | + nation3 | 2199 | nation + nation4 | 2199 | nation +(4 rows) + +SELECT relative_path, size, tag FROM dir_table2 ORDER BY 1; + relative_path | size | tag +---------------+------+-------- + nation1 | 2199 | + nation2 | 2199 | + nation3 | 2199 | nation + nation4 | 2199 | nation +(4 rows) + +UPDATE dir_table1 SET relative_path = 'nation_updated'; -- fail +ERROR: UPDATE on distributed key column not allowed on relation with update triggers +UPDATE dir_table2 SET relative_path = 'nation_updated' WHERE relative_path = 'nation2'; -- fail +ERROR: Only allow to update directory "tag" column. +UPDATE dir_table1 SET size = 512; -- fail +ERROR: Only allow to update directory "tag" column. +UPDATE dir_table2 SET size = 1024 WHERE relative_path = 'nation1'; -- fail +ERROR: Only allow to update directory "tag" column. +UPDATE dir_table1 SET last_modified = '2000-03-21 16:55:07+08'; -- fail +ERROR: Only allow to update directory "tag" column. +UPDATE dir_table2 SET last_modified = '2000-03-21 16:55:07+08' WHERE relative_path = 'nation3'; -- fail +ERROR: Only allow to update directory "tag" column. +UPDATE dir_table1 SET md5 = '70f09140d1b83eb3ecf9a0e28494d2a4'; -- fail +ERROR: Only allow to update directory "tag" column. +UPDATE dir_table2 SET md5 = '70f09140d1b83eb3ecf9a0e28494d2a4' WHERE relative_path = 'nation4'; -- fail +ERROR: Only allow to update directory "tag" column. +UPDATE dir_table1 SET tag = 'nation_new_tag'; -- ok +NOTICE: dir_table1 UPDATE BEFORE ROW (seg1 127.0.1.1:7003 pid=31465) +NOTICE: dir_table1 UPDATE BEFORE ROW (seg1 127.0.1.1:7003 pid=31465) +NOTICE: dir_table1 UPDATE BEFORE ROW (seg2 127.0.1.1:7004 pid=31466) +NOTICE: dir_table1 UPDATE BEFORE ROW (seg2 127.0.1.1:7004 pid=31466) +NOTICE: dir_table1 UPDATE AFTER ROW (seg2 127.0.1.1:7004 pid=31466) +NOTICE: dir_table1 UPDATE AFTER ROW (seg1 127.0.1.1:7003 pid=31465) +NOTICE: dir_table1 UPDATE AFTER ROW (seg1 127.0.1.1:7003 pid=31465) +NOTICE: dir_table1 UPDATE AFTER ROW (seg2 127.0.1.1:7004 pid=31466) +UPDATE dir_table1 SET tag = 'nation2_new_tag' WHERE relative_path = 'nation2'; -- ok +NOTICE: dir_table1 UPDATE BEFORE ROW (seg2 127.0.1.1:7004 pid=31466) +NOTICE: dir_table1 UPDATE AFTER ROW (seg2 127.0.1.1:7004 pid=31466) +UPDATE dir_table2 SET tag = 'nation4_new_tag' WHERE relative_path = 'nation3'; -- ok +UPDATE dir_table1 SET tag = 'failed_tag' WHERE relative_path = 'not_exist_path'; +UPDATE dir_table2 SET tag = 'no_tag' WHERE relative_path = 'not_exist_path'; +SELECT relative_path, size, tag FROM dir_table1 ORDER BY 1; + relative_path | size | tag +---------------+------+----------------- + nation1 | 2199 | nation_new_tag + nation2 | 2199 | nation2_new_tag + nation3 | 2199 | nation_new_tag + nation4 | 2199 | nation_new_tag +(4 rows) + +SELECT relative_path, size, tag FROM dir_table2 ORDER BY 1; + relative_path | size | tag +---------------+------+----------------- + nation1 | 2199 | + nation2 | 2199 | + nation3 | 2199 | nation4_new_tag + nation4 | 2199 | nation +(4 rows) + +-- Test alter table directory schema table +ALTER TABLE dir_table1 ADD COLUMN a int; -- fail +ERROR: "dir_table1" is not a table, composite type, or foreign table +ALTER DIRECTORY TABLE dir_table1 ADD COLUMN a int; -- fail +ERROR: syntax error at or near "DIRECTORY" +LINE 1: ALTER DIRECTORY TABLE dir_table1 ADD COLUMN a int; + ^ +ALTER TABLE dir_table2 DROP COLUMN relative_path; -- fail +ERROR: "dir_table2" is not a table, composite type, or foreign table +ALTER DIRECTORY TABLE dir_table2 DROP COLUMN relative_path; -- fail +ERROR: syntax error at or near "DIRECTORY" +LINE 1: ALTER DIRECTORY TABLE dir_table2 DROP COLUMN relative_path; + ^ +ALTER TABLE dir_table1 RENAME TO dir_table_new; -- fail +ERROR: Rename directory table is not allowed. +ALTER DIRECTORY TABLE dir_table1 RENAME TO dir_table_new; -- fail +ERROR: syntax error at or near "DIRECTORY" +LINE 1: ALTER DIRECTORY TABLE dir_table1 RENAME TO dir_table_new; + ^ +ALTER TABLE dir_table2 ADD CONSTRAINT dirtable_constraint UNIQUE (tag); -- fail +ERROR: "dir_table2" is not a table or foreign table +ALTER DIRECTORY TABLE dir_table2 ADD CONSTRAINT dirtable_constraint UNIQUE (tag); -- fail +ERROR: syntax error at or near "DIRECTORY" +LINE 1: ALTER DIRECTORY TABLE dir_table2 ADD CONSTRAINT dirtable_con... + ^ +ALTER TABLE dir_table1 DROP CONSTRAINT DROP CONSTRAINT test_pkey; -- fail +ERROR: syntax error at or near "CONSTRAINT" +LINE 1: ALTER TABLE dir_table1 DROP CONSTRAINT DROP CONSTRAINT test_... + ^ +ALTER DIRECTORY TABLE dir_table1 DROP CONSTRAINT DROP CONSTRAINT test_pkey; -- fail +ERROR: syntax error at or near "DIRECTORY" +LINE 1: ALTER DIRECTORY TABLE dir_table1 DROP CONSTRAINT DROP CONSTR... + ^ +-- Test remove_table +SELECT remove_file('dir_table1', 'nation5'); -- fail + remove_file +------------- + f +(1 row) + +SELECT remove_file('dir_table1', 'nation1'); + remove_file +------------- + t +(1 row) + +SELECT remove_file('dir_table2', 'nation1', 'nation2'); -- fail +ERROR: function remove_file(unknown, unknown, unknown) does not exist +LINE 1: SELECT remove_file('dir_table2', 'nation1', 'nation2'); + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +SELECT remove_file('dir_table1', 'nation2'); + remove_file +------------- + t +(1 row) + +SELECT remove_file('dir_table3', 'nation1'); -- fail + remove_file +------------- + f +(1 row) + +SELECT remove_file('dir_table2', 'nation3'); + remove_file +------------- + t +(1 row) + +SELECT remove_file('dir_table1', 'nation1'); -- fail + remove_file +------------- + f +(1 row) + +SELECT relative_path, size, tag FROM dir_table1 ORDER BY 1; + relative_path | size | tag +---------------+------+---------------- + nation3 | 2199 | nation_new_tag + nation4 | 2199 | nation_new_tag +(2 rows) + +SELECT relative_path, size, tag FROM dir_table2 ORDER BY 1; + relative_path | size | tag +---------------+------+-------- + nation1 | 2199 | + nation2 | 2199 | + nation4 | 2199 | nation +(3 rows) + +-- Test transaction commit of directory table manipulation +CREATE DIRECTORY TABLE dir_table4 TABLESPACE directory_tblspc; +BEGIN; +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_commit'; +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_commit2' WITH TAG 'nation'; +COMMIT; +SELECT relative_path, content FROM directory_table('dir_table4') ORDER BY 1; + relative_path | content +----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + nation_commit | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a + nation_commit2 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a +(2 rows) + +BEGIN; +SELECT remove_file('dir_table4', 'nation_commit'); + remove_file +------------- + t +(1 row) + +SELECT relative_path, content FROM directory_table('dir_table4') ORDER BY 1; + relative_path | content +----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + nation_commit2 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a +(1 row) + +COMMIT; +SELECT relative_path, content FROM directory_table('dir_table4') ORDER BY 1; + relative_path | content +----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + nation_commit2 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a +(1 row) + +BEGIN; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +----------------+-------- + nation_commit2 | nation +(1 row) + +UPDATE dir_table4 SET tag = 'nation_updated' WHERE relative_path = 'nation_commit2'; +COMMIT; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +----------------+---------------- + nation_commit2 | nation_updated +(1 row) + +-- Test transaction rollback of directory table manipulation +BEGIN; +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_rollback'; +SELECT relative_path, content FROM directory_table('dir_table4') ORDER BY 1; + relative_path | content +-----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + nation_commit2 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a + nation_rollback | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a +(2 rows) + +ROLLBACK; +SELECT relative_path, content FROM directory_table('dir_table4') ORDER BY 1; + relative_path | content +----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + nation_commit2 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a +(1 row) + +BEGIN; +SELECT remove_file('dir_table4', 'nation_commit2'); + remove_file +------------- + t +(1 row) + +SELECT relative_path, content FROM directory_table('dir_table4') ORDER BY 1; + relative_path | content +---------------+--------- +(0 rows) + +ROLLBACK; +SELECT relative_path, content FROM directory_table('dir_table4') ORDER BY 1; + relative_path | content +----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + nation_commit2 | \x307c414c47455249417c307c20686167676c652e206361726566756c6c792066696e616c206465706f736974732064657465637420736c796c7920616761690a317c415247454e54494e417c317c616c20666f7865732070726f6d69736520736c796c79206163636f7264696e6720746f2074686520726567756c6172206163636f756e74732e20626f6c6420726571756573747320616c6f6e0a327c4252415a494c7c317c7920616c6f6e6773696465206f66207468652070656e64696e67206465706f736974732e206361726566756c6c79207370656369616c207061636b61676573206172652061626f7574207468652069726f6e696320666f726765732e20736c796c79207370656369616c200a337c43414e4144417c317c6561732068616e672069726f6e69632c2073696c656e74207061636b616765732e20736c796c7920726567756c6172207061636b616765732061726520667572696f75736c79206f76657220746865207469746865732e20666c756666696c7920626f6c640a347c45475950547c347c792061626f766520746865206361726566756c6c7920756e757375616c207468656f646f6c697465732e2066696e616c206475676f7574732061726520717569636b6c79206163726f73732074686520667572696f75736c7920726567756c617220640a357c455448494f5049417c307c76656e207061636b616765732077616b6520717569636b6c792e20726567750a367c4652414e43457c337c726566756c6c792066696e616c2072657175657374732e20726567756c61722c2069726f6e690a377c4745524d414e597c337c6c20706c6174656c6574732e20726567756c6172206163636f756e747320782d7261793a20756e757375616c2c20726567756c6172206163636f0a387c494e4449417c327c737320657863757365732063616a6f6c6520736c796c79206163726f737320746865207061636b616765732e206465706f73697473207072696e742061726f756e0a397c494e444f4e455349417c327c20736c796c792065787072657373206173796d70746f7465732e20726567756c6172206465706f7369747320686167676c6520736c796c792e206361726566756c6c792069726f6e696320686f636b657920706c617965727320736c65657020626c697468656c792e206361726566756c6c0a31307c4952414e7c347c6566756c6c7920616c6f6e6773696465206f662074686520736c796c792066696e616c20646570656e64656e636965732e200a31317c495241517c347c6e6963206465706f7369747320626f6f73742061746f702074686520717569636b6c792066696e616c2072657175657374733f20717569636b6c7920726567756c610a31327c4a4150414e7c327c6f75736c792e2066696e616c2c20657870726573732067696674732063616a6f6c6520610a31337c4a4f5244414e7c347c6963206465706f736974732061726520626c697468656c792061626f757420746865206361726566756c6c7920726567756c61722070610a31347c4b454e59417c307c2070656e64696e67206578637573657320686167676c6520667572696f75736c79206465706f736974732e2070656e64696e672c20657870726573732070696e746f206265616e732077616b6520666c756666696c79207061737420740a31357c4d4f524f43434f7c307c726e732e20626c697468656c7920626f6c6420636f7572747320616d6f6e672074686520636c6f73656c7920726567756c6172207061636b616765732075736520667572696f75736c7920626f6c6420706c6174656c6574733f0a31367c4d4f5a414d42495155457c307c732e2069726f6e69632c20756e757375616c206173796d70746f7465732077616b6520626c697468656c7920720a31377c504552557c317c706c6174656c6574732e20626c697468656c792070656e64696e6720646570656e64656e636965732075736520666c756666696c79206163726f737320746865206576656e2070696e746f206265616e732e206361726566756c6c792073696c656e74206163636f756e0a31387c4348494e417c327c6320646570656e64656e636965732e20667572696f75736c792065787072657373206e6f746f726e697320736c65657020736c796c7920726567756c6172206163636f756e74732e20696465617320736c6565702e206465706f730a31397c524f4d414e49417c337c756c6172206173796d70746f746573206172652061626f75742074686520667572696f7573206d756c7469706c696572732e206578707265737320646570656e64656e63696573206e61672061626f7665207468652069726f6e6963616c6c792069726f6e6963206163636f756e740a32307c5341554449204152414249417c347c74732e2073696c656e7420726571756573747320686167676c652e20636c6f73656c792065787072657373207061636b6167657320736c656570206163726f73732074686520626c697468656c790a32317c564945544e414d7c327c68656c7920656e746963696e676c792065787072657373206163636f756e74732e206576656e2c2066696e616c200a32327c5255535349417c337c20726571756573747320616761696e73742074686520706c6174656c65747320757365206e65766572206163636f7264696e6720746f2074686520717569636b6c7920726567756c61722070696e740a32337c554e49544544204b494e47444f4d7c337c65616e7320626f6f7374206361726566756c6c79207370656369616c2072657175657374732e206163636f756e7473206172652e206361726566756c6c0a32347c554e49544544205354415445537c317c792066696e616c207061636b616765732e20736c6f7720666f7865732063616a6f6c6520717569636b6c792e20717569636b6c792073696c656e7420706c6174656c657473206272656163682069726f6e6963206163636f756e74732e20756e757375616c2070696e746f2062650a +(1 row) + +BEGIN; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +----------------+---------------- + nation_commit2 | nation_updated +(1 row) + +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_rollback2' WITH TAG 'nation'; +UPDATE dir_table4 SET tag = 'nation_updated' WHERE relative_path = 'nation_rollback2'; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +------------------+---------------- + nation_commit2 | nation_updated + nation_rollback2 | nation_updated +(2 rows) + +ROLLBACK; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +----------------+---------------- + nation_commit2 | nation_updated +(1 row) + +-- Test subtransaction commit of directory table manipulation +BEGIN; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +----------------+---------------- + nation_commit2 | nation_updated +(1 row) + +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subcommit' WITH TAG 'nation'; +SAVEPOINT s1; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit | nation +(2 rows) + +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subcommit2'; +SAVEPOINT s2; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit | nation + nation_subcommit2 | +(3 rows) + +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subcommit3'; +RELEASE SAVEPOINT s1; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit | nation + nation_subcommit2 | + nation_subcommit3 | +(4 rows) + +COMMIT; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit | nation + nation_subcommit2 | + nation_subcommit3 | +(4 rows) + +BEGIN; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit | nation + nation_subcommit2 | + nation_subcommit3 | +(4 rows) + +SELECT remove_file('dir_table4', 'nation_subcommit'); + remove_file +------------- + t +(1 row) + +SAVEPOINT s1; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit2 | + nation_subcommit3 | +(3 rows) + +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subcommit'; +SAVEPOINT s2; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit | + nation_subcommit2 | + nation_subcommit3 | +(4 rows) + +RELEASE SAVEPOINT s1; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit | + nation_subcommit2 | + nation_subcommit3 | +(4 rows) + +COMMIT; +BEGIN; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit | + nation_subcommit2 | + nation_subcommit3 | +(4 rows) + +SELECT remove_file('dir_table4', 'nation_subcommit'); + remove_file +------------- + t +(1 row) + +SAVEPOINT s1; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit2 | + nation_subcommit3 | +(3 rows) + +SELECT remove_file('dir_table4', 'nation_subcommit2'); + remove_file +------------- + t +(1 row) + +SAVEPOINT s2; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | +(2 rows) + +RELEASE SAVEPOINT s2; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | +(2 rows) + +COMMIT; +BEGIN; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | +(2 rows) + +SELECT remove_file('dir_table4', 'nation_subcommit2'); + remove_file +------------- + f +(1 row) + +SAVEPOINT s1; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | +(2 rows) + +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subcommit4'; +SAVEPOINT s2; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +-------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | + nation_subcommit4 | +(3 rows) + +ROLLBACK TO SAVEPOINT s1; +COMMIT; +-- Test subtransaction rollback of directory table manipulation +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subrollback1'; +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subrollback2'; +BEGIN; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +---------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | + nation_subrollback1 | + nation_subrollback2 | +(4 rows) + +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subrollback3'; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +---------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | + nation_subrollback1 | + nation_subrollback2 | + nation_subrollback3 | +(5 rows) + +SAVEPOINT s1; +SELECT remove_file('dir_table4', 'nation_subrollback1'); + remove_file +------------- + t +(1 row) + +SAVEPOINT s2; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +---------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | + nation_subrollback2 | + nation_subrollback3 | +(4 rows) + +ROLLBACK; +BEGIN; +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subrollback4'; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +---------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | + nation_subrollback1 | + nation_subrollback2 | + nation_subrollback4 | +(5 rows) + +SAVEPOINT s1; +SELECT remove_file('dir_table4', 'nation_subrollback4'); + remove_file +------------- + t +(1 row) + +SAVEPOINT s2; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +---------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | + nation_subrollback1 | + nation_subrollback2 | +(4 rows) + +RELEASE SAVEPOINT s1; +ROLLBACK; +BEGIN; +SELECT remove_file('dir_table4', 'nation_subrollback2'); + remove_file +------------- + t +(1 row) + +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subrollback5'; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +---------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | + nation_subrollback1 | + nation_subrollback5 | +(4 rows) + +SAVEPOINT s1; +SELECT remove_file('dir_table4', 'nation_subrollback5'); + remove_file +------------- + t +(1 row) + +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +---------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | + nation_subrollback1 | +(3 rows) + +ROLLBACK TO SAVEPOINT s1; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +---------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | + nation_subrollback1 | + nation_subrollback5 | +(4 rows) + +COPY BINARY dir_table4 FROM '@abs_srcdir@/data/nation.csv' 'nation_subrollback6'; +SELECT relative_path, tag FROM dir_table4 ORDER BY 1; + relative_path | tag +---------------------+---------------- + nation_commit2 | nation_updated + nation_subcommit3 | + nation_subrollback1 | + nation_subrollback5 | + nation_subrollback6 | +(5 rows) + +SAVEPOINT s2; +ROLLBACK; +-- clean up +DROP DIRECTORY TABLE IF EXISTS dir_table1; +DROP DIRECTORY TABLE IF EXISTS dir_table2; +DROP DIRECTORY TABLE IF EXISTS dir_table3; +DROP DIRECTORY TABLE IF EXISTS dir_table4; +DROP DIRECTORY TABLE IF EXISTS dir_table5; +NOTICE: directory table "dir_table5" does not exist, skipping +DROP DIRECTORY TABLE IF EXISTS dir_table6; +DROP FUNCTION IF EXISTS trigtest; +DROP STORAGE USER MAPPING IF EXISTS FOR CURRENT_USER STORAGE SERVER oss_server1; +DROP STORAGE USER MAPPING IF EXISTS FOR CURRENT_USER STORAGE SERVER oss_server2; +NOTICE: storage user mapping for "gpadmin" does not exist for storage server "oss_server2", skipping +DROP STORAGE USER MAPPING IF EXISTS FOR CURRENT_USER STORAGE SERVER oss_server3; +DROP STORAGE USER MAPPING IF EXISTS FOR CURRENT_USER STORAGE SERVER oss_server4; +NOTICE: storage server "oss_server4" does not exist, skipping +DROP STORAGE USER MAPPING IF EXISTS FOR test_dirtable1 STORAGE SERVER oss_server1; +NOTICE: storage user mapping for "test_dirtable1" does not exist for storage server "oss_server1", skipping +DROP STORAGE USER MAPPING IF EXISTS FOR test_dirtable1 STORAGE SERVER oss_server2; +DROP STORAGE USER MAPPING IF EXISTS FOR test_dirtable1 STORAGE SERVER oss_server3; +DROP STORAGE USER MAPPING IF EXISTS FOR test_dirtable2 STORAGE SERVER oss_server3; +DROP STORAGE USER MAPPING IF EXISTS FOR test_dirtable3 STORAGE SERVER oss_server8; +DROP STORAGE SERVER IF EXISTS oss_server1; +DROP STORAGE SERVER IF EXISTS oss_server2; +DROP STORAGE SERVER IF EXISTS oss_server3; +DROP STORAGE SERVER IF EXISTS oss_server4; +NOTICE: storage server "oss_server4" not exists, skipping +DROP STORAGE SERVER IF EXISTS oss_server5; +DROP STORAGE SERVER IF EXISTS oss_server6; +DROP STORAGE SERVER IF EXISTS oss_server7; +DROP STORAGE SERVER IF EXISTS oss_server8; +DROP STORAGE SERVER IF EXISTS oss_server9; +NOTICE: storage server "oss_server9" not exists, skipping +DROP STORAGE SERVER IF EXISTS oss_server10; +NOTICE: storage server "oss_server10" not exists, skipping +DROP STORAGE SERVER IF EXISTS oss_server11; +DROP STORAGE SERVER IF EXISTS oss_server12; +DROP STORAGE SERVER IF EXISTS oss_server13; +NOTICE: storage server "oss_server13" not exists, skipping +SELECT srvname, srvacl, srvoptions FROM gp_storage_server; + srvname | srvacl | srvoptions +---------+--------+------------ +(0 rows) + +DROP USER test_dirtable1; +DROP USER test_dirtable2; +DROP USER test_dirtable3; +DROP USER test_dirtable4; +DROP FUNCTION IF EXISTS file_content; +DROP FUNCTION IF EXISTS file_md5; +DROP FUNCTION IF EXISTS md5_equal; +DROP DATABASE dirtable_db; +DROP TRIGGER IF EXISTS trigtest_b_row_tg_dirtable_1 ON dir_table1; +NOTICE: relation "dir_table1" does not exist, skipping +DROP TRIGGER IF EXISTS trigtest_a_row_tg_dirtable_1 ON dir_table1; +NOTICE: relation "dir_table1" does not exist, skipping +DROP TRIGGER IF EXISTS trigtest_b_stmt_tg_dirtable_1 ON dir_table1; +NOTICE: relation "dir_table1" does not exist, skipping +DROP TRIGGER IF EXISTS trigtest_a_stmt_tg_dirtable_1 ON dir_table1; +NOTICE: relation "dir_table1" does not exist, skipping +DROP TABLESPACE directory_tblspc; diff --git a/src/test/regress/output/external_table.source b/src/test/regress/output/external_table.source index 61ea2c938af..bcea4533111 100644 --- a/src/test/regress/output/external_table.source +++ b/src/test/regress/output/external_table.source @@ -4896,7 +4896,7 @@ DROP TABLE test_part_integrity; -- Testing altering the distribution policy of external tables. CREATE WRITABLE EXTERNAL WEB TABLE ext_w_dist(a int, b int) EXECUTE 'cat > @abs_srcdir@/data/ext_w_dist.tbl' FORMAT 'TEXT' (DELIMITER AS '|' NULL AS 'null' ESCAPE AS ' ') DISTRIBUTED BY (a); ALTER TABLE ext_w_dist SET WITH (reorganize=true); -- should error out if forcing reorganize -ERROR: "ext_w_dist" is not a table +ERROR: "ext_w_dist" is not a table or directory table SELECT policytype, distkey FROM gp_distribution_policy WHERE localoid = 'ext_w_dist'::regclass; policytype | distkey ------------+--------- @@ -4904,7 +4904,7 @@ SELECT policytype, distkey FROM gp_distribution_policy WHERE localoid = 'ext_w_d (1 row) ALTER TABLE ext_w_dist SET DISTRIBUTED BY (b); -ERROR: "ext_w_dist" is not a table +ERROR: "ext_w_dist" is not a table or directory table SELECT policytype, distkey FROM gp_distribution_policy WHERE localoid = 'ext_w_dist'::regclass; policytype | distkey ------------+--------- @@ -4912,7 +4912,7 @@ SELECT policytype, distkey FROM gp_distribution_policy WHERE localoid = 'ext_w_d (1 row) ALTER TABLE ext_w_dist SET DISTRIBUTED RANDOMLY; -ERROR: "ext_w_dist" is not a table +ERROR: "ext_w_dist" is not a table or directory table SELECT policytype, distkey FROM gp_distribution_policy WHERE localoid = 'ext_w_dist'::regclass; policytype | distkey ------------+--------- @@ -4923,7 +4923,7 @@ CREATE EXTERNAL WEB TABLE ext_r_dist(a int) EXECUTE 'printf ${GP_SEGMENT_ID}' FO ERROR: readable external tables can't specify a DISTRIBUTED BY clause CREATE EXTERNAL WEB TABLE ext_r_dist(a int) EXECUTE 'printf ${GP_SEGMENT_ID}' FORMAT 'TEXT'; ALTER TABLE ext_r_dist SET DISTRIBUTED BY (a); -- should error out altering readable external tables' distribution policy -ERROR: "ext_r_dist" is not a table +ERROR: "ext_r_dist" is not a table or directory table -- Testing external table as the partition child. CREATE TABLE part_root(a int) PARTITION BY RANGE(a); CREATE TABLE part_child (LIKE part_root); @@ -4941,7 +4941,7 @@ SELECT policytype, distkey FROM gp_distribution_policy WHERE localoid = 'part_ex (1 row) ALTER TABLE part_root SET DISTRIBUTED BY (b); -ERROR: "part_ext_w" is not a table +ERROR: "part_ext_w" is not a table or directory table SELECT policytype, distkey FROM gp_distribution_policy WHERE localoid = 'part_ext_w'::regclass; policytype | distkey ------------+--------- diff --git a/src/test/singlenode_regress/expected/create_index.out b/src/test/singlenode_regress/expected/create_index.out index 60cc25a1609..3e561402a61 100644 --- a/src/test/singlenode_regress/expected/create_index.out +++ b/src/test/singlenode_regress/expected/create_index.out @@ -2372,14 +2372,14 @@ SELECT relid, parentrelid, level FROM pg_partition_tree('concur_reindex_part_ind -- REINDEX TABLE fails for partitioned indexes -- Top-most parent index REINDEX TABLE concur_reindex_part_index; -- error -ERROR: "concur_reindex_part_index" is not a table or materialized view +ERROR: "concur_reindex_part_index" is not a table, directory table or materialized view REINDEX TABLE CONCURRENTLY concur_reindex_part_index; -- error -ERROR: "concur_reindex_part_index" is not a table or materialized view +ERROR: "concur_reindex_part_index" is not a table, directory table or materialized view -- Partitioned index with no leaves REINDEX TABLE concur_reindex_part_index_10; -- error -ERROR: "concur_reindex_part_index_10" is not a table or materialized view +ERROR: "concur_reindex_part_index_10" is not a table, directory table or materialized view REINDEX TABLE CONCURRENTLY concur_reindex_part_index_10; -- error -ERROR: "concur_reindex_part_index_10" is not a table or materialized view +ERROR: "concur_reindex_part_index_10" is not a table, directory table or materialized view -- Cannot run in a transaction block BEGIN; REINDEX INDEX concur_reindex_part_index; diff --git a/src/test/singlenode_regress/expected/create_table_like.out b/src/test/singlenode_regress/expected/create_table_like.out index e308771620e..f7544b7e2d1 100644 --- a/src/test/singlenode_regress/expected/create_table_like.out +++ b/src/test/singlenode_regress/expected/create_table_like.out @@ -504,7 +504,7 @@ DROP TABLE noinh_con_copy, noinh_con_copy1; CREATE TABLE ctlt4 (a int, b text); CREATE SEQUENCE ctlseq1; CREATE TABLE ctlt10 (LIKE ctlseq1); -- fail -ERROR: "ctlseq1" is not a table, view, materialized view, composite type, or foreign table +ERROR: "ctlseq1" is not a table, directory table, view, materialized view, composite type, or foreign table LINE 1: CREATE TABLE ctlt10 (LIKE ctlseq1); ^ CREATE VIEW ctlv1 AS SELECT * FROM ctlt4; diff --git a/src/test/singlenode_regress/expected/oidjoins.out b/src/test/singlenode_regress/expected/oidjoins.out index 8ef30c843c7..4d6ad39fbb8 100644 --- a/src/test/singlenode_regress/expected/oidjoins.out +++ b/src/test/singlenode_regress/expected/oidjoins.out @@ -142,6 +142,9 @@ NOTICE: checking pg_largeobject {loid} => pg_largeobject_metadata {oid} NOTICE: checking pg_aggregate {aggfnoid} => pg_proc {oid} NOTICE: checking pg_aggregate {aggtransfn} => pg_proc {oid} NOTICE: checking pg_aggregate {aggfinalfn} => pg_proc {oid} +NOTICE: checking gp_storage_server {srvowner} => pg_authid {oid} +NOTICE: checking gp_storage_user_mapping {umserver} => gp_storage_server {oid} +NOTICE: checking gp_storage_user_mapping {umuser} => pg_authid {oid} NOTICE: checking pg_aggregate {aggcombinefn} => pg_proc {oid} NOTICE: checking pg_aggregate {aggserialfn} => pg_proc {oid} NOTICE: checking pg_aggregate {aggdeserialfn} => pg_proc {oid} @@ -179,6 +182,8 @@ NOTICE: checking pg_trigger {tgrelid,tgattr} => pg_attribute {attrelid,attnum} NOTICE: checking pg_event_trigger {evtowner} => pg_authid {oid} NOTICE: checking pg_event_trigger {evtfoid} => pg_proc {oid} NOTICE: checking pg_description {classoid} => pg_class {oid} +NOTICE: checking pg_directory_table {dtrelid} => pg_class {oid} +NOTICE: checking pg_directory_table {dttablespace} => pg_tablespace {oid} NOTICE: checking pg_cast {castsource} => pg_type {oid} NOTICE: checking pg_cast {casttarget} => pg_type {oid} NOTICE: checking pg_cast {castfunc} => pg_proc {oid} diff --git a/src/test/singlenode_regress/expected/opr_sanity.out b/src/test/singlenode_regress/expected/opr_sanity.out index fbac24e2306..85b3ce33312 100644 --- a/src/test/singlenode_regress/expected/opr_sanity.out +++ b/src/test/singlenode_regress/expected/opr_sanity.out @@ -402,12 +402,14 @@ WHERE 'cstring'::regtype = ANY (p1.proargtypes) AND NOT EXISTS(SELECT 1 FROM pg_conversion WHERE conproc = p1.oid) AND p1.oid != 'shell_in(cstring)'::regprocedure ORDER BY 1; - oid | proname -------+----------------- + oid | proname +------+--------------------- 2293 | cstring_out 2501 | cstring_send 7060 | get_role_status -(3 rows) + 8996 | remove_file + 9109 | remove_file_segment +(5 rows) -- Likewise, look for functions that return cstring and aren't datatype output -- functions nor typmod output functions. diff --git a/src/test/singlenode_regress/expected/sanity_check.out b/src/test/singlenode_regress/expected/sanity_check.out index 94b31962a9b..b47c31bc7e6 100644 --- a/src/test/singlenode_regress/expected/sanity_check.out +++ b/src/test/singlenode_regress/expected/sanity_check.out @@ -128,6 +128,7 @@ pg_db_role_setting|t pg_default_acl|t pg_depend|t pg_description|t +pg_directory_table|t pg_enum|t pg_event_trigger|t pg_extension|t diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index 7a0216ff100..9cecc124ce3 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -86,6 +86,8 @@ AlterRoleSetStmt AlterRoleStmt AlterSeqStmt AlterStatsStmt +AlterStorageServer +AlterStorageUserMappingStmt AlterSubscriptionStmt AlterSubscriptionType AlterSystemStmt @@ -484,6 +486,8 @@ CreateSeqStmt CreateStatsStmt CreateStmt CreateStmtContext +CreateStorageServerStmt +CreateStorageUserMappingStmt CreateSubscriptionStmt CreateTableAsStmt CreateTableSpaceStmt @@ -572,6 +576,8 @@ DropProfileStmt DropReplicationSlotCmd DropRoleStmt DropStmt +DropStorageServer +DropStorageUserMappingStmt DropSubscriptionStmt DropTableSpaceStmt DropUserMappingStmt