blob: 3af143a92faba6aa0583b1aeb0261a7cd510a9c1 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/*-------------------------------------------------------------------------
*
* cdbdirectopen.c
*
*-------------------------------------------------------------------------
*/
#include "cdb/cdbdirectopen.h"
#include "utils/guc.h"
#include "storage/smgr.h"
#include "utils/memutils.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_am.h"
#include "catalog/pg_index.h"
#include "catalog/pg_opclass.h"
#include "utils/builtins.h"
#include "cdb/cdbvars.h"
/*
* pg_class.
*/
static FormData_pg_class
DatabaseInfo_PgClassPgClass =
{Class_pg_class};
static FormData_pg_attribute
DatabaseInfo_PgClassAttrArray[Natts_pg_class] =
{Schema_pg_class};
DirectOpenDefineStatic(DirectOpen_PgClass,\
DatabaseInfo_PgClassPgClass,\
DatabaseInfo_PgClassAttrArray,\
true);
/*
* gp_relation_node.
*/
static FormData_pg_class
DatabaseInfo_GpRelfileNodePgClass =
{Class_gp_relfile_node};
static FormData_pg_attribute
DatabaseInfo_GpRelfileNodeAttrArray[Natts_gp_relfile_node] =
{Schema_gp_relfile_node};
DirectOpenDefineStatic(DirectOpen_GpRelfileNode,\
DatabaseInfo_GpRelfileNodePgClass,\
DatabaseInfo_GpRelfileNodeAttrArray,\
false);
/*
* pg_appendonly.
*/
static FormData_pg_class
DatabaseInfo_PgAppendOnlyPgClass =
{Class_pg_appendonly};
static FormData_pg_attribute
DatabaseInfo_PgAppendOnlyAttrArray[Natts_pg_appendonly] =
{Schema_pg_appendonly};
DirectOpenDefineStatic(DirectOpen_PgAppendOnly,\
DatabaseInfo_PgAppendOnlyPgClass,\
DatabaseInfo_PgAppendOnlyAttrArray,\
false);
/*
* pg_aogseg.
*/
static FormData_pg_class
DatabaseInfo_PgAoSegPgClass =
{Class_pg_aoseg};
static FormData_pg_attribute
DatabaseInfo_PgAoSegAttrArray[Natts_pg_aoseg] =
{Schema_pg_aoseg};
DirectOpenDefineStatic(DirectOpen_PgAoSeg,\
DatabaseInfo_PgAoSegPgClass,\
DatabaseInfo_PgAoSegAttrArray,\
false);
/*
* gp_global_sequence.
*/
static FormData_pg_class
GlobalSequence_PgClass =
{Class_gp_global_sequence};
static FormData_pg_attribute
GlobalSequence_AttrArray[Natts_gp_global_sequence] =
{Schema_gp_global_sequence};
DirectOpenDefineStatic(DirectOpen_GpGlobalSequence,\
GlobalSequence_PgClass,\
GlobalSequence_AttrArray,\
false);
/*
* gp_persistent_relfile_node.
*/
static FormData_pg_class
PersistentFileSysObj_RelfilePgClass =
{Class_gp_persistent_relfile_node};
static FormData_pg_attribute
PersistentFileSysObj_RelfileAttrArray[Natts_gp_persistent_relfile_node] =
{Schema_gp_persistent_relfile_node};
DirectOpenDefineStatic(DirectOpen_GpPersistentRelfileNode,\
PersistentFileSysObj_RelfilePgClass,\
PersistentFileSysObj_RelfileAttrArray,\
false);
/*
* gp_persistent_relation_node.
*/
static FormData_pg_class
PersistentFileSysObj_RelationPgClass =
{Class_gp_persistent_relation_node};
static FormData_pg_attribute
PersistentFileSysObj_RelationAttrArray[Natts_gp_persistent_relation_node] =
{Schema_gp_persistent_relation_node};
DirectOpenDefineStatic(DirectOpen_GpPersistentRelationNode,\
PersistentFileSysObj_RelationPgClass,\
PersistentFileSysObj_RelationAttrArray,\
false);
/*
* gp_persistent_database_node.
*/
static FormData_pg_class
PersistentFileSysObj_DatabasePgClass =
{Class_gp_persistent_database_node};
static FormData_pg_attribute
PersistentFileSysObj_DatabaseAttrArray[Natts_gp_persistent_database_node] =
{Schema_gp_persistent_database_node};
DirectOpenDefineStatic(DirectOpen_GpPersistentDatabaseNode,\
PersistentFileSysObj_DatabasePgClass,\
PersistentFileSysObj_DatabaseAttrArray,\
false);
/*
* This HUGE MAGIC DEFINE expands into module globals and two routines:
* PersistentFileSysObj_TablespaceOpenShared
* PersistentFileSysObj_TablespaceClose
* It allows for opening the relation without going through pg_class, etc.
*/
static FormData_pg_class
PersistentFileSysObj_TablespacePgClass =
{Class_gp_persistent_tablespace_node};
static FormData_pg_attribute
PersistentFileSysObj_TablespaceAttrArray[Natts_gp_persistent_tablespace_node] =
{Schema_gp_persistent_tablespace_node};
DirectOpenDefineStatic(DirectOpen_GpPersistentTableSpaceNode,\
PersistentFileSysObj_TablespacePgClass,\
PersistentFileSysObj_TablespaceAttrArray,\
false);
/*
* This HUGE MAGIC DEFINE expands into module globals and two routines:
* PersistentFileSysObj_FilespaceOpenShared
* PersistentFileSysObj_FilespaceClose
* It allows for opening the relation without going through pg_class, etc.
*/
static FormData_pg_class
PersistentFileSysObj_FilespacePgClass =
{Class_gp_persistent_filespace_node};
static FormData_pg_attribute
PersistentFileSysObj_FilespaceAttrArray[Natts_gp_persistent_filespace_node] =
{Schema_gp_persistent_filespace_node};
DirectOpenDefineStatic(DirectOpen_GpPersistentFileSpaceNode,\
PersistentFileSysObj_FilespacePgClass,\
PersistentFileSysObj_FilespaceAttrArray,\
false);
// INDEX Variants
/*
* gp_relation_node_index.
*/
static FormData_pg_class
DatabaseInfo_GpRelfileNodeIndexPgClass =
{Class_gp_relfile_node_index};
static FormData_pg_attribute
DatabaseInfo_GpRelfileNodeIndexAttrArray[Natts_gp_relfile_node_index] =
{Schema_gp_relfile_node_index};
static FormData_pg_am
DatabaseInfo_GpRelfileNodeIndexPgAm =
{Am_gp_relfile_node_index};
static FormData_pg_index
DatabaseInfo_GpRelfileNodeIndexPgIndex =
{Index_gp_relfile_node_index};
static int2 DatabaseInfo_GpRelfileNodeIndexIndKeyArray[Natts_gp_relfile_node_index] =
{IndKey_gp_relfile_node_index};
static Oid DatabaseInfo_GpRelfileNodeIndexIndClassArray[Natts_gp_relfile_node_index] =
{IndClass_gp_relfile_node_index};
DirectOpenIndexDefineStatic(DirectOpen_GpRelfileNodeIndex,\
DatabaseInfo_GpRelfileNodeIndexPgClass,\
DatabaseInfo_GpRelfileNodeIndexAttrArray,\
DatabaseInfo_GpRelfileNodeIndexPgAm,\
DatabaseInfo_GpRelfileNodeIndexPgIndex,\
DatabaseInfo_GpRelfileNodeIndexIndKeyArray,\
DatabaseInfo_GpRelfileNodeIndexIndClassArray,\
false);
Relation DirectOpen_Open(
DirectOpen *direct,
Oid relationId,
Oid tablespace,
Oid database,
Oid relfilenode,
FormData_pg_class *pgClass,
FormData_pg_attribute *attrArray,
FormData_pg_am *pgAm,
FormData_pg_index *pgIndex,
int2 *indKeyArray,
Oid *indClassArray,
bool relHasOid)
{
int natts;
int i;
Assert(pgClass != NULL);
natts = pgClass->relnatts;
if (relationId == -1)
relationId = pgClass->relfilenode; // Assume it is ok to use the relfilenode as the relationId in our limited usage.
if (relfilenode == -1)
relfilenode = pgClass->relfilenode;
if (!direct->isInit)
{
/*
* Lots of Hard-coded construction of the gp_persistent* RelationS and
* dependent objects like tuple descriptors, etc.
*/
direct->relationData.rd_refcnt = 0;
direct->relationData.rd_isvalid = true;
direct->relationData.rd_id = relationId;
direct->relationData.rd_rel = pgClass;
if (pgIndex != NULL)
{
int pgIndexFixedLen = offsetof(FormData_pg_index, indkey);
int indKeyVectorLen = Int2VectorSize(natts);
int2vector *indKeyVector;
uint16 amstrategies;
uint16 amsupport;
Oid *operator;
RegProcedure *support;
FmgrInfo *supportinfo;
Assert(pgAm != NULL);
Assert(indKeyArray != NULL);
Assert(indClassArray != NULL);
/*
* Allocate Formdata_pg_index with fields through indkey
* where indkey is a variable length int2vector with indKeyArray values.
*/
direct->relationData.rd_index =
(FormData_pg_index*)palloc(
pgIndexFixedLen + indKeyVectorLen);
memcpy(direct->relationData.rd_index, pgIndex, pgIndexFixedLen);
indKeyVector = buildint2vector(
indKeyArray,
natts);
memcpy(
&direct->relationData.rd_index->indkey,
indKeyVector,
indKeyVectorLen);
pfree(indKeyVector);
/*
* Create oidvector in rd_indclass with values from indClassArray.
*/
direct->relationData.rd_indclass =
buildoidvector(
indClassArray,
natts);
direct->relationData.rd_am = pgAm;
amstrategies = pgAm->amstrategies;
amsupport = pgAm->amsupport;
direct->relationData.rd_indexcxt = TopMemoryContext;
/*
* Allocate arrays to hold data
*/
direct->relationData.rd_aminfo = (RelationAmInfo *)
MemoryContextAllocZero(TopMemoryContext, sizeof(RelationAmInfo));
if (amstrategies > 0)
operator = (Oid *)
MemoryContextAllocZero(TopMemoryContext,
natts * amstrategies * sizeof(Oid));
else
operator = NULL;
if (amsupport > 0)
{
int nsupport = natts * amsupport;
support = (RegProcedure *)
MemoryContextAllocZero(TopMemoryContext, nsupport * sizeof(RegProcedure));
supportinfo = (FmgrInfo *)
MemoryContextAllocZero(TopMemoryContext, nsupport * sizeof(FmgrInfo));
}
else
{
support = NULL;
supportinfo = NULL;
}
direct->relationData.rd_operator = operator;
direct->relationData.rd_support = support;
direct->relationData.rd_supportinfo = supportinfo;
/*
* Fill the operator and support procedure OID arrays. (aminfo and
* supportinfo are left as zeroes, and are filled on-the-fly when used)
*/
IndexSupportInitialize(direct->relationData.rd_indclass,
operator, support,
amstrategies, amsupport, natts);
/*
* expressions and predicate cache will be filled later.
*/
direct->relationData.rd_indexprs = NIL;
direct->relationData.rd_indpred = NIL;
direct->relationData.rd_amcache = NULL;
}
// Not much in terms of contraints.
direct->constrData.has_not_null = true;
/*
* Setup tuple descriptor for columns.
*/
direct->descData.natts = pgClass->relnatts;
// Make the array of pointers.
direct->descData.attrs =
(Form_pg_attribute*)
MemoryContextAllocZero(
TopMemoryContext,
sizeof(Form_pg_attribute*) * pgClass->relnatts);
for (i = 0; i < pgClass->relnatts; i++)
{
direct->descData.attrs[i] =
(Form_pg_attribute)
MemoryContextAllocZero(
TopMemoryContext,
sizeof(FormData_pg_attribute));
memcpy(direct->descData.attrs[i], &(attrArray[i]), sizeof(FormData_pg_attribute));
// Patch up relation id.
direct->descData.attrs[i]->attrelid = relationId;
}
direct->descData.constr = &direct->constrData;
direct->descData.tdtypeid = pgClass->reltype;
direct->descData.tdtypmod = -1;
direct->descData.tdhasoid = relHasOid;
direct->descData.tdrefcount = 1;
direct->relationData.rd_att = &direct->descData;
direct->pgStat.t_id = relationId;
direct->pgStat.t_shared = 1;
direct->relationData.pgstat_info = &direct->pgStat;
direct->relationData.rd_relationnodeinfo.isPresent = FALSE;
direct->relationData.rd_relationnodeinfo.tidAllowedToBeZero = FALSE;
direct->isInit = true;
}
// UNDONE: Should verify for NON-SHARED relations we don't open relations in different databases / or
// UNDONE: open different relations in same database at same time !!!
direct->relationData.rd_node.spcNode = tablespace;
direct->relationData.rd_node.dbNode = database;
direct->relationData.rd_node.relNode = relfilenode;
for (i = 0; i < direct->relationData.rd_rel->relnatts; i++)
{
Assert(direct->descData.attrs[i] != NULL);
// Patch up relation id.
direct->descData.attrs[i]->attrelid = direct->relationData.rd_id;
}
direct->relationData.rd_refcnt++;
RelationOpenSmgr(&direct->relationData);
return &direct->relationData;
}
void DirectOpen_Close(
DirectOpen *direct,
Relation rel)
{
Assert(rel == &direct->relationData);
Assert (direct->isInit);
RelationCloseSmgr(&direct->relationData);
Assert(direct->relationData.rd_refcnt > 0);
direct->relationData.rd_refcnt--;
}