This is an automated email from the ASF dual-hosted git repository.

maxyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudberry.git


The following commit(s) were added to refs/heads/main by this push:
     new 3cd299d9b0 Support create directory table with location.
3cd299d9b0 is described below

commit 3cd299d9b0e2e04180c3d38e89f293a458bbaf2a
Author: zhangwenchao <[email protected]>
AuthorDate: Wed Dec 18 14:29:16 2024 +0800

    Support create directory table with location.
    
    When we create directory table with location, the file directory path will 
concat
    with location at beginning.
    
    Authored-by: Zhang Wenchao [email protected]
---
 src/backend/commands/dirtablecmds.c                | 47 ++++++++++++++++------
 src/backend/nodes/copyfuncs.c                      |  1 +
 src/backend/nodes/equalfuncs.c                     |  1 +
 src/backend/nodes/outfuncs.c                       |  1 +
 src/backend/nodes/readfast.c                       |  1 +
 src/backend/parser/gram.y                          | 16 ++++++--
 src/include/nodes/parsenodes.h                     |  1 +
 src/test/regress/input/directory_table.source      |  8 ++++
 src/test/regress/output/directory_table.source     | 13 ++++++
 .../output/directory_table_optimizer.source        | 13 ++++++
 10 files changed, 86 insertions(+), 16 deletions(-)

diff --git a/src/backend/commands/dirtablecmds.c 
b/src/backend/commands/dirtablecmds.c
index 4efcf83800..1216eaac58 100644
--- a/src/backend/commands/dirtablecmds.c
+++ b/src/backend/commands/dirtablecmds.c
@@ -122,22 +122,45 @@ CreateDirectoryTable(CreateDirectoryTableStmt *stmt, Oid 
relId)
        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);
+       if (stmt->location)
+       {
+               if (spcId == InvalidOid ||
+                       spcId == DEFAULTTABLESPACE_OID)
+                       dirTablePath = psprintf("base/%s", stmt->location);
+               else if (spcId == GLOBALTABLESPACE_OID)
+                       dirTablePath = psprintf("global/%s", stmt->location);
+               else
+                       dirTablePath = psprintf("pg_tblspc/%s", stmt->location);
+       }
+       else
+       {
+               Form_pg_class pg_class_tuple = NULL;
+               HeapTuple       class_tuple = NULL;
+               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);
+               relFileNode.spcNode = spcId;
+               relFileNode.dbNode = MyDatabaseId;
+               relFileNode.relNode = pg_class_tuple->relfilenode;
 
-       ReleaseSysCache(class_tuple);
+               dirTablePath = UFileFormatPathName(&relFileNode);
+               ReleaseSysCache(class_tuple);
+       }
+
+       /*
+        * We will check whether the directory path has existed only when use 
the local file am.
+        */
+       if (UFileExists(spcId, dirTablePath) && GetTablespaceFileHandler(spcId) 
== &localFileAm)
+               ereport(ERROR,
+                               (errcode(ERRCODE_DUPLICATE_OBJECT),
+                                errmsg("directory table path \"%s\" already 
exists",
+                                dirTablePath)));
 
        /*
         * Acquire DirectoryTableLock to ensure that no DROP DIRECTORY TABLE
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index f47aaaf300..950f052bf0 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -6290,6 +6290,7 @@ _copyCreateDirectoryTableStmt(const 
CreateDirectoryTableStmt *from)
        CopyCreateStmtFields((const CreateStmt *) from, (CreateStmt *) newnode);
 
        COPY_STRING_FIELD(tablespacename);
+       COPY_STRING_FIELD(location);
 
        return newnode;
 }
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 5a03f341aa..1d548acfb8 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -3474,6 +3474,7 @@ _equalCreateDirectoryTableStmt(const 
CreateDirectoryTableStmt *a, const CreateDi
                return false;
 
        COMPARE_STRING_FIELD(tablespacename);
+       COMPARE_STRING_FIELD(location);
 
        return true;
 }
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 4e9ff83501..4a5c7286c7 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -4095,6 +4095,7 @@ _outCreateDirectoryTableStmt(StringInfo str, const 
CreateDirectoryTableStmt *nod
 
        _outCreateStmtInfo(str, (const CreateStmt *) node);
        WRITE_STRING_FIELD(tablespacename);
+       WRITE_STRING_FIELD(location);
 }
 
 static void
diff --git a/src/backend/nodes/readfast.c b/src/backend/nodes/readfast.c
index d9e5bc3414..8b64036eeb 100644
--- a/src/backend/nodes/readfast.c
+++ b/src/backend/nodes/readfast.c
@@ -1852,6 +1852,7 @@ _readCreateDirectoryTableStmt(void)
        _readCreateStmt_common(&local_node->base);
 
        READ_STRING_FIELD(tablespacename);
+       READ_STRING_FIELD(location);
 
        READ_DONE();
 }
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index c93b839acd..3c76124fad 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -416,6 +416,7 @@ static void 
check_expressions_in_partition_key(PartitionSpec *spec, core_yyscan_
                                access_method_clause attr_name
                                table_access_method_clause name cursor_name 
file_name
                                opt_index_name cluster_index_specification 
opt_file_name
+%type <str>            OptWithLocation
 
 %type <list>   func_name handler_name qual_Op qual_all_Op subquery_Op
                                opt_class opt_inline_handler opt_validator 
validator_clause
@@ -6013,6 +6014,11 @@ OptWith:
                        | /*EMPTY*/                                     { $$ = 
NIL; }
                ;
 
