1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-09 06:21:09 +03:00

Convert oidvector and int2vector into variable-length arrays. This

change saves a great deal of space in pg_proc and its primary index,
and it eliminates the former requirement that INDEX_MAX_KEYS and
FUNC_MAX_ARGS have the same value.  INDEX_MAX_KEYS is still embedded
in the on-disk representation (because it affects index tuple header
size), but FUNC_MAX_ARGS is not.  I believe it would now be possible
to increase FUNC_MAX_ARGS at little cost, but haven't experimented yet.
There are still a lot of vestigial references to FUNC_MAX_ARGS, which
I will clean up in a separate pass.  However, getting rid of it
altogether would require changing the FunctionCallInfoData struct,
and I'm not sure I want to buy into that.
This commit is contained in:
Tom Lane
2005-03-29 00:17:27 +00:00
parent 119191609c
commit 70c9763d48
61 changed files with 819 additions and 581 deletions

View File

@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.22 2004/12/31 21:59:41 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.23 2005/03/29 00:16:57 tgl Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@@ -246,11 +246,11 @@ RenameAggregate(List *name, TypeName *basetype, const char *newname)
namespaceOid = procForm->pronamespace;
/* make sure the new name doesn't exist */
if (SearchSysCacheExists(PROCNAMENSP,
if (SearchSysCacheExists(PROCNAMEARGSNSP,
CStringGetDatum(newname),
Int16GetDatum(procForm->pronargs),
PointerGetDatum(procForm->proargtypes),
ObjectIdGetDatum(namespaceOid)))
PointerGetDatum(&procForm->proargtypes),
ObjectIdGetDatum(namespaceOid),
0))
{
if (basetypeOid == ANYOID)
ereport(ERROR,
@@ -264,7 +264,7 @@ RenameAggregate(List *name, TypeName *basetype, const char *newname)
errmsg("function %s already exists in schema \"%s\"",
funcname_signature_string(newname,
procForm->pronargs,
procForm->proargtypes),
procForm->proargtypes.values),
get_namespace_name(namespaceOid))));
}

View File

@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.133 2005/03/20 22:00:52 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.134 2005/03/29 00:16:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -347,7 +347,7 @@ check_index_is_clusterable(Relation OldHeap, Oid indexOid)
* at the first column; multicolumn-capable AMs are *required* to
* index nulls in columns after the first.
*/
colno = OldIndex->rd_index->indkey[0];
colno = OldIndex->rd_index->indkey.values[0];
if (colno > 0)
{
/* ordinary user attribute */

View File

@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.56 2005/03/14 00:19:36 neilc Exp $
* $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.57 2005/03/29 00:16:57 tgl Exp $
*
* DESCRIPTION
* These routines take the parse tree and pick out the
@@ -716,18 +716,18 @@ RenameFunction(List *name, List *argtypes, const char *newname)
namespaceOid = procForm->pronamespace;
/* make sure the new name doesn't exist */
if (SearchSysCacheExists(PROCNAMENSP,
if (SearchSysCacheExists(PROCNAMEARGSNSP,
CStringGetDatum(newname),
Int16GetDatum(procForm->pronargs),
PointerGetDatum(procForm->proargtypes),
ObjectIdGetDatum(namespaceOid)))
PointerGetDatum(&procForm->proargtypes),
ObjectIdGetDatum(namespaceOid),
0))
{
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_FUNCTION),
errmsg("function %s already exists in schema \"%s\"",
funcname_signature_string(newname,
procForm->pronargs,
procForm->proargtypes),
procForm->proargtypes.values),
get_namespace_name(namespaceOid))));
}
@@ -962,11 +962,11 @@ SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType)
procForm = (Form_pg_proc) GETSTRUCT(tup);
if (argIndex < 0 || argIndex >= procForm->pronargs ||
procForm->proargtypes[argIndex] != OPAQUEOID)
procForm->proargtypes.values[argIndex] != OPAQUEOID)
elog(ERROR, "function %u doesn't take OPAQUE", funcOid);
/* okay to overwrite copied tuple */
procForm->proargtypes[argIndex] = newArgType;
procForm->proargtypes.values[argIndex] = newArgType;
/* update the catalog and its indexes */
simple_heap_update(pg_proc_rel, &tup->t_self, tup);
@@ -1064,15 +1064,15 @@ CreateCast(CreateCastStmt *stmt)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("cast function must take one to three arguments")));
if (procstruct->proargtypes[0] != sourcetypeid)
if (procstruct->proargtypes.values[0] != sourcetypeid)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("argument of cast function must match source data type")));
if (nargs > 1 && procstruct->proargtypes[1] != INT4OID)
if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("second argument of cast function must be type integer")));
if (nargs > 2 && procstruct->proargtypes[2] != BOOLOID)
if (nargs > 2 && procstruct->proargtypes.values[2] != BOOLOID)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("third argument of cast function must be type boolean")));

