1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-24 00:23:06 +03:00

Track collation versions for indexes.

Record the current version of dependent collations in pg_depend when
creating or rebuilding an index.  When accessing the index later, warn
that the index may be corrupted if the current version doesn't match.

Thanks to Douglas Doole, Peter Eisentraut, Christoph Berg, Laurenz Albe,
Michael Paquier, Robert Haas, Tom Lane and others for very helpful
discussion.

Author: Thomas Munro <thomas.munro@gmail.com>
Author: Julien Rouhaud <rjuju123@gmail.com>
Reviewed-by: Peter Eisentraut <peter.eisentraut@2ndquadrant.com> (earlier versions)
Discussion: https://postgr.es/m/CAEepm%3D0uEQCpfq_%2BLYFBdArCe4Ot98t1aR4eYiYTe%3DyavQygiQ%40mail.gmail.com
This commit is contained in:
Thomas Munro
2020-11-02 19:50:45 +13:00
parent cd6f479e79
commit 257836a755
43 changed files with 1287 additions and 94 deletions

View File

@@ -19,6 +19,7 @@
#include "access/table.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_depend.h"
#include "catalog/pg_extension.h"
@@ -27,6 +28,7 @@
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/pg_locale.h"
#include "utils/rel.h"
@@ -45,19 +47,24 @@ recordDependencyOn(const ObjectAddress *depender,
const ObjectAddress *referenced,
DependencyType behavior)
{
recordMultipleDependencies(depender, referenced, 1, NULL, behavior);
recordMultipleDependencies(depender, referenced, 1, behavior, false);
}
/*
* Record multiple dependencies (of the same kind) for a single dependent
* object. This has a little less overhead than recording each separately.
*
* If record_version is true, then a record is added even if the referenced
* object is pinned, and the dependency version will be retrieved according to
* the referenced object kind. For now, only collation version is
* supported.
*/
void
recordMultipleDependencies(const ObjectAddress *depender,
const ObjectAddress *referenced,
int nreferenced,
const char *version,
DependencyType behavior)
DependencyType behavior,
bool record_version)
{
Relation dependDesc;
CatalogIndexState indstate;
@@ -66,6 +73,7 @@ recordMultipleDependencies(const ObjectAddress *depender,
max_slots,
slot_init_count,
slot_stored_count;
char *version = NULL;
if (nreferenced <= 0)
return; /* nothing to do */
@@ -96,12 +104,38 @@ recordMultipleDependencies(const ObjectAddress *depender,
slot_init_count = 0;
for (i = 0; i < nreferenced; i++, referenced++)
{
bool ignore_systempin = false;
if (record_version)
{
/* For now we only know how to deal with collations. */
if (referenced->classId == CollationRelationId)
{
/* C and POSIX don't need version tracking. */
if (referenced->objectId == C_COLLATION_OID ||
referenced->objectId == POSIX_COLLATION_OID)
continue;
version = get_collation_version_for_oid(referenced->objectId);
/*
* Default collation is pinned, so we need to force recording
* the dependency to store the version.
*/
if (referenced->objectId == DEFAULT_COLLATION_OID)
ignore_systempin = true;
}
}
else
Assert(!version);
/*
* If the referenced object is pinned by the system, there's no real
* need to record dependencies on it. This saves lots of space in
* pg_depend, so it's worth the time taken to check.
* need to record dependencies on it, unless we need to record a
* version. This saves lots of space in pg_depend, so it's worth the
* time taken to check.
*/
if (isObjectPinned(referenced, dependDesc))
if (!ignore_systempin && isObjectPinned(referenced, dependDesc))
continue;
if (slot_init_count < max_slots)