mirror of https://github.com/citusdata/citus.git
Relax version check (#8356)
Relaxes the Citus version compatibility check for asynchronous replica upgrades. Citus requires the loaded shared library and the installed extension to have identical major and minor versions. This change keeps the library vs. control-file version checks the same (a restart is still needed after upgrading the library), but allows the installed extension to differ by at most one minor version from the loaded library. With this relaxation in place, replicas can lag by a single minor version during phased upgrades without triggering a version mismatch for distributed queries. Tested the change on release branch 13.2 as main already points to the next major version. Versioned test capability from https://github.com/citusdata/citus/pull/8361 is used in test. See branch for test https://github.com/citusdata/citus/tree/eag/release-13.2/relax-test , the so and sql versions are 13.2-1. ``` // Create extension fails CITUSVERSION=13.0-1 citus_tests/run_test.py adaptive_executor .... CREATE DATABASE ERROR: specified version incompatible with loaded Citus library DETAIL: Loaded library requires 13.2, but 13.0-1 was specified. HINT: If a newer library is present, restart the database and try the command again. .... // Test proceeds as expected CITUSVERSION=13.1-1 citus_tests/run_test.py adaptive_executor CREATE DATABASE CREATE EXTENSION CREATE FUNCTION // Test proceeds as expected CITUSVERSION=13.2-1 citus_tests/run_test.py adaptive_executor CREATE DATABASE CREATE EXTENSION CREATE FUNCTION ```pull/7823/merge
parent
84fc6801ba
commit
c125b9bec5
|
|
@ -162,6 +162,8 @@ static bool CitusColumnarHasBeenLoadedInternal(void);
|
||||||
static bool CitusColumnarHasBeenLoaded(void);
|
static bool CitusColumnarHasBeenLoaded(void);
|
||||||
static bool CheckCitusColumnarVersion(int elevel);
|
static bool CheckCitusColumnarVersion(int elevel);
|
||||||
static bool MajorVersionsCompatibleColumnar(char *leftVersion, char *rightVersion);
|
static bool MajorVersionsCompatibleColumnar(char *leftVersion, char *rightVersion);
|
||||||
|
static bool MinorVersionsCompatibleRelaxedColumnar(char *leftVersion, char *rightVersion);
|
||||||
|
static int ParseVersionComponent(const char *version, char **endPtr);
|
||||||
|
|
||||||
/* global variables for CheckCitusColumnarVersion */
|
/* global variables for CheckCitusColumnarVersion */
|
||||||
static bool extensionLoadedColumnar = false;
|
static bool extensionLoadedColumnar = false;
|
||||||
|
|
@ -2869,7 +2871,7 @@ CheckInstalledVersionColumnar(int elevel)
|
||||||
|
|
||||||
char *installedVersion = InstalledExtensionVersionColumnar();
|
char *installedVersion = InstalledExtensionVersionColumnar();
|
||||||
|
|
||||||
if (!MajorVersionsCompatibleColumnar(installedVersion, CITUS_EXTENSIONVERSION))
|
if (!MinorVersionsCompatibleRelaxedColumnar(installedVersion, CITUS_EXTENSIONVERSION))
|
||||||
{
|
{
|
||||||
ereport(elevel, (errmsg("loaded Citus library version differs from installed "
|
ereport(elevel, (errmsg("loaded Citus library version differs from installed "
|
||||||
"extension version"),
|
"extension version"),
|
||||||
|
|
@ -2928,6 +2930,55 @@ MajorVersionsCompatibleColumnar(char *leftVersion, char *rightVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ParseVersionComponent parses the integer at the current position and
|
||||||
|
* advances endPtr past the parsed digits to the next character.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
ParseVersionComponent(const char *version, char **endPtr)
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
long int val = strtol(version, endPtr, 10);
|
||||||
|
|
||||||
|
if (errno == ERANGE || val > INT_MAX || val < INT_MIN)
|
||||||
|
{
|
||||||
|
ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
|
errmsg("Invalid integer in version string")));
|
||||||
|
}
|
||||||
|
return (int) val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MinorVersionsCompatibleRelaxedColumnar checks if two versions have the same major
|
||||||
|
* version and their minor versions differ by at most 1. The schema version
|
||||||
|
* (after '-') is ignored. Returns true if compatible, false otherwise.
|
||||||
|
*
|
||||||
|
* Version format expected: "major.minor-schema" (e.g., "13.1-2")
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
MinorVersionsCompatibleRelaxedColumnar(char *leftVersion, char *rightVersion)
|
||||||
|
{
|
||||||
|
char *leftSep;
|
||||||
|
char *rightSep;
|
||||||
|
|
||||||
|
int leftMajor = ParseVersionComponent(leftVersion, &leftSep);
|
||||||
|
int rightMajor = ParseVersionComponent(rightVersion, &rightSep);
|
||||||
|
|
||||||
|
if (leftMajor != rightMajor)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int leftMinor = (*leftSep == '.') ? ParseVersionComponent(leftSep + 1, &leftSep) : 0;
|
||||||
|
int rightMinor = (*rightSep == '.') ? ParseVersionComponent(rightSep + 1, &rightSep) :
|
||||||
|
0;
|
||||||
|
|
||||||
|
int diff = leftMinor - rightMinor;
|
||||||
|
return diff >= -1 && diff <= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AvailableExtensionVersion returns the Citus version from citus.control file. It also
|
* AvailableExtensionVersion returns the Citus version from citus.control file. It also
|
||||||
* saves the result, thus consecutive calls to CitusExtensionAvailableVersion will
|
* saves the result, thus consecutive calls to CitusExtensionAvailableVersion will
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ ErrorIfUnstableCreateOrAlterExtensionStmt(Node *parseTree)
|
||||||
if (newExtensionVersion != NULL)
|
if (newExtensionVersion != NULL)
|
||||||
{
|
{
|
||||||
/* explicit version provided in CREATE or ALTER EXTENSION UPDATE; verify */
|
/* explicit version provided in CREATE or ALTER EXTENSION UPDATE; verify */
|
||||||
if (!MajorVersionsCompatible(newExtensionVersion, CITUS_EXTENSIONVERSION))
|
if (!MinorVersionsCompatibleRelaxed(newExtensionVersion, CITUS_EXTENSIONVERSION))
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errmsg("specified version incompatible with loaded "
|
ereport(ERROR, (errmsg("specified version incompatible with loaded "
|
||||||
"Citus library"),
|
"Citus library"),
|
||||||
|
|
|
||||||
|
|
@ -335,6 +335,7 @@ static Oid DistAuthinfoRelationId(void);
|
||||||
static Oid DistAuthinfoIndexId(void);
|
static Oid DistAuthinfoIndexId(void);
|
||||||
static Oid DistPoolinfoRelationId(void);
|
static Oid DistPoolinfoRelationId(void);
|
||||||
static Oid DistPoolinfoIndexId(void);
|
static Oid DistPoolinfoIndexId(void);
|
||||||
|
static int ParseVersionComponent(const char *version, char **endPtr);
|
||||||
|
|
||||||
/* exports for SQL callable functions */
|
/* exports for SQL callable functions */
|
||||||
PG_FUNCTION_INFO_V1(citus_dist_partition_cache_invalidate);
|
PG_FUNCTION_INFO_V1(citus_dist_partition_cache_invalidate);
|
||||||
|
|
@ -2436,7 +2437,7 @@ CheckInstalledVersion(int elevel)
|
||||||
|
|
||||||
char *installedVersion = InstalledExtensionVersion();
|
char *installedVersion = InstalledExtensionVersion();
|
||||||
|
|
||||||
if (!MajorVersionsCompatible(installedVersion, CITUS_EXTENSIONVERSION))
|
if (!MinorVersionsCompatibleRelaxed(installedVersion, CITUS_EXTENSIONVERSION))
|
||||||
{
|
{
|
||||||
ereport(elevel, (errmsg("loaded Citus library version differs from installed "
|
ereport(elevel, (errmsg("loaded Citus library version differs from installed "
|
||||||
"extension version"),
|
"extension version"),
|
||||||
|
|
@ -2514,6 +2515,55 @@ MajorVersionsCompatible(char *leftVersion, char *rightVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ParseVersionComponent parses the integer at the current position and
|
||||||
|
* advances endPtr past the parsed digits to the next character.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
ParseVersionComponent(const char *version, char **endPtr)
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
long int val = strtol(version, endPtr, 10);
|
||||||
|
|
||||||
|
if (errno == ERANGE || val > INT_MAX || val < INT_MIN)
|
||||||
|
{
|
||||||
|
ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
|
errmsg("Invalid integer in version string")));
|
||||||
|
}
|
||||||
|
return (int) val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MinorVersionsCompatibleRelaxed checks if two versions have the same major
|
||||||
|
* version and their minor versions differ by at most 1. The schema version
|
||||||
|
* (after '-') is ignored. Returns true if compatible, false otherwise.
|
||||||
|
*
|
||||||
|
* Version format expected: "major.minor-schema" (e.g., "13.1-2")
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
MinorVersionsCompatibleRelaxed(char *leftVersion, char *rightVersion)
|
||||||
|
{
|
||||||
|
char *leftSep;
|
||||||
|
char *rightSep;
|
||||||
|
|
||||||
|
int leftMajor = ParseVersionComponent(leftVersion, &leftSep);
|
||||||
|
int rightMajor = ParseVersionComponent(rightVersion, &rightSep);
|
||||||
|
|
||||||
|
if (leftMajor != rightMajor)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int leftMinor = (*leftSep == '.') ? ParseVersionComponent(leftSep + 1, &leftSep) : 0;
|
||||||
|
int rightMinor = (*rightSep == '.') ? ParseVersionComponent(rightSep + 1, &rightSep) :
|
||||||
|
0;
|
||||||
|
|
||||||
|
int diff = leftMinor - rightMinor;
|
||||||
|
return diff >= -1 && diff <= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AvailableExtensionVersion returns the Citus version from citus.control file. It also
|
* AvailableExtensionVersion returns the Citus version from citus.control file. It also
|
||||||
* saves the result, thus consecutive calls to CitusExtensionAvailableVersion will
|
* saves the result, thus consecutive calls to CitusExtensionAvailableVersion will
|
||||||
|
|
|
||||||
|
|
@ -217,6 +217,7 @@ extern bool CheckCitusVersion(int elevel);
|
||||||
extern bool CheckAvailableVersion(int elevel);
|
extern bool CheckAvailableVersion(int elevel);
|
||||||
extern bool InstalledAndAvailableVersionsSame(void);
|
extern bool InstalledAndAvailableVersionsSame(void);
|
||||||
extern bool MajorVersionsCompatible(char *leftVersion, char *rightVersion);
|
extern bool MajorVersionsCompatible(char *leftVersion, char *rightVersion);
|
||||||
|
extern bool MinorVersionsCompatibleRelaxed(char *leftVersion, char *rightVersion);
|
||||||
extern void ErrorIfInconsistentShardIntervals(CitusTableCacheEntry *cacheEntry);
|
extern void ErrorIfInconsistentShardIntervals(CitusTableCacheEntry *cacheEntry);
|
||||||
extern void EnsureModificationsCanRun(void);
|
extern void EnsureModificationsCanRun(void);
|
||||||
extern void EnsureModificationsCanRunOnRelation(Oid relationId);
|
extern void EnsureModificationsCanRunOnRelation(Oid relationId);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue