Repository: incubator-hawq Updated Branches: refs/heads/master 38b447d7e -> 475dbb5cb
HAWQ-1130. Make HCatalog integration work with non-superusers. Project: http://git-wip-us.apache.org/repos/asf/incubator-hawq/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-hawq/commit/475dbb5c Tree: http://git-wip-us.apache.org/repos/asf/incubator-hawq/tree/475dbb5c Diff: http://git-wip-us.apache.org/repos/asf/incubator-hawq/diff/475dbb5c Branch: refs/heads/master Commit: 475dbb5cb264177199a9722ca2f0b7f2c8c6743b Parents: 38b447d Author: Oleksandr Diachenko <[email protected]> Authored: Mon Nov 21 11:14:01 2016 -0800 Committer: Oleksandr Diachenko <[email protected]> Committed: Mon Nov 21 11:14:01 2016 -0800 ---------------------------------------------------------------------- src/backend/access/transam/varsup.c | 143 ++++++++++++++++++++++--------- 1 file changed, 103 insertions(+), 40 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/475dbb5c/src/backend/access/transam/varsup.c ---------------------------------------------------------------------- diff --git a/src/backend/access/transam/varsup.c b/src/backend/access/transam/varsup.c index fadefd5..73a4769 100644 --- a/src/backend/access/transam/varsup.c +++ b/src/backend/access/transam/varsup.c @@ -16,6 +16,7 @@ #include "access/clog.h" #include "access/subtrans.h" #include "access/transam.h" +#include "catalog/catquery.h" #include "executor/spi.h" #include "miscadmin.h" #include "postmaster/autovacuum.h" @@ -408,6 +409,9 @@ GetNewExternalObjectId(void) /* * must perform check on External Oid range on * initial access of NextExternalOid + * + * It's needed for upgrade scenario from old version + * of HAWQ which doesn't support dedicated oid pool for HCatalog objects */ if (!IsExternalOidInitialized) { @@ -416,6 +420,11 @@ GetNewExternalObjectId(void) ResetExternalObjectId(); } + /* + * This check is needed for upgrade from old HAWQ versions, which don't support + * oid pool for HCatalog objects. + * In current implementation max oid will be always less than FirstExternalObjectId. + */ if (!IsValidExternalOidRange) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_RESOURCES), @@ -474,74 +483,128 @@ ResetExternalObjectId(void) /* * master_highest_used_oid - * Query the database to find the highest used Oid by + * Uses CAQL and SPI to find the highest used Oid among user and catalog tables + * + * Uses CAQL to query catalog tables + * Uses SPI to query user tables, because CAQL supports tables from CatCoreRelation array only * 1) Find all the relations that has Oids * 2) Find max oid from those relations */ Oid master_highest_used_oid(void) { + Oid oidMaxCatalog = InvalidOid; + Oid oidMaxUser = InvalidOid; Oid oidMax = InvalidOid; + Oid currentOid; + Form_pg_class classForm; + cqContext *pcqOuterCtx; + cqContext *pcqInnerCtx; + HeapTuple outerTuple; + HeapTuple innerTuple; + /* number of user tables having oids*/ + int userTablesNum = 0; + int ret; + + pcqOuterCtx = caql_beginscan(NULL, cql("SELECT * FROM pg_class WHERE relhasoids = :1", BoolGetDatum(true))); - if (SPI_OK_CONNECT != SPI_connect()) + outerTuple = caql_getnext(pcqOuterCtx); + + if (!HeapTupleIsValid(outerTuple)) { - ereport(ERROR, (errcode(ERRCODE_CDB_INTERNAL_ERROR), - errmsg("Unable to connect to execute internal query for HCatalog."))); + caql_endscan(pcqOuterCtx); + elog(DEBUG1, "Unable to get list of tables having oids"); + return oidMax; } - int ret = SPI_execute("SELECT relname FROM pg_class where relhasoids=true", true, 0); + /* construct query to get max oid from all tables with oids */ + StringInfo sqlstrCatalog = makeStringInfo(); + StringInfo sqlstrUser = makeStringInfo(); + appendStringInfo(sqlstrUser, "SELECT max(oid) FROM ("); + while (HeapTupleIsValid(outerTuple)) + { + classForm = (Form_pg_class) GETSTRUCT(outerTuple); - int rows = SPI_processed; + /* use CAQL for accessing catalog tables*/ + if (classForm->relnamespace == PG_CATALOG_NAMESPACE) + { + appendStringInfo(sqlstrCatalog, + "SELECT oid FROM %s WHERE oid > :1 ORDER BY oid", + classForm->relname.data); - char *tableNames[rows]; + pcqInnerCtx = caql_beginscan(NULL, + cql1(sqlstrCatalog->data, __FILE__, __LINE__, + ObjectIdGetDatum(oidMaxCatalog))); - if (rows == 0 || ret <= 0 || NULL == SPI_tuptable) - { - SPI_finish(); - return oidMax; - } + innerTuple = caql_getnext(pcqInnerCtx); - TupleDesc tupdesc = SPI_tuptable->tupdesc; - SPITupleTable *tuptable = SPI_tuptable; + currentOid = InvalidOid; - for (int i = 0; i < rows; i++) - { - HeapTuple tuple = tuptable->vals[i]; - tableNames[i] = SPI_getvalue(tuple, tupdesc, 1); - } + while (HeapTupleIsValid(innerTuple)) + { + currentOid = HeapTupleGetOid(innerTuple); + innerTuple = caql_getnext(pcqInnerCtx); + } - /* construct query to get max oid from all tables with oids */ - StringInfoData sqlstr; - initStringInfo(&sqlstr); - appendStringInfo(&sqlstr, "SELECT max(oid) FROM ("); - for (int i = 0; i < rows; i++) - { - if (i > 0) + elog(DEBUG1, "Max Oid in catalog table %s: %d", classForm->relname.data, currentOid); + + caql_endscan(pcqInnerCtx); + + oidMaxCatalog = currentOid > oidMaxCatalog ? currentOid : oidMaxCatalog; + + resetStringInfo(sqlstrCatalog); + } + else + /* use SPI for user tables*/ { - appendStringInfo(&sqlstr, " UNION ALL "); + userTablesNum++; + { + if (userTablesNum > 1) + { + appendStringInfo(sqlstrUser, " UNION ALL "); + } + appendStringInfo(sqlstrUser, "SELECT MAX(oid) AS oid FROM %s", classForm->relname.data); + } } - appendStringInfo(&sqlstr, "SELECT max(oid) AS oid FROM %s", tableNames[i]); + + outerTuple = caql_getnext(pcqOuterCtx); } - appendStringInfo(&sqlstr, ") AS x"); - ret = SPI_execute(sqlstr.data, true, 1); + caql_endscan(pcqOuterCtx); - if (ret > 0 && NULL != SPI_tuptable) - { - TupleDesc tupdesc = SPI_tuptable->tupdesc; - SPITupleTable *tuptable = SPI_tuptable; - HeapTuple tuple = tuptable->vals[0]; - char *oidString = SPI_getvalue(tuple, tupdesc, 1); - if (NULL != oidString) + if (userTablesNum) { + + appendStringInfo(sqlstrUser, ") AS x"); + + if (SPI_OK_CONNECT != SPI_connect()) { - oidMax = DatumGetObjectId(DirectFunctionCall1(oidin, CStringGetDatum(oidString))); + ereport(ERROR, (errcode(ERRCODE_CDB_INTERNAL_ERROR), + errmsg("Unable to connect to execute internal query for HCatalog."))); } - } - pfree(sqlstr.data); + ret = SPI_execute(sqlstrUser->data, true, 1); + if (ret > 0 && NULL != SPI_tuptable) { + TupleDesc tupdesc = SPI_tuptable->tupdesc; + SPITupleTable *tuptable = SPI_tuptable; + HeapTuple tuple = tuptable->vals[0]; + char *oidString = SPI_getvalue(tuple, tupdesc, 1); + if (NULL != oidString) + { + oidMaxUser = DatumGetObjectId(DirectFunctionCall1(oidin, CStringGetDatum(oidString))); + } + } + } + + pfree(sqlstrCatalog->data); + pfree(sqlstrUser->data); SPI_finish(); + elog(DEBUG1, "Highest Oid currently in use among catalog tables: %u", oidMaxCatalog); + elog(DEBUG1, "Highest Oid currently in use among user tables having oid: %u", oidMaxUser); + + oidMax = oidMaxCatalog > oidMaxUser ? oidMaxCatalog : oidMaxUser; + elog(DEBUG1, "Highest Oid currently in use: %u", oidMax); return oidMax;
