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;

Reply via email to