text: /* -------------------------------------------------------------------------
   *
   * pg_namespace.cpp
   *	  routines to support manipulation of the pg_namespace relation
   *
   * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
   * Portions Copyright (c) 1994, Regents of the University of California
   *
   *
   * IDENTIFICATION
   *	  src/common/backend/catalog/pg_namespace.cpp
   *
   * -------------------------------------------------------------------------
   */
  #include "postgres.h"
  #include "knl/knl_variable.h"
  
  #include "access/heapam.h"
  #include "access/transam.h"
  #include "catalog/dependency.h"
  #include "catalog/indexing.h"
  #include "catalog/namespace.h"
  #include "catalog/objectaccess.h"
  #include "catalog/pg_control.h"
  #include "catalog/pg_namespace.h"
  #include "pgxc/pgxc.h"
  #include "utils/builtins.h"
  #include "utils/rel.h"
  #include "utils/rel_gs.h"
  #include "utils/syscache.h"
  
  /* ----------------
   * NamespaceCreate
   *
   * Create a namespace (schema) with the given name and owner OID.
   *
   * If isTemp is true, this schema is a per-backend schema for holding
   * temporary tables.  Currently, the only effect of that is to prevent it
   * from being linked as a member of any active extension.  (If someone
   * does CREATE TEMP TABLE in an extension script, we don't want the temp
   * schema to become part of the extension.)
   * ---------------
   */
  Oid NamespaceCreate(const char* nspName, Oid ownerId, bool isTemp, bool hasBlockChain)
  {
      Relation nspdesc;
      HeapTuple tup;
      Oid nspoid;
      bool nulls[Natts_pg_namespace];
      Datum values[Natts_pg_namespace];
      NameData nname;
      TupleDesc tupDesc;
      ObjectAddress myself;
      int i;
  
      /* sanity checks */
      if (nspName == NULL)
          ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("no namespace name supplied")));
  
      /* make sure there is no existing namespace of same name */
      if (SearchSysCacheExists1(NAMESPACENAME, PointerGetDatum(nspName)))
          ereport(ERROR, (errcode(ERRCODE_DUPLICATE_SCHEMA), errmsg("schema \"%s\" already exists", nspName)));
  
      /* initialize nulls and values */
      for (i = 0; i < Natts_pg_namespace; i++) {
          nulls[i] = false;
          values[i] = (Datum)NULL;
      }
      (void)namestrcpy(&nname, nspName);
      values[Anum_pg_namespace_nspname - 1] = NameGetDatum(&nname);
      values[Anum_pg_namespace_nspowner - 1] = ObjectIdGetDatum(ownerId);
      values[Anum_pg_namespace_nspblockchain - 1] = hasBlockChain;
      if (IS_PGXC_DATANODE && !isSingleMode && !isRestoreMode && !u_sess->attr.attr_common.xc_maintenance_mode &&
          (isTempNamespaceName(nspName) || isToastTempNamespaceName(nspName)))
          values[Anum_pg_namespace_nsptimeline - 1] = get_controlfile_timeline();
      else
          values[Anum_pg_namespace_nsptimeline - 1] = 0; /* the controlfile_timeline is at least 1, so 0 is invalid */
      nulls[Anum_pg_namespace_nspacl - 1] = true;
  
      values[Anum_pg_namespace_in_redistribution - 1] = 'n';
      nspdesc = heap_open(NamespaceRelationId, RowExclusiveLock);
      tupDesc = nspdesc->rd_att;
  
      tup = heap_form_tuple(tupDesc, values, nulls);
  
      if (u_sess->attr.attr_common.IsInplaceUpgrade &&
          u_sess->upg_cxt.Inplace_upgrade_next_pg_namespace_oid != InvalidOid) {
          HeapTupleSetOid(tup, u_sess->upg_cxt.Inplace_upgrade_next_pg_namespace_oid);
          u_sess->upg_cxt.Inplace_upgrade_next_pg_namespace_oid = InvalidOid;
      }
  
      nspoid = simple_heap_insert(nspdesc, tup);
      Assert(OidIsValid(nspoid));
  
      CatalogUpdateIndexes(nspdesc, tup);
  
      heap_close(nspdesc, RowExclusiveLock);
  
      /* Record dependencies */
      myself.classId = NamespaceRelationId;
      myself.objectId = nspoid;
      myself.objectSubId = 0;
  
      if (u_sess->attr.attr_common.IsInplaceUpgrade && myself.objectId < FirstBootstrapObjectId)
          recordPinnedDependency(&myself);
      else {
          /* dependency on owner */
          recordDependencyOnOwner(NamespaceRelationId, nspoid, ownerId);
  
          /* dependency on extension ... but not for magic temp schemas */
          if (!isTemp)
              recordDependencyOnCurrentExtension(&myself, false);
      }
  
      /* Post creation hook for new schema */
      InvokeObjectAccessHook(OAT_POST_CREATE, NamespaceRelationId, nspoid, 0, NULL);
  
      return nspoid;
  }
  
  bool IsLedgerNameSpace(Oid nspOid)
  {
      if (!OidIsValid(nspOid)) {
          return false;
      }
      HeapTuple tuple;
      bool is_nspblockchain = false;
  
      tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nspOid));
      if (HeapTupleIsValid(tuple)) {
          bool is_null = true;
          Datum datum = SysCacheGetAttr(NAMESPACEOID, tuple, Anum_pg_namespace_nspblockchain, &is_null);
          if (!is_null) {
              is_nspblockchain = DatumGetBool(datum);
          }
          ReleaseSysCache(tuple);
      } else {
          ereport(ERROR, (errcode(ERRCODE_UNDEFINED_SCHEMA), errmsg("schema of oid \"%u\" does not exist", nspOid)));
      }
      return is_nspblockchain;
  }