Re: Database-level collation version tracking - Mailing list pgsql-hackers

From Peter Eisentraut
Subject Re: Database-level collation version tracking
Date
Msg-id c04b1477-80f1-34ea-42ab-df171cbd7a50@enterprisedb.com
Whole thread Raw
In response to Re: Database-level collation version tracking  (Julien Rouhaud <rjuju123@gmail.com>)
Responses Re: Database-level collation version tracking  (Julien Rouhaud <rjuju123@gmail.com>)
Re: Database-level collation version tracking  (Michael Banck <michael.banck@credativ.de>)
List pgsql-hackers
On 07.02.22 11:29, Julien Rouhaud wrote:
> - there should be a mention to the need for a catversion bump in the message
>    comment

done

> - there is no test

Suggestions where to put it?  We don't really have tests for the 
collation-level versioning either, do we?

> - it's missing some updates in create_database.sgml, and psql tab completion
>    for CREATE DATABASE with the new collation_version defelem.

Added to create_database.sgml, but not to psql.  We don't have 
completion for the collation option either, since it's only meant to be 
used by pg_upgrade, not interactively.

> - that's not really something new with this patch, but should we output the
>    collation version info or mismatch info in \l / \dO?

It's a possibility.  Perhaps there is a question of performance if we 
show it in \l and people have tons of databases and they have to make a 
locale call for each one.  As you say, it's more an independent feature, 
but it's worth looking into.

> +       if (!actual_versionstr)
> +           ereport(ERROR,
> +                   (errmsg("database \"%s\" has no actual collation version, but a version was specified",
> +                           name)));-
> 
> this means you can't connect on such a database anymore.  The level is probably
> ok for collation version check, but for db isn't that too much?

Right, changed to warning.

> +Oid
> +AlterDatabaseRefreshColl(AlterDatabaseRefreshCollStmt *stmt)
> +{
> +   Relation    rel;
> +   Oid         dboid;
> +   HeapTuple   tup;
> +   Datum       datum;
> +   bool        isnull;
> +   char       *oldversion;
> +   char       *newversion;
> +
> +   rel = table_open(DatabaseRelationId, RowExclusiveLock);
> +   dboid = get_database_oid(stmt->dbname, false);
> +
> +   if (!pg_database_ownercheck(dboid, GetUserId()))
> +       aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_DATABASE,
> +                      stmt->dbname);
> +
> +   tup = SearchSysCacheCopy1(DATABASEOID, ObjectIdGetDatum(dboid));
> +   if (!HeapTupleIsValid(tup))
> +       elog(ERROR, "cache lookup failed for database %u", dboid);
> 
> Is that ok to not obtain a lock on the database when refreshing the collation?

That code takes a RowExclusiveLock on pg_database.  Did you have 
something else in mind?

> +   /*
> +    * Check collation version.  See similar code in
> +    * pg_newlocale_from_collation().
> +    */
> +   datum = SysCacheGetAttr(DATABASEOID, tup, Anum_pg_database_datcollversion,
> +                           &isnull);
> +   if (!isnull)
> +   {
> 
> This (and pg_newlocale_from_collation()) reports a problem if a recorded
> collation version is found but there's no reported collation version.
> Shouldn't it also complain if it's the opposite?  It's otherwise a backdoor to
> make sure there won't be any check about the version anymore, and while it can
> probably happen if you mess with the catalogs it still doesn't look great.

get_collation_actual_version() always returns either null or not null 
for a given installation.  So the situation that the stored version is 
null and the actual version is not null can only happen as part of a 
software upgrade.  In that case, all uses of collations after an upgrade 
would immediately start complaining about missing versions, which seems 
like a bad experience.  Users can explicitly opt in to version tracking 
by running REFRESH VERSION once.

> +       /*
> +        * template0 shouldn't have any collation-dependent objects, so unset
> +        * the collation version.  This avoids warnings when making a new
> +        * database from it.
> +        */
> +       "UPDATE pg_database SET datcollversion = NULL WHERE datname = 'template0';\n\n",
> 
> I'm not opposed, but shouldn't there indeed be a warning in case of discrepancy
> in the source database (whether template or not)?
> 
> # update pg_database set datcollversion = 'meh' where datname in ('postgres', 'template1');
> UPDATE 2
> 
> # create database test1 template postgres;
> CREATE DATABASE
> 
> # create database test2 template template1;
> CREATE DATABASE
> 
> # \c test2
> WARNING:  database "test2" has a collation version mismatch

I don't understand what the complaint is here.  It seems to work ok?
Attachment

pgsql-hackers by date:

Previous
From: Robert Haas
Date:
Subject: Re: [PATCH v2] use has_privs_for_role for predefined roles
Next
From: Esteban Zimanyi
Date:
Subject: Re: Storage for multiple variable-length attributes in a single row