Hello Alvaro, all,
I have done some research regarding this bug.
Basically, we forbid the creation of partitioned tables and indexes if a
default_tablespace is specified in postgresql.conf.
In tablespace.c, the comment says:
"Don't allow specifying that when creating a partitioned table, however,
since the result is confusing."
I did not see why the result is confusing.
I just disabled the checks in tablespace.c, tablecmds.c and indexcmds.c
and now it works.
I modified the expected result in tests, and the tests are passing too.
See the attached patch.
Regards,
Marius Raicu
On 10/25/23 11:58, tender wang wrote:
Alvaro Herrera <alvhe...@alvh.no-ip.org> 于2023年10月25日周三 17:41写道:
On 2023-Oct-24, PG Bug reporting form wrote:
> marius@[local]:5434/postgres=# show default_tablespace;
> default_tablespace
> --------------------
> tblspc1
> (1 row)
>
> marius@[local]:5434/postgres=# create tablespace tblspc1 location
> '/home/marius/pgcode/tblspc1';
> CREATE TABLESPACE
> marius@[local]:5434/postgres=# create database test tablespace
tblspc1;
> CREATE DATABASE
> marius@[local]:5434/postgres=# \c test
> You are now connected to database "test" as user "marius".
> marius@[local]:5434/test=# create table toto(id numeric)
partition by
> list(id);
> ERROR: cannot specify default tablespace for partitioned relations
Oh, so the problem here is that *both* default_tablespace and the
database's tablespace are set, and then a partitioned table creation
fails when it doesn't specify any tablespace? That indeed sounds
like a
bug. I'll have a look, thanks. I'm surprised it took so long for
this
to be reported.
Oh, interesting issue!
I found another two case:
First: default_tablespace not set and create part rel failed
postgres=# create tablespace tbsp3 location '/tender/pgsql/tbsp3';
CREATE TABLESPACE
postgres=# create database test3 tablespace tbsp3;
CREATE DATABASE
postgres=# \c test3
You are now connected to database "test3" as user "gpadmin".
test3=# show default_tablespace ;
default_tablespace
--------------------
(1 row)
test3=# create table part1(a int) partition by list(a) tablespace tbsp3;
ERROR: cannot specify default tablespace for partitioned relations
Second: default_tablespace and database's tablespace both set, but
part rel created
test3=# set default_tablespace = tbsp2;
SET
test3=# create table part1(a int) partition by list(a);
CREATE TABLE
I'm not sure if the above two cases are a bug. If the document could
provide detailed explanations, that would be great.
--
Álvaro Herrera 48°01'N 7°57'E —
https://www.EnterpriseDB.com/ <https://www.EnterpriseDB.com/>
"Someone said that it is at least an order of magnitude more work
to do
production software than a prototype. I think he is wrong by at least
an order of magnitude." (Brian Kernighan)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index c160d8a301..afba303e13 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -758,10 +758,12 @@ DefineIndex(Oid tableId,
if (stmt->tableSpace)
{
tablespaceId = get_tablespace_oid(stmt->tableSpace, false);
+ /*
if (partitioned && tablespaceId == MyDatabaseTableSpace)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot specify default tablespace for partitioned relations")));
+ */
}
else
{
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 416a98e7ce..1a50c9c479 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -790,11 +790,12 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
if (stmt->tablespacename)
{
tablespaceId = get_tablespace_oid(stmt->tablespacename, false);
-
+ /*
if (partitioned && tablespaceId == MyDatabaseTableSpace)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot specify default tablespace for partitioned relations")));
+ */
}
else if (stmt->partbound)
{
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index 13b0dee146..f73c6a1286 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -1133,9 +1133,7 @@ check_default_tablespace(char **newval, void **extra, GucSource source)
* GetDefaultTablespace -- get the OID of the current default tablespace
*
* Temporary objects have different default tablespaces, hence the
- * relpersistence parameter must be specified. Also, for partitioned tables,
- * we disallow specifying the database default, so that needs to be specified
- * too.
+ * relpersistence parameter must be specified.
*
* May return InvalidOid to indicate "use the database's default tablespace".
*
@@ -1172,16 +1170,15 @@ GetDefaultTablespace(char relpersistence, bool partitioned)
/*
* Allow explicit specification of database's default tablespace in
- * default_tablespace without triggering permissions checks. Don't allow
- * specifying that when creating a partitioned table, however, since the
- * result is confusing.
+ * default_tablespace without triggering permissions checks.
*/
if (result == MyDatabaseTableSpace)
{
- if (partitioned)
+ /* if (partitioned)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot specify default tablespace for partitioned relations")));
+ */
result = InvalidOid;
}
return result;
diff --git a/src/test/regress/expected/tablespace.out b/src/test/regress/expected/tablespace.out
index 9aabb85349..b9070d269f 100644
--- a/src/test/regress/expected/tablespace.out
+++ b/src/test/regress/expected/tablespace.out
@@ -396,17 +396,14 @@ Partitions: testschema.part1_a_idx,
testschema.part2_a_idx
Tablespace: "regress_tblspace"
--- partitioned rels cannot specify the default tablespace. These fail:
+-- partitioned rels can specify the default tablespace. These should not fail:
CREATE TABLE testschema.dflt (a int PRIMARY KEY) PARTITION BY LIST (a) TABLESPACE pg_default;
-ERROR: cannot specify default tablespace for partitioned relations
-CREATE TABLE testschema.dflt (a int PRIMARY KEY USING INDEX TABLESPACE pg_default) PARTITION BY LIST (a);
-ERROR: cannot specify default tablespace for partitioned relations
+CREATE TABLE testschema.dflt2 (a int PRIMARY KEY USING INDEX TABLESPACE pg_default) PARTITION BY LIST (a);
SET default_tablespace TO 'pg_default';
-CREATE TABLE testschema.dflt (a int PRIMARY KEY) PARTITION BY LIST (a) TABLESPACE regress_tblspace;
-ERROR: cannot specify default tablespace for partitioned relations
-CREATE TABLE testschema.dflt (a int PRIMARY KEY USING INDEX TABLESPACE regress_tblspace) PARTITION BY LIST (a);
-ERROR: cannot specify default tablespace for partitioned relations
--- but these work:
+CREATE TABLE testschema.dflt3 (a int PRIMARY KEY) PARTITION BY LIST (a) TABLESPACE regress_tblspace;
+CREATE TABLE testschema.dflt4 (a int PRIMARY KEY USING INDEX TABLESPACE regress_tblspace) PARTITION BY LIST (a);
+DROP TABLE testschema.dflt, testschema.dflt2, testschema.dflt3, testschema.dflt4;
+-- and these work:
CREATE TABLE testschema.dflt (a int PRIMARY KEY USING INDEX TABLESPACE regress_tblspace) PARTITION BY LIST (a) TABLESPACE regress_tblspace;
SET default_tablespace TO '';
CREATE TABLE testschema.dflt2 (a int PRIMARY KEY) PARTITION BY LIST (a);
diff --git a/src/test/regress/sql/tablespace.sql b/src/test/regress/sql/tablespace.sql
index d274d9615e..7bd2b72a69 100644
--- a/src/test/regress/sql/tablespace.sql
+++ b/src/test/regress/sql/tablespace.sql
@@ -231,13 +231,14 @@ SELECT relname, spcname FROM pg_catalog.pg_tablespace t, pg_catalog.pg_class c
\d testschema.part_a_idx
\d+ testschema.part_a_idx
--- partitioned rels cannot specify the default tablespace. These fail:
+-- partitioned rels can specify the default tablespace. These should not fail:
CREATE TABLE testschema.dflt (a int PRIMARY KEY) PARTITION BY LIST (a) TABLESPACE pg_default;
-CREATE TABLE testschema.dflt (a int PRIMARY KEY USING INDEX TABLESPACE pg_default) PARTITION BY LIST (a);
+CREATE TABLE testschema.dflt2 (a int PRIMARY KEY USING INDEX TABLESPACE pg_default) PARTITION BY LIST (a);
SET default_tablespace TO 'pg_default';
-CREATE TABLE testschema.dflt (a int PRIMARY KEY) PARTITION BY LIST (a) TABLESPACE regress_tblspace;
-CREATE TABLE testschema.dflt (a int PRIMARY KEY USING INDEX TABLESPACE regress_tblspace) PARTITION BY LIST (a);
--- but these work:
+CREATE TABLE testschema.dflt3 (a int PRIMARY KEY) PARTITION BY LIST (a) TABLESPACE regress_tblspace;
+CREATE TABLE testschema.dflt4 (a int PRIMARY KEY USING INDEX TABLESPACE regress_tblspace) PARTITION BY LIST (a);
+DROP TABLE testschema.dflt, testschema.dflt2, testschema.dflt3, testschema.dflt4;
+-- and these work:
CREATE TABLE testschema.dflt (a int PRIMARY KEY USING INDEX TABLESPACE regress_tblspace) PARTITION BY LIST (a) TABLESPACE regress_tblspace;
SET default_tablespace TO '';
CREATE TABLE testschema.dflt2 (a int PRIMARY KEY) PARTITION BY LIST (a);