/* * makeWholeRowVar - * creates a Var node representing a whole row of the specified RTE * * A whole-row reference is a Var with varno set to the correct range * table entry, and varattno == 0 to signal that it references the whole * tuple. (Use of zero here is unclean, since it could easily be confused * with error cases, but it's not worth changing now.) The vartype indicates * a rowtype; either a named composite type, or RECORD. This function * encapsulates the logic for determining the correct rowtype OID to use. * * If allowScalar is true, then for the case where the RTE is a function * returning a non-composite result type, we produce a normal Var referencing * the function's result directly, instead of the single-column composite * value that the whole-row notation might otherwise suggest. */ Var * makeWholeRowVar(RangeTblEntry *rte, Index varno, Index varlevelsup, bool allowScalar) { Var *result; Oid toid; switch (rte->rtekind) { case RTE_RELATION: /* relation: the rowtype is a named composite type */ toid = get_rel_type_id(rte->relid); if (!OidIsValid(toid)) elog(ERROR, "could not find type OID for relation %u", rte->relid); result = makeVar(varno, InvalidAttrNumber, toid, -1, InvalidOid, varlevelsup); break; case RTE_FUNCTION: toid = exprType(rte->funcexpr); if (type_is_rowtype(toid)) { /* func returns composite; same as relation case */ result = makeVar(varno, InvalidAttrNumber, toid, -1, InvalidOid, varlevelsup); } else if (allowScalar) { /* func returns scalar; just return its output as-is */ result = makeVar(varno, 1, toid, -1, exprCollation(rte->funcexpr), varlevelsup); } else { /* func returns scalar, but we want a composite result */ result = makeVar(varno, InvalidAttrNumber, RECORDOID, -1, InvalidOid, varlevelsup); } break; default: /* * RTE is a join, subselect, or VALUES. We represent this as a * whole-row Var of RECORD type. (Note that in most cases the Var * will be expanded to a RowExpr during planning, but that is not * our concern here.) */ result = makeVar(varno, InvalidAttrNumber, RECORDOID, -1, InvalidOid, varlevelsup); break; } return result; }
/* * makeWholeRowVar - * creates a Var node representing a whole row of the specified RTE * * A whole-row reference is a Var with varno set to the correct range * table entry, and varattno == 0 to signal that it references the whole * tuple. (Use of zero here is unclean, since it could easily be confused * with error cases, but it's not worth changing now.) The vartype indicates * a rowtype; either a named composite type, or RECORD. This function * encapsulates the logic for determining the correct rowtype OID to use. */ Var * makeWholeRowVar(RangeTblEntry *rte, Index varno, Index varlevelsup) { Var *result; Oid toid; switch (rte->rtekind) { case RTE_RELATION: /* relation: the rowtype is a named composite type */ toid = get_rel_type_id(rte->relid); if (!OidIsValid(toid)) elog(ERROR, "could not find type OID for relation %u", rte->relid); result = makeVar(varno, InvalidAttrNumber, toid, -1, InvalidOid, varlevelsup); break; case RTE_FUNCTION: toid = exprType(rte->funcexpr); if (type_is_rowtype(toid)) { /* func returns composite; same as relation case */ result = makeVar(varno, InvalidAttrNumber, toid, -1, InvalidOid, varlevelsup); } else { /* * func returns scalar; instead of making a whole-row Var, * just reference the function's scalar output. (XXX this * seems a tad inconsistent, especially if "f.*" was * explicitly written ...) */ result = makeVar(varno, 1, toid, -1, InvalidOid, varlevelsup); } break; case RTE_VALUES: toid = RECORDOID; /* returns composite; same as relation case */ result = makeVar(varno, InvalidAttrNumber, toid, -1, InvalidOid, varlevelsup); break; default: /* * RTE is a join or subselect. We represent this as a whole-row * Var of RECORD type. (Note that in most cases the Var will be * expanded to a RowExpr during planning, but that is not our * concern here.) */ result = makeVar(varno, InvalidAttrNumber, RECORDOID, -1, InvalidOid, varlevelsup); break; } return result; }
/* * makeWholeRowVar - * creates a Var node representing a whole row of the specified RTE * * A whole-row reference is a Var with varno set to the correct range * table entry, and varattno == 0 to signal that it references the whole * tuple. (Use of zero here is unclean, since it could easily be confused * with error cases, but it's not worth changing now.) The vartype indicates * a rowtype; either a named composite type, or RECORD. This function * encapsulates the logic for determining the correct rowtype OID to use. * * If allowScalar is true, then for the case where the RTE is a single function * returning a non-composite result type, we produce a normal Var referencing * the function's result directly, instead of the single-column composite * value that the whole-row notation might otherwise suggest. */ Var * makeWholeRowVar(RangeTblEntry *rte, Index varno, Index varlevelsup, bool allowScalar) { Var *result; Oid toid; Node *fexpr; switch (rte->rtekind) { case RTE_RELATION: /* relation: the rowtype is a named composite type */ toid = get_rel_type_id(rte->relid); if (!OidIsValid(toid)) elog(ERROR, "could not find type OID for relation %u", rte->relid); result = makeVar(varno, InvalidAttrNumber, toid, -1, InvalidOid, varlevelsup); break; case RTE_FUNCTION: /* * If there's more than one function, or ordinality is requested, * force a RECORD result, since there's certainly more than one * column involved and it can't be a known named type. */ if (rte->funcordinality || list_length(rte->functions) != 1) { /* always produces an anonymous RECORD result */ result = makeVar(varno, InvalidAttrNumber, RECORDOID, -1, InvalidOid, varlevelsup); break; } fexpr = ((RangeTblFunction *) linitial(rte->functions))->funcexpr; toid = exprType(fexpr); if (type_is_rowtype(toid)) { /* func returns composite; same as relation case */ result = makeVar(varno, InvalidAttrNumber, toid, -1, InvalidOid, varlevelsup); } else if (allowScalar) { /* func returns scalar; just return its output as-is */ result = makeVar(varno, 1, toid, -1, exprCollation(fexpr), varlevelsup); } else { /* func returns scalar, but we want a composite result */ result = makeVar(varno, InvalidAttrNumber, RECORDOID, -1, InvalidOid, varlevelsup); } break; default: /* * RTE is a join, subselect, or VALUES. We represent this as a * whole-row Var of RECORD type. (Note that in most cases the Var * will be expanded to a RowExpr during planning, but that is not * our concern here.) */ result = makeVar(varno, InvalidAttrNumber, RECORDOID, -1, InvalidOid, varlevelsup); break; } return result; }
void _bitmap_create_lov_heapandindex(Relation rel, Oid lovComptypeOid, Oid *lovHeapOid, Oid *lovIndexOid, Oid lovHeapRelfilenode, Oid lovIndexRelfilenode) { char lovHeapName[NAMEDATALEN]; char lovIndexName[NAMEDATALEN]; TupleDesc tupDesc; IndexInfo *indexInfo; ObjectAddress objAddr, referenced; Oid *classObjectId; int16 *coloptions; Oid heapid; Oid idxid; int indattrs; int i; Oid unusedArrayOid = InvalidOid; Assert(rel != NULL); /* create the new names for the new lov heap and index */ snprintf(lovHeapName, sizeof(lovHeapName), "pg_bm_%u", RelationGetRelid(rel)); snprintf(lovIndexName, sizeof(lovIndexName), "pg_bm_%u_index", RelationGetRelid(rel)); heapid = get_relname_relid(lovHeapName, PG_BITMAPINDEX_NAMESPACE); /* * If heapid exists, then this is happening during re-indexing. * We allocate new relfilenodes for lov heap and lov index. * * XXX Each segment db may have different relfilenodes for lov heap and * lov index, which should not be an issue now. Ideally, we would like each * segment db use the same oids. */ if (OidIsValid(heapid)) { Relation lovHeap; Relation lovIndex; Buffer btree_metabuf; Page btree_metapage; *lovHeapOid = heapid; idxid = get_relname_relid(lovIndexName, PG_BITMAPINDEX_NAMESPACE); Assert(OidIsValid(idxid)); *lovIndexOid = idxid; lovComptypeOid = get_rel_type_id(heapid); Assert(OidIsValid(lovComptypeOid)); lovHeap = heap_open(heapid, AccessExclusiveLock); lovIndex = index_open(idxid, AccessExclusiveLock); if (OidIsValid(lovHeapRelfilenode)) setNewRelfilenodeToOid(lovHeap, lovHeapRelfilenode); else setNewRelfilenode(lovHeap); if (OidIsValid(lovIndexRelfilenode)) setNewRelfilenodeToOid(lovIndex, lovIndexRelfilenode); else setNewRelfilenode(lovIndex); /* * After creating the new relfilenode for a btee index, this is not * a btree anymore. We create the new metapage for this btree. */ btree_metabuf = _bt_getbuf(lovIndex, P_NEW, BT_WRITE); Assert (BTREE_METAPAGE == BufferGetBlockNumber(btree_metabuf)); btree_metapage = BufferGetPage(btree_metabuf); _bt_initmetapage(btree_metapage, P_NONE, 0); /* XLOG the metapage */ if (!XLog_UnconvertedCanBypassWal() && !lovIndex->rd_istemp) { // Fetch gp_persistent_relation_node information that will be added to XLOG record. RelationFetchGpRelationNodeForXLog(lovIndex); _bt_lognewpage(lovIndex, btree_metapage, BufferGetBlockNumber(btree_metabuf)); } /* This cache value is not valid anymore. */ if (lovIndex->rd_amcache) { pfree(lovIndex->rd_amcache); lovIndex->rd_amcache = NULL; } MarkBufferDirty(btree_metabuf); _bt_relbuf(lovIndex, btree_metabuf); index_close(lovIndex, NoLock); heap_close(lovHeap, NoLock); return; } /* * create a new empty heap to store all attribute values with their * corresponding block number and offset in LOV. */ tupDesc = _bitmap_create_lov_heapTupleDesc(rel); Assert(rel->rd_rel != NULL); heapid = heap_create_with_catalog(lovHeapName, PG_BITMAPINDEX_NAMESPACE, rel->rd_rel->reltablespace, *lovHeapOid, rel->rd_rel->relowner, tupDesc, /* relam */ InvalidOid, RELKIND_RELATION, RELSTORAGE_HEAP, rel->rd_rel->relisshared, false, /* bufferPoolBulkLoad */ false, 0, ONCOMMIT_NOOP, NULL /* GP Policy */, (Datum)0, true, /* valid_opts */ true, &lovComptypeOid, &unusedArrayOid, /* persistentTid */ NULL, /* persistentSerialNum */ NULL); Assert(heapid == *lovHeapOid); /* * We must bump the command counter to make the newly-created relation * tuple visible for opening. */ CommandCounterIncrement(); objAddr.classId = RelationRelationId; objAddr.objectId = *lovHeapOid; objAddr.objectSubId = 0 ; referenced.classId = RelationRelationId; referenced.objectId = RelationGetRelid(rel); referenced.objectSubId = 0; recordDependencyOn(&objAddr, &referenced, DEPENDENCY_INTERNAL); /* * create a btree index on the newly-created heap. * The key includes all attributes to be indexed in this bitmap index. */ indattrs = tupDesc->natts - 2; indexInfo = makeNode(IndexInfo); indexInfo->ii_NumIndexAttrs = indattrs; indexInfo->ii_Expressions = NIL; indexInfo->ii_ExpressionsState = NIL; indexInfo->ii_Predicate = make_ands_implicit(NULL); indexInfo->ii_PredicateState = NIL; indexInfo->ii_Unique = true; indexInfo->opaque = NULL; classObjectId = (Oid *) palloc(indattrs * sizeof(Oid)); coloptions = (int16 *) palloc(indattrs * sizeof(int16)); for (i = 0; i < indattrs; i++) { Oid typid = tupDesc->attrs[i]->atttypid; indexInfo->ii_KeyAttrNumbers[i] = i + 1; classObjectId[i] = GetDefaultOpClass(typid, BTREE_AM_OID); coloptions[i] = 0; } idxid = index_create(*lovHeapOid, lovIndexName, *lovIndexOid, indexInfo, BTREE_AM_OID, rel->rd_rel->reltablespace, classObjectId, coloptions, 0, false, false, (Oid *) NULL, true, false, false, NULL); Assert(idxid == *lovIndexOid); }