Error out if binary citus version does not match installed extension

With this change, we start to error out if loaded citus binaries does not match
the available major version or installed citus extension version. In this case
we force user to restart the server or run ALTER EXTENSION depending on the
situation
pull/1277/head
Burak Yucesoy 2017-03-09 16:11:27 +03:00 committed by Jason Petersen
parent bb5ae5eca4
commit 087d8427e3
No known key found for this signature in database
GPG Key ID: 9F1D3510D110ABA9
12 changed files with 478 additions and 122 deletions

View File

@ -13,14 +13,14 @@ include Makefile.global
all: extension all: extension
# build extension # build extension
extension: extension: $(citus_abs_srcdir)/src/include/citus_version.h
$(MAKE) -C src/backend/distributed/ all $(MAKE) -C src/backend/distributed/ all
install-extension: extension install-extension: extension
$(MAKE) -C src/backend/distributed/ install $(MAKE) -C src/backend/distributed/ install
install-headers: extension install-headers: extension
$(MKDIR_P) '$(DESTDIR)$(includedir_server)/distributed/' $(MKDIR_P) '$(DESTDIR)$(includedir_server)/distributed/'
# generated headers are located in the build directory # generated headers are located in the build directory
$(INSTALL_DATA) src/include/citus_config.h '$(DESTDIR)$(includedir_server)/' $(INSTALL_DATA) $(citus_abs_srcdir)/src/include/citus_config.h '$(DESTDIR)$(includedir_server)/'
# the rest in the source tree # the rest in the source tree
$(INSTALL_DATA) $(citus_abs_srcdir)/src/include/distributed/*.h '$(DESTDIR)$(includedir_server)/distributed/' $(INSTALL_DATA) $(citus_abs_srcdir)/src/include/distributed/*.h '$(DESTDIR)$(includedir_server)/distributed/'
clean-extension: clean-extension:

View File

@ -44,8 +44,8 @@ $(citus_top_builddir)/Makefile.global: $(citus_abs_top_srcdir)/configure $(citus
# Ensure configuration is generated by the most recent configure, # Ensure configuration is generated by the most recent configure,
# useful for longer existing build directories. # useful for longer existing build directories.
$(citus_top_builddir)/config.status: $(citus_abs_top_srcdir)/configure $(citus_top_builddir)/config.status: $(citus_abs_top_srcdir)/configure $(citus_abs_top_srcdir)/src/backend/distributed/citus.control
cd @abs_top_builddir@ && ./config.status --recheck cd @abs_top_builddir@ && ./config.status --recheck && ./config.status
# Regenerate configure if configure.in changed # Regenerate configure if configure.in changed
$(citus_abs_top_srcdir)/configure: $(citus_abs_top_srcdir)/configure.in $(citus_abs_top_srcdir)/configure: $(citus_abs_top_srcdir)/configure.in

58
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for Citus 5.0. # Generated by GNU Autoconf 2.69 for Citus 6.2devel.
# #
# #
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@ -9,7 +9,7 @@
# This configure script is free software; the Free Software Foundation # This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it. # gives unlimited permission to copy, distribute and modify it.
# #
# Copyright (c) 2012-2016, Citus Data, Inc. # Copyright (c) 2012-2017, Citus Data, Inc.
## -------------------- ## ## -------------------- ##
## M4sh Initialization. ## ## M4sh Initialization. ##
## -------------------- ## ## -------------------- ##
@ -579,8 +579,8 @@ MAKEFLAGS=
# Identity of this package. # Identity of this package.
PACKAGE_NAME='Citus' PACKAGE_NAME='Citus'
PACKAGE_TARNAME='citus' PACKAGE_TARNAME='citus'
PACKAGE_VERSION='5.0' PACKAGE_VERSION='6.2devel'
PACKAGE_STRING='Citus 5.0' PACKAGE_STRING='Citus 6.2devel'
PACKAGE_BUGREPORT='' PACKAGE_BUGREPORT=''
PACKAGE_URL='' PACKAGE_URL=''
@ -1194,7 +1194,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
\`configure' configures Citus 5.0 to adapt to many kinds of systems. \`configure' configures Citus 6.2devel to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1255,7 +1255,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of Citus 5.0:";; short | recursive ) echo "Configuration of Citus 6.2devel:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@ -1343,14 +1343,14 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
Citus configure 5.0 Citus configure 6.2devel
generated by GNU Autoconf 2.69 generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc. Copyright (C) 2012 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it. gives unlimited permission to copy, distribute and modify it.
Copyright (c) 2012-2016, Citus Data, Inc. Copyright (c) 2012-2017, Citus Data, Inc.
_ACEOF _ACEOF
exit exit
fi fi
@ -1400,7 +1400,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by Citus $as_me 5.0, which was It was created by Citus $as_me 6.2devel, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@ $ $0 $@
@ -1750,6 +1750,39 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
# CITUS_MAJORVERSION definition
CITUS_MAJORVERSION=`expr "$PACKAGE_VERSION" : '\([0-9][0-9]*\.[0-9][0-9]*\)'`
cat >>confdefs.h <<_ACEOF
#define CITUS_MAJORVERSION "$CITUS_MAJORVERSION"
_ACEOF
# CITUS_VERSION definition
cat >>confdefs.h <<_ACEOF
#define CITUS_VERSION "$PACKAGE_VERSION"
_ACEOF
# CITUS_VERSION_NUM definition
CITUS_VERSION_NUM="`echo "$PACKAGE_VERSION" | sed 's/[A-Za-z].*$//' |
tr '.' ' ' |
$AWK '{printf "%d%02d%02d", $1, $2, (NF >= 3) ? $3 : 0}'`"
cat >>confdefs.h <<_ACEOF
#define CITUS_VERSION_NUM $CITUS_VERSION_NUM
_ACEOF
# CITUS_EXTENSIONVERSION definition
citus_extensionversion=$(grep "^default_version" src/backend/distributed/citus.control | cut -d\' -f2)
cat >>confdefs.h <<_ACEOF
#define CITUS_EXTENSIONVERSION "$citus_extensionversion"
_ACEOF
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
$as_echo_n "checking for a sed that does not truncate output... " >&6; } $as_echo_n "checking for a sed that does not truncate output... " >&6; }
if ${ac_cv_path_SED+:} false; then : if ${ac_cv_path_SED+:} false; then :
@ -2974,7 +3007,7 @@ POSTGRES_BUILDDIR="$POSTGRES_BUILDDIR"
ac_config_files="$ac_config_files Makefile.global" ac_config_files="$ac_config_files Makefile.global"
ac_config_headers="$ac_config_headers src/include/citus_config.h" ac_config_headers="$ac_config_headers src/include/citus_config.h src/include/citus_version.h"
cat >confcache <<\_ACEOF cat >confcache <<\_ACEOF
@ -3483,7 +3516,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by Citus $as_me 5.0, which was This file was extended by Citus $as_me 6.2devel, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@ -3545,7 +3578,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\ ac_cs_version="\\
Citus config.status 5.0 Citus config.status 6.2devel
configured by $0, generated by GNU Autoconf 2.69, configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\" with options \\"\$ac_cs_config\\"
@ -3668,6 +3701,7 @@ do
case $ac_config_target in case $ac_config_target in
"Makefile.global") CONFIG_FILES="$CONFIG_FILES Makefile.global" ;; "Makefile.global") CONFIG_FILES="$CONFIG_FILES Makefile.global" ;;
"src/include/citus_config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/include/citus_config.h" ;; "src/include/citus_config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/include/citus_config.h" ;;
"src/include/citus_version.h") CONFIG_HEADERS="$CONFIG_HEADERS src/include/citus_version.h" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
esac esac

View File

@ -5,8 +5,25 @@
# everyone needing autoconf installed, the resulting files are checked # everyone needing autoconf installed, the resulting files are checked
# into the SCM. # into the SCM.
AC_INIT([Citus], [5.0], [], [citus], []) AC_INIT([Citus], [6.2devel])
AC_COPYRIGHT([Copyright (c) 2012-2016, Citus Data, Inc.]) AC_COPYRIGHT([Copyright (c) 2012-2017, Citus Data, Inc.])
# CITUS_MAJORVERSION definition
[CITUS_MAJORVERSION=`expr "$PACKAGE_VERSION" : '\([0-9][0-9]*\.[0-9][0-9]*\)'`]
AC_DEFINE_UNQUOTED(CITUS_MAJORVERSION, "$CITUS_MAJORVERSION", [Citus major version as a string])
# CITUS_VERSION definition
AC_DEFINE_UNQUOTED(CITUS_VERSION, "$PACKAGE_VERSION", [Citus version as a string])
# CITUS_VERSION_NUM definition
[CITUS_VERSION_NUM="`echo "$PACKAGE_VERSION" | sed 's/[A-Za-z].*$//' |
tr '.' ' ' |
$AWK '{printf "%d%02d%02d", $1, $2, (NF >= 3) ? $3 : 0}'`"]
AC_DEFINE_UNQUOTED(CITUS_VERSION_NUM, $CITUS_VERSION_NUM, [Citus version as a number])
# CITUS_EXTENSIONVERSION definition
citus_extensionversion=$(grep "^default_version" src/backend/distributed/citus.control | cut -d\' -f2)
AC_DEFINE_UNQUOTED([CITUS_EXTENSIONVERSION], "$citus_extensionversion", [so the shared-library knows its own version])
AC_PROG_SED AC_PROG_SED
@ -122,7 +139,7 @@ AC_SUBST(POSTGRES_SRCDIR, "$POSTGRES_SRCDIR")
AC_SUBST(POSTGRES_BUILDDIR, "$POSTGRES_BUILDDIR") AC_SUBST(POSTGRES_BUILDDIR, "$POSTGRES_BUILDDIR")
AC_CONFIG_FILES([Makefile.global]) AC_CONFIG_FILES([Makefile.global])
AC_CONFIG_HEADERS([src/include/citus_config.h]) AC_CONFIG_HEADERS([src/include/citus_config.h] [src/include/citus_version.h])
AH_TOP([ AH_TOP([
/* /*
* citus_config.h.in is generated by autoconf/autoheader and * citus_config.h.in is generated by autoconf/autoheader and

View File

@ -28,6 +28,7 @@
#include "catalog/namespace.h" #include "catalog/namespace.h"
#include "catalog/pg_attribute.h" #include "catalog/pg_attribute.h"
#include "catalog/pg_class.h" #include "catalog/pg_class.h"
#include "citus_version.h"
#include "commands/defrem.h" #include "commands/defrem.h"
#include "commands/tablecmds.h" #include "commands/tablecmds.h"
#include "commands/prepare.h" #include "commands/prepare.h"
@ -120,6 +121,7 @@ static char * DeparseVacuumColumnNames(List *columnNameList);
/* Local functions forward declarations for unsupported command checks */ /* Local functions forward declarations for unsupported command checks */
static void ErrorIfUnstableCreateOrAlterExtensionStmt(Node *parsetree);
static void ErrorIfUnsupportedIndexStmt(IndexStmt *createIndexStatement); static void ErrorIfUnsupportedIndexStmt(IndexStmt *createIndexStatement);
static void ErrorIfUnsupportedDropIndexStmt(DropStmt *dropIndexStatement); static void ErrorIfUnsupportedDropIndexStmt(DropStmt *dropIndexStatement);
static void ErrorIfUnsupportedAlterTableStmt(AlterTableStmt *alterTableStatement); static void ErrorIfUnsupportedAlterTableStmt(AlterTableStmt *alterTableStatement);
@ -170,6 +172,7 @@ multi_ProcessUtility(Node *parsetree,
Oid savedUserId = InvalidOid; Oid savedUserId = InvalidOid;
int savedSecurityContext = 0; int savedSecurityContext = 0;
List *ddlJobs = NIL; List *ddlJobs = NIL;
bool extensionStatement = false;
if (IsA(parsetree, TransactionStmt)) if (IsA(parsetree, TransactionStmt))
{ {
@ -185,6 +188,53 @@ multi_ProcessUtility(Node *parsetree,
return; return;
} }
if (IsA(parsetree, CreateExtensionStmt))
{
CreateExtensionStmt *createExtensionStmt = (CreateExtensionStmt *) parsetree;
if (strcmp(createExtensionStmt->extname, "citus") == 0)
{
ErrorIfUnstableCreateOrAlterExtensionStmt(parsetree);
}
extensionStatement = true;
}
if (IsA(parsetree, AlterExtensionStmt))
{
AlterExtensionStmt *alterExtensionStmt = (AlterExtensionStmt *) parsetree;
if (strcmp(alterExtensionStmt->extname, "citus") == 0)
{
ErrorIfUnstableCreateOrAlterExtensionStmt(parsetree);
}
extensionStatement = true;
}
if (IsA(parsetree, DropStmt))
{
DropStmt *dropStatement = (DropStmt *) parsetree;
if (dropStatement->removeType == OBJECT_EXTENSION)
{
extensionStatement = true;
}
}
if (extensionStatement)
{
/*
* In CitusHasBeenLoaded check below, we compare binary Citus version,
* extension version and available version. If they are different, we
* force user to execute ALTER EXTENSION citus UPDATE. Therefore, if
* user executes ALTER EXTENSION or DROP EXTENSION query we should drop
* to the standart utility before CitusHasBeenLoaded check.
*/
standard_ProcessUtility(parsetree, queryString, context,
params, dest, completionTag);
return;
}
if (!CitusHasBeenLoaded()) if (!CitusHasBeenLoaded())
{ {
/* /*
@ -1256,6 +1306,62 @@ DeparseVacuumColumnNames(List *columnNameList)
} }
/*
* ErrorIfUnstableCreateOrAlterExtensionStmt compares CITUS_EXTENSIONVERSION
* and version given CREATE/ALTER EXTENSION statement will create/update to. If
* they are not same in major or minor version numbers, this function errors
* out. It ignores the catalog version.
*/
static void
ErrorIfUnstableCreateOrAlterExtensionStmt(Node *parsetree)
{
List *optionsList = NIL;
ListCell *optionsCell = NULL;
if (IsA(parsetree, CreateExtensionStmt))
{
CreateExtensionStmt *createExtensionStmt = (CreateExtensionStmt *) parsetree;
optionsList = createExtensionStmt->options;
}
else if (IsA(parsetree, AlterExtensionStmt))
{
AlterExtensionStmt *alterExtensionStmt = (AlterExtensionStmt *) parsetree;
optionsList = alterExtensionStmt->options;
}
else
{
ereport(ERROR, (errmsg("unsupported node type, create or alter extension "
"is expected")));
}
foreach(optionsCell, optionsList)
{
DefElem *defElement = (DefElem *) lfirst(optionsCell);
if (strcmp(defElement->defname, "new_version") == 0)
{
char *newVersion = strVal(defElement->arg);
if (!CompareVersions(newVersion, CITUS_EXTENSIONVERSION))
{
ereport(ERROR, (errmsg("requested version is not compatible with "
"loaded Citus binaries.")));
}
return;
}
}
/*
* new_version is not specified in ALTER EXTENSION statement, PostgreSQL will use
* default_version from citus.control file. We will flush availableMajorVersion to
* re-check the available version from citus.control file.
*/
availableMajorVersion = NULL;
ErrorIfNewMajorVersionAvailable();
}
/* /*
* ErrorIfUnsupportedIndexStmt checks if the corresponding index statement is * ErrorIfUnsupportedIndexStmt checks if the corresponding index statement is
* supported for distributed tables and errors out if it is not. * supported for distributed tables and errors out if it is not.

View File

@ -16,6 +16,7 @@
#include "fmgr.h" #include "fmgr.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "citus_version.h"
#include "commands/explain.h" #include "commands/explain.h"
#include "executor/executor.h" #include "executor/executor.h"
#include "distributed/citus_nodefuncs.h" #include "distributed/citus_nodefuncs.h"
@ -48,6 +49,8 @@
/* marks shared object as one loadable by the postgres version compiled against */ /* marks shared object as one loadable by the postgres version compiled against */
PG_MODULE_MAGIC; PG_MODULE_MAGIC;
static char *CitusVersion;
void _PG_init(void); void _PG_init(void);
static void CreateRequiredDirectories(void); static void CreateRequiredDirectories(void);
@ -610,6 +613,16 @@ RegisterCitusConfigVariables(void)
0, 0,
NULL, NULL, NULL); NULL, NULL, NULL);
DefineCustomStringVariable(
"citus.version",
gettext_noop("Shows the running Citus version"),
NULL,
&CitusVersion,
CITUS_VERSION,
PGC_INTERNAL,
0,
NULL, NULL, NULL);
/* warn about config items in the citus namespace that are not registered above */ /* warn about config items in the citus namespace that are not registered above */
EmitWarningsOnPlaceholders("citus"); EmitWarningsOnPlaceholders("citus");
} }

View File

@ -22,6 +22,7 @@
#include "catalog/pg_extension.h" #include "catalog/pg_extension.h"
#include "catalog/pg_namespace.h" #include "catalog/pg_namespace.h"
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "citus_version.h"
#include "commands/extension.h" #include "commands/extension.h"
#include "commands/trigger.h" #include "commands/trigger.h"
#include "distributed/colocation_utils.h" #include "distributed/colocation_utils.h"
@ -35,6 +36,7 @@
#include "distributed/shardinterval_utils.h" #include "distributed/shardinterval_utils.h"
#include "distributed/worker_manager.h" #include "distributed/worker_manager.h"
#include "distributed/worker_protocol.h" #include "distributed/worker_protocol.h"
#include "executor/executor.h"
#include "parser/parse_func.h" #include "parser/parse_func.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/catcache.h" #include "utils/catcache.h"
@ -98,6 +100,10 @@ static Oid distTransactionRelationId = InvalidOid;
static Oid distTransactionGroupIndexId = InvalidOid; static Oid distTransactionGroupIndexId = InvalidOid;
static Oid extraDataContainerFuncId = InvalidOid; static Oid extraDataContainerFuncId = InvalidOid;
/* Citus installed extension version */
char *availableMajorVersion = NULL;
static char *installedExtensionVersion = NULL;
/* Hash table for informations about each partition */ /* Hash table for informations about each partition */
static HTAB *DistTableCacheHash = NULL; static HTAB *DistTableCacheHash = NULL;
@ -133,6 +139,9 @@ static bool HasUniformHashDistribution(ShardInterval **shardIntervalArray,
int shardIntervalArrayLength); int shardIntervalArrayLength);
static bool HasUninitializedShardInterval(ShardInterval **sortedShardIntervalArray, static bool HasUninitializedShardInterval(ShardInterval **sortedShardIntervalArray,
int shardCount); int shardCount);
static void ErrorIfExtensionUpdateNeeded(void);
static char * AvailableMajorVersion(void);
static char * InstalledExtensionVersion(void);
static void InitializeDistTableCache(void); static void InitializeDistTableCache(void);
static void InitializeWorkerNodeCache(void); static void InitializeWorkerNodeCache(void);
static uint32 WorkerNodeHashCode(const void *key, Size keySize); static uint32 WorkerNodeHashCode(const void *key, Size keySize);
@ -927,7 +936,7 @@ bool
CitusHasBeenLoaded(void) CitusHasBeenLoaded(void)
{ {
/* recheck presence until citus has been loaded */ /* recheck presence until citus has been loaded */
if (!extensionLoaded) if (!extensionLoaded || creating_extension)
{ {
bool extensionPresent = false; bool extensionPresent = false;
bool extensionScriptExecuted = true; bool extensionScriptExecuted = true;
@ -964,13 +973,246 @@ CitusHasBeenLoaded(void)
* present during early stages of upgrade operation. * present during early stages of upgrade operation.
*/ */
DistPartitionRelationId(); DistPartitionRelationId();
/*
* We also set installedExtensionVersion to NULL so that it will be re-read
* in case of extension update.
*/
installedExtensionVersion = NULL;
} }
} }
if (extensionLoaded)
{
ErrorIfNewMajorVersionAvailable();
ErrorIfExtensionUpdateNeeded();
}
return extensionLoaded; return extensionLoaded;
} }
/*
* ErrorIfNewMajorVersionAvailable compares CITUS_EXTENSIONVERSION and currently
* available version from citus.control file. If they are not same in major or
* minor version numbers, this function errors out. It ignores the schema version.
*/
void
ErrorIfNewMajorVersionAvailable(void)
{
char *availableVersion = AvailableMajorVersion();
if (!CompareVersions(availableVersion, CITUS_EXTENSIONVERSION))
{
ereport(ERROR, (errmsg("server restart is needed because, loaded Citus binaries "
"does not match the available extension version")));
}
}
/*
* ErrorIfExtensionUpdateNeeded compares CITUS_EXTENSIONVERSION and currently and
* catalog version from pg_extemsion catalog table. If they are not same in major or
* minor version numbers, this function errors out. It ignores the schema version.
*/
static void
ErrorIfExtensionUpdateNeeded(void)
{
char *installedVersion = InstalledExtensionVersion();
if (!CompareVersions(installedVersion, CITUS_EXTENSIONVERSION))
{
ereport(ERROR, (errmsg("\"ALTER EXTENSION citus UPDATE;\" is needed, because "
"loaded Citus binaries does not match the installed "
"extension version")));
}
}
/*
* CompareVersions compares given two versions. If they are same in major and
* minor version numbers, this function returns true. It ignores the schema version.
*/
bool
CompareVersions(char *leftVersion, char *rightVersion)
{
const char schemaVersionSeparator = '-';
char *seperatorPosition = strchr(leftVersion, schemaVersionSeparator);
int comparisionLimit = 0;
if (seperatorPosition != NULL)
{
comparisionLimit = seperatorPosition - leftVersion;
}
else
{
comparisionLimit = strlen(leftVersion);
}
return strncmp(leftVersion, rightVersion, comparisionLimit) == 0;
}
/*
* AvailableMajorVersion returns the Citus version from citus.control file. It also
* saves the result, thus consecutive calls to CitusExtensionAvailableVersion will
* not read the citus.control file again.
*/
static char *
AvailableMajorVersion(void)
{
ReturnSetInfo *extensionsResultSet = NULL;
TupleTableSlot *tupleTableSlot = NULL;
FunctionCallInfoData *fcinfo = NULL;
FmgrInfo *flinfo = NULL;
int argumentCount = 0;
EState *estate = NULL;
bool hasTuple = false;
bool goForward = true;
bool doCopy = false;
/* if we cached the result before, return it*/
if (availableMajorVersion != NULL)
{
return availableMajorVersion;
}
estate = CreateExecutorState();
extensionsResultSet = makeNode(ReturnSetInfo);
extensionsResultSet->econtext = GetPerTupleExprContext(estate);
extensionsResultSet->allowedModes = SFRM_Materialize;
fcinfo = palloc0(sizeof(FunctionCallInfoData));
flinfo = palloc0(sizeof(FmgrInfo));
fmgr_info(F_PG_AVAILABLE_EXTENSIONS, flinfo);
InitFunctionCallInfoData(*fcinfo, flinfo, argumentCount, InvalidOid, NULL,
(Node *) extensionsResultSet);
/* pg_available_extensions returns result set containing all available extensions */
(*pg_available_extensions)(fcinfo);
tupleTableSlot = MakeSingleTupleTableSlot(extensionsResultSet->setDesc);
hasTuple = tuplestore_gettupleslot(extensionsResultSet->setResult, goForward, doCopy,
tupleTableSlot);
while (hasTuple)
{
Datum extensionNameDatum = 0;
char *extensionName = NULL;
bool isNull = false;
extensionNameDatum = slot_getattr(tupleTableSlot, 1, &isNull);
extensionName = NameStr(*DatumGetName(extensionNameDatum));
if (strcmp(extensionName, "citus") == 0)
{
MemoryContext oldMemoryContext = NULL;
Datum citusVersionDatum = slot_getattr(tupleTableSlot, 2, &isNull);
/* we will cache the result of citus version to prevent catalog access */
if (CacheMemoryContext == NULL)
{
CreateCacheMemoryContext();
}
oldMemoryContext = MemoryContextSwitchTo(CacheMemoryContext);
availableMajorVersion = text_to_cstring(DatumGetTextPP(citusVersionDatum));
MemoryContextSwitchTo(oldMemoryContext);
ExecClearTuple(tupleTableSlot);
ExecDropSingleTupleTableSlot(tupleTableSlot);
return availableMajorVersion;
}
ExecClearTuple(tupleTableSlot);
hasTuple = tuplestore_gettupleslot(extensionsResultSet->setResult, goForward,
doCopy, tupleTableSlot);
}
ExecDropSingleTupleTableSlot(tupleTableSlot);
ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("citus extension is not found")));
return NULL;
}
/*
* InstalledExtensionVersion returns the Citus version in PostgreSQL pg_extension table.
* It also saves the result, thus consecutive calls to CitusExtensionCatalogVersion
* will not read the catalog tables again.
*/
static char *
InstalledExtensionVersion(void)
{
Relation relation = NULL;
SysScanDesc scandesc;
ScanKeyData entry[1];
HeapTuple extensionTuple = NULL;
/* if we cached the result before, return it*/
if (installedExtensionVersion != NULL)
{
return installedExtensionVersion;
}
relation = heap_open(ExtensionRelationId, AccessShareLock);
ScanKeyInit(&entry[0], Anum_pg_extension_extname, BTEqualStrategyNumber, F_NAMEEQ,
CStringGetDatum("citus"));
scandesc = systable_beginscan(relation, ExtensionNameIndexId, true,
NULL, 1, entry);
extensionTuple = systable_getnext(scandesc);
/* We assume that there can be at most one matching tuple */
if (HeapTupleIsValid(extensionTuple))
{
MemoryContext oldMemoryContext = NULL;
int extensionIndex = Anum_pg_extension_extversion;
TupleDesc tupleDescriptor = RelationGetDescr(relation);
bool isNull = false;
Datum extensionVersionDatum = heap_getattr(extensionTuple, extensionIndex,
tupleDescriptor, &isNull);
if (isNull)
{
ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("citus extension version is null")));
}
/* we will cache the result of citus version to prevent catalog access */
if (CacheMemoryContext == NULL)
{
CreateCacheMemoryContext();
}
oldMemoryContext = MemoryContextSwitchTo(CacheMemoryContext);
installedExtensionVersion = text_to_cstring(DatumGetTextPP(
extensionVersionDatum));
MemoryContextSwitchTo(oldMemoryContext);
}
else
{
ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("citus extension is not loaded")));
}
systable_endscan(scandesc);
heap_close(relation, AccessShareLock);
return installedExtensionVersion;
}
/* return oid of pg_dist_shard relation */ /* return oid of pg_dist_shard relation */
Oid Oid
DistShardRelationId(void) DistShardRelationId(void)

