diff --git a/src/backend/columnar/columnar_storage.c b/src/backend/columnar/columnar_storage.c index 4aa2ae24d..a73275249 100644 --- a/src/backend/columnar/columnar_storage.c +++ b/src/backend/columnar/columnar_storage.c @@ -87,6 +87,10 @@ typedef struct PhysicalAddr #define COLUMNAR_FIRST_STRIPE_ID 1 +#define OLD_METAPAGE_VERSION_HINT "Use \"VACUUM\" to upgrade the columnar table format " \ + "version or run \"ALTER EXTENSION citus UPDATE\"." + + /* * Map logical offsets to a physical page and offset where the data is kept. */ @@ -325,7 +329,7 @@ ColumnarStorageGetReservedOffset(Relation rel, bool force) /* - * ColumnarMetapageNeedsUpgrade - return true if metapage exists and is not + * ColumnarStorageIsCurrent - return true if metapage exists and is not * the current version. */ bool @@ -610,13 +614,27 @@ ColumnarMetapageRead(Relation rel, bool force) BlockNumber nblocks = smgrnblocks(rel->rd_smgr, MAIN_FORKNUM); if (nblocks == 0) { - elog(ERROR, "columnar metapage for relation \"%s\" does not exist", - RelationGetRelationName(rel)); + /* + * We only expect this to happen during binary ugrades. This is because, + * in current version of columnar, we immediately create the metapage + * for columnar tables, i.e right after creating the table. + * However in older versions, we were creating metapages lazily, i.e + * when ingesting data to columnar table. + */ + ereport(ERROR, (errmsg("columnar metapage for relation \"%s\" does not exist", + RelationGetRelationName(rel)), + errhint(OLD_METAPAGE_VERSION_HINT))); } + /* + * Regardless of "force" parameter, always force read metapage block. + * We will check metapage version in ColumnarMetapageCheckVersion + * depending on "force". + */ + bool forceReadBlock = true; ColumnarMetapage metapage; ReadFromBlock(rel, COLUMNAR_METAPAGE_BLOCKNO, SizeOfPageHeaderData, - (char *) &metapage, sizeof(ColumnarMetapage), force); + (char *) &metapage, sizeof(ColumnarMetapage), forceReadBlock); if (!force) { @@ -786,7 +804,6 @@ ColumnarMetapageCheckVersion(Relation rel, ColumnarMetapage *metapage) COLUMNAR_VERSION_MAJOR, COLUMNAR_VERSION_MINOR, RelationGetRelationName(rel), metapage->versionMajor, metapage->versionMinor), - errhint( - "Use VACUUM to upgrade the columnar table format version."))); + errhint(OLD_METAPAGE_VERSION_HINT))); } } diff --git a/src/backend/columnar/columnar_tableam.c b/src/backend/columnar/columnar_tableam.c index f9d0626b2..2dfcb945e 100644 --- a/src/backend/columnar/columnar_tableam.c +++ b/src/backend/columnar/columnar_tableam.c @@ -696,6 +696,14 @@ static void columnar_vacuum_rel(Relation rel, VacuumParams *params, BufferAccessStrategy bstrategy) { + /* + * If metapage version of relation is older, then we hint users to VACUUM + * the relation in ColumnarMetapageCheckVersion. So if needed, upgrade + * the metapage before doing anything. + */ + bool isUpgrade = true; + ColumnarStorageUpdateIfNeeded(rel, isUpgrade); + int elevel = (params->options & VACOPT_VERBOSE) ? INFO : DEBUG2; /* this should have been resolved by vacuum.c until now */ diff --git a/src/backend/columnar/sql/downgrades/columnar--10.1-1--10.0-3.sql b/src/backend/columnar/sql/downgrades/columnar--10.1-1--10.0-3.sql index 11b9dfe95..6473f1524 100644 --- a/src/backend/columnar/sql/downgrades/columnar--10.1-1--10.0-3.sql +++ b/src/backend/columnar/sql/downgrades/columnar--10.1-1--10.0-3.sql @@ -12,7 +12,7 @@ REFERENCES columnar.stripe(storage_id, stripe_num) ON DELETE CASCADE; -- define columnar_ensure_objects_exist again #include "../udfs/columnar_ensure_objects_exist/10.0-1.sql" --- upgrade storage for all columnar relations +-- downgrade storage for all columnar relations SELECT citus_internal.downgrade_columnar_storage(c.oid) FROM pg_class c, pg_am a WHERE c.relam = a.oid AND amname = 'columnar';