You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hawq.apache.org by od...@apache.org on 2016/11/21 19:14:39 UTC

incubator-hawq git commit: HAWQ-1130. Make HCatalog integration work with non-superusers.

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 <od...@pivotal.io>
Authored: Mon Nov 21 11:14:01 2016 -0800
Committer: Oleksandr Diachenko <od...@pivotal.io>
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;