View File

@ -10,6 +10,18 @@
*/ */
/* so the shared-library knows its own version */
#undef CITUS_EXTENSIONVERSION
/* Citus major version as a string */
#undef CITUS_MAJORVERSION
/* Citus version as a string */
#undef CITUS_VERSION
/* Citus version as a number */
#undef CITUS_VERSION_NUM
/* Define to the address where bug reports for this package should be sent. */ /* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT #undef PACKAGE_BUGREPORT

View File

@ -0,0 +1,13 @@
/* This file is created manually */
/* so the shared-library knows its own version */
#undef CITUS_EXTENSIONVERSION
/* Citus major version as a string */
#undef CITUS_MAJORVERSION
/* Citus version as a string */
#undef CITUS_VERSION
/* Citus version as a number */
#undef CITUS_VERSION_NUM

View File

@ -17,6 +17,7 @@
#include "distributed/worker_manager.h" #include "distributed/worker_manager.h"
#include "utils/hsearch.h" #include "utils/hsearch.h"
extern char *availableMajorVersion;
/* /*
* Representation of a table's metadata that is frequently used for * Representation of a table's metadata that is frequently used for
@ -68,6 +69,8 @@ extern void CitusInvalidateRelcacheByRelid(Oid relationId);
extern void CitusInvalidateRelcacheByShardId(int64 shardId); extern void CitusInvalidateRelcacheByShardId(int64 shardId);
extern bool CitusHasBeenLoaded(void); extern bool CitusHasBeenLoaded(void);
void ErrorIfNewMajorVersionAvailable(void);
bool CompareVersions(char *leftVersion, char *rightVersion);
/* access WorkerNodeHash */ /* access WorkerNodeHash */
extern HTAB * GetWorkerNodeHash(void); extern HTAB * GetWorkerNodeHash(void);