View File

@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.29 2004/12/31 21:59:41 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.30 2005/03/29 00:16:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -486,7 +486,7 @@ assignProcSubtype(Oid amoid, Oid typeoid, Oid procOid)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("btree procedures must return integer")));
if (procform->proargtypes[0] != typeoid)
if (procform->proargtypes.values[0] != typeoid)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("btree procedures must have index type as first input")));
@@ -495,10 +495,10 @@ assignProcSubtype(Oid amoid, Oid typeoid, Oid procOid)
* The subtype is "default" (0) if second input type matches the
* operator class, otherwise it is the second input type.
*/
if (procform->proargtypes[1] == typeoid)
if (procform->proargtypes.values[1] == typeoid)
subtype = InvalidOid;
else
subtype = procform->proargtypes[1];
subtype = procform->proargtypes.values[1];
ReleaseSysCache(proctup);
return subtype;
}

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.151 2005/03/25 18:04:34 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.152 2005/03/29 00:16:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1419,7 +1419,7 @@ renameatt(Oid myrelid,
for (i = 0; i < indexform->indnatts; i++)
{
if (attnum != indexform->indkey[i])
if (attnum != indexform->indkey.values[i])
continue;
/*
@@ -1676,9 +1676,10 @@ update_ri_trigger_args(Oid relid,
* line; so does trigger.c ...
*/
tgnargs = pg_trigger->tgnargs;
val = (bytea *) fastgetattr(tuple,
Anum_pg_trigger_tgargs,
tgrel->rd_att, &isnull);
val = (bytea *)
DatumGetPointer(fastgetattr(tuple,
Anum_pg_trigger_tgargs,
tgrel->rd_att, &isnull));
if (isnull || tgnargs < RI_FIRST_ATTNAME_ARGNO ||
tgnargs > RI_MAX_ARGUMENTS)
{
@@ -3202,7 +3203,7 @@ ATExecDropNotNull(Relation rel, const char *colName)
*/
for (i = 0; i < indexStruct->indnatts; i++)
{
if (indexStruct->indkey[i] == attnum)
if (indexStruct->indkey.values[i] == attnum)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("column \"%s\" is in a primary key",
@@ -4096,6 +4097,9 @@ transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
ListCell *indexoidscan;
HeapTuple indexTuple = NULL;
Form_pg_index indexStruct = NULL;
Datum indclassDatum;
bool isnull;
oidvector *indclass;
int i;
/*
@@ -4135,6 +4139,12 @@ transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
errmsg("there is no primary key for referenced table \"%s\"",
RelationGetRelationName(pkrel))));
/* Must get indclass the hard way */
indclassDatum = SysCacheGetAttr(INDEXRELID, indexTuple,
Anum_pg_index_indclass, &isnull);
Assert(!isnull);
indclass = (oidvector *) DatumGetPointer(indclassDatum);
/*
* Now build the list of PK attributes from the indkey definition (we
* assume a primary key cannot have expressional elements)
@@ -4142,11 +4152,11 @@ transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
*attnamelist = NIL;
for (i = 0; i < indexStruct->indnatts; i++)
{
int pkattno = indexStruct->indkey[i];
int pkattno = indexStruct->indkey.values[i];
attnums[i] = pkattno;
atttypids[i] = attnumTypeId(pkrel, pkattno);
opclasses[i] = indexStruct->indclass[i];
opclasses[i] = indclass->values[i];
*attnamelist = lappend(*attnamelist,
makeString(pstrdup(NameStr(*attnumAttName(pkrel, pkattno)))));
}
@@ -4205,6 +4215,16 @@ transformFkeyCheckAttrs(Relation pkrel,
heap_attisnull(indexTuple, Anum_pg_index_indpred) &&
heap_attisnull(indexTuple, Anum_pg_index_indexprs))
{
/* Must get indclass the hard way */
Datum indclassDatum;
bool isnull;
oidvector *indclass;
indclassDatum = SysCacheGetAttr(INDEXRELID, indexTuple,
Anum_pg_index_indclass, &isnull);
Assert(!isnull);
indclass = (oidvector *) DatumGetPointer(indclassDatum);
/*
* The given attnum list may match the index columns in any
* order. Check that each list is a subset of the other.
@@ -4214,7 +4234,7 @@ transformFkeyCheckAttrs(Relation pkrel,
found = false;
for (j = 0; j < numattrs; j++)
{
if (attnums[i] == indexStruct->indkey[j])
if (attnums[i] == indexStruct->indkey.values[j])
{
found = true;
break;
@@ -4230,9 +4250,9 @@ transformFkeyCheckAttrs(Relation pkrel,
found = false;
for (j = 0; j < numattrs; j++)
{
if (attnums[j] == indexStruct->indkey[i])
if (attnums[j] == indexStruct->indkey.values[i])
{
opclasses[j] = indexStruct->indclass[i];
opclasses[j] = indclass->values[i];
found = true;
break;
}

View File

@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.181 2005/03/25 21:57:58 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.182 2005/03/29 00:16:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -67,7 +67,7 @@ Oid
CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
{
int16 tgtype;
int16 tgattr[FUNC_MAX_ARGS];
int2vector *tgattr;
Datum values[Natts_pg_trigger];
char nulls[Natts_pg_trigger];
Relation rel;
@@ -77,7 +77,7 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
ScanKeyData key;
Relation pgrel;
HeapTuple tuple;
Oid fargtypes[FUNC_MAX_ARGS];
Oid fargtypes[1]; /* dummy */
Oid funcoid;
Oid funcrettype;
Oid trigoid;
@@ -275,7 +275,6 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
/*
* Find and validate the trigger function.
*/
MemSet(fargtypes, 0, FUNC_MAX_ARGS * sizeof(Oid));
funcoid = LookupFuncName(stmt->funcname, 0, fargtypes, false);
funcrettype = get_func_rettype(funcoid);
if (funcrettype != TRIGGEROID)
@@ -359,7 +358,8 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain,
CStringGetDatum(""));
}
MemSet(tgattr, 0, FUNC_MAX_ARGS * sizeof(int16));
/* tgattr is currently always a zero-length array */
tgattr = buildint2vector(NULL, 0);
values[Anum_pg_trigger_tgattr - 1] = PointerGetDatum(tgattr);
tuple = heap_formtuple(tgrel->rd_att, values, nulls);
@@ -774,8 +774,16 @@ RelationBuildTriggers(Relation relation)
build->tgdeferrable = pg_trigger->tgdeferrable;
build->tginitdeferred = pg_trigger->tginitdeferred;
build->tgnargs = pg_trigger->tgnargs;
memcpy(build->tgattr, &(pg_trigger->tgattr),
FUNC_MAX_ARGS * sizeof(int16));
/* tgattr is first var-width field, so OK to access directly */
build->tgnattr = pg_trigger->tgattr.dim1;
if (build->tgnattr > 0)
{
build->tgattr = (int2 *) palloc(build->tgnattr * sizeof(int2));
memcpy(build->tgattr, &(pg_trigger->tgattr.values),
build->tgnattr * sizeof(int2));
}
else
build->tgattr = NULL;
if (build->tgnargs > 0)
{
bytea *val;
@@ -783,9 +791,10 @@ RelationBuildTriggers(Relation relation)
char *p;
int i;
val = (bytea *) fastgetattr(htup,
Anum_pg_trigger_tgargs,
tgrel->rd_att, &isnull);
val = (bytea *)
DatumGetPointer(fastgetattr(htup,
Anum_pg_trigger_tgargs,
tgrel->rd_att, &isnull));
if (isnull)
elog(ERROR, "tgargs is null in trigger for relation \"%s\"",
RelationGetRelationName(relation));
@@ -928,6 +937,15 @@ CopyTriggerDesc(TriggerDesc *trigdesc)
for (i = 0; i < trigdesc->numtriggers; i++)
{
trigger->tgname = pstrdup(trigger->tgname);
if (trigger->tgnattr > 0)
{
int2 *newattr;
newattr = (int2 *) palloc(trigger->tgnattr * sizeof(int2));
memcpy(newattr, trigger->tgattr,
trigger->tgnattr * sizeof(int2));
trigger->tgattr = newattr;
}
if (trigger->tgnargs > 0)
{
char **newargs;
@@ -1031,6 +1049,8 @@ FreeTriggerDesc(TriggerDesc *trigdesc)
for (i = 0; i < trigdesc->numtriggers; i++)
{
pfree(trigger->tgname);
if (trigger->tgnattr > 0)
pfree(trigger->tgattr);
if (trigger->tgnargs > 0)
{
while (--(trigger->tgnargs) >= 0)
@@ -1092,8 +1112,11 @@ equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2)
return false;
if (trig1->tgnargs != trig2->tgnargs)
return false;
if (memcmp(trig1->tgattr, trig2->tgattr,
sizeof(trig1->tgattr)) != 0)
if (trig1->tgnattr != trig2->tgnattr)
return false;
if (trig1->tgnattr > 0 &&
memcmp(trig1->tgattr, trig2->tgattr,
trig1->tgnattr * sizeof(int2)) != 0)
return false;
for (j = 0; j < trig1->tgnargs; j++)
if (strcmp(trig1->tgargs[j], trig2->tgargs[j]) != 0)