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:
@@ -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))));
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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")));
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user