View File

@ -24,59 +24,19 @@ WHERE pgd.refclassid = 'pg_extension'::regclass AND
-- DROP EXTENSION pre-created by the regression suite -- DROP EXTENSION pre-created by the regression suite
DROP EXTENSION citus; DROP EXTENSION citus;
\c \c
-- Create extension in oldest version, test every upgrade step -- Create extension in oldest version, this is expected to fail
CREATE EXTENSION citus VERSION '5.0'; CREATE EXTENSION citus VERSION '5.0';
ALTER EXTENSION citus UPDATE TO '5.0-1'; ERROR: requested version is not compatible with loaded Citus binaries.
ALTER EXTENSION citus UPDATE TO '5.0-2'; -- Create extension in newest major version, test every upgrade step
ALTER EXTENSION citus UPDATE TO '5.1-1'; CREATE EXTENSION citus VERSION '6.2-1';
ALTER EXTENSION citus UPDATE TO '5.1-2';
ALTER EXTENSION citus UPDATE TO '5.1-3';
ALTER EXTENSION citus UPDATE TO '5.1-4';
ALTER EXTENSION citus UPDATE TO '5.1-5';
ALTER EXTENSION citus UPDATE TO '5.1-6';
ALTER EXTENSION citus UPDATE TO '5.1-7';
ALTER EXTENSION citus UPDATE TO '5.1-8';
ALTER EXTENSION citus UPDATE TO '5.2-1';
ALTER EXTENSION citus UPDATE TO '5.2-2';
ALTER EXTENSION citus UPDATE TO '5.2-3';
ALTER EXTENSION citus UPDATE TO '5.2-4';
ALTER EXTENSION citus UPDATE TO '6.0-1';
ALTER EXTENSION citus UPDATE TO '6.0-2';
ALTER EXTENSION citus UPDATE TO '6.0-3';
ALTER EXTENSION citus UPDATE TO '6.0-4';
ALTER EXTENSION citus UPDATE TO '6.0-5';
ALTER EXTENSION citus UPDATE TO '6.0-6';
ALTER EXTENSION citus UPDATE TO '6.0-7';
ALTER EXTENSION citus UPDATE TO '6.0-8';
ALTER EXTENSION citus UPDATE TO '6.0-9';
ALTER EXTENSION citus UPDATE TO '6.0-10';
ALTER EXTENSION citus UPDATE TO '6.0-11';
ALTER EXTENSION citus UPDATE TO '6.0-12';
ALTER EXTENSION citus UPDATE TO '6.0-13';
ALTER EXTENSION citus UPDATE TO '6.0-14';
ALTER EXTENSION citus UPDATE TO '6.0-15';
ALTER EXTENSION citus UPDATE TO '6.0-16';
ALTER EXTENSION citus UPDATE TO '6.0-17';
ALTER EXTENSION citus UPDATE TO '6.0-18';
ALTER EXTENSION citus UPDATE TO '6.1-1';
ALTER EXTENSION citus UPDATE TO '6.1-2';
ALTER EXTENSION citus UPDATE TO '6.1-3';
ALTER EXTENSION citus UPDATE TO '6.1-4';
ALTER EXTENSION citus UPDATE TO '6.1-5';
ALTER EXTENSION citus UPDATE TO '6.1-6';
ALTER EXTENSION citus UPDATE TO '6.1-7';
ALTER EXTENSION citus UPDATE TO '6.1-8';
ALTER EXTENSION citus UPDATE TO '6.1-9';
ALTER EXTENSION citus UPDATE TO '6.1-10';
ALTER EXTENSION citus UPDATE TO '6.1-11';
ALTER EXTENSION citus UPDATE TO '6.1-12';
ALTER EXTENSION citus UPDATE TO '6.1-13';
ALTER EXTENSION citus UPDATE TO '6.1-14';
ALTER EXTENSION citus UPDATE TO '6.1-15';
ALTER EXTENSION citus UPDATE TO '6.1-16';
ALTER EXTENSION citus UPDATE TO '6.1-17';
ALTER EXTENSION citus UPDATE TO '6.2-1';
ALTER EXTENSION citus UPDATE TO '6.2-2'; ALTER EXTENSION citus UPDATE TO '6.2-2';
-- show running version
SHOW citus.version;
citus.version
---------------
6.2devel
(1 row)
-- ensure no objects were created outside pg_catalog -- ensure no objects were created outside pg_catalog
SELECT COUNT(*) SELECT COUNT(*)
FROM pg_depend AS pgd, FROM pg_depend AS pgd,

