#include "postgres.h"#include "access/htup_details.h"#include "access/multixact.h"#include "access/sysattr.h"#include "access/transam.h"#include "access/xact.h"#include "catalog/catalog.h"#include "catalog/dependency.h"#include "catalog/heap.h"#include "catalog/index.h"#include "catalog/objectaccess.h"#include "catalog/pg_attrdef.h"#include "catalog/pg_collation.h"#include "catalog/pg_constraint.h"#include "catalog/pg_foreign_table.h"#include "catalog/pg_inherits.h"#include "catalog/pg_namespace.h"#include "catalog/pg_statistic.h"#include "catalog/pg_tablespace.h"#include "catalog/pg_type.h"#include "catalog/pg_type_fn.h"#include "catalog/storage.h"#include "catalog/storage_xlog.h"#include "commands/tablecmds.h"#include "commands/typecmds.h"#include "miscadmin.h"#include "nodes/nodeFuncs.h"#include "optimizer/var.h"#include "parser/parse_coerce.h"#include "parser/parse_collate.h"#include "parser/parse_expr.h"#include "parser/parse_relation.h"#include "storage/predicate.h"#include "storage/smgr.h"#include "utils/acl.h"#include "utils/builtins.h"#include "utils/fmgroids.h"#include "utils/inval.h"#include "utils/lsyscache.h"#include "utils/rel.h"#include "utils/snapmgr.h"#include "utils/syscache.h"#include "utils/tqual.h"
Go to the source code of this file.
Functions | |
| static void | AddNewRelationTuple (Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Oid new_type_oid, Oid reloftype, Oid relowner, char relkind, Datum relacl, Datum reloptions) |
| static Oid | AddNewRelationType (const char *typeName, Oid typeNamespace, Oid new_rel_oid, char new_rel_kind, Oid ownerid, Oid new_row_type, Oid new_array_type) |
| static void | RelationRemoveInheritance (Oid relid) |
| static void | StoreRelCheck (Relation rel, char *ccname, Node *expr, bool is_validated, bool is_local, int inhcount, bool is_no_inherit, bool is_internal) |
| static void | StoreConstraints (Relation rel, List *cooked_constraints, bool is_internal) |
| static bool | MergeWithExistingConstraint (Relation rel, char *ccname, Node *expr, bool allow_merge, bool is_local, bool is_no_inherit) |
| static void | SetRelationNumChecks (Relation rel, int numchecks) |
| static Node * | cookConstraint (ParseState *pstate, Node *raw_constraint, char *relname) |
| static List * | insert_ordered_unique_oid (List *list, Oid datum) |
| Form_pg_attribute | SystemAttributeDefinition (AttrNumber attno, bool relhasoids) |
| Form_pg_attribute | SystemAttributeByName (const char *attname, bool relhasoids) |
| Relation | heap_create (const char *relname, Oid relnamespace, Oid reltablespace, Oid relid, Oid relfilenode, TupleDesc tupDesc, char relkind, char relpersistence, bool shared_relation, bool mapped_relation) |
| void | CheckAttributeNamesTypes (TupleDesc tupdesc, char relkind, bool allow_system_table_mods) |
| void | CheckAttributeType (const char *attname, Oid atttypid, Oid attcollation, List *containing_rowtypes, bool allow_system_table_mods) |
| void | InsertPgAttributeTuple (Relation pg_attribute_rel, Form_pg_attribute new_attribute, CatalogIndexState indstate) |
| static void | AddNewAttributeTuples (Oid new_rel_oid, TupleDesc tupdesc, char relkind, bool oidislocal, int oidinhcount) |
| void | InsertPgClassTuple (Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Datum relacl, Datum reloptions) |
| Oid | heap_create_with_catalog (const char *relname, Oid relnamespace, Oid reltablespace, Oid relid, Oid reltypeid, Oid reloftypeid, Oid ownerid, TupleDesc tupdesc, List *cooked_constraints, char relkind, char relpersistence, bool shared_relation, bool mapped_relation, bool oidislocal, int oidinhcount, OnCommitAction oncommit, Datum reloptions, bool use_user_acl, bool allow_system_table_mods, bool is_internal) |
| void | heap_create_init_fork (Relation rel) |
| bool | heap_is_matview_init_state (Relation rel) |
| void | DeleteRelationTuple (Oid relid) |
| void | DeleteAttributeTuples (Oid relid) |
| void | DeleteSystemAttributeTuples (Oid relid) |
| void | RemoveAttributeById (Oid relid, AttrNumber attnum) |
| void | RemoveAttrDefault (Oid relid, AttrNumber attnum, DropBehavior behavior, bool complain, bool internal) |
| void | RemoveAttrDefaultById (Oid attrdefId) |
| void | heap_drop_with_catalog (Oid relid) |
| void | StoreAttrDefault (Relation rel, AttrNumber attnum, Node *expr, bool is_internal) |
| List * | AddRelationNewConstraints (Relation rel, List *newColDefaults, List *newConstraints, bool allow_merge, bool is_local, bool is_internal) |
| Node * | cookDefault (ParseState *pstate, Node *raw_default, Oid atttypid, int32 atttypmod, char *attname) |
| void | RemoveStatistics (Oid relid, AttrNumber attnum) |
| static void | RelationTruncateIndexes (Relation heapRelation) |
| void | heap_truncate (List *relids) |
| void | heap_truncate_one_rel (Relation rel) |
| void | heap_truncate_check_FKs (List *relations, bool tempTables) |
| List * | heap_truncate_find_FKs (List *relationIds) |
Variables | |
| Oid | binary_upgrade_next_heap_pg_class_oid = InvalidOid |
| Oid | binary_upgrade_next_toast_pg_class_oid = InvalidOid |
| static FormData_pg_attribute | a1 |
| static FormData_pg_attribute | a2 |
| static FormData_pg_attribute | a3 |
| static FormData_pg_attribute | a4 |
| static FormData_pg_attribute | a5 |
| static FormData_pg_attribute | a6 |
| static FormData_pg_attribute | a7 |
| static const Form_pg_attribute | SysAtt [] = {&a1, &a2, &a3, &a4, &a5, &a6, &a7} |
| static void AddNewAttributeTuples | ( | Oid | new_rel_oid, | |
| TupleDesc | tupdesc, | |||
| char | relkind, | |||
| bool | oidislocal, | |||
| int | oidinhcount | |||
| ) | [static] |
Definition at line 634 of file heap.c.
References AttributeRelationId, tupleDesc::attrs, CatalogCloseIndexes(), CatalogOpenIndexes(), ObjectAddress::classId, DEFAULT_COLLATION_OID, DEPENDENCY_NORMAL, FormData_pg_attribute, heap_close, heap_open(), i, InsertPgAttributeTuple(), lengthof, tupleDesc::natts, ObjectAddress::objectId, ObjectIdAttributeNumber, ObjectAddress::objectSubId, OidIsValid, recordDependencyOn(), RELKIND_COMPOSITE_TYPE, RELKIND_VIEW, RowExclusiveLock, and tupleDesc::tdhasoid.
Referenced by heap_create_with_catalog().
{
Form_pg_attribute attr;
int i;
Relation rel;
CatalogIndexState indstate;
int natts = tupdesc->natts;
ObjectAddress myself,
referenced;
/*
* open pg_attribute and its indexes.
*/
rel = heap_open(AttributeRelationId, RowExclusiveLock);
indstate = CatalogOpenIndexes(rel);
/*
* First we add the user attributes. This is also a convenient place to
* add dependencies on their datatypes and collations.
*/
for (i = 0; i < natts; i++)
{
attr = tupdesc->attrs[i];
/* Fill in the correct relation OID */
attr->attrelid = new_rel_oid;
/* Make sure these are OK, too */
attr->attstattarget = -1;
attr->attcacheoff = -1;
InsertPgAttributeTuple(rel, attr, indstate);
/* Add dependency info */
myself.classId = RelationRelationId;
myself.objectId = new_rel_oid;
myself.objectSubId = i + 1;
referenced.classId = TypeRelationId;
referenced.objectId = attr->atttypid;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
/* The default collation is pinned, so don't bother recording it */
if (OidIsValid(attr->attcollation) &&
attr->attcollation != DEFAULT_COLLATION_OID)
{
referenced.classId = CollationRelationId;
referenced.objectId = attr->attcollation;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
}
/*
* Next we add the system attributes. Skip OID if rel has no OIDs. Skip
* all for a view or type relation. We don't bother with making datatype
* dependencies here, since presumably all these types are pinned.
*/
if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
{
for (i = 0; i < (int) lengthof(SysAtt); i++)
{
FormData_pg_attribute attStruct;
/* skip OID where appropriate */
if (!tupdesc->tdhasoid &&
SysAtt[i]->attnum == ObjectIdAttributeNumber)
continue;
memcpy(&attStruct, (char *) SysAtt[i], sizeof(FormData_pg_attribute));
/* Fill in the correct relation OID in the copied tuple */
attStruct.attrelid = new_rel_oid;
/* Fill in correct inheritance info for the OID column */
if (attStruct.attnum == ObjectIdAttributeNumber)
{
attStruct.attislocal = oidislocal;
attStruct.attinhcount = oidinhcount;
}
InsertPgAttributeTuple(rel, &attStruct, indstate);
}
}
/*
* clean up
*/
CatalogCloseIndexes(indstate);
heap_close(rel, RowExclusiveLock);
}
| static void AddNewRelationTuple | ( | Relation | pg_class_desc, | |
| Relation | new_rel_desc, | |||
| Oid | new_rel_oid, | |||
| Oid | new_type_oid, | |||
| Oid | reloftype, | |||
| Oid | relowner, | |||
| char | relkind, | |||
| Datum | relacl, | |||
| Datum | reloptions | |||
| ) | [static] |
Definition at line 818 of file heap.c.
References GetOldestMultiXactId(), InsertPgClassTuple(), RelationData::rd_att, RelationData::rd_rel, RecentXmin, RELKIND_INDEX, RELKIND_MATVIEW, RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_TOASTVALUE, and tupleDesc::tdtypeid.
Referenced by heap_create_with_catalog().
{
Form_pg_class new_rel_reltup;
/*
* first we update some of the information in our uncataloged relation's
* relation descriptor.
*/
new_rel_reltup = new_rel_desc->rd_rel;
switch (relkind)
{
case RELKIND_RELATION:
case RELKIND_MATVIEW:
case RELKIND_INDEX:
case RELKIND_TOASTVALUE:
/* The relation is real, but as yet empty */
new_rel_reltup->relpages = 0;
new_rel_reltup->reltuples = 0;
new_rel_reltup->relallvisible = 0;
break;
case RELKIND_SEQUENCE:
/* Sequences always have a known size */
new_rel_reltup->relpages = 1;
new_rel_reltup->reltuples = 1;
new_rel_reltup->relallvisible = 0;
break;
default:
/* Views, etc, have no disk storage */
new_rel_reltup->relpages = 0;
new_rel_reltup->reltuples = 0;
new_rel_reltup->relallvisible = 0;
break;
}
/* Initialize relfrozenxid and relminmxid */
if (relkind == RELKIND_RELATION ||
relkind == RELKIND_MATVIEW ||
relkind == RELKIND_TOASTVALUE)
{
/*
* Initialize to the minimum XID that could put tuples in the table.
* We know that no xacts older than RecentXmin are still running, so
* that will do.
*/
new_rel_reltup->relfrozenxid = RecentXmin;
/*
* Similarly, initialize the minimum Multixact to the first value that
* could possibly be stored in tuples in the table. Running
* transactions could reuse values from their local cache, so we are
* careful to consider all currently running multis.
*
* XXX this could be refined further, but is it worth the hassle?
*/
new_rel_reltup->relminmxid = GetOldestMultiXactId();
}
else
{
/*
* Other relation types will not contain XIDs, so set relfrozenxid to
* InvalidTransactionId. (Note: a sequence does contain a tuple, but
* we force its xmin to be FrozenTransactionId always; see
* commands/sequence.c.)
*/
new_rel_reltup->relfrozenxid = InvalidTransactionId;
new_rel_reltup->relfrozenxid = InvalidMultiXactId;
}
new_rel_reltup->relowner = relowner;
new_rel_reltup->reltype = new_type_oid;
new_rel_reltup->reloftype = reloftype;
new_rel_desc->rd_att->tdtypeid = new_type_oid;
/* Now build and insert the tuple */
InsertPgClassTuple(pg_class_desc, new_rel_desc, new_rel_oid,
relacl, reloptions);
}
| static Oid AddNewRelationType | ( | const char * | typeName, | |
| Oid | typeNamespace, | |||
| Oid | new_rel_oid, | |||
| char | new_rel_kind, | |||
| Oid | ownerid, | |||
| Oid | new_row_type, | |||
| Oid | new_array_type | |||
| ) | [static] |
Definition at line 913 of file heap.c.
References DEFAULT_TYPDELIM, InvalidOid, NULL, TYPCATEGORY_COMPOSITE, TypeCreate(), and TYPTYPE_COMPOSITE.
Referenced by heap_create_with_catalog().
{
return
TypeCreate(new_row_type, /* optional predetermined OID */
typeName, /* type name */
typeNamespace, /* type namespace */
new_rel_oid, /* relation oid */
new_rel_kind, /* relation kind */
ownerid, /* owner's ID */
-1, /* internal size (varlena) */
TYPTYPE_COMPOSITE, /* type-type (composite) */
TYPCATEGORY_COMPOSITE, /* type-category (ditto) */
false, /* composite types are never preferred */
DEFAULT_TYPDELIM, /* default array delimiter */
F_RECORD_IN, /* input procedure */
F_RECORD_OUT, /* output procedure */
F_RECORD_RECV, /* receive procedure */
F_RECORD_SEND, /* send procedure */
InvalidOid, /* typmodin procedure - none */
InvalidOid, /* typmodout procedure - none */
InvalidOid, /* analyze procedure - default */
InvalidOid, /* array element type - irrelevant */
false, /* this is not an array type */
new_array_type, /* array type if any */
InvalidOid, /* domain base type - irrelevant */
NULL, /* default value - none */
NULL, /* default binary representation */
false, /* passed by reference */
'd', /* alignment - must be the largest! */
'x', /* fully TOASTable */
-1, /* typmod */
0, /* array dimensions for typBaseType */
false, /* Type NOT NULL */
InvalidOid); /* rowtypes never have a collation */
}
| List* AddRelationNewConstraints | ( | Relation | rel, | |
| List * | newColDefaults, | |||
| List * | newConstraints, | |||
| bool | allow_merge, | |||
| bool | is_local, | |||
| bool | is_internal | |||
| ) |
Definition at line 2122 of file heap.c.
References addRangeTableEntryForRelation(), addRTEtoQuery(), Assert, CookedConstraint::attnum, RawColumnDefault::attnum, tupleDesc::attrs, ChooseConstraintName(), Constraint::conname, tupleDesc::constr, CONSTR_CHECK, Constraint::contype, CookedConstraint::contype, cookConstraint(), cookDefault(), Constraint::cooked_expr, ereport, errcode(), errmsg(), ERROR, CookedConstraint::expr, get_attname(), CookedConstraint::inhcount, CookedConstraint::is_local, Constraint::is_no_inherit, CookedConstraint::is_no_inherit, IsA, lappend(), lfirst, linitial, list_length(), list_union(), make_parsestate(), MergeWithExistingConstraint(), CookedConstraint::name, NameStr, NIL, NULL, tupleConstr::num_check, palloc(), pull_var_clause(), PVC_REJECT_AGGREGATES, PVC_REJECT_PLACEHOLDERS, RawColumnDefault::raw_default, Constraint::raw_expr, RelationData::rd_att, RelationGetDescr, RelationGetNamespace, RelationGetRelationName, RelationGetRelid, SetRelationNumChecks(), Constraint::skip_validation, CookedConstraint::skip_validation, StoreAttrDefault(), StoreRelCheck(), and stringToNode().
Referenced by ATAddCheckConstraint(), ATExecAddColumn(), ATExecColumnDefault(), and DefineRelation().
{
List *cookedConstraints = NIL;
TupleDesc tupleDesc;
TupleConstr *oldconstr;
int numoldchecks;
ParseState *pstate;
RangeTblEntry *rte;
int numchecks;
List *checknames;
ListCell *cell;
Node *expr;
CookedConstraint *cooked;
/*
* Get info about existing constraints.
*/
tupleDesc = RelationGetDescr(rel);
oldconstr = tupleDesc->constr;
if (oldconstr)
numoldchecks = oldconstr->num_check;
else
numoldchecks = 0;
/*
* Create a dummy ParseState and insert the target relation as its sole
* rangetable entry. We need a ParseState for transformExpr.
*/
pstate = make_parsestate(NULL);
rte = addRangeTableEntryForRelation(pstate,
rel,
NULL,
false,
true);
addRTEtoQuery(pstate, rte, true, true, true);
/*
* Process column default expressions.
*/
foreach(cell, newColDefaults)
{
RawColumnDefault *colDef = (RawColumnDefault *) lfirst(cell);
Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1];
expr = cookDefault(pstate, colDef->raw_default,
atp->atttypid, atp->atttypmod,
NameStr(atp->attname));
/*
* If the expression is just a NULL constant, we do not bother to make
* an explicit pg_attrdef entry, since the default behavior is
* equivalent.
*
* Note a nonobvious property of this test: if the column is of a
* domain type, what we'll get is not a bare null Const but a
* CoerceToDomain expr, so we will not discard the default. This is
* critical because the column default needs to be retained to
* override any default that the domain might have.
*/
if (expr == NULL ||
(IsA(expr, Const) &&((Const *) expr)->constisnull))
continue;
StoreAttrDefault(rel, colDef->attnum, expr, is_internal);
cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
cooked->contype = CONSTR_DEFAULT;
cooked->name = NULL;
cooked->attnum = colDef->attnum;
cooked->expr = expr;
cooked->skip_validation = false;
cooked->is_local = is_local;
cooked->inhcount = is_local ? 0 : 1;
cooked->is_no_inherit = false;
cookedConstraints = lappend(cookedConstraints, cooked);
}
/*
* Process constraint expressions.
*/
numchecks = numoldchecks;
checknames = NIL;
foreach(cell, newConstraints)
{
Constraint *cdef = (Constraint *) lfirst(cell);
char *ccname;
if (cdef->contype != CONSTR_CHECK)
continue;
if (cdef->raw_expr != NULL)
{
Assert(cdef->cooked_expr == NULL);
/*
* Transform raw parsetree to executable expression, and verify
* it's valid as a CHECK constraint.
*/
expr = cookConstraint(pstate, cdef->raw_expr,
RelationGetRelationName(rel));
}
else
{
Assert(cdef->cooked_expr != NULL);
/*
* Here, we assume the parser will only pass us valid CHECK
* expressions, so we do no particular checking.
*/
expr = stringToNode(cdef->cooked_expr);
}
/*
* Check name uniqueness, or generate a name if none was given.
*/
if (cdef->conname != NULL)
{
ListCell *cell2;
ccname = cdef->conname;
/* Check against other new constraints */
/* Needed because we don't do CommandCounterIncrement in loop */
foreach(cell2, checknames)
{
if (strcmp((char *) lfirst(cell2), ccname) == 0)
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("check constraint \"%s\" already exists",
ccname)));
}
/* save name for future checks */
checknames = lappend(checknames, ccname);
/*
* Check against pre-existing constraints. If we are allowed to
* merge with an existing constraint, there's no more to do here.
* (We omit the duplicate constraint from the result, which is
* what ATAddCheckConstraint wants.)
*/
if (MergeWithExistingConstraint(rel, ccname, expr,
allow_merge, is_local,
cdef->is_no_inherit))
continue;
}
else
{
/*
* When generating a name, we want to create "tab_col_check" for a
* column constraint and "tab_check" for a table constraint. We
* no longer have any info about the syntactic positioning of the
* constraint phrase, so we approximate this by seeing whether the
* expression references more than one column. (If the user
* played by the rules, the result is the same...)
*
* Note: pull_var_clause() doesn't descend into sublinks, but we
* eliminated those above; and anyway this only needs to be an
* approximate answer.
*/
List *vars;
char *colname;
vars = pull_var_clause(expr,
PVC_REJECT_AGGREGATES,
PVC_REJECT_PLACEHOLDERS);
/* eliminate duplicates */
vars = list_union(NIL, vars);
if (list_length(vars) == 1)
colname = get_attname(RelationGetRelid(rel),
((Var *) linitial(vars))->varattno);
else
colname = NULL;
ccname = ChooseConstraintName(RelationGetRelationName(rel),
colname,
"check",
RelationGetNamespace(rel),
checknames);
/* save name for future checks */
checknames = lappend(checknames, ccname);
}
/*
* OK, store it.
*/
StoreRelCheck(rel, ccname, expr, !cdef->skip_validation, is_local,
is_local ? 0 : 1, cdef->is_no_inherit, is_internal);
numchecks++;
cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
cooked->contype = CONSTR_CHECK;
cooked->name = ccname;
cooked->attnum = 0;
cooked->expr = expr;
cooked->skip_validation = cdef->skip_validation;
cooked->is_local = is_local;
cooked->inhcount = is_local ? 0 : 1;
cooked->is_no_inherit = cdef->is_no_inherit;
cookedConstraints = lappend(cookedConstraints, cooked);
}
/*
* Update the count of constraints in the relation's pg_class tuple. We do
* this even if there was no change, in order to ensure that an SI update
* message is sent out for the pg_class tuple, which will force other
* backends to rebuild their relcache entries for the rel. (This is
* critical if we added defaults but not constraints.)
*/
SetRelationNumChecks(rel, numchecks);
return cookedConstraints;
}
Definition at line 379 of file heap.c.
References tupleDesc::attrs, CheckAttributeType(), ereport, errcode(), errmsg(), ERROR, i, MaxHeapAttributeNumber, NameStr, tupleDesc::natts, NIL, NULL, RELKIND_COMPOSITE_TYPE, RELKIND_VIEW, SystemAttributeByName(), and tupleDesc::tdhasoid.
Referenced by heap_create_with_catalog(), and transformRangeFunction().
{
int i;
int j;
int natts = tupdesc->natts;
/* Sanity check on column count */
if (natts < 0 || natts > MaxHeapAttributeNumber)
ereport(ERROR,
(errcode(ERRCODE_TOO_MANY_COLUMNS),
errmsg("tables can have at most %d columns",
MaxHeapAttributeNumber)));
/*
* first check for collision with system attribute names
*
* Skip this for a view or type relation, since those don't have system
* attributes.
*/
if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
{
for (i = 0; i < natts; i++)
{
if (SystemAttributeByName(NameStr(tupdesc->attrs[i]->attname),
tupdesc->tdhasoid) != NULL)
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_COLUMN),
errmsg("column name \"%s\" conflicts with a system column name",
NameStr(tupdesc->attrs[i]->attname))));
}
}
/*
* next check for repeated attribute names
*/
for (i = 1; i < natts; i++)
{
for (j = 0; j < i; j++)
{
if (strcmp(NameStr(tupdesc->attrs[j]->attname),
NameStr(tupdesc->attrs[i]->attname)) == 0)
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_COLUMN),
errmsg("column name \"%s\" specified more than once",
NameStr(tupdesc->attrs[j]->attname))));
}
}
/*
* next check the attribute types
*/
for (i = 0; i < natts; i++)
{
CheckAttributeType(NameStr(tupdesc->attrs[i]->attname),
tupdesc->attrs[i]->atttypid,
tupdesc->attrs[i]->attcollation,
NIL, /* assume we're creating a new rowtype */
allow_system_table_mods);
}
}
| void CheckAttributeType | ( | const char * | attname, | |
| Oid | atttypid, | |||
| Oid | attcollation, | |||
| List * | containing_rowtypes, | |||
| bool | allow_system_table_mods | |||
| ) |
Definition at line 457 of file heap.c.
References AccessShareLock, ANYARRAYOID, tupleDesc::attrs, CheckAttributeType(), ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, format_type_be(), get_element_type(), get_typ_typrelid(), get_typtype(), getBaseType(), i, lcons_oid(), list_delete_first(), list_member_oid(), NameStr, tupleDesc::natts, OidIsValid, relation_close(), relation_open(), RelationGetDescr, type_is_collatable(), TYPTYPE_COMPOSITE, TYPTYPE_DOMAIN, TYPTYPE_PSEUDO, UNKNOWNOID, and WARNING.
Referenced by ATExecAddColumn(), ATPrepAlterColumnType(), CheckAttributeNamesTypes(), CheckAttributeType(), and ConstructTupleDescriptor().
{
char att_typtype = get_typtype(atttypid);
Oid att_typelem;
if (atttypid == UNKNOWNOID)
{
/*
* Warn user, but don't fail, if column to be created has UNKNOWN type
* (usually as a result of a 'retrieve into' - jolly)
*/
ereport(WARNING,
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("column \"%s\" has type \"unknown\"", attname),
errdetail("Proceeding with relation creation anyway.")));
}
else if (att_typtype == TYPTYPE_PSEUDO)
{
/*
* Refuse any attempt to create a pseudo-type column, except for a
* special hack for pg_statistic: allow ANYARRAY when modifying system
* catalogs (this allows creating pg_statistic and cloning it during
* VACUUM FULL)
*/
if (atttypid != ANYARRAYOID || !allow_system_table_mods)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("column \"%s\" has pseudo-type %s",
attname, format_type_be(atttypid))));
}
else if (att_typtype == TYPTYPE_DOMAIN)
{
/*
* If it's a domain, recurse to check its base type.
*/
CheckAttributeType(attname, getBaseType(atttypid), attcollation,
containing_rowtypes,
allow_system_table_mods);
}
else if (att_typtype == TYPTYPE_COMPOSITE)
{
/*
* For a composite type, recurse into its attributes.
*/
Relation relation;
TupleDesc tupdesc;
int i;
/*
* Check for self-containment. Eventually we might be able to allow
* this (just return without complaint, if so) but it's not clear how
* many other places would require anti-recursion defenses before it
* would be safe to allow tables to contain their own rowtype.
*/
if (list_member_oid(containing_rowtypes, atttypid))
ereport(ERROR,
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("composite type %s cannot be made a member of itself",
format_type_be(atttypid))));
containing_rowtypes = lcons_oid(atttypid, containing_rowtypes);
relation = relation_open(get_typ_typrelid(atttypid), AccessShareLock);
tupdesc = RelationGetDescr(relation);
for (i = 0; i < tupdesc->natts; i++)
{
Form_pg_attribute attr = tupdesc->attrs[i];
if (attr->attisdropped)
continue;
CheckAttributeType(NameStr(attr->attname),
attr->atttypid, attr->attcollation,
containing_rowtypes,
allow_system_table_mods);
}
relation_close(relation, AccessShareLock);
containing_rowtypes = list_delete_first(containing_rowtypes);
}
else if (OidIsValid((att_typelem = get_element_type(atttypid))))
{
/*
* Must recurse into array types, too, in case they are composite.
*/
CheckAttributeType(attname, att_typelem, attcollation,
containing_rowtypes,
allow_system_table_mods);
}
/*
* This might not be strictly invalid per SQL standard, but it is pretty
* useless, and it cannot be dumped, so we must disallow it.
*/
if (!OidIsValid(attcollation) && type_is_collatable(atttypid))
ereport(ERROR,
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("no collation was derived for column \"%s\" with collatable type %s",
attname, format_type_be(atttypid)),
errhint("Use the COLLATE clause to set the collation explicitly.")));
}
| static Node * cookConstraint | ( | ParseState * | pstate, | |
| Node * | raw_constraint, | |||
| char * | relname | |||
| ) | [static] |
Definition at line 2578 of file heap.c.
References assign_expr_collations(), coerce_to_boolean(), ereport, errcode(), errmsg(), ERROR, EXPR_KIND_CHECK_CONSTRAINT, list_length(), ParseState::p_rtable, and transformExpr().
Referenced by AddRelationNewConstraints().
{
Node *expr;
/*
* Transform raw parsetree to executable expression.
*/
expr = transformExpr(pstate, raw_constraint, EXPR_KIND_CHECK_CONSTRAINT);
/*
* Make sure it yields a boolean result.
*/
expr = coerce_to_boolean(pstate, expr, "CHECK");
/*
* Take care of collations.
*/
assign_expr_collations(pstate, expr);
/*
* Make sure no outside relations are referred to (this is probably dead
* code now that add_missing_from is history).
*/
if (list_length(pstate->p_rtable) != 1)
ereport(ERROR,
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
errmsg("only table \"%s\" can be referenced in check constraint",
relname)));
return expr;
}
| Node* cookDefault | ( | ParseState * | pstate, | |
| Node * | raw_default, | |||
| Oid | atttypid, | |||
| int32 | atttypmod, | |||
| char * | attname | |||
| ) |
Definition at line 2502 of file heap.c.
References Assert, assign_expr_collations(), COERCE_IMPLICIT_CAST, coerce_to_target_type(), COERCION_ASSIGNMENT, contain_var_clause(), ereport, errcode(), errhint(), errmsg(), ERROR, EXPR_KIND_COLUMN_DEFAULT, expression_returns_set(), exprType(), format_type_be(), NULL, OidIsValid, and transformExpr().
Referenced by AddRelationNewConstraints(), AlterDomainDefault(), and DefineDomain().
{
Node *expr;
Assert(raw_default != NULL);
/*
* Transform raw parsetree to executable expression.
*/
expr = transformExpr(pstate, raw_default, EXPR_KIND_COLUMN_DEFAULT);
/*
* Make sure default expr does not refer to any vars (we need this check
* since the pstate includes the target table).
*/
if (contain_var_clause(expr))
ereport(ERROR,
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
errmsg("cannot use column references in default expression")));
/*
* transformExpr() should have already rejected subqueries, aggregates,
* and window functions, based on the EXPR_KIND_ for a default expression.
*
* It can't return a set either.
*/
if (expression_returns_set(expr))
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("default expression must not return a set")));
/*
* Coerce the expression to the correct type and typmod, if given. This
* should match the parser's processing of non-defaulted expressions ---
* see transformAssignedExpr().
*/
if (OidIsValid(atttypid))
{
Oid type_id = exprType(expr);
expr = coerce_to_target_type(pstate, expr, type_id,
atttypid, atttypmod,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST,
-1);
if (expr == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("column \"%s\" is of type %s"
" but default expression is of type %s",
attname,
format_type_be(atttypid),
format_type_be(type_id)),
errhint("You will need to rewrite or cast the expression.")));
}
/*
* Finally, take care of collations in the finished expression.
*/
assign_expr_collations(pstate, expr);
return expr;
}
| void DeleteAttributeTuples | ( | Oid | relid | ) |
Definition at line 1440 of file heap.c.
References Anum_pg_attribute_attrelid, AttributeRelationId, AttributeRelidNumIndexId, BTEqualStrategyNumber, heap_close, heap_open(), NULL, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), simple_heap_delete(), SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.
Referenced by heap_drop_with_catalog(), and index_drop().
{
Relation attrel;
SysScanDesc scan;
ScanKeyData key[1];
HeapTuple atttup;
/* Grab an appropriate lock on the pg_attribute relation */
attrel = heap_open(AttributeRelationId, RowExclusiveLock);
/* Use the index to scan only attributes of the target relation */
ScanKeyInit(&key[0],
Anum_pg_attribute_attrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(relid));
scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
SnapshotNow, 1, key);
/* Delete all the matching tuples */
while ((atttup = systable_getnext(scan)) != NULL)
simple_heap_delete(attrel, &atttup->t_self);
/* Clean up after the scan */
systable_endscan(scan);
heap_close(attrel, RowExclusiveLock);
}
| void DeleteRelationTuple | ( | Oid | relid | ) |
Definition at line 1411 of file heap.c.
References elog, ERROR, heap_close, heap_open(), HeapTupleIsValid, ObjectIdGetDatum, RelationRelationId, ReleaseSysCache(), RELOID, RowExclusiveLock, SearchSysCache1, simple_heap_delete(), and HeapTupleData::t_self.
Referenced by heap_drop_with_catalog(), and index_drop().
{
Relation pg_class_desc;
HeapTuple tup;
/* Grab an appropriate lock on the pg_class relation */
pg_class_desc = heap_open(RelationRelationId, RowExclusiveLock);
tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for relation %u", relid);
/* delete the relation tuple from pg_class, and finish up */
simple_heap_delete(pg_class_desc, &tup->t_self);
ReleaseSysCache(tup);
heap_close(pg_class_desc, RowExclusiveLock);
}
| void DeleteSystemAttributeTuples | ( | Oid | relid | ) |
Definition at line 1477 of file heap.c.
References Anum_pg_attribute_attnum, Anum_pg_attribute_attrelid, AttributeRelationId, AttributeRelidNumIndexId, BTEqualStrategyNumber, BTLessEqualStrategyNumber, heap_close, heap_open(), Int16GetDatum, NULL, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), simple_heap_delete(), SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.
Referenced by DefineQueryRewrite().
{
Relation attrel;
SysScanDesc scan;
ScanKeyData key[2];
HeapTuple atttup;
/* Grab an appropriate lock on the pg_attribute relation */
attrel = heap_open(AttributeRelationId, RowExclusiveLock);
/* Use the index to scan only system attributes of the target relation */
ScanKeyInit(&key[0],
Anum_pg_attribute_attrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(relid));
ScanKeyInit(&key[1],
Anum_pg_attribute_attnum,
BTLessEqualStrategyNumber, F_INT2LE,
Int16GetDatum(0));
scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
SnapshotNow, 2, key);
/* Delete all the matching tuples */
while ((atttup = systable_getnext(scan)) != NULL)
simple_heap_delete(attrel, &atttup->t_self);
/* Clean up after the scan */
systable_endscan(scan);
heap_close(attrel, RowExclusiveLock);
}
| Relation heap_create | ( | const char * | relname, | |
| Oid | relnamespace, | |||
| Oid | reltablespace, | |||
| Oid | relid, | |||
| Oid | relfilenode, | |||
| TupleDesc | tupDesc, | |||
| char | relkind, | |||
| char | relpersistence, | |||
| bool | shared_relation, | |||
| bool | mapped_relation | |||
| ) |
Definition at line 240 of file heap.c.
References Assert, MyDatabaseTableSpace, OidIsValid, RelationData::rd_node, RelationBuildLocalRelation(), RelationCreateStorage(), RelationOpenSmgr, RELKIND_COMPOSITE_TYPE, RELKIND_FOREIGN_TABLE, RELKIND_SEQUENCE, and RELKIND_VIEW.
Referenced by heap_create_with_catalog(), and index_create().
{
bool create_storage;
Relation rel;
/* The caller must have provided an OID for the relation. */
Assert(OidIsValid(relid));
/*
* Decide if we need storage or not, and handle a couple other special
* cases for particular relkinds.
*/
switch (relkind)
{
case RELKIND_VIEW:
case RELKIND_COMPOSITE_TYPE:
case RELKIND_FOREIGN_TABLE:
create_storage = false;
/*
* Force reltablespace to zero if the relation has no physical
* storage. This is mainly just for cleanliness' sake.
*/
reltablespace = InvalidOid;
break;
case RELKIND_SEQUENCE:
create_storage = true;
/*
* Force reltablespace to zero for sequences, since we don't
* support moving them around into different tablespaces.
*/
reltablespace = InvalidOid;
break;
default:
create_storage = true;
break;
}
/*
* Unless otherwise requested, the physical ID (relfilenode) is initially
* the same as the logical ID (OID). When the caller did specify a
* relfilenode, it already exists; do not attempt to create it.
*/
if (OidIsValid(relfilenode))
create_storage = false;
else
relfilenode = relid;
/*
* Never allow a pg_class entry to explicitly specify the database's
* default tablespace in reltablespace; force it to zero instead. This
* ensures that if the database is cloned with a different default
* tablespace, the pg_class entry will still match where CREATE DATABASE
* will put the physically copied relation.
*
* Yes, this is a bit of a hack.
*/
if (reltablespace == MyDatabaseTableSpace)
reltablespace = InvalidOid;
/*
* build the relcache entry.
*/
rel = RelationBuildLocalRelation(relname,
relnamespace,
tupDesc,
relid,
relfilenode,
reltablespace,
shared_relation,
mapped_relation,
relpersistence,
relkind);
/*
* Have the storage manager create the relation's disk file, if needed.
*
* We only create the main fork here, other forks will be created on
* demand.
*/
if (create_storage)
{
RelationOpenSmgr(rel);
RelationCreateStorage(rel->rd_node, relpersistence);
}
return rel;
}
| void heap_create_init_fork | ( | Relation | rel | ) |
Definition at line 1339 of file heap.c.
References INIT_FORKNUM, log_smgrcreate(), RelFileNodeBackend::node, RelationData::rd_smgr, RelationOpenSmgr, SMgrRelationData::smgr_rnode, smgrcreate(), smgrimmedsync(), and XLogIsNeeded.
Referenced by ExecuteTruncate(), and heap_create_with_catalog().
{
RelationOpenSmgr(rel);
smgrcreate(rel->rd_smgr, INIT_FORKNUM, false);
if (XLogIsNeeded())
log_smgrcreate(&rel->rd_smgr->smgr_rnode.node, INIT_FORKNUM);
smgrimmedsync(rel->rd_smgr, INIT_FORKNUM);
}
| Oid heap_create_with_catalog | ( | const char * | relname, | |
| Oid | relnamespace, | |||
| Oid | reltablespace, | |||
| Oid | relid, | |||
| Oid | reltypeid, | |||
| Oid | reloftypeid, | |||
| Oid | ownerid, | |||
| TupleDesc | tupdesc, | |||
| List * | cooked_constraints, | |||
| char | relkind, | |||
| char | relpersistence, | |||
| bool | shared_relation, | |||
| bool | mapped_relation, | |||
| bool | oidislocal, | |||
| int | oidinhcount, | |||
| OnCommitAction | oncommit, | |||
| Datum | reloptions, | |||
| bool | use_user_acl, | |||
| bool | allow_system_table_mods, | |||
| bool | is_internal | |||
| ) |
Definition at line 986 of file heap.c.
References ACL_OBJECT_RELATION, ACL_OBJECT_SEQUENCE, aclmembers(), AddNewAttributeTuples(), AddNewRelationTuple(), AddNewRelationType(), Assert, AssignTypeArrayOid(), binary_upgrade_next_heap_pg_class_oid, binary_upgrade_next_toast_pg_class_oid, CheckAttributeNamesTypes(), ObjectAddress::classId, CStringGetDatum, DEFAULT_TYPDELIM, DEPENDENCY_NORMAL, elog, ereport, errcode(), errhint(), errmsg(), ERROR, get_relname_relid(), get_user_default_acl(), GetNewRelFileNode(), GetSysCacheOid2, GLOBALTABLESPACE_OID, heap_close, heap_create(), heap_create_init_fork(), heap_open(), InvalidOid, InvokeObjectPostCreateHookArg, IsBinaryUpgrade, IsBootstrapProcessingMode, IsNormalProcessingMode, IsUnderPostmaster, makeArrayTypeName(), moveArrayTypeName(), NoLock, NULL, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, ONCOMMIT_NOOP, pfree(), PointerGetDatum, RelationData::rd_att, recordDependencyOn(), recordDependencyOnCurrentExtension(), recordDependencyOnOwner(), register_on_commit_action(), RelationGetRelid, RelationRelationId, RELKIND_COMPOSITE_TYPE, RELKIND_FOREIGN_TABLE, RELKIND_MATVIEW, RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_TOASTVALUE, RELKIND_VIEW, RELPERSISTENCE_TEMP, RELPERSISTENCE_UNLOGGED, RowExclusiveLock, StoreConstraints(), TYPCATEGORY_ARRAY, TypeCreate(), TYPENAMENSP, TYPTYPE_BASE, and updateAclDependencies().
Referenced by create_toast_table(), DefineRelation(), and make_new_heap().
{
Relation pg_class_desc;
Relation new_rel_desc;
Acl *relacl;
Oid existing_relid;
Oid old_type_oid;
Oid new_type_oid;
Oid new_array_oid = InvalidOid;
pg_class_desc = heap_open(RelationRelationId, RowExclusiveLock);
/*
* sanity checks
*/
Assert(IsNormalProcessingMode() || IsBootstrapProcessingMode());
CheckAttributeNamesTypes(tupdesc, relkind, allow_system_table_mods);
/*
* This would fail later on anyway, if the relation already exists. But
* by catching it here we can emit a nicer error message.
*/
existing_relid = get_relname_relid(relname, relnamespace);
if (existing_relid != InvalidOid)
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_TABLE),
errmsg("relation \"%s\" already exists", relname)));
/*
* Since we are going to create a rowtype as well, also check for
* collision with an existing type name. If there is one and it's an
* autogenerated array, we can rename it out of the way; otherwise we can
* at least give a good error message.
*/
old_type_oid = GetSysCacheOid2(TYPENAMENSP,
CStringGetDatum(relname),
ObjectIdGetDatum(relnamespace));
if (OidIsValid(old_type_oid))
{
if (!moveArrayTypeName(old_type_oid, relname, relnamespace))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("type \"%s\" already exists", relname),
errhint("A relation has an associated type of the same name, "
"so you must use a name that doesn't conflict "
"with any existing type.")));
}
/*
* Shared relations must be in pg_global (last-ditch check)
*/
if (shared_relation && reltablespace != GLOBALTABLESPACE_OID)
elog(ERROR, "shared relations must be placed in pg_global tablespace");
/*
* Allocate an OID for the relation, unless we were told what to use.
*
* The OID will be the relfilenode as well, so make sure it doesn't
* collide with either pg_class OIDs or existing physical files.
*/
if (!OidIsValid(relid))
{
/*
* Use binary-upgrade override for pg_class.oid/relfilenode, if
* supplied.
*/
if (IsBinaryUpgrade &&
OidIsValid(binary_upgrade_next_heap_pg_class_oid) &&
(relkind == RELKIND_RELATION || relkind == RELKIND_SEQUENCE ||
relkind == RELKIND_VIEW || relkind == RELKIND_MATVIEW ||
relkind == RELKIND_COMPOSITE_TYPE || relkind == RELKIND_FOREIGN_TABLE))
{
relid = binary_upgrade_next_heap_pg_class_oid;
binary_upgrade_next_heap_pg_class_oid = InvalidOid;
}
else if (IsBinaryUpgrade &&
OidIsValid(binary_upgrade_next_toast_pg_class_oid) &&
relkind == RELKIND_TOASTVALUE)
{
relid = binary_upgrade_next_toast_pg_class_oid;
binary_upgrade_next_toast_pg_class_oid = InvalidOid;
}
else
relid = GetNewRelFileNode(reltablespace, pg_class_desc,
relpersistence);
}
/*
* Determine the relation's initial permissions.
*/
if (use_user_acl)
{
switch (relkind)
{
case RELKIND_RELATION:
case RELKIND_VIEW:
case RELKIND_MATVIEW:
case RELKIND_FOREIGN_TABLE:
relacl = get_user_default_acl(ACL_OBJECT_RELATION, ownerid,
relnamespace);
break;
case RELKIND_SEQUENCE:
relacl = get_user_default_acl(ACL_OBJECT_SEQUENCE, ownerid,
relnamespace);
break;
default:
relacl = NULL;
break;
}
}
else
relacl = NULL;
/*
* Create the relcache entry (mostly dummy at this point) and the physical
* disk file. (If we fail further down, it's the smgr's responsibility to
* remove the disk file again.)
*/
new_rel_desc = heap_create(relname,
relnamespace,
reltablespace,
relid,
InvalidOid,
tupdesc,
relkind,
relpersistence,
shared_relation,
mapped_relation);
Assert(relid == RelationGetRelid(new_rel_desc));
/*
* Decide whether to create an array type over the relation's rowtype. We
* do not create any array types for system catalogs (ie, those made
* during initdb). We create array types for regular relations, views,
* composite types and foreign tables ... but not, eg, for toast tables or
* sequences.
*/
if (IsUnderPostmaster && (relkind == RELKIND_RELATION ||
relkind == RELKIND_VIEW ||
relkind == RELKIND_MATVIEW ||
relkind == RELKIND_FOREIGN_TABLE ||
relkind == RELKIND_COMPOSITE_TYPE))
new_array_oid = AssignTypeArrayOid();
/*
* Since defining a relation also defines a complex type, we add a new
* system type corresponding to the new relation. The OID of the type can
* be preselected by the caller, but if reltypeid is InvalidOid, we'll
* generate a new OID for it.
*
* NOTE: we could get a unique-index failure here, in case someone else is
* creating the same type name in parallel but hadn't committed yet when
* we checked for a duplicate name above.
*/
new_type_oid = AddNewRelationType(relname,
relnamespace,
relid,
relkind,
ownerid,
reltypeid,
new_array_oid);
/*
* Now make the array type if wanted.
*/
if (OidIsValid(new_array_oid))
{
char *relarrayname;
relarrayname = makeArrayTypeName(relname, relnamespace);
TypeCreate(new_array_oid, /* force the type's OID to this */
relarrayname, /* Array type name */
relnamespace, /* Same namespace as parent */
InvalidOid, /* Not composite, no relationOid */
0, /* relkind, also N/A here */
ownerid, /* owner's ID */
-1, /* Internal size (varlena) */
TYPTYPE_BASE, /* Not composite - typelem is */
TYPCATEGORY_ARRAY, /* type-category (array) */
false, /* array types are never preferred */
DEFAULT_TYPDELIM, /* default array delimiter */
F_ARRAY_IN, /* array input proc */
F_ARRAY_OUT, /* array output proc */
F_ARRAY_RECV, /* array recv (bin) proc */
F_ARRAY_SEND, /* array send (bin) proc */
InvalidOid, /* typmodin procedure - none */
InvalidOid, /* typmodout procedure - none */
F_ARRAY_TYPANALYZE, /* array analyze procedure */
new_type_oid, /* array element type - the rowtype */
true, /* yes, this is an array type */
InvalidOid, /* this has no array type */
InvalidOid, /* domain base type - irrelevant */
NULL, /* default value - none */
NULL, /* default binary representation */
false, /* passed by reference */
'd', /* alignment - must be the largest! */
'x', /* fully TOASTable */
-1, /* typmod */
0, /* array dimensions for typBaseType */
false, /* Type NOT NULL */
InvalidOid); /* rowtypes never have a collation */
pfree(relarrayname);
}
/*
* now create an entry in pg_class for the relation.
*
* NOTE: we could get a unique-index failure here, in case someone else is
* creating the same relation name in parallel but hadn't committed yet
* when we checked for a duplicate name above.
*/
AddNewRelationTuple(pg_class_desc,
new_rel_desc,
relid,
new_type_oid,
reloftypeid,
ownerid,
relkind,
PointerGetDatum(relacl),
reloptions);
/*
* now add tuples to pg_attribute for the attributes in our new relation.
*/
AddNewAttributeTuples(relid, new_rel_desc->rd_att, relkind,
oidislocal, oidinhcount);
/*
* Make a dependency link to force the relation to be deleted if its
* namespace is. Also make a dependency link to its owner, as well as
* dependencies for any roles mentioned in the default ACL.
*
* For composite types, these dependencies are tracked for the pg_type
* entry, so we needn't record them here. Likewise, TOAST tables don't
* need a namespace dependency (they live in a pinned namespace) nor an
* owner dependency (they depend indirectly through the parent table), nor
* should they have any ACL entries. The same applies for extension
* dependencies.
*
* If it's a temp table, we do not make it an extension member; this
* prevents the unintuitive result that deletion of the temp table at
* session end would make the whole extension go away.
*
* Also, skip this in bootstrap mode, since we don't make dependencies
* while bootstrapping.
*/
if (relkind != RELKIND_COMPOSITE_TYPE &&
relkind != RELKIND_TOASTVALUE &&
!IsBootstrapProcessingMode())
{
ObjectAddress myself,
referenced;
myself.classId = RelationRelationId;
myself.objectId = relid;
myself.objectSubId = 0;
referenced.classId = NamespaceRelationId;
referenced.objectId = relnamespace;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
recordDependencyOnOwner(RelationRelationId, relid, ownerid);
if (relpersistence != RELPERSISTENCE_TEMP)
recordDependencyOnCurrentExtension(&myself, false);
if (reloftypeid)
{
referenced.classId = TypeRelationId;
referenced.objectId = reloftypeid;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
if (relacl != NULL)
{
int nnewmembers;
Oid *newmembers;
nnewmembers = aclmembers(relacl, &newmembers);
updateAclDependencies(RelationRelationId, relid, 0,
ownerid,
0, NULL,
nnewmembers, newmembers);
}
}
/* Post creation hook for new relation */
InvokeObjectPostCreateHookArg(RelationRelationId, relid, 0, is_internal);
/*
* Store any supplied constraints and defaults.
*
* NB: this may do a CommandCounterIncrement and rebuild the relcache
* entry, so the relation must be valid and self-consistent at this point.
* In particular, there are not yet constraints and defaults anywhere.
*/
StoreConstraints(new_rel_desc, cooked_constraints, is_internal);
/*
* If there's a special on-commit action, remember it
*/
if (oncommit != ONCOMMIT_NOOP)
register_on_commit_action(relid, oncommit);
if (relpersistence == RELPERSISTENCE_UNLOGGED)
{
Assert(relkind == RELKIND_RELATION || relkind == RELKIND_MATVIEW ||
relkind == RELKIND_TOASTVALUE);
heap_create_init_fork(new_rel_desc);
}
/*
* ok, the relation has been cataloged, so close our relations and return
* the OID of the newly created relation.
*/
heap_close(new_rel_desc, NoLock); /* do not unlock till end of xact */
heap_close(pg_class_desc, RowExclusiveLock);
return relid;
}
| void heap_drop_with_catalog | ( | Oid | relid | ) |
Definition at line 1739 of file heap.c.
References AccessExclusiveLock, CheckTableForSerializableConflictIn(), CheckTableNotInUse(), DeleteAttributeTuples(), DeleteRelationTuple(), elog, ERROR, FOREIGNTABLEREL, ForeignTableRelationId, heap_close, heap_open(), HeapTupleIsValid, NoLock, ObjectIdGetDatum, RelationData::rd_rel, relation_close(), relation_open(), RelationDropStorage(), RelationForgetRelation(), RelationRemoveInheritance(), ReleaseSysCache(), RELKIND_COMPOSITE_TYPE, RELKIND_FOREIGN_TABLE, RELKIND_VIEW, remove_on_commit_action(), RemoveStatistics(), RowExclusiveLock, SearchSysCache1, simple_heap_delete(), and HeapTupleData::t_self.
Referenced by doDeletion().
{
Relation rel;
/*
* Open and lock the relation.
*/
rel = relation_open(relid, AccessExclusiveLock);
/*
* There can no longer be anyone *else* touching the relation, but we
* might still have open queries or cursors, or pending trigger events, in
* our own session.
*/
CheckTableNotInUse(rel, "DROP TABLE");
/*
* This effectively deletes all rows in the table, and may be done in a
* serializable transaction. In that case we must record a rw-conflict in
* to this transaction from each transaction holding a predicate lock on
* the table.
*/
CheckTableForSerializableConflictIn(rel);
/*
* Delete pg_foreign_table tuple first.
*/
if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
{
Relation rel;
HeapTuple tuple;
rel = heap_open(ForeignTableRelationId, RowExclusiveLock);
tuple = SearchSysCache1(FOREIGNTABLEREL, ObjectIdGetDatum(relid));
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for foreign table %u", relid);
simple_heap_delete(rel, &tuple->t_self);
ReleaseSysCache(tuple);
heap_close(rel, RowExclusiveLock);
}
/*
* Schedule unlinking of the relation's physical files at commit.
*/
if (rel->rd_rel->relkind != RELKIND_VIEW &&
rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
{
RelationDropStorage(rel);
}
/*
* Close relcache entry, but *keep* AccessExclusiveLock on the relation
* until transaction commit. This ensures no one else will try to do
* something with the doomed relation.
*/
relation_close(rel, NoLock);
/*
* Forget any ON COMMIT action for the rel
*/
remove_on_commit_action(relid);
/*
* Flush the relation from the relcache. We want to do this before
* starting to remove catalog entries, just to be certain that no relcache
* entry rebuild will happen partway through. (That should not really
* matter, since we don't do CommandCounterIncrement here, but let's be
* safe.)
*/
RelationForgetRelation(relid);
/*
* remove inheritance information
*/
RelationRemoveInheritance(relid);
/*
* delete statistics
*/
RemoveStatistics(relid, 0);
/*
* delete attribute tuples
*/
DeleteAttributeTuples(relid);
/*
* delete relation tuple
*/
DeleteRelationTuple(relid);
}
Definition at line 1356 of file heap.c.
References Assert, MAIN_FORKNUM, RelationData::rd_rel, RelationData::rd_smgr, RelationOpenSmgr, RELKIND_MATVIEW, smgrexists(), and smgrnblocks().
Referenced by load_relcache_init_file(), RelationBuildDesc(), and RelationClearRelation().
{
Assert(rel->rd_rel->relkind == RELKIND_MATVIEW);
RelationOpenSmgr(rel);
if (!smgrexists(rel->rd_smgr, MAIN_FORKNUM))
return true;
return (smgrnblocks(rel->rd_smgr, MAIN_FORKNUM) < 1);
}
| void heap_truncate | ( | List * | relids | ) |
Definition at line 2708 of file heap.c.
References AccessExclusiveLock, heap_close, heap_open(), heap_truncate_check_FKs(), heap_truncate_one_rel(), lappend(), lfirst, lfirst_oid, and NoLock.
Referenced by PreCommit_on_commit_actions().
{
List *relations = NIL;
ListCell *cell;
/* Open relations for processing, and grab exclusive access on each */
foreach(cell, relids)
{
Oid rid = lfirst_oid(cell);
Relation rel;
rel = heap_open(rid, AccessExclusiveLock);
relations = lappend(relations, rel);
}
/* Don't allow truncate on tables that are referenced by foreign keys */
heap_truncate_check_FKs(relations, true);
/* OK to do it */
foreach(cell, relations)
{
Relation rel = lfirst(cell);
/* Truncate the relation */
heap_truncate_one_rel(rel);
/* Close the relation, but keep exclusive lock on it until commit */
heap_close(rel, NoLock);
}
}
Definition at line 2786 of file heap.c.
References ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, get_rel_name(), heap_truncate_find_FKs(), lappend_oid(), lfirst, lfirst_oid, list_make1_oid, list_member_oid(), NIL, RelationData::rd_rel, and RelationGetRelid.
Referenced by ExecuteTruncate(), and heap_truncate().
{
List *oids = NIL;
List *dependents;
ListCell *cell;
/*
* Build a list of OIDs of the interesting relations.
*
* If a relation has no triggers, then it can neither have FKs nor be
* referenced by a FK from another table, so we can ignore it.
*/
foreach(cell, relations)
{
Relation rel = lfirst(cell);
if (rel->rd_rel->relhastriggers)
oids = lappend_oid(oids, RelationGetRelid(rel));
}
/*
* Fast path: if no relation has triggers, none has FKs either.
*/
if (oids == NIL)
return;
/*
* Otherwise, must scan pg_constraint. We make one pass with all the
* relations considered; if this finds nothing, then all is well.
*/
dependents = heap_truncate_find_FKs(oids);
if (dependents == NIL)
return;
/*
* Otherwise we repeat the scan once per relation to identify a particular
* pair of relations to complain about. This is pretty slow, but
* performance shouldn't matter much in a failure path. The reason for
* doing things this way is to ensure that the message produced is not
* dependent on chance row locations within pg_constraint.
*/
foreach(cell, oids)
{
Oid relid = lfirst_oid(cell);
ListCell *cell2;
dependents = heap_truncate_find_FKs(list_make1_oid(relid));
foreach(cell2, dependents)
{
Oid relid2 = lfirst_oid(cell2);
if (!list_member_oid(oids, relid2))
{
char *relname = get_rel_name(relid);
char *relname2 = get_rel_name(relid2);
if (tempTables)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("unsupported ON COMMIT and foreign key combination"),
errdetail("Table \"%s\" references \"%s\", but they do not have the same ON COMMIT setting.",
relname2, relname)));
else
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot truncate a table referenced in a foreign key constraint"),
errdetail("Table \"%s\" references \"%s\".",
relname2, relname),
errhint("Truncate table \"%s\" at the same time, "
"or use TRUNCATE ... CASCADE.",
relname2)));
}
}
}
}
Definition at line 2878 of file heap.c.
References AccessShareLock, CONSTRAINT_FOREIGN, ConstraintRelationId, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, insert_ordered_unique_oid(), InvalidOid, list_member_oid(), NULL, SnapshotNow, systable_beginscan(), systable_endscan(), and systable_getnext().
Referenced by ExecuteTruncate(), and heap_truncate_check_FKs().
{
List *result = NIL;
Relation fkeyRel;
SysScanDesc fkeyScan;
HeapTuple tuple;
/*
* Must scan pg_constraint. Right now, it is a seqscan because there is
* no available index on confrelid.
*/
fkeyRel = heap_open(ConstraintRelationId, AccessShareLock);
fkeyScan = systable_beginscan(fkeyRel, InvalidOid, false,
SnapshotNow, 0, NULL);
while (HeapTupleIsValid(tuple = systable_getnext(fkeyScan)))
{
Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
/* Not a foreign key */
if (con->contype != CONSTRAINT_FOREIGN)
continue;
/* Not referencing one of our list of tables */
if (!list_member_oid(relationIds, con->confrelid))
continue;
/* Add referencer unless already in input or result list */
if (!list_member_oid(relationIds, con->conrelid))
result = insert_ordered_unique_oid(result, con->conrelid);
}
systable_endscan(fkeyScan);
heap_close(fkeyRel, AccessShareLock);
return result;
}
| void heap_truncate_one_rel | ( | Relation | rel | ) |
Definition at line 2749 of file heap.c.
References AccessExclusiveLock, heap_close, heap_open(), NoLock, OidIsValid, RelationData::rd_rel, RelationTruncate(), and RelationTruncateIndexes().
Referenced by ExecuteTruncate(), and heap_truncate().
{
Oid toastrelid;
/* Truncate the actual file (and discard buffers) */
RelationTruncate(rel, 0);
/* If the relation has indexes, truncate the indexes too */
RelationTruncateIndexes(rel);
/* If there is a toast table, truncate that too */
toastrelid = rel->rd_rel->reltoastrelid;
if (OidIsValid(toastrelid))
{
Relation toastrel = heap_open(toastrelid, AccessExclusiveLock);
RelationTruncate(toastrel, 0);
RelationTruncateIndexes(toastrel);
/* keep the lock... */
heap_close(toastrel, NoLock);
}
}
Definition at line 2928 of file heap.c.
References lappend_cell_oid(), lcons_oid(), lfirst_oid, linitial_oid, list_head(), lnext, NIL, and NULL.
Referenced by heap_truncate_find_FKs().
{
ListCell *prev;
/* Does the datum belong at the front? */
if (list == NIL || datum < linitial_oid(list))
return lcons_oid(datum, list);
/* Does it match the first entry? */
if (datum == linitial_oid(list))
return list; /* duplicate, so don't insert */
/* No, so find the entry it belongs after */
prev = list_head(list);
for (;;)
{
ListCell *curr = lnext(prev);
if (curr == NULL || datum < lfirst_oid(curr))
break; /* it belongs after 'prev', before 'curr' */
if (datum == lfirst_oid(curr))
return list; /* duplicate, so don't insert */
prev = curr;
}
/* Insert datum into list after 'prev' */
lappend_cell_oid(list, prev, datum);
return list;
}
| void InsertPgAttributeTuple | ( | Relation | pg_attribute_rel, | |
| Form_pg_attribute | new_attribute, | |||
| CatalogIndexState | indstate | |||
| ) |
Definition at line 577 of file heap.c.
References Anum_pg_attribute_attacl, Anum_pg_attribute_attalign, Anum_pg_attribute_attbyval, Anum_pg_attribute_attcacheoff, Anum_pg_attribute_attcollation, Anum_pg_attribute_attfdwoptions, Anum_pg_attribute_atthasdef, Anum_pg_attribute_attinhcount, Anum_pg_attribute_attisdropped, Anum_pg_attribute_attislocal, Anum_pg_attribute_attlen, Anum_pg_attribute_attname, Anum_pg_attribute_attndims, Anum_pg_attribute_attnotnull, Anum_pg_attribute_attnum, Anum_pg_attribute_attoptions, Anum_pg_attribute_attrelid, Anum_pg_attribute_attstattarget, Anum_pg_attribute_attstorage, Anum_pg_attribute_atttypid, Anum_pg_attribute_atttypmod, BoolGetDatum, CatalogIndexInsert(), CatalogUpdateIndexes(), CharGetDatum, heap_form_tuple(), heap_freetuple(), Int16GetDatum, Int32GetDatum, NameGetDatum, NULL, ObjectIdGetDatum, RelationGetDescr, simple_heap_insert(), and values.
Referenced by AddNewAttributeTuples(), AppendAttributeTuples(), and ATExecAddColumn().
{
Datum values[Natts_pg_attribute];
bool nulls[Natts_pg_attribute];
HeapTuple tup;
/* This is a tad tedious, but way cleaner than what we used to do... */
memset(values, 0, sizeof(values));
memset(nulls, false, sizeof(nulls));
values[Anum_pg_attribute_attrelid - 1] = ObjectIdGetDatum(new_attribute->attrelid);
values[Anum_pg_attribute_attname - 1] = NameGetDatum(&new_attribute->attname);
values[Anum_pg_attribute_atttypid - 1] = ObjectIdGetDatum(new_attribute->atttypid);
values[Anum_pg_attribute_attstattarget - 1] = Int32GetDatum(new_attribute->attstattarget);
values[Anum_pg_attribute_attlen - 1] = Int16GetDatum(new_attribute->attlen);
values[Anum_pg_attribute_attnum - 1] = Int16GetDatum(new_attribute->attnum);
values[Anum_pg_attribute_attndims - 1] = Int32GetDatum(new_attribute->attndims);
values[Anum_pg_attribute_attcacheoff - 1] = Int32GetDatum(new_attribute->attcacheoff);
values[Anum_pg_attribute_atttypmod - 1] = Int32GetDatum(new_attribute->atttypmod);
values[Anum_pg_attribute_attbyval - 1] = BoolGetDatum(new_attribute->attbyval);
values[Anum_pg_attribute_attstorage - 1] = CharGetDatum(new_attribute->attstorage);
values[Anum_pg_attribute_attalign - 1] = CharGetDatum(new_attribute->attalign);
values[Anum_pg_attribute_attnotnull - 1] = BoolGetDatum(new_attribute->attnotnull);
values[Anum_pg_attribute_atthasdef - 1] = BoolGetDatum(new_attribute->atthasdef);
values[Anum_pg_attribute_attisdropped - 1] = BoolGetDatum(new_attribute->attisdropped);
values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(new_attribute->attislocal);
values[Anum_pg_attribute_attinhcount - 1] = Int32GetDatum(new_attribute->attinhcount);
values[Anum_pg_attribute_attcollation - 1] = ObjectIdGetDatum(new_attribute->attcollation);
/* start out with empty permissions and empty options */
nulls[Anum_pg_attribute_attacl - 1] = true;
nulls[Anum_pg_attribute_attoptions - 1] = true;
nulls[Anum_pg_attribute_attfdwoptions - 1] = true;
tup = heap_form_tuple(RelationGetDescr(pg_attribute_rel), values, nulls);
/* finally insert the new tuple, update the indexes, and clean up */
simple_heap_insert(pg_attribute_rel, tup);
if (indstate != NULL)
CatalogIndexInsert(indstate, tup);
else
CatalogUpdateIndexes(pg_attribute_rel, tup);
heap_freetuple(tup);
}
| void InsertPgClassTuple | ( | Relation | pg_class_desc, | |
| Relation | new_rel_desc, | |||
| Oid | new_rel_oid, | |||
| Datum | relacl, | |||
| Datum | reloptions | |||
| ) |
Definition at line 744 of file heap.c.
References Anum_pg_class_relacl, Anum_pg_class_relallvisible, Anum_pg_class_relam, Anum_pg_class_relchecks, Anum_pg_class_relfilenode, Anum_pg_class_relfrozenxid, Anum_pg_class_relhasindex, Anum_pg_class_relhasoids, Anum_pg_class_relhaspkey, Anum_pg_class_relhasrules, Anum_pg_class_relhassubclass, Anum_pg_class_relhastriggers, Anum_pg_class_relisshared, Anum_pg_class_relkind, Anum_pg_class_relminmxid, Anum_pg_class_relname, Anum_pg_class_relnamespace, Anum_pg_class_relnatts, Anum_pg_class_reloftype, Anum_pg_class_reloptions, Anum_pg_class_relowner, Anum_pg_class_relpages, Anum_pg_class_relpersistence, Anum_pg_class_reltablespace, Anum_pg_class_reltoastidxid, Anum_pg_class_reltoastrelid, Anum_pg_class_reltuples, Anum_pg_class_reltype, BoolGetDatum, CatalogUpdateIndexes(), CharGetDatum, Float4GetDatum(), heap_form_tuple(), heap_freetuple(), HeapTupleSetOid, Int16GetDatum, Int32GetDatum, MultiXactIdGetDatum, NameGetDatum, ObjectIdGetDatum, RelationData::rd_rel, RelationGetDescr, simple_heap_insert(), TransactionIdGetDatum, and values.
Referenced by AddNewRelationTuple(), and index_create().
{
Form_pg_class rd_rel = new_rel_desc->rd_rel;
Datum values[Natts_pg_class];
bool nulls[Natts_pg_class];
HeapTuple tup;
/* This is a tad tedious, but way cleaner than what we used to do... */
memset(values, 0, sizeof(values));
memset(nulls, false, sizeof(nulls));
values[Anum_pg_class_relname - 1] = NameGetDatum(&rd_rel->relname);
values[Anum_pg_class_relnamespace - 1] = ObjectIdGetDatum(rd_rel->relnamespace);
values[Anum_pg_class_reltype - 1] = ObjectIdGetDatum(rd_rel->reltype);
values[Anum_pg_class_reloftype - 1] = ObjectIdGetDatum(rd_rel->reloftype);
values[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(rd_rel->relowner);
values[Anum_pg_class_relam - 1] = ObjectIdGetDatum(rd_rel->relam);
values[Anum_pg_class_relfilenode - 1] = ObjectIdGetDatum(rd_rel->relfilenode);
values[Anum_pg_class_reltablespace - 1] = ObjectIdGetDatum(rd_rel->reltablespace);
values[Anum_pg_class_relpages - 1] = Int32GetDatum(rd_rel->relpages);
values[Anum_pg_class_reltuples - 1] = Float4GetDatum(rd_rel->reltuples);
values[Anum_pg_class_relallvisible - 1] = Int32GetDatum(rd_rel->relallvisible);
values[Anum_pg_class_reltoastrelid - 1] = ObjectIdGetDatum(rd_rel->reltoastrelid);
values[Anum_pg_class_reltoastidxid - 1] = ObjectIdGetDatum(rd_rel->reltoastidxid);
values[Anum_pg_class_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex);
values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared);
values[Anum_pg_class_relpersistence - 1] = CharGetDatum(rd_rel->relpersistence);
values[Anum_pg_class_relkind - 1] = CharGetDatum(rd_rel->relkind);
values[Anum_pg_class_relnatts - 1] = Int16GetDatum(rd_rel->relnatts);
values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks);
values[Anum_pg_class_relhasoids - 1] = BoolGetDatum(rd_rel->relhasoids);
values[Anum_pg_class_relhaspkey - 1] = BoolGetDatum(rd_rel->relhaspkey);
values[Anum_pg_class_relhasrules - 1] = BoolGetDatum(rd_rel->relhasrules);
values[Anum_pg_class_relhastriggers - 1] = BoolGetDatum(rd_rel->relhastriggers);
values[Anum_pg_class_relhassubclass - 1] = BoolGetDatum(rd_rel->relhassubclass);
values[Anum_pg_class_relfrozenxid - 1] = TransactionIdGetDatum(rd_rel->relfrozenxid);
values[Anum_pg_class_relminmxid - 1] = MultiXactIdGetDatum(rd_rel->relminmxid);
if (relacl != (Datum) 0)
values[Anum_pg_class_relacl - 1] = relacl;
else
nulls[Anum_pg_class_relacl - 1] = true;
if (reloptions != (Datum) 0)
values[Anum_pg_class_reloptions - 1] = reloptions;
else
nulls[Anum_pg_class_reloptions - 1] = true;
tup = heap_form_tuple(RelationGetDescr(pg_class_desc), values, nulls);
/*
* The new tuple must have the oid already chosen for the rel. Sure would
* be embarrassing to do this sort of thing in polite company.
*/
HeapTupleSetOid(tup, new_rel_oid);
/* finally insert the new tuple, update the indexes, and clean up */
simple_heap_insert(pg_class_desc, tup);
CatalogUpdateIndexes(pg_class_desc, tup);
heap_freetuple(tup);
}
| static bool MergeWithExistingConstraint | ( | Relation | rel, | |
| char * | ccname, | |||
| Node * | expr, | |||
| bool | allow_merge, | |||
| bool | is_local, | |||
| bool | is_no_inherit | |||
| ) | [static] |
Definition at line 2355 of file heap.c.
References Anum_pg_constraint_conbin, Anum_pg_constraint_conname, Anum_pg_constraint_connamespace, Assert, BTEqualStrategyNumber, CatalogUpdateIndexes(), CONSTRAINT_CHECK, ConstraintNameNspIndexId, ConstraintRelationId, CStringGetDatum, elog, equal(), ereport, errcode(), errmsg(), ERROR, fastgetattr, GETSTRUCT, heap_close, heap_copytuple(), heap_open(), HeapTupleIsValid, NOTICE, ObjectIdGetDatum, RelationData::rd_att, RelationGetNamespace, RelationGetRelationName, RelationGetRelid, RowExclusiveLock, ScanKeyInit(), simple_heap_update(), SnapshotNow, stringToNode(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, TextDatumGetCString, and val.
Referenced by AddRelationNewConstraints().
{
bool found;
Relation conDesc;
SysScanDesc conscan;
ScanKeyData skey[2];
HeapTuple tup;
/* Search for a pg_constraint entry with same name and relation */
conDesc = heap_open(ConstraintRelationId, RowExclusiveLock);
found = false;
ScanKeyInit(&skey[0],
Anum_pg_constraint_conname,
BTEqualStrategyNumber, F_NAMEEQ,
CStringGetDatum(ccname));
ScanKeyInit(&skey[1],
Anum_pg_constraint_connamespace,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetNamespace(rel)));
conscan = systable_beginscan(conDesc, ConstraintNameNspIndexId, true,
SnapshotNow, 2, skey);
while (HeapTupleIsValid(tup = systable_getnext(conscan)))
{
Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tup);
if (con->conrelid == RelationGetRelid(rel))
{
/* Found it. Conflicts if not identical check constraint */
if (con->contype == CONSTRAINT_CHECK)
{
Datum val;
bool isnull;
val = fastgetattr(tup,
Anum_pg_constraint_conbin,
conDesc->rd_att, &isnull);
if (isnull)
elog(ERROR, "null conbin for rel %s",
RelationGetRelationName(rel));
if (equal(expr, stringToNode(TextDatumGetCString(val))))
found = true;
}
if (!found || !allow_merge)
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("constraint \"%s\" for relation \"%s\" already exists",
ccname, RelationGetRelationName(rel))));
tup = heap_copytuple(tup);
con = (Form_pg_constraint) GETSTRUCT(tup);
/* If the constraint is "no inherit" then cannot merge */
if (con->connoinherit)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\"",
ccname, RelationGetRelationName(rel))));
if (is_local)
con->conislocal = true;
else
con->coninhcount++;
if (is_no_inherit)
{
Assert(is_local);
con->connoinherit = true;
}
/* OK to update the tuple */
ereport(NOTICE,
(errmsg("merging constraint \"%s\" with inherited definition",
ccname)));
simple_heap_update(conDesc, &tup->t_self, tup);
CatalogUpdateIndexes(conDesc, tup);
break;
}
}
systable_endscan(conscan);
heap_close(conDesc, RowExclusiveLock);
return found;
}
| static void RelationRemoveInheritance | ( | Oid | relid | ) | [static] |
Definition at line 1378 of file heap.c.
References Anum_pg_inherits_inhrelid, BTEqualStrategyNumber, heap_close, heap_open(), HeapTupleIsValid, InheritsRelationId, InheritsRelidSeqnoIndexId, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), simple_heap_delete(), SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.
Referenced by heap_drop_with_catalog().
{
Relation catalogRelation;
SysScanDesc scan;
ScanKeyData key;
HeapTuple tuple;
catalogRelation = heap_open(InheritsRelationId, RowExclusiveLock);
ScanKeyInit(&key,
Anum_pg_inherits_inhrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(relid));
scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId, true,
SnapshotNow, 1, &key);
while (HeapTupleIsValid(tuple = systable_getnext(scan)))
simple_heap_delete(catalogRelation, &tuple->t_self);
systable_endscan(scan);
heap_close(catalogRelation, RowExclusiveLock);
}
| static void RelationTruncateIndexes | ( | Relation | heapRelation | ) | [static] |
Definition at line 2667 of file heap.c.
References AccessExclusiveLock, BuildIndexInfo(), index_build(), index_close(), index_open(), lfirst_oid, NoLock, RelationGetIndexList(), and RelationTruncate().
Referenced by heap_truncate_one_rel().
{
ListCell *indlist;
/* Ask the relcache to produce a list of the indexes of the rel */
foreach(indlist, RelationGetIndexList(heapRelation))
{
Oid indexId = lfirst_oid(indlist);
Relation currentIndex;
IndexInfo *indexInfo;
/* Open the index relation; use exclusive lock, just to be sure */
currentIndex = index_open(indexId, AccessExclusiveLock);
/* Fetch info needed for index_build */
indexInfo = BuildIndexInfo(currentIndex);
/*
* Now truncate the actual file (and discard buffers).
*/
RelationTruncate(currentIndex, 0);
/* Initialize the index and rebuild */
/* Note: we do not need to re-establish pkey setting */
index_build(heapRelation, currentIndex, indexInfo, false, true);
/* We're done with this index */
index_close(currentIndex, NoLock);
}
}
| void RemoveAttrDefault | ( | Oid | relid, | |
| AttrNumber | attnum, | |||
| DropBehavior | behavior, | |||
| bool | complain, | |||
| bool | internal | |||
| ) |
Definition at line 1609 of file heap.c.
References Anum_pg_attrdef_adnum, Anum_pg_attrdef_adrelid, AttrDefaultIndexId, AttrDefaultRelationId, BTEqualStrategyNumber, ObjectAddress::classId, elog, ERROR, heap_close, heap_open(), HeapTupleGetOid, HeapTupleIsValid, Int16GetDatum, ObjectAddressStack::object, ObjectIdGetDatum, PERFORM_DELETION_INTERNAL, performDeletion(), RowExclusiveLock, ScanKeyInit(), SnapshotNow, systable_beginscan(), systable_endscan(), and systable_getnext().
Referenced by ATExecAlterColumnType(), and ATExecColumnDefault().
{
Relation attrdef_rel;
ScanKeyData scankeys[2];
SysScanDesc scan;
HeapTuple tuple;
bool found = false;
attrdef_rel = heap_open(AttrDefaultRelationId, RowExclusiveLock);
ScanKeyInit(&scankeys[0],
Anum_pg_attrdef_adrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(relid));
ScanKeyInit(&scankeys[1],
Anum_pg_attrdef_adnum,
BTEqualStrategyNumber, F_INT2EQ,
Int16GetDatum(attnum));
scan = systable_beginscan(attrdef_rel, AttrDefaultIndexId, true,
SnapshotNow, 2, scankeys);
/* There should be at most one matching tuple, but we loop anyway */
while (HeapTupleIsValid(tuple = systable_getnext(scan)))
{
ObjectAddress object;
object.classId = AttrDefaultRelationId;
object.objectId = HeapTupleGetOid(tuple);
object.objectSubId = 0;
performDeletion(&object, behavior,
internal ? PERFORM_DELETION_INTERNAL : 0);
found = true;
}
systable_endscan(scan);
heap_close(attrdef_rel, RowExclusiveLock);
if (complain && !found)
elog(ERROR, "could not find attrdef tuple for relation %u attnum %d",
relid, attnum);
}
| void RemoveAttrDefaultById | ( | Oid | attrdefId | ) |
Definition at line 1663 of file heap.c.
References AccessExclusiveLock, ATTNUM, AttrDefaultOidIndexId, AttrDefaultRelationId, AttributeRelationId, BTEqualStrategyNumber, CatalogUpdateIndexes(), elog, ERROR, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, Int16GetDatum, NoLock, ObjectIdAttributeNumber, ObjectIdGetDatum, relation_close(), relation_open(), RowExclusiveLock, ScanKeyInit(), SearchSysCacheCopy2, simple_heap_delete(), simple_heap_update(), SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.
Referenced by doDeletion().
{
Relation attrdef_rel;
Relation attr_rel;
Relation myrel;
ScanKeyData scankeys[1];
SysScanDesc scan;
HeapTuple tuple;
Oid myrelid;
AttrNumber myattnum;
/* Grab an appropriate lock on the pg_attrdef relation */
attrdef_rel = heap_open(AttrDefaultRelationId, RowExclusiveLock);
/* Find the pg_attrdef tuple */
ScanKeyInit(&scankeys[0],
ObjectIdAttributeNumber,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(attrdefId));
scan = systable_beginscan(attrdef_rel, AttrDefaultOidIndexId, true,
SnapshotNow, 1, scankeys);
tuple = systable_getnext(scan);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "could not find tuple for attrdef %u", attrdefId);
myrelid = ((Form_pg_attrdef) GETSTRUCT(tuple))->adrelid;
myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum;
/* Get an exclusive lock on the relation owning the attribute */
myrel = relation_open(myrelid, AccessExclusiveLock);
/* Now we can delete the pg_attrdef row */
simple_heap_delete(attrdef_rel, &tuple->t_self);
systable_endscan(scan);
heap_close(attrdef_rel, RowExclusiveLock);
/* Fix the pg_attribute row */
attr_rel = heap_open(AttributeRelationId, RowExclusiveLock);
tuple = SearchSysCacheCopy2(ATTNUM,
ObjectIdGetDatum(myrelid),
Int16GetDatum(myattnum));
if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
elog(ERROR, "cache lookup failed for attribute %d of relation %u",
myattnum, myrelid);
((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;
simple_heap_update(attr_rel, &tuple->t_self, tuple);
/* keep the system catalog indexes current */
CatalogUpdateIndexes(attr_rel, tuple);
/*
* Our update of the pg_attribute row will force a relcache rebuild, so
* there's nothing else to do here.
*/
heap_close(attr_rel, RowExclusiveLock);
/* Keep lock on attribute's rel until end of xact */
relation_close(myrel, NoLock);
}
| void RemoveAttributeById | ( | Oid | relid, | |
| AttrNumber | attnum | |||
| ) |
Definition at line 1518 of file heap.c.
References AccessExclusiveLock, ATTNUM, AttributeRelationId, CatalogUpdateIndexes(), elog, ERROR, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, Int16GetDatum, namestrcpy(), NoLock, ObjectIdGetDatum, relation_close(), relation_open(), RemoveStatistics(), RowExclusiveLock, SearchSysCacheCopy2, simple_heap_delete(), simple_heap_update(), snprintf(), and HeapTupleData::t_self.
Referenced by doDeletion().
{
Relation rel;
Relation attr_rel;
HeapTuple tuple;
Form_pg_attribute attStruct;
char newattname[NAMEDATALEN];
/*
* Grab an exclusive lock on the target table, which we will NOT release
* until end of transaction. (In the simple case where we are directly
* dropping this column, AlterTableDropColumn already did this ... but
* when cascading from a drop of some other object, we may not have any
* lock.)
*/
rel = relation_open(relid, AccessExclusiveLock);
attr_rel = heap_open(AttributeRelationId, RowExclusiveLock);
tuple = SearchSysCacheCopy2(ATTNUM,
ObjectIdGetDatum(relid),
Int16GetDatum(attnum));
if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
elog(ERROR, "cache lookup failed for attribute %d of relation %u",
attnum, relid);
attStruct = (Form_pg_attribute) GETSTRUCT(tuple);
if (attnum < 0)
{
/* System attribute (probably OID) ... just delete the row */
simple_heap_delete(attr_rel, &tuple->t_self);
}
else
{
/* Dropping user attributes is lots harder */
/* Mark the attribute as dropped */
attStruct->attisdropped = true;
/*
* Set the type OID to invalid. A dropped attribute's type link
* cannot be relied on (once the attribute is dropped, the type might
* be too). Fortunately we do not need the type row --- the only
* really essential information is the type's typlen and typalign,
* which are preserved in the attribute's attlen and attalign. We set
* atttypid to zero here as a means of catching code that incorrectly
* expects it to be valid.
*/
attStruct->atttypid = InvalidOid;
/* Remove any NOT NULL constraint the column may have */
attStruct->attnotnull = false;
/* We don't want to keep stats for it anymore */
attStruct->attstattarget = 0;
/*
* Change the column name to something that isn't likely to conflict
*/
snprintf(newattname, sizeof(newattname),
"........pg.dropped.%d........", attnum);
namestrcpy(&(attStruct->attname), newattname);
simple_heap_update(attr_rel, &tuple->t_self, tuple);
/* keep the system catalog indexes current */
CatalogUpdateIndexes(attr_rel, tuple);
}
/*
* Because updating the pg_attribute row will trigger a relcache flush for
* the target relation, we need not do anything else to notify other
* backends of the change.
*/
heap_close(attr_rel, RowExclusiveLock);
if (attnum > 0)
RemoveStatistics(relid, attnum);
relation_close(rel, NoLock);
}
| void RemoveStatistics | ( | Oid | relid, | |
| AttrNumber | attnum | |||
| ) |
Definition at line 2620 of file heap.c.
References Anum_pg_statistic_staattnum, Anum_pg_statistic_starelid, BTEqualStrategyNumber, heap_close, heap_open(), HeapTupleIsValid, Int16GetDatum, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), simple_heap_delete(), SnapshotNow, StatisticRelationId, StatisticRelidAttnumInhIndexId, systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.
Referenced by ATExecAlterColumnType(), heap_drop_with_catalog(), index_drop(), and RemoveAttributeById().
{
Relation pgstatistic;
SysScanDesc scan;
ScanKeyData key[2];
int nkeys;
HeapTuple tuple;
pgstatistic = heap_open(StatisticRelationId, RowExclusiveLock);
ScanKeyInit(&key[0],
Anum_pg_statistic_starelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(relid));
if (attnum == 0)
nkeys = 1;
else
{
ScanKeyInit(&key[1],
Anum_pg_statistic_staattnum,
BTEqualStrategyNumber, F_INT2EQ,
Int16GetDatum(attnum));
nkeys = 2;
}
scan = systable_beginscan(pgstatistic, StatisticRelidAttnumInhIndexId, true,
SnapshotNow, nkeys, key);
/* we must loop even when attnum != 0, in case of inherited stats */
while (HeapTupleIsValid(tuple = systable_getnext(scan)))
simple_heap_delete(pgstatistic, &tuple->t_self);
systable_endscan(scan);
heap_close(pgstatistic, RowExclusiveLock);
}
| static void SetRelationNumChecks | ( | Relation | rel, | |
| int | numchecks | |||
| ) | [static] |
Definition at line 2456 of file heap.c.
References CacheInvalidateRelcache(), CatalogUpdateIndexes(), elog, ERROR, GETSTRUCT, heap_close, heap_freetuple(), heap_open(), HeapTupleIsValid, ObjectIdGetDatum, RelationGetRelid, RelationRelationId, RELOID, RowExclusiveLock, SearchSysCacheCopy1, simple_heap_update(), and HeapTupleData::t_self.
Referenced by AddRelationNewConstraints(), and StoreConstraints().
{
Relation relrel;
HeapTuple reltup;
Form_pg_class relStruct;
relrel = heap_open(RelationRelationId, RowExclusiveLock);
reltup = SearchSysCacheCopy1(RELOID,
ObjectIdGetDatum(RelationGetRelid(rel)));
if (!HeapTupleIsValid(reltup))
elog(ERROR, "cache lookup failed for relation %u",
RelationGetRelid(rel));
relStruct = (Form_pg_class) GETSTRUCT(reltup);
if (relStruct->relchecks != numchecks)
{
relStruct->relchecks = numchecks;
simple_heap_update(relrel, &reltup->t_self, reltup);
/* keep catalog indexes current */
CatalogUpdateIndexes(relrel, reltup);
}
else
{
/* Skip the disk update, but force relcache inval anyway */
CacheInvalidateRelcache(rel);
}
heap_freetuple(reltup);
heap_close(relrel, RowExclusiveLock);
}
| void StoreAttrDefault | ( | Relation | rel, | |
| AttrNumber | attnum, | |||
| Node * | expr, | |||
| bool | is_internal | |||
| ) |
Definition at line 1840 of file heap.c.
References Anum_pg_attrdef_adbin, Anum_pg_attrdef_adnum, Anum_pg_attrdef_adrelid, Anum_pg_attrdef_adsrc, ATTNUM, AttrDefaultRelationId, AttributeRelationId, CatalogUpdateIndexes(), ObjectAddress::classId, CStringGetTextDatum, DatumGetPointer, deparse_context_for(), deparse_expression(), DEPENDENCY_AUTO, DEPENDENCY_NORMAL, elog, ERROR, GETSTRUCT, heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), HeapTupleIsValid, Int16GetDatum, InvokeObjectPostCreateHookArg, NIL, nodeToString(), ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, pfree(), RelationData::rd_att, recordDependencyOn(), recordDependencyOnExpr(), RelationGetRelationName, RelationGetRelid, RowExclusiveLock, SearchSysCacheCopy2, simple_heap_insert(), simple_heap_update(), HeapTupleData::t_self, and values.
Referenced by AddRelationNewConstraints(), ATExecAlterColumnType(), and StoreConstraints().
{
char *adbin;
char *adsrc;
Relation adrel;
HeapTuple tuple;
Datum values[4];
static bool nulls[4] = {false, false, false, false};
Relation attrrel;
HeapTuple atttup;
Form_pg_attribute attStruct;
Oid attrdefOid;
ObjectAddress colobject,
defobject;
/*
* Flatten expression to string form for storage.
*/
adbin = nodeToString(expr);
/*
* Also deparse it to form the mostly-obsolete adsrc field.
*/
adsrc = deparse_expression(expr,
deparse_context_for(RelationGetRelationName(rel),
RelationGetRelid(rel)),
false, false);
/*
* Make the pg_attrdef entry.
*/
values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
values[Anum_pg_attrdef_adnum - 1] = attnum;
values[Anum_pg_attrdef_adbin - 1] = CStringGetTextDatum(adbin);
values[Anum_pg_attrdef_adsrc - 1] = CStringGetTextDatum(adsrc);
adrel = heap_open(AttrDefaultRelationId, RowExclusiveLock);
tuple = heap_form_tuple(adrel->rd_att, values, nulls);
attrdefOid = simple_heap_insert(adrel, tuple);
CatalogUpdateIndexes(adrel, tuple);
defobject.classId = AttrDefaultRelationId;
defobject.objectId = attrdefOid;
defobject.objectSubId = 0;
heap_close(adrel, RowExclusiveLock);
/* now can free some of the stuff allocated above */
pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));
pfree(DatumGetPointer(values[Anum_pg_attrdef_adsrc - 1]));
heap_freetuple(tuple);
pfree(adbin);
pfree(adsrc);
/*
* Update the pg_attribute entry for the column to show that a default
* exists.
*/
attrrel = heap_open(AttributeRelationId, RowExclusiveLock);
atttup = SearchSysCacheCopy2(ATTNUM,
ObjectIdGetDatum(RelationGetRelid(rel)),
Int16GetDatum(attnum));
if (!HeapTupleIsValid(atttup))
elog(ERROR, "cache lookup failed for attribute %d of relation %u",
attnum, RelationGetRelid(rel));
attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
if (!attStruct->atthasdef)
{
attStruct->atthasdef = true;
simple_heap_update(attrrel, &atttup->t_self, atttup);
/* keep catalog indexes current */
CatalogUpdateIndexes(attrrel, atttup);
}
heap_close(attrrel, RowExclusiveLock);
heap_freetuple(atttup);
/*
* Make a dependency so that the pg_attrdef entry goes away if the column
* (or whole table) is deleted.
*/
colobject.classId = RelationRelationId;
colobject.objectId = RelationGetRelid(rel);
colobject.objectSubId = attnum;
recordDependencyOn(&defobject, &colobject, DEPENDENCY_AUTO);
/*
* Record dependencies on objects used in the expression, too.
*/
recordDependencyOnExpr(&defobject, expr, NIL, DEPENDENCY_NORMAL);
/*
* Post creation hook for attribute defaults.
*
* XXX. ALTER TABLE ALTER COLUMN SET/DROP DEFAULT is implemented
* with a couple of deletion/creation of the attribute's default entry,
* so the callee should check existence of an older version of this
* entry if it needs to distinguish.
*/
InvokeObjectPostCreateHookArg(AttrDefaultRelationId,
RelationGetRelid(rel), attnum, is_internal);
}
Definition at line 2055 of file heap.c.
References CookedConstraint::attnum, CommandCounterIncrement(), CONSTR_CHECK, CONSTR_DEFAULT, CookedConstraint::contype, elog, ERROR, CookedConstraint::expr, CookedConstraint::inhcount, CookedConstraint::is_local, CookedConstraint::is_no_inherit, lfirst, CookedConstraint::name, SetRelationNumChecks(), CookedConstraint::skip_validation, StoreAttrDefault(), and StoreRelCheck().
Referenced by heap_create_with_catalog().
{
int numchecks = 0;
ListCell *lc;
if (!cooked_constraints)
return; /* nothing to do */
/*
* Deparsing of constraint expressions will fail unless the just-created
* pg_attribute tuples for this relation are made visible. So, bump the
* command counter. CAUTION: this will cause a relcache entry rebuild.
*/
CommandCounterIncrement();
foreach(lc, cooked_constraints)
{
CookedConstraint *con = (CookedConstraint *) lfirst(lc);
switch (con->contype)
{
case CONSTR_DEFAULT:
StoreAttrDefault(rel, con->attnum, con->expr, is_internal);
break;
case CONSTR_CHECK:
StoreRelCheck(rel, con->name, con->expr, !con->skip_validation,
con->is_local, con->inhcount,
con->is_no_inherit, is_internal);
numchecks++;
break;
default:
elog(ERROR, "unrecognized constraint type: %d",
(int) con->contype);
}
}
if (numchecks > 0)
SetRelationNumChecks(rel, numchecks);
}
| static void StoreRelCheck | ( | Relation | rel, | |
| char * | ccname, | |||
| Node * | expr, | |||
| bool | is_validated, | |||
| bool | is_local, | |||
| int | inhcount, | |||
| bool | is_no_inherit, | |||
| bool | is_internal | |||
| ) | [static] |
Definition at line 1953 of file heap.c.
References CONSTRAINT_CHECK, CreateConstraintEntry(), deparse_context_for(), deparse_expression(), i, InvalidOid, lfirst, list_length(), nodeToString(), NULL, palloc(), pfree(), pull_var_clause(), PVC_REJECT_AGGREGATES, PVC_REJECT_PLACEHOLDERS, RelationGetNamespace, RelationGetRelationName, RelationGetRelid, and Var::varattno.
Referenced by AddRelationNewConstraints(), and StoreConstraints().
{
char *ccbin;
char *ccsrc;
List *varList;
int keycount;
int16 *attNos;
/*
* Flatten expression to string form for storage.
*/
ccbin = nodeToString(expr);
/*
* Also deparse it to form the mostly-obsolete consrc field.
*/
ccsrc = deparse_expression(expr,
deparse_context_for(RelationGetRelationName(rel),
RelationGetRelid(rel)),
false, false);
/*
* Find columns of rel that are used in expr
*
* NB: pull_var_clause is okay here only because we don't allow subselects
* in check constraints; it would fail to examine the contents of
* subselects.
*/
varList = pull_var_clause(expr,
PVC_REJECT_AGGREGATES,
PVC_REJECT_PLACEHOLDERS);
keycount = list_length(varList);
if (keycount > 0)
{
ListCell *vl;
int i = 0;
attNos = (int16 *) palloc(keycount * sizeof(int16));
foreach(vl, varList)
{
Var *var = (Var *) lfirst(vl);
int j;
for (j = 0; j < i; j++)
if (attNos[j] == var->varattno)
break;
if (j == i)
attNos[i++] = var->varattno;
}
keycount = i;
}
else
attNos = NULL;
/*
* Create the Check Constraint
*/
CreateConstraintEntry(ccname, /* Constraint Name */
RelationGetNamespace(rel), /* namespace */
CONSTRAINT_CHECK, /* Constraint Type */
false, /* Is Deferrable */
false, /* Is Deferred */
is_validated,
RelationGetRelid(rel), /* relation */
attNos, /* attrs in the constraint */
keycount, /* # attrs in the constraint */
InvalidOid, /* not a domain constraint */
InvalidOid, /* no associated index */
InvalidOid, /* Foreign key fields */
NULL,
NULL,
NULL,
NULL,
0,
' ',
' ',
' ',
NULL, /* not an exclusion constraint */
expr, /* Tree form of check constraint */
ccbin, /* Binary form of check constraint */
ccsrc, /* Source form of check constraint */
is_local, /* conislocal */
inhcount, /* coninhcount */
is_no_inherit, /* connoinherit */
is_internal); /* internally constructed? */
pfree(ccbin);
pfree(ccsrc);
}
| Form_pg_attribute SystemAttributeByName | ( | const char * | attname, | |
| bool | relhasoids | |||
| ) |
Definition at line 204 of file heap.c.
References lengthof, NameStr, and ObjectIdAttributeNumber.
Referenced by CheckAttributeNamesTypes(), specialAttNum(), SPI_fnumber(), and transformIndexConstraint().
{
int j;
for (j = 0; j < (int) lengthof(SysAtt); j++)
{
Form_pg_attribute att = SysAtt[j];
if (relhasoids || att->attnum != ObjectIdAttributeNumber)
{
if (strcmp(NameStr(att->attname), attname) == 0)
return att;
}
}
return NULL;
}
| Form_pg_attribute SystemAttributeDefinition | ( | AttrNumber | attno, | |
| bool | relhasoids | |||
| ) |
Definition at line 190 of file heap.c.
References elog, ERROR, lengthof, and ObjectIdAttributeNumber.
Referenced by attnumAttName(), attnumTypeId(), build_index_tlist(), ConstructTupleDescriptor(), SPI_fname(), SPI_gettype(), SPI_gettypeid(), SPI_getvalue(), and transformIndexConstraint().
FormData_pg_attribute a1 [static] |
{
0, {"ctid"}, TIDOID, 0, sizeof(ItemPointerData),
SelfItemPointerAttributeNumber, 0, -1, -1,
false, 'p', 's', true, false, false, true, 0
}
Definition at line 134 of file heap.c.
Referenced by aclitem_eq(), aclitemComparator(), chkpass_eq(), chkpass_ne(), cmpaffix(), deccall2(), deccall3(), macaddr_cmp(), macaddr_eq(), macaddr_ge(), macaddr_gt(), macaddr_le(), macaddr_lt(), macaddr_ne(), network_cmp(), network_eq(), network_ge(), network_gt(), network_le(), network_lt(), network_ne(), network_sub(), network_subeq(), network_sup(), and network_supeq().
FormData_pg_attribute a2 [static] |
{
0, {"oid"}, OIDOID, 0, sizeof(Oid),
ObjectIdAttributeNumber, 0, -1, -1,
true, 'p', 'i', true, false, false, true, 0
}
Definition at line 140 of file heap.c.
Referenced by aclitem_eq(), aclitemComparator(), chkpass_eq(), chkpass_ne(), cmpaffix(), deccall2(), deccall3(), macaddr_cmp(), macaddr_eq(), macaddr_ge(), macaddr_gt(), macaddr_le(), macaddr_lt(), macaddr_ne(), network_cmp(), network_eq(), network_ge(), network_gt(), network_le(), network_lt(), network_ne(), network_sub(), network_subeq(), network_sup(), and network_supeq().
FormData_pg_attribute a3 [static] |
{
0, {"xmin"}, XIDOID, 0, sizeof(TransactionId),
MinTransactionIdAttributeNumber, 0, -1, -1,
true, 'p', 'i', true, false, false, true, 0
}
FormData_pg_attribute a4 [static] |
{
0, {"cmin"}, CIDOID, 0, sizeof(CommandId),
MinCommandIdAttributeNumber, 0, -1, -1,
true, 'p', 'i', true, false, false, true, 0
}
FormData_pg_attribute a5 [static] |
{
0, {"xmax"}, XIDOID, 0, sizeof(TransactionId),
MaxTransactionIdAttributeNumber, 0, -1, -1,
true, 'p', 'i', true, false, false, true, 0
}
FormData_pg_attribute a6 [static] |
{
0, {"cmax"}, CIDOID, 0, sizeof(CommandId),
MaxCommandIdAttributeNumber, 0, -1, -1,
true, 'p', 'i', true, false, false, true, 0
}
FormData_pg_attribute a7 [static] |
{
0, {"tableoid"}, OIDOID, 0, sizeof(Oid),
TableOidAttributeNumber, 0, -1, -1,
true, 'p', 'i', true, false, false, true, 0
}
| Oid binary_upgrade_next_heap_pg_class_oid = InvalidOid |
Definition at line 77 of file heap.c.
Referenced by heap_create_with_catalog(), and set_next_heap_pg_class_oid().
| Oid binary_upgrade_next_toast_pg_class_oid = InvalidOid |
Definition at line 78 of file heap.c.
Referenced by create_toast_table(), heap_create_with_catalog(), and set_next_toast_pg_class_oid().
1.7.1