This is an automated email from the ASF dual-hosted git repository. tuhaihe pushed a commit to branch add-behave-test-ci in repository https://gitbox.apache.org/repos/asf/cloudberry.git
commit 93d141d18382c59682c52945244a85ae21a8f499 Author: Dianjin Wang <[email protected]> AuthorDate: Fri Sep 11 12:56:47 2026 +0800 gpinitsystem: import system collations after the cluster is up A freshly initialised cluster had no system collations at all, and the two halves of that are in different layers. initdb deliberately skips pg_import_system_collations(): the call has to be dispatched to the segments, so it cannot run before the cluster exists. Greenplum makes up for that in gpinitsystem; Cloudberry had dropped the function. Add IMPORT_COLLATION, called once the coordinator is up in production mode, importing into template0, template1 and postgres, each followed by ANALYZE and VACUUM FREEZE so the built-in databases end up as initdb would have left them. That alone is not enough, because pg_import_system_collations() itself only half worked. Every collation has to exist on the segments with the same OID; the alias and ICU paths dispatch CREATE COLLATION to arrange that, but the path for the locale names themselves did not -- the PostgreSQL 16 merge moved that code into create_collation_from_locale() and dropped the DispatchCollationCreate() call. The result is a pg_collation populated on the coordinator only, which gpcheckcat duly reports as inconsistent_pg_collation. Nothing noticed until now because nothing ever called the function. Skip locales whose encoding differs from the database encoding before creating anything, rather than after: such a collation is unusable in this database and a segment rejects CREATE COLLATION for it with "encoding UTF8 does not match locale en_AU", so creating it on the coordinator alone would reintroduce the very inconsistency being fixed. --- gpMgmt/bin/gpinitsystem | 39 ++++++++++++++++++++++++++++++++++++ src/backend/commands/collationcmds.c | 20 ++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/gpMgmt/bin/gpinitsystem b/gpMgmt/bin/gpinitsystem index fa85d42ae3f..a4569e913cc 100755 --- a/gpMgmt/bin/gpinitsystem +++ b/gpMgmt/bin/gpinitsystem @@ -1621,6 +1621,44 @@ CREATE_GPEXTENSIONS() { done } +# Import system collations through pg_import_system_collations, and leave the +# built-in databases in the state initdb would have left them (borrowed from +# initdb.c:setup_collation() and initdb.c:vacuum_db()). +# +# initdb cannot do this itself: pg_import_system_collations() has to be +# dispatched to the segments, so it can only run once the cluster is up. +IMPORT_COLLATION () { + LOG_MSG "[INFO]:-Start Function $FUNCNAME" + LOG_MSG "[INFO]:-Importing system collations" 1 + + # temporarily allow connections to template0, so we can import collations to it. + $PSQL -p $GP_PORT -d postgres -A -t -c "ALTER DATABASE template0 ALLOW_CONNECTIONS on" >> $LOG_FILE 2>&1; + $PSQL -p $GP_PORT -d template0 -A -t -c "SELECT pg_import_system_collations('pg_catalog')" >> $LOG_FILE 2>&1; + ERROR_CHK $? "importing system collations to 'template0' database" 1 + $PSQL -p $GP_PORT -d template0 -A -t -c "ANALYZE" >> $LOG_FILE 2>&1; + ERROR_CHK $? "ANALYZE 'template0' database" 1 + $PSQL -p $GP_PORT -d template0 -A -t -c "VACUUM FREEZE" >> $LOG_FILE 2>&1; + ERROR_CHK $? "VACUUM FREEZE 'template0' database" 1 + $PSQL -p $GP_PORT -d postgres -A -t -c "ALTER DATABASE template0 ALLOW_CONNECTIONS off" >> $LOG_FILE 2>&1; + + # import to template1 + $PSQL -p $GP_PORT -d template1 -A -t -c "SELECT pg_import_system_collations('pg_catalog')" >> $LOG_FILE 2>&1; + ERROR_CHK $? "importing system collations to 'template1' database" 1 + $PSQL -p $GP_PORT -d template1 -A -t -c "ANALYZE" >> $LOG_FILE 2>&1; + ERROR_CHK $? "ANALYZE 'template1' database" 1 + $PSQL -p $GP_PORT -d template1 -A -t -c "VACUUM FREEZE" >> $LOG_FILE 2>&1; + ERROR_CHK $? "VACUUM FREEZE 'template1' database" 1 + + # import to postgres + $PSQL -p $GP_PORT -d postgres -A -t -c "SELECT pg_import_system_collations('pg_catalog')" >> $LOG_FILE 2>&1; + ERROR_CHK $? "importing system collations to 'postgres' database" 1 + $PSQL -p $GP_PORT -d postgres -A -t -c "ANALYZE" >> $LOG_FILE 2>&1; + ERROR_CHK $? "ANALYZE 'postgres' database" 1 + $PSQL -p $GP_PORT -d postgres -A -t -c "VACUUM FREEZE" >> $LOG_FILE 2>&1; + ERROR_CHK $? "VACUUM FREEZE 'postgres' database" 1 + LOG_MSG "[INFO]:-End Function $FUNCNAME" +} + FORCE_FTS_PROBE () { LOG_MSG "[INFO]:-Start Function $FUNCNAME" @@ -2249,6 +2287,7 @@ STOP_QD_PRODUCTION START_QD_PRODUCTION CREATE_GPEXTENSIONS +IMPORT_COLLATION if [ x"" != x"$DATABASE_NAME" ]; then CREATE_DATABASE diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c index 69fa630ee02..ede18b0442d 100644 --- a/src/backend/commands/collationcmds.c +++ b/src/backend/commands/collationcmds.c @@ -755,6 +755,17 @@ create_collation_from_locale(const char *locale, int nspid, /* count valid locales found in operating system */ (*nvalidp)++; + /* + * A collation whose encoding differs from the database encoding cannot be + * used in this database, and CREATE COLLATION on a segment would reject + * it ("encoding X does not match locale Y"). Creating it on the + * coordinator alone would leave pg_collation inconsistent across the + * cluster, so skip it entirely. The caller skips it as well, for the + * purpose of generating aliases. + */ + if (enc != GetDatabaseEncoding()) + return enc; + /* * Create a collation named the same as the locale, but quietly doing * nothing if it already exists. This is the behavior we need even at @@ -770,6 +781,15 @@ create_collation_from_locale(const char *locale, int nspid, true, true); if (OidIsValid(collid)) { + /* + * The collation has to exist on the segments too, with the same OID. + * Dispatching CREATE COLLATION with the OID just assigned here is how + * the alias and ICU paths do it; this path must do the same, or + * pg_collation ends up populated on the coordinator only and + * gpcheckcat reports pg_collation as inconsistent. + */ + DispatchCollationCreate(unconstify(char *, locale), + unconstify(char *, locale), nspid, "libc"); (*ncreatedp)++; /* Must do CCI between inserts to handle duplicates correctly */ --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