View File

@ -24,60 +24,16 @@ WHERE pgd.refclassid = 'pg_extension'::regclass AND
DROP EXTENSION citus; DROP EXTENSION citus;
\c \c
-- Create extension in oldest version, test every upgrade step -- Create extension in oldest version, this is expected to fail
CREATE EXTENSION citus VERSION '5.0'; CREATE EXTENSION citus VERSION '5.0';
ALTER EXTENSION citus UPDATE TO '5.0-1';
ALTER EXTENSION citus UPDATE TO '5.0-2'; -- Create extension in newest major version, test every upgrade step
ALTER EXTENSION citus UPDATE TO '5.1-1'; CREATE EXTENSION citus VERSION '6.2-1';
ALTER EXTENSION citus UPDATE TO '5.1-2';
ALTER EXTENSION citus UPDATE TO '5.1-3';
ALTER EXTENSION citus UPDATE TO '5.1-4';
ALTER EXTENSION citus UPDATE TO '5.1-5';
ALTER EXTENSION citus UPDATE TO '5.1-6';
ALTER EXTENSION citus UPDATE TO '5.1-7';
ALTER EXTENSION citus UPDATE TO '5.1-8';
ALTER EXTENSION citus UPDATE TO '5.2-1';
ALTER EXTENSION citus UPDATE TO '5.2-2';
ALTER EXTENSION citus UPDATE TO '5.2-3';
ALTER EXTENSION citus UPDATE TO '5.2-4';
ALTER EXTENSION citus UPDATE TO '6.0-1';
ALTER EXTENSION citus UPDATE TO '6.0-2';
ALTER EXTENSION citus UPDATE TO '6.0-3';
ALTER EXTENSION citus UPDATE TO '6.0-4';
ALTER EXTENSION citus UPDATE TO '6.0-5';
ALTER EXTENSION citus UPDATE TO '6.0-6';
ALTER EXTENSION citus UPDATE TO '6.0-7';
ALTER EXTENSION citus UPDATE TO '6.0-8';
ALTER EXTENSION citus UPDATE TO '6.0-9';
ALTER EXTENSION citus UPDATE TO '6.0-10';
ALTER EXTENSION citus UPDATE TO '6.0-11';
ALTER EXTENSION citus UPDATE TO '6.0-12';
ALTER EXTENSION citus UPDATE TO '6.0-13';
ALTER EXTENSION citus UPDATE TO '6.0-14';
ALTER EXTENSION citus UPDATE TO '6.0-15';
ALTER EXTENSION citus UPDATE TO '6.0-16';
ALTER EXTENSION citus UPDATE TO '6.0-17';
ALTER EXTENSION citus UPDATE TO '6.0-18';
ALTER EXTENSION citus UPDATE TO '6.1-1';
ALTER EXTENSION citus UPDATE TO '6.1-2';
ALTER EXTENSION citus UPDATE TO '6.1-3';
ALTER EXTENSION citus UPDATE TO '6.1-4';
ALTER EXTENSION citus UPDATE TO '6.1-5';
ALTER EXTENSION citus UPDATE TO '6.1-6';
ALTER EXTENSION citus UPDATE TO '6.1-7';
ALTER EXTENSION citus UPDATE TO '6.1-8';
ALTER EXTENSION citus UPDATE TO '6.1-9';
ALTER EXTENSION citus UPDATE TO '6.1-10';
ALTER EXTENSION citus UPDATE TO '6.1-11';
ALTER EXTENSION citus UPDATE TO '6.1-12';
ALTER EXTENSION citus UPDATE TO '6.1-13';
ALTER EXTENSION citus UPDATE TO '6.1-14';
ALTER EXTENSION citus UPDATE TO '6.1-15';
ALTER EXTENSION citus UPDATE TO '6.1-16';
ALTER EXTENSION citus UPDATE TO '6.1-17';
ALTER EXTENSION citus UPDATE TO '6.2-1';
ALTER EXTENSION citus UPDATE TO '6.2-2'; ALTER EXTENSION citus UPDATE TO '6.2-2';
-- show running version
SHOW citus.version;
-- ensure no objects were created outside pg_catalog -- ensure no objects were created outside pg_catalog
SELECT COUNT(*) SELECT COUNT(*)
FROM pg_depend AS pgd, FROM pg_depend AS pgd,