+OptWithLocation:
+                       WITH LOCATION Sconst            { $$ = $3; }
+                       | /*EMPTY*/                                     { $$ = 
NULL; }
+               ;
+
 OnCommitOption:  ON COMMIT DROP                                { $$ = 
ONCOMMIT_DROP; }
                        | ON COMMIT DELETE_P ROWS               { $$ = 
ONCOMMIT_DELETE_ROWS; }
                        | ON COMMIT PRESERVE ROWS               { $$ = 
ONCOMMIT_PRESERVE_ROWS; }
@@ -8530,7 +8536,7 @@ AlterStorageUserMappingStmt:
 
 CreateDirectoryTableStmt:
             CREATE DIRECTORY TABLE qualified_name
-            table_access_method_clause OptTableSpace OptTagOptList
+            table_access_method_clause OptTableSpace OptWithLocation 
OptTagOptList
                 {
                     CreateDirectoryTableStmt *n = 
makeNode(CreateDirectoryTableStmt);
                     $4->relpersistence = RELPERSISTENCE_PERMANENT;
@@ -8545,13 +8551,14 @@ CreateDirectoryTableStmt:
                     n->base.if_not_exists = false;
                     n->base.distributedBy = GetDirectoryTableDistributedBy();
                     n->base.relKind = RELKIND_DIRECTORY_TABLE;
-                    n->base.tags = $7;
                     n->tablespacename = $6;
+                    n->location = $7;
+                    n->base.tags = $8;
 
                     $$ = (Node *) n;
                 }
             | CREATE DIRECTORY TABLE IF_P NOT EXISTS qualified_name
-            table_access_method_clause OptTableSpace OptTagOptList
+            table_access_method_clause OptTableSpace OptWithLocation 
OptTagOptList
                 {
                     CreateDirectoryTableStmt *n = 
makeNode(CreateDirectoryTableStmt);
                     $7->relpersistence = RELPERSISTENCE_PERMANENT;
@@ -8566,8 +8573,9 @@ CreateDirectoryTableStmt:
                     n->base.if_not_exists = true;
                     n->base.distributedBy = GetDirectoryTableDistributedBy();
                     n->base.relKind = RELKIND_DIRECTORY_TABLE;
-                    n->base.tags = $10;
                     n->tablespacename = $9;
+                    n->location = $10;
+                    n->base.tags = $11;
 
                     $$ = (Node *) n;
                 }
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 7a2118bad6..0e59c66994 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -3414,6 +3414,7 @@ typedef struct CreateDirectoryTableStmt
 {
        CreateStmt      base;
        char       *tablespacename;
+       char       *location;   /* dtlocation for pg_directory_table */
 } CreateDirectoryTableStmt;
 
 typedef struct AlterDirectoryTableStmt
diff --git a/src/test/regress/input/directory_table.source 
b/src/test/regress/input/directory_table.source
index a027ae1234..664673919c 100644
--- a/src/test/regress/input/directory_table.source
+++ b/src/test/regress/input/directory_table.source
@@ -648,6 +648,14 @@ SELECT relative_path, tag FROM dir_table4 ORDER BY 1;
 SAVEPOINT s2;
 ROLLBACK;
 
+-- test create directory table with location
+CREATE DIRECTORY TABLE dir_table_with_location TABLESPACE directory_tblspc 
WITH LOCATION '/test_dirtable';
+CREATE DIRECTORY TABLE dir_table_with_location2 TABLESPACE directory_tblspc 
WITH LOCATION '/test_dirtable'; -- error
+CREATE DIRECTORY TABLE dir_table_with_location3 WITH LOCATION '/test_dirtable';
+SELECT count(*) FROM pg_directory_table;
+DROP DIRECTORY TABLE dir_table_with_location WITH CONTENT;
+DROP DIRECTORY TABLE dir_table_with_location3 WITH CONTENT;
+
 -- clean up
 DROP DIRECTORY TABLE IF EXISTS dir_table1;
 DROP DIRECTORY TABLE IF EXISTS dir_table2;
diff --git a/src/test/regress/output/directory_table.source 
b/src/test/regress/output/directory_table.source
index 8915fba513..3fdc23bec1 100644
--- a/src/test/regress/output/directory_table.source
+++ b/src/test/regress/output/directory_table.source
@@ -2063,6 +2063,19 @@ SELECT relative_path, tag FROM dir_table4 ORDER BY 1;
 
 SAVEPOINT s2;
 ROLLBACK;
+-- test create directory table with location
+CREATE DIRECTORY TABLE dir_table_with_location TABLESPACE directory_tblspc 
WITH LOCATION '/test_dirtable';
+CREATE DIRECTORY TABLE dir_table_with_location2 TABLESPACE directory_tblspc 
WITH LOCATION '/test_dirtable'; -- error
+ERROR:  directory table path "pg_tblspc//test_dirtable" already exists
+CREATE DIRECTORY TABLE dir_table_with_location3 WITH LOCATION '/test_dirtable';
+SELECT count(*) FROM pg_directory_table;
+ count 
+-------
+     8
+(1 row)
+
+DROP DIRECTORY TABLE dir_table_with_location WITH CONTENT;
+DROP DIRECTORY TABLE dir_table_with_location3 WITH CONTENT;
 -- clean up
 DROP DIRECTORY TABLE IF EXISTS dir_table1;
 DROP DIRECTORY TABLE IF EXISTS dir_table2;
diff --git a/src/test/regress/output/directory_table_optimizer.source 
b/src/test/regress/output/directory_table_optimizer.source
index cf5743c246..4a9adbba58 100644
--- a/src/test/regress/output/directory_table_optimizer.source
+++ b/src/test/regress/output/directory_table_optimizer.source
@@ -2063,6 +2063,19 @@ SELECT relative_path, tag FROM dir_table4 ORDER BY 1;
 
 SAVEPOINT s2;
 ROLLBACK;
+-- test create directory table with location
+CREATE DIRECTORY TABLE dir_table_with_location TABLESPACE directory_tblspc 
WITH LOCATION '/test_dirtable';
+CREATE DIRECTORY TABLE dir_table_with_location2 TABLESPACE directory_tblspc 
WITH LOCATION '/test_dirtable'; -- error
+ERROR:  directory table path "pg_tblspc//test_dirtable" already exists
+CREATE DIRECTORY TABLE dir_table_with_location3 WITH LOCATION '/test_dirtable';
+SELECT count(*) FROM pg_directory_table;
+ count 
+-------
+     8
+(1 row)
+
+DROP DIRECTORY TABLE dir_table_with_location WITH CONTENT;
+DROP DIRECTORY TABLE dir_table_with_location3 WITH CONTENT;
 -- clean up
 DROP DIRECTORY TABLE IF EXISTS dir_table1;
 DROP DIRECTORY TABLE IF EXISTS dir_table2;


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to