1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-15 03:41:20 +03:00

Code review for standalone composite types, query-specified composite

types, SRFs.  Not happy with memory management yet, but I'll commit these
other changes.
This commit is contained in:
Tom Lane
2002-08-29 00:17:06 +00:00
parent 7483749d82
commit 64505ed58b
41 changed files with 836 additions and 744 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.85 2002/08/05 02:30:49 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.86 2002/08/29 00:17:02 tgl Exp $
*
* NOTES
* some of the executor utility code such as "ExecTypeFromTL" should be
@@ -570,7 +570,7 @@ BuildDescForRelation(List *schema)
* Given a (possibly qualified) relation name, build a TupleDesc.
*/
TupleDesc
RelationNameGetTupleDesc(char *relname)
RelationNameGetTupleDesc(const char *relname)
{
RangeVar *relvar;
Relation rel;
@@ -580,7 +580,7 @@ RelationNameGetTupleDesc(char *relname)
/* Open relation and get the tuple description */
relname_list = stringToQualifiedNameList(relname, "RelationNameGetTupleDesc");
relvar = makeRangeVarFromNameList(relname_list);
rel = heap_openrv(relvar, AccessShareLock);
rel = relation_openrv(relvar, AccessShareLock);
tupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
relation_close(rel, AccessShareLock);
@@ -611,50 +611,46 @@ TypeGetTupleDesc(Oid typeoid, List *colaliases)
{
/* Composite data type, i.e. a table's row type */
Oid relid = typeidTypeRelid(typeoid);
Relation rel;
int natts;
if (OidIsValid(relid))
if (!OidIsValid(relid))
elog(ERROR, "Invalid typrelid for complex type %u", typeoid);
rel = relation_open(relid, AccessShareLock);
tupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
natts = tupdesc->natts;
relation_close(rel, AccessShareLock);
/* XXX should we hold the lock to ensure table doesn't change? */
if (colaliases != NIL)
{
Relation rel;
int natts;
int varattno;
rel = relation_open(relid, AccessShareLock);
tupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
natts = tupdesc->natts;
relation_close(rel, AccessShareLock);
/* does the list length match the number of attributes? */
if (length(colaliases) != natts)
elog(ERROR, "TypeGetTupleDesc: number of aliases does not match number of attributes");
/* check to see if we've given column aliases */
if(colaliases != NIL)
/* OK, use the aliases instead */
for (varattno = 0; varattno < natts; varattno++)
{
char *label;
int varattno;
char *label = strVal(nth(varattno, colaliases));
/* does the List length match the number of attributes */
if (length(colaliases) != natts)
elog(ERROR, "TypeGetTupleDesc: number of aliases does not match number of attributes");
/* OK, use the aliases instead */
for (varattno = 0; varattno < natts; varattno++)
{
label = strVal(nth(varattno, colaliases));
if (label != NULL)
namestrcpy(&(tupdesc->attrs[varattno]->attname), label);
}
if (label != NULL)
namestrcpy(&(tupdesc->attrs[varattno]->attname), label);
}
}
else
elog(ERROR, "Invalid return relation specified for function");
}
else if (functyptype == 'b' || functyptype == 'd')
{
/* Must be a base data type, i.e. scalar */
char *attname;
/* the alias List is required for base types */
/* the alias list is required for base types */
if (colaliases == NIL)
elog(ERROR, "TypeGetTupleDesc: no column alias was provided");
/* the alias List length must be 1 */
/* the alias list length must be 1 */
if (length(colaliases) != 1)
elog(ERROR, "TypeGetTupleDesc: number of aliases does not match number of attributes");
@@ -671,8 +667,7 @@ TypeGetTupleDesc(Oid typeoid, List *colaliases)
false);
}
else if (functyptype == 'p' && typeoid == RECORDOID)
elog(ERROR, "Unable to determine tuple description for function"
" returning \"record\"");
elog(ERROR, "Unable to determine tuple description for function returning \"record\"");
else
elog(ERROR, "Unknown kind of return type specified for function");

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.145 2002/08/13 20:11:03 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.146 2002/08/29 00:17:02 tgl Exp $
*
*
* INTERFACE ROUTINES
@@ -607,6 +607,9 @@ heap_open(Oid relationId, LOCKMODE lockmode)
else if (r->rd_rel->relkind == RELKIND_SPECIAL)
elog(ERROR, "%s is a special relation",
RelationGetRelationName(r));
else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
elog(ERROR, "%s is a composite type",
RelationGetRelationName(r));
pgstat_initstats(&r->pgstat_info, r);
@@ -633,6 +636,9 @@ heap_openrv(const RangeVar *relation, LOCKMODE lockmode)
else if (r->rd_rel->relkind == RELKIND_SPECIAL)
elog(ERROR, "%s is a special relation",
RelationGetRelationName(r));
else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
elog(ERROR, "%s is a composite type",
RelationGetRelationName(r));
pgstat_initstats(&r->pgstat_info, r);
@@ -659,6 +665,9 @@ heap_openr(const char *sysRelationName, LOCKMODE lockmode)
else if (r->rd_rel->relkind == RELKIND_SPECIAL)
elog(ERROR, "%s is a special relation",
RelationGetRelationName(r));
else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
elog(ERROR, "%s is a composite type",
RelationGetRelationName(r));
pgstat_initstats(&r->pgstat_info, r);

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.221 2002/08/15 16:36:00 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.222 2002/08/29 00:17:02 tgl Exp $
*
*
* INTERFACE ROUTINES
@@ -69,6 +69,7 @@ static void AddNewRelationTuple(Relation pg_class_desc,
static void AddNewRelationType(const char *typeName,
Oid typeNamespace,
Oid new_rel_oid,
char new_rel_kind,
Oid new_type_oid);
static void RelationRemoveInheritance(Relation relation);
static void StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin);
@@ -357,7 +358,7 @@ CheckAttributeNames(TupleDesc tupdesc, bool relhasoids, char relkind)
/*
* first check for collision with system attribute names
*
* Skip this for a view and type relation, since it doesn't have system
* Skip this for a view or type relation, since those don't have system
* attributes.
*/
if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
@@ -618,6 +619,7 @@ static void
AddNewRelationType(const char *typeName,
Oid typeNamespace,
Oid new_rel_oid,
char new_rel_kind,
Oid new_type_oid)
{
/*
@@ -633,6 +635,7 @@ AddNewRelationType(const char *typeName,
typeNamespace, /* type namespace */
new_type_oid, /* preassigned oid for type */
new_rel_oid, /* relation oid */
new_rel_kind, /* relation kind */
sizeof(Oid), /* internal size */
'c', /* type-type (complex) */
',', /* default array delimiter */
@@ -728,7 +731,11 @@ heap_create_with_catalog(const char *relname,
* NOTE: we could get a unique-index failure here, in case the same name
* has already been used for a type.
*/
AddNewRelationType(relname, relnamespace, new_rel_oid, new_type_oid);
AddNewRelationType(relname,
relnamespace,
new_rel_oid,
relkind,
new_type_oid);
/*
* now add tuples to pg_attribute for the attributes in our new
@@ -904,7 +911,7 @@ RemoveAttributeById(Oid relid, AttrNumber attnum)
* did this ... but when cascading from a drop of some other object,
* we may not have any lock.)
*/
rel = heap_open(relid, AccessExclusiveLock);
rel = relation_open(relid, AccessExclusiveLock);
attr_rel = heap_openr(AttributeRelationName, RowExclusiveLock);
@@ -943,7 +950,7 @@ RemoveAttributeById(Oid relid, AttrNumber attnum)
heap_close(attr_rel, RowExclusiveLock);
heap_close(rel, NoLock);
relation_close(rel, NoLock);
}
/*
@@ -1036,7 +1043,7 @@ RemoveAttrDefaultById(Oid attrdefId)
myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum;
/* Get an exclusive lock on the relation owning the attribute */
myrel = heap_open(myrelid, AccessExclusiveLock);
myrel = relation_open(myrelid, AccessExclusiveLock);
/* Now we can delete the pg_attrdef row */
simple_heap_delete(attrdef_rel, &tuple->t_self);
@@ -1069,7 +1076,7 @@ RemoveAttrDefaultById(Oid attrdefId)
heap_close(attr_rel, RowExclusiveLock);
/* Keep lock on attribute's rel until end of xact */
heap_close(myrel, NoLock);
relation_close(myrel, NoLock);
}
/* ----------------------------------------------------------------
@@ -1099,7 +1106,7 @@ heap_drop_with_catalog(Oid rid)
/*
* Open and lock the relation.
*/
rel = heap_open(rid, AccessExclusiveLock);
rel = relation_open(rid, AccessExclusiveLock);
/*
* Release all buffers that belong to this relation, after writing any
@@ -1134,7 +1141,7 @@ heap_drop_with_catalog(Oid rid)
* unlink the relation's physical file and finish up.
*/
if (rel->rd_rel->relkind != RELKIND_VIEW &&
rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE)
rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE)
smgrunlink(DEFAULT_SMGR, rel);
/*
@@ -1142,7 +1149,7 @@ heap_drop_with_catalog(Oid rid)
* relation until transaction commit. This ensures no one else will
* try to do something with the doomed relation.
*/
heap_close(rel, NoLock);
relation_close(rel, NoLock);
/*
* flush the relation from the relcache

View File

@@ -13,7 +13,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.31 2002/08/15 16:36:01 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.32 2002/08/29 00:17:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1585,7 +1585,6 @@ RemoveTempRelations(Oid tempNamespaceId)
case RELKIND_RELATION:
case RELKIND_SEQUENCE:
case RELKIND_VIEW:
case RELKIND_COMPOSITE_TYPE:
AssertTupleDescHasOid(pgclass->rd_att);
object.classId = RelOid_pg_class;
object.objectId = HeapTupleGetOid(tuple);

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.90 2002/08/23 16:41:37 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.91 2002/08/29 00:17:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -400,7 +400,7 @@ checkretval(Oid rettype, char fn_typtype, List *queryTreeList)
* attributes to ensure that they match the datatypes of the
* non-resjunk columns.
*/
reln = heap_open(typerelid, AccessShareLock);
reln = relation_open(typerelid, AccessShareLock);
relnatts = reln->rd_rel->relnatts;
rellogcols = 0; /* we'll count nondeleted cols as we go */
colindex = 0;
@@ -447,7 +447,7 @@ checkretval(Oid rettype, char fn_typtype, List *queryTreeList)
elog(ERROR, "function declared to return %s does not SELECT the right number of columns (%d)",
format_type_be(rettype), rellogcols);
heap_close(reln, AccessShareLock);
relation_close(reln, AccessShareLock);
}
else if (fn_typtype == 'p' && rettype == RECORDOID)
{

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.79 2002/08/24 15:00:46 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.80 2002/08/29 00:17:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -129,7 +129,8 @@ Oid
TypeCreate(const char *typeName,
Oid typeNamespace,
Oid assignedTypeOid,
Oid relationOid, /* only for 'c'atalog typeTypes */
Oid relationOid, /* only for 'c'atalog typeType */
char relationKind, /* ditto */
int16 internalSize,
char typeType,
char typDelim,
@@ -332,15 +333,11 @@ TypeCreate(const char *typeName,
*/
if (OidIsValid(relationOid))
{
Relation rel = relation_open(relationOid, AccessShareLock);
char relkind = rel->rd_rel->relkind;
relation_close(rel, AccessShareLock);
referenced.classId = RelOid_pg_class;
referenced.objectId = relationOid;
referenced.objectSubId = 0;
if (relkind != RELKIND_COMPOSITE_TYPE)
if (relationKind != RELKIND_COMPOSITE_TYPE)
recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
else
recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);

View File

@@ -7,7 +7,7 @@
* Copyright (c) 1996-2001, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.57 2002/08/22 00:01:41 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.58 2002/08/29 00:17:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -362,7 +362,7 @@ CommentAttribute(List *qualname, char *comment)
/* Open the containing relation to ensure it won't go away meanwhile */
rel = makeRangeVarFromNameList(relname);
relation = heap_openrv(rel, AccessShareLock);
relation = relation_openrv(rel, AccessShareLock);
/* Check object security */
@@ -383,7 +383,7 @@ CommentAttribute(List *qualname, char *comment)
/* Done, but hold lock until commit */
heap_close(relation, NoLock);
relation_close(relation, NoLock);
}
/*

View File

@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.167 2002/08/24 15:00:46 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.168 2002/08/29 00:17:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -399,9 +399,6 @@ DoCopy(const CopyStmt *stmt)
if (rel->rd_rel->relkind == RELKIND_VIEW)
elog(ERROR, "You cannot copy view %s",
RelationGetRelationName(rel));
else if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
elog(ERROR, "You cannot copy type relation %s",
RelationGetRelationName(rel));
else if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
elog(ERROR, "You cannot change sequence relation %s",
RelationGetRelationName(rel));
@@ -447,9 +444,6 @@ DoCopy(const CopyStmt *stmt)
if (rel->rd_rel->relkind == RELKIND_VIEW)
elog(ERROR, "You cannot copy view %s",
RelationGetRelationName(rel));
else if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
elog(ERROR, "You cannot copy type relation %s",
RelationGetRelationName(rel));
else if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
elog(ERROR, "You cannot copy sequence %s",
RelationGetRelationName(rel));

View File

@@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994-5, Regents of the University of California
*
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.84 2002/07/20 15:12:55 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.85 2002/08/29 00:17:03 tgl Exp $
*
*/
@@ -79,7 +79,7 @@ ExplainQuery(ExplainStmt *stmt, CommandDest dest)
if (query->commandType == CMD_UTILITY)
{
/* rewriter will not cope with utility statements */
PROJECT_LINE_OF_TEXT(tstate, "Utility statements have no plan structure");
do_text_output_oneline(tstate, "Utility statements have no plan structure");
}
else
{
@@ -89,7 +89,7 @@ ExplainQuery(ExplainStmt *stmt, CommandDest dest)
if (rewritten == NIL)
{
/* In the case of an INSTEAD NOTHING, tell at least that */
PROJECT_LINE_OF_TEXT(tstate, "Query rewrites to nothing");
do_text_output_oneline(tstate, "Query rewrites to nothing");
}
else
{
@@ -99,7 +99,7 @@ ExplainQuery(ExplainStmt *stmt, CommandDest dest)
ExplainOneQuery(lfirst(l), stmt, tstate);
/* put a blank line between plans */
if (lnext(l) != NIL)
PROJECT_LINE_OF_TEXT(tstate, "");
do_text_output_oneline(tstate, "");
}
}
}
@@ -122,9 +122,9 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate)
if (query->commandType == CMD_UTILITY)
{
if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt))
PROJECT_LINE_OF_TEXT(tstate, "NOTIFY");
do_text_output_oneline(tstate, "NOTIFY");
else
PROJECT_LINE_OF_TEXT(tstate, "UTILITY");
do_text_output_oneline(tstate, "UTILITY");
return;
}
@@ -189,7 +189,7 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate)
do_text_output_multiline(tstate, f);
pfree(f);
if (es->printCost)
PROJECT_LINE_OF_TEXT(tstate, ""); /* separator line */
do_text_output_oneline(tstate, ""); /* separator line */
}
}

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.35 2002/08/28 20:18:29 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.36 2002/08/29 00:17:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -228,7 +228,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
* see the new rel anyway until we commit), but it keeps the lock
* manager from complaining about deadlock risks.
*/
rel = heap_open(relationId, AccessExclusiveLock);
rel = relation_open(relationId, AccessExclusiveLock);
/*
* Now add any newly specified column default values and CHECK
@@ -293,7 +293,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
* Clean up. We keep lock on new relation (although it shouldn't be
* visible to anyone else anyway, until commit).
*/
heap_close(rel, NoLock);
relation_close(rel, NoLock);
return relationId;
}
@@ -1064,7 +1064,7 @@ renameatt(Oid relid,
* Grab an exclusive lock on the target table, which we will NOT
* release until end of transaction.
*/
targetrelation = heap_open(relid, AccessExclusiveLock);
targetrelation = relation_open(relid, AccessExclusiveLock);
/*
* permissions checking. this would normally be done in utility.c,
@@ -1210,7 +1210,7 @@ renameatt(Oid relid,
true, false);
}
heap_close(targetrelation, NoLock); /* close rel but keep lock! */
relation_close(targetrelation, NoLock); /* close rel but keep lock! */
}
/*
@@ -3247,13 +3247,12 @@ CheckTupleType(Form_pg_class tuple_class)
case RELKIND_RELATION:
case RELKIND_INDEX:
case RELKIND_VIEW:
case RELKIND_COMPOSITE_TYPE:
case RELKIND_SEQUENCE:
case RELKIND_TOASTVALUE:
/* ok to change owner */
break;
default:
elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table, TOAST table, index, view, type, or sequence",
elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table, TOAST table, index, view, or sequence",
NameStr(tuple_class->relname));
}
}

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.11 2002/08/23 16:41:37 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.12 2002/08/29 00:17:03 tgl Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@@ -233,6 +233,7 @@ DefineType(List *names, List *parameters)
typeNamespace, /* namespace */
InvalidOid, /* preassigned type oid (not done here) */
InvalidOid, /* relation oid (n/a here) */
0, /* relation kind (ditto) */
internalLength, /* internal size */
'b', /* type-type (base type) */
delimiter, /* array element delimiter */
@@ -262,6 +263,7 @@ DefineType(List *names, List *parameters)
typeNamespace, /* namespace */
InvalidOid, /* preassigned type oid (not done here) */
InvalidOid, /* relation oid (n/a here) */
0, /* relation kind (ditto) */
-1, /* internal size */
'b', /* type-type (base type) */
DEFAULT_TYPDELIM, /* array element delimiter */
@@ -562,6 +564,7 @@ DefineDomain(CreateDomainStmt *stmt)
domainNamespace, /* namespace */
InvalidOid, /* preassigned type oid (none here) */
InvalidOid, /* relation oid (n/a here) */
0, /* relation kind (ditto) */
internalLength, /* internal size */
'd', /* type-type (domain type) */
delimiter, /* array element delimiter */

View File

@@ -27,7 +27,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.175 2002/08/28 20:46:22 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.176 2002/08/29 00:17:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -786,10 +786,6 @@ initResultRelInfo(ResultRelInfo *resultRelInfo,
elog(ERROR, "You can't change view relation %s",
RelationGetRelationName(resultRelationDesc));
break;
case RELKIND_COMPOSITE_TYPE:
elog(ERROR, "You can't change type relation %s",
RelationGetRelationName(resultRelationDesc));
break;
}
MemSet(resultRelInfo, 0, sizeof(ResultRelInfo));

View File

@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.56 2002/07/20 05:49:27 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.57 2002/08/29 00:17:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -109,8 +109,9 @@
#include "funcapi.h"
#include "access/heapam.h"
#include "catalog/pg_type.h"
#include "executor/executor.h"
#include "utils/lsyscache.h"
/* ----------------------------------------------------------------
* tuple table create/delete functions
@@ -676,8 +677,7 @@ ExecTypeFromTL(List *targetList, hasoid_t withoid)
}
/*
* TupleDescGetSlot - Initialize a slot based on the supplied
* tupledesc
* TupleDescGetSlot - Initialize a slot based on the supplied tupledesc
*/
TupleTableSlot *
TupleDescGetSlot(TupleDesc tupdesc)
@@ -695,40 +695,36 @@ TupleDescGetSlot(TupleDesc tupdesc)
}
/*
* TupleDescGetAttInMetadata - Get a pointer to AttInMetadata based on the
* TupleDescGetAttInMetadata - Build an AttInMetadata structure based on the
* supplied TupleDesc. AttInMetadata can be used in conjunction with C strings
* to produce a properly formed tuple.
*/
AttInMetadata *
TupleDescGetAttInMetadata(TupleDesc tupdesc)
{
int natts;
int natts = tupdesc->natts;
int i;
Oid atttypeid;
Oid attinfuncid;
Oid attelem;
FmgrInfo *attinfuncinfo;
Oid *attelems;
int4 *atttypmods;
int32 *atttypmods;
AttInMetadata *attinmeta;
attinmeta = (AttInMetadata *) palloc(sizeof(AttInMetadata));
natts = tupdesc->natts;
/*
* Gather info needed later to call the "in" function for each attribute
*/
attinfuncinfo = (FmgrInfo *) palloc(natts * sizeof(FmgrInfo));
attelems = (Oid *) palloc(natts * sizeof(Oid));
atttypmods = (int4 *) palloc(natts * sizeof(int4));
atttypmods = (int32 *) palloc(natts * sizeof(int32));
for (i = 0; i < natts; i++)
{
atttypeid = tupdesc->attrs[i]->atttypid;
get_type_metadata(atttypeid, &attinfuncid, &attelem);
getTypeInputInfo(atttypeid, &attinfuncid, &attelems[i]);
fmgr_info(attinfuncid, &attinfuncinfo[i]);
attelems[i] = attelem;
atttypmods[i] = tupdesc->attrs[i]->atttypmod;
}
attinmeta->tupdesc = tupdesc;
@@ -746,39 +742,35 @@ TupleDescGetAttInMetadata(TupleDesc tupdesc)
HeapTuple
BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
{
TupleDesc tupdesc;
int natts;
HeapTuple tuple;
TupleDesc tupdesc = attinmeta->tupdesc;
int natts = tupdesc->natts;
Datum *dvalues;
char *nulls;
int i;
Datum *dvalues;
FmgrInfo attinfuncinfo;
Oid attelem;
int4 atttypmod;
tupdesc = attinmeta->tupdesc;
natts = tupdesc->natts;
int32 atttypmod;
HeapTuple tuple;
dvalues = (Datum *) palloc(natts * sizeof(Datum));
nulls = (char *) palloc(natts * sizeof(char));
/* Call the "in" function for each attribute */
/* Call the "in" function for each non-null attribute */
for (i = 0; i < natts; i++)
{
if (values[i] != NULL)
{
attinfuncinfo = attinmeta->attinfuncs[i];
attelem = attinmeta->attelems[i];
atttypmod = attinmeta->atttypmods[i];
dvalues[i] = FunctionCall3(&attinfuncinfo, CStringGetDatum(values[i]),
ObjectIdGetDatum(attelem),
Int32GetDatum(atttypmod));
dvalues[i] = FunctionCall3(&attinmeta->attinfuncs[i],
CStringGetDatum(values[i]),
ObjectIdGetDatum(attelem),
Int32GetDatum(atttypmod));
nulls[i] = ' ';
}
else
{
dvalues[i] = PointerGetDatum(NULL);
dvalues[i] = (Datum) 0;
nulls[i] = 'n';
}
}
@@ -788,6 +780,13 @@ BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
*/
tuple = heap_formtuple(tupdesc, dvalues, nulls);
/*
* Release locally palloc'd space. XXX would probably be good to
* pfree values of pass-by-reference datums, as well.
*/
pfree(dvalues);
pfree(nulls);
return tuple;
}
@@ -804,7 +803,7 @@ begin_tup_output_tupdesc(CommandDest dest, TupleDesc tupdesc)
tstate = (TupOutputState *) palloc(sizeof(TupOutputState));
tstate->tupdesc = tupdesc;
tstate->metadata = TupleDescGetAttInMetadata(tupdesc);
tstate->destfunc = DestToFunction(dest);
(*tstate->destfunc->setup) (tstate->destfunc, (int) CMD_SELECT,
@@ -823,20 +822,22 @@ void
do_tup_output(TupOutputState *tstate, char **values)
{
/* build a tuple from the input strings using the tupdesc */
AttInMetadata *attinmeta = TupleDescGetAttInMetadata(tstate->tupdesc);
HeapTuple tuple = BuildTupleFromCStrings(attinmeta, values);
HeapTuple tuple = BuildTupleFromCStrings(tstate->metadata, values);
/* send the tuple to the receiver */
(*tstate->destfunc->receiveTuple) (tuple,
tstate->tupdesc,
tstate->metadata->tupdesc,
tstate->destfunc);
/* clean up */
heap_freetuple(tuple);
}
/* write a chunk of text, breaking at newline characters
/*
* write a chunk of text, breaking at newline characters
*
* NB: scribbles on its input!
* Should only be used for a single TEXT attribute tupdesc.
*
* Should only be used with a single-TEXT-attribute tupdesc.
*/
void
do_text_output_multiline(TupOutputState *tstate, char *text)
@@ -859,5 +860,6 @@ void
end_tup_output(TupOutputState *tstate)
{
(*tstate->destfunc->cleanup) (tstate->destfunc);
/* XXX worth cleaning up the attinmetadata? */
pfree(tstate);
}

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.55 2002/08/23 16:41:37 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.56 2002/08/29 00:17:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -193,9 +193,10 @@ init_sql_fcache(FmgrInfo *finfo)
*/
fcache->typlen = typeStruct->typlen;
if (typeStruct->typtype != 'c')
if (typeStruct->typtype != 'c' &&
procedureStruct->prorettype != RECORDOID)
{
/* The return type is not a relation, so just use byval */
/* The return type is not a composite type, so just use byval */
fcache->typbyval = typeStruct->typbyval;
fcache->returnsTuple = false;
}

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.5 2002/08/05 02:30:50 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.6 2002/08/29 00:17:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -130,10 +130,10 @@ FunctionNext(FunctionScan *node)
/* ----------------------------------------------------------------
* ExecFunctionScan(node)
*
* Scans the Function sequentially and returns the next qualifying
* Scans the function sequentially and returns the next qualifying
* tuple.
* It calls the ExecScan() routine and passes it the access method
* which retrieve tuples sequentially.
* which retrieves tuples sequentially.
*
*/
@@ -156,7 +156,6 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent)
FunctionScanState *scanstate;
RangeTblEntry *rte;
Oid funcrettype;
Oid funcrelid;
char functyptype;
TupleDesc tupdesc = NULL;
@@ -201,31 +200,26 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent)
/*
* Now determine if the function returns a simple or composite type,
* and check/add column aliases.
* and build an appropriate tupdesc.
*/
functyptype = get_typtype(funcrettype);
/*
* Build a suitable tupledesc representing the output rows
*/
if (functyptype == 'c')
{
funcrelid = typeidTypeRelid(funcrettype);
if (OidIsValid(funcrelid))
{
/*
* Composite data type, i.e. a table's row type
* Same as ordinary relation RTE
*/
Relation rel;
/*
* Composite data type, i.e. a table's row type
*/
Oid funcrelid;
Relation rel;
rel = relation_open(funcrelid, AccessShareLock);
tupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
relation_close(rel, AccessShareLock);
scanstate->returnsTuple = true;
}
else
elog(ERROR, "Invalid return relation specified for function");
funcrelid = typeidTypeRelid(funcrettype);
if (!OidIsValid(funcrelid))
elog(ERROR, "Invalid typrelid for complex type %u",
funcrettype);
rel = relation_open(funcrelid, AccessShareLock);
tupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
relation_close(rel, AccessShareLock);
scanstate->returnsTuple = true;
}
else if (functyptype == 'b' || functyptype == 'd')
{
@@ -461,8 +455,7 @@ function_getonetuple(FunctionScanState *scanstate,
*/
if (fn_typtype == 'p' && fn_typeid == RECORDOID)
if (tupledesc_mismatch(tupdesc, slot->ttc_tupleDescriptor))
elog(ERROR, "Query-specified return tuple and actual"
" function return tuple do not match");
elog(ERROR, "Query-specified return tuple and actual function return tuple do not match");
}
else
{
@@ -480,7 +473,7 @@ function_getonetuple(FunctionScanState *scanstate,
slot, /* slot to store in */
InvalidBuffer, /* buffer associated with
* this tuple */
true); /* pfree this pointer */
true); /* pfree this tuple */
}
}

View File

@@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.169 2002/08/26 17:53:58 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.170 2002/08/29 00:17:04 tgl Exp $
*
* NOTES
* Every (plan) node in POSTGRES has an associated "out" routine which
@@ -145,7 +145,7 @@ _outIndexStmt(StringInfo str, IndexStmt *node)
static void
_outNotifyStmt(StringInfo str, NotifyStmt *node)
{
appendStringInfo(str, "NOTIFY :relation ");
appendStringInfo(str, " NOTIFY :relation ");
_outNode(str, node->relation);
}
@@ -153,14 +153,14 @@ static void
_outSelectStmt(StringInfo str, SelectStmt *node)
{
/* XXX this is pretty durn incomplete */
appendStringInfo(str, "SELECT :where ");
appendStringInfo(str, " SELECT :where ");
_outNode(str, node->whereClause);
}
static void
_outFuncCall(StringInfo str, FuncCall *node)
{
appendStringInfo(str, "FUNCTION ");
appendStringInfo(str, " FUNCCALL ");
_outNode(str, node->funcname);
appendStringInfo(str, " :args ");
_outNode(str, node->args);
@@ -1006,7 +1006,7 @@ _outRangeTblEntry(StringInfo str, RangeTblEntry *node)
case RTE_FUNCTION:
appendStringInfo(str, ":funcexpr ");
_outNode(str, node->funcexpr);
appendStringInfo(str, ":coldeflist ");
appendStringInfo(str, " :coldeflist ");
_outNode(str, node->coldeflist);
break;
case RTE_JOIN:

View File

@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.363 2002/08/28 20:46:23 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.364 2002/08/29 00:17:04 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -204,8 +204,8 @@ static void doNegateFloat(Value *v);
%type <list> stmtblock, stmtmulti,
OptTableElementList, TableElementList, OptInherit, definition,
opt_distinct, opt_definition, func_args, rowdefinition
func_args_list, func_as, createfunc_opt_list
opt_distinct, opt_definition, func_args,
func_args_list, func_as, createfunc_opt_list,
oper_argtypes, RuleActionList, RuleActionMulti,
opt_column_list, columnList, opt_name_list,
sort_clause, opt_sort_clause, sortby_list, index_params,
@@ -216,7 +216,7 @@ static void doNegateFloat(Value *v);
insert_target_list, def_list, opt_indirection,
group_clause, TriggerFuncArgs, select_limit,
opt_select_limit, opclass_item_list, trans_options,
TableFuncElementList, OptTableFuncElementList,
TableFuncElementList,
convert_args, prep_type_clause, prep_type_list,
execute_param_clause, execute_param_list
@@ -1424,14 +1424,14 @@ OptTableElementList:
;
TableElementList:
TableElementList ',' TableElement
{
$$ = lappend($1, $3);
}
| TableElement
TableElement
{
$$ = makeList1($1);
}
| TableElementList ',' TableElement
{
$$ = lappend($1, $3);
}
;
TableElement:
@@ -2234,11 +2234,12 @@ DefineStmt:
n->definition = $4;
$$ = (Node *)n;
}
| CREATE TYPE_P any_name AS rowdefinition
| CREATE TYPE_P any_name AS '(' TableFuncElementList ')'
{
CompositeTypeStmt *n = makeNode(CompositeTypeStmt);
RangeVar *r = makeNode(RangeVar);
/* can't use qualified_name, sigh */
switch (length($3))
{
case 1:
@@ -2258,13 +2259,12 @@ DefineStmt:
break;
default:
elog(ERROR,
"Improper qualified name "
"(too many dotted names): %s",
"Improper qualified name (too many dotted names): %s",
NameListToString($3));
break;
}
n->typevar = r;
n->coldeflist = $5;
n->coldeflist = $6;
$$ = (Node *)n;
}
| CREATE CHARACTER SET opt_as any_name GET definition opt_collate
@@ -2277,9 +2277,6 @@ DefineStmt:
}
;
rowdefinition: '(' TableFuncElementList ')' { $$ = $2; }
;
definition: '(' def_list ')' { $$ = $2; }
;
@@ -4539,14 +4536,22 @@ table_ref: relation_expr
n->coldeflist = NIL;
$$ = (Node *) n;
}
| func_table AS '(' OptTableFuncElementList ')'
| func_table alias_clause
{
RangeFunction *n = makeNode(RangeFunction);
n->funccallnode = $1;
n->alias = $2;
n->coldeflist = NIL;
$$ = (Node *) n;
}
| func_table AS '(' TableFuncElementList ')'
{
RangeFunction *n = makeNode(RangeFunction);
n->funccallnode = $1;
n->coldeflist = $4;
$$ = (Node *) n;
}
| func_table AS ColId '(' OptTableFuncElementList ')'
| func_table AS ColId '(' TableFuncElementList ')'
{
RangeFunction *n = makeNode(RangeFunction);
Alias *a = makeNode(Alias);
@@ -4556,7 +4561,7 @@ table_ref: relation_expr
n->coldeflist = $5;
$$ = (Node *) n;
}
| func_table ColId '(' OptTableFuncElementList ')'
| func_table ColId '(' TableFuncElementList ')'
{
RangeFunction *n = makeNode(RangeFunction);
Alias *a = makeNode(Alias);
@@ -4566,14 +4571,6 @@ table_ref: relation_expr
n->coldeflist = $4;
$$ = (Node *) n;
}
| func_table alias_clause
{
RangeFunction *n = makeNode(RangeFunction);
n->funccallnode = $1;
n->alias = $2;
n->coldeflist = NIL;
$$ = (Node *) n;
}
| select_with_parens
{
/*
@@ -4815,25 +4812,19 @@ func_table: func_name '(' ')'
where_clause:
WHERE a_expr { $$ = $2; }
/* no qualifiers */
| /*EMPTY*/ { $$ = NULL; }
;
OptTableFuncElementList:
TableFuncElementList { $$ = $1; }
| /*EMPTY*/ { $$ = NIL; }
;
TableFuncElementList:
TableFuncElementList ',' TableFuncElement
{
$$ = lappend($1, $3);
}
| TableFuncElement
TableFuncElement
{
$$ = makeList1($1);
}
| TableFuncElementList ',' TableFuncElement
{
$$ = lappend($1, $3);
}
;
TableFuncElement: ColId Typename
@@ -4842,7 +4833,6 @@ TableFuncElement: ColId Typename
n->colname = $1;
n->typename = $2;
n->constraints = NIL;
$$ = (Node *)n;
}
;

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.77 2002/08/08 17:00:19 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.78 2002/08/29 00:17:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -900,17 +900,14 @@ addRangeTableEntryForFunction(ParseState *pstate,
* Now determine if the function returns a simple or composite type,
* and check/add column aliases.
*/
functyptype = get_typtype(funcrettype);
if (coldeflist != NIL)
{
/*
* we *only* allow a coldeflist for functions returning a
* RECORD pseudo-type
*/
if (functyptype != 'p' || (functyptype == 'p' && funcrettype != RECORDOID))
elog(ERROR, "A column definition list is only allowed for"
" functions returning RECORD");
if (funcrettype != RECORDOID)
elog(ERROR, "A column definition list is only allowed for functions returning RECORD");
}
else
{
@@ -918,57 +915,55 @@ addRangeTableEntryForFunction(ParseState *pstate,
* ... and a coldeflist is *required* for functions returning a
* RECORD pseudo-type
*/
if (functyptype == 'p' && funcrettype == RECORDOID)
elog(ERROR, "A column definition list is required for functions"
" returning RECORD");
if (funcrettype == RECORDOID)
elog(ERROR, "A column definition list is required for functions returning RECORD");
}
functyptype = get_typtype(funcrettype);
if (functyptype == 'c')
{
/*
* Named composite data type, i.e. a table's row type
*/
Oid funcrelid = typeidTypeRelid(funcrettype);
Relation rel;
int maxattrs;
if (OidIsValid(funcrelid))
if (!OidIsValid(funcrelid))
elog(ERROR, "Invalid typrelid for complex type %u",
funcrettype);
/*
* Get the rel's relcache entry. This access ensures that we have an
* up-to-date relcache entry for the rel.
*/
rel = relation_open(funcrelid, AccessShareLock);
/*
* Since the rel is open anyway, let's check that the number of column
* aliases is reasonable.
*/
maxattrs = RelationGetNumberOfAttributes(rel);
if (maxattrs < numaliases)
elog(ERROR, "Table \"%s\" has %d columns available but %d columns specified",
RelationGetRelationName(rel), maxattrs, numaliases);
/* fill in alias columns using actual column names */
for (varattno = numaliases; varattno < maxattrs; varattno++)
{
/*
* Get the rel's relcache entry. This access ensures that we have an
* up-to-date relcache entry for the rel.
*/
Relation rel;
int maxattrs;
char *attrname;
rel = heap_open(funcrelid, AccessShareLock);
/*
* Since the rel is open anyway, let's check that the number of column
* aliases is reasonable.
*/
maxattrs = RelationGetNumberOfAttributes(rel);
if (maxattrs < numaliases)
elog(ERROR, "Table \"%s\" has %d columns available but %d columns specified",
RelationGetRelationName(rel), maxattrs, numaliases);
/* fill in alias columns using actual column names */
for (varattno = numaliases; varattno < maxattrs; varattno++)
{
char *attrname;
attrname = pstrdup(NameStr(rel->rd_att->attrs[varattno]->attname));
eref->colnames = lappend(eref->colnames, makeString(attrname));
}
/*
* Drop the rel refcount, but keep the access lock till end of
* transaction so that the table can't be deleted or have its schema
* modified underneath us.
*/
heap_close(rel, NoLock);
attrname = pstrdup(NameStr(rel->rd_att->attrs[varattno]->attname));
eref->colnames = lappend(eref->colnames, makeString(attrname));
}
else
elog(ERROR, "Invalid return relation specified for function %s",
funcname);
/*
* Drop the rel refcount, but keep the access lock till end of
* transaction so that the table can't be deleted or have its schema
* modified underneath us.
*/
relation_close(rel, NoLock);
}
else if (functyptype == 'b' || functyptype == 'd')
{
@@ -986,10 +981,12 @@ addRangeTableEntryForFunction(ParseState *pstate,
{
List *col;
/* Use the column definition list to form the alias list */
eref->colnames = NIL;
foreach(col, coldeflist)
{
char *attrname;
ColumnDef *n = lfirst(col);
char *attrname;
attrname = pstrdup(n->colname);
eref->colnames = lappend(eref->colnames, makeString(attrname));
@@ -1277,63 +1274,58 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte,
char functyptype = get_typtype(funcrettype);
List *coldeflist = rte->coldeflist;
/*
* Build a suitable tupledesc representing the output rows
*/
if (functyptype == 'c')
{
/*
* Composite data type, i.e. a table's row type
* Same as ordinary relation RTE
*/
Oid funcrelid = typeidTypeRelid(funcrettype);
if (OidIsValid(funcrelid))
Relation rel;
int maxattrs;
int numaliases;
if (!OidIsValid(funcrelid))
elog(ERROR, "Invalid typrelid for complex type %u",
funcrettype);
rel = relation_open(funcrelid, AccessShareLock);
maxattrs = RelationGetNumberOfAttributes(rel);
numaliases = length(rte->eref->colnames);
for (varattno = 0; varattno < maxattrs; varattno++)
{
/*
* Composite data type, i.e. a table's row type
* Same as ordinary relation RTE
*/
Relation rel;
int maxattrs;
int numaliases;
Form_pg_attribute attr = rel->rd_att->attrs[varattno];
rel = heap_open(funcrelid, AccessShareLock);
maxattrs = RelationGetNumberOfAttributes(rel);
numaliases = length(rte->eref->colnames);
if (attr->attisdropped)
continue;
for (varattno = 0; varattno < maxattrs; varattno++)
if (colnames)
{
Form_pg_attribute attr = rel->rd_att->attrs[varattno];
char *label;
if (attr->attisdropped)
continue;
if (colnames)
{
char *label;
if (varattno < numaliases)
label = strVal(nth(varattno, rte->eref->colnames));
else
label = NameStr(attr->attname);
*colnames = lappend(*colnames, makeString(pstrdup(label)));
}
if (colvars)
{
Var *varnode;
varnode = makeVar(rtindex,
attr->attnum,
attr->atttypid,
attr->atttypmod,
sublevels_up);
*colvars = lappend(*colvars, varnode);
}
if (varattno < numaliases)
label = strVal(nth(varattno, rte->eref->colnames));
else
label = NameStr(attr->attname);
*colnames = lappend(*colnames, makeString(pstrdup(label)));
}
heap_close(rel, AccessShareLock);
if (colvars)
{
Var *varnode;
varnode = makeVar(rtindex,
attr->attnum,
attr->atttypid,
attr->atttypmod,
sublevels_up);
*colvars = lappend(*colvars, varnode);
}
}
else
elog(ERROR, "Invalid return relation specified"
" for function");
relation_close(rel, AccessShareLock);
}
else if (functyptype == 'b' || functyptype == 'd')
{
@@ -1376,12 +1368,9 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte,
if (colvars)
{
Var *varnode;
HeapTuple typeTuple;
Oid atttypid;
typeTuple = typenameType(colDef->typename);
atttypid = HeapTupleGetOid(typeTuple);
ReleaseSysCache(typeTuple);
atttypid = typenameTypeId(colDef->typename);
varnode = makeVar(rtindex,
attnum,
@@ -1394,8 +1383,7 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte,
}
}
else
elog(ERROR, "Unknown kind of return type specified"
" for function");
elog(ERROR, "Unknown kind of return type specified for function");
}
break;
case RTE_JOIN:
@@ -1595,9 +1583,6 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
char functyptype = get_typtype(funcrettype);
List *coldeflist = rte->coldeflist;
/*
* Build a suitable tupledesc representing the output rows
*/
if (functyptype == 'c')
{
/*
@@ -1605,36 +1590,33 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
* Same as ordinary relation RTE
*/
Oid funcrelid = typeidTypeRelid(funcrettype);
HeapTuple tp;
Form_pg_attribute att_tup;
if (OidIsValid(funcrelid))
{
HeapTuple tp;
Form_pg_attribute att_tup;
if (!OidIsValid(funcrelid))
elog(ERROR, "Invalid typrelid for complex type %u",
funcrettype);
tp = SearchSysCache(ATTNUM,
ObjectIdGetDatum(funcrelid),
Int16GetDatum(attnum),
0, 0);
/* this shouldn't happen... */
if (!HeapTupleIsValid(tp))
elog(ERROR, "Relation %s does not have attribute %d",
get_rel_name(funcrelid), attnum);
att_tup = (Form_pg_attribute) GETSTRUCT(tp);
/*
* If dropped column, pretend it ain't there. See notes
* in scanRTEForColumn.
*/
if (att_tup->attisdropped)
elog(ERROR, "Relation \"%s\" has no column \"%s\"",
get_rel_name(funcrelid),
NameStr(att_tup->attname));
*vartype = att_tup->atttypid;
*vartypmod = att_tup->atttypmod;
ReleaseSysCache(tp);
}
else
elog(ERROR, "Invalid return relation specified"
" for function");
tp = SearchSysCache(ATTNUM,
ObjectIdGetDatum(funcrelid),
Int16GetDatum(attnum),
0, 0);
/* this shouldn't happen... */
if (!HeapTupleIsValid(tp))
elog(ERROR, "Relation \"%s\" does not have attribute %d",
get_rel_name(funcrelid), attnum);
att_tup = (Form_pg_attribute) GETSTRUCT(tp);
/*
* If dropped column, pretend it ain't there. See notes
* in scanRTEForColumn.
*/
if (att_tup->attisdropped)
elog(ERROR, "Relation \"%s\" has no column \"%s\"",
get_rel_name(funcrelid),
NameStr(att_tup->attname));
*vartype = att_tup->atttypid;
*vartypmod = att_tup->atttypmod;
ReleaseSysCache(tp);
}
else if (functyptype == 'b' || functyptype == 'd')
{
@@ -1647,19 +1629,12 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
else if (functyptype == 'p' && funcrettype == RECORDOID)
{
ColumnDef *colDef = nth(attnum - 1, coldeflist);
HeapTuple typeTuple;
Oid atttypid;
typeTuple = typenameType(colDef->typename);
atttypid = HeapTupleGetOid(typeTuple);
ReleaseSysCache(typeTuple);
*vartype = atttypid;
*vartype = typenameTypeId(colDef->typename);
*vartypmod = -1;
}
else
elog(ERROR, "Unknown kind of return type specified"
" for function");
elog(ERROR, "Unknown kind of return type specified for function");
}
break;
case RTE_JOIN:

View File

@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.173 2002/08/27 04:55:11 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.174 2002/08/29 00:17:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -583,14 +583,9 @@ ProcessUtility(Node *parsetree,
case T_CompositeTypeStmt: /* CREATE TYPE (composite) */
{
Oid relid;
CompositeTypeStmt *stmt = (CompositeTypeStmt *) parsetree;
/*
* DefineCompositeType returns relid for use when creating
* an implicit composite type during function creation
*/
relid = DefineCompositeType(stmt->typevar, stmt->coldeflist);
DefineCompositeType(stmt->typevar, stmt->coldeflist);
}
break;

View File

@@ -5,22 +5,22 @@
* Copyright (c) 2002, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/lockfuncs.c,v 1.2 2002/08/27 04:00:28 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/lockfuncs.c,v 1.3 2002/08/29 00:17:05 tgl Exp $
*/
#include "postgres.h"
#include "fmgr.h"
#include "funcapi.h"
#include "catalog/pg_type.h"
#include "storage/lmgr.h"
#include "storage/lock.h"
#include "storage/lwlock.h"
#include "storage/proc.h"
#include "utils/builtins.h"
Datum pg_lock_status(PG_FUNCTION_ARGS);
static int next_lock(int locks[]);
Datum
pg_lock_status(PG_FUNCTION_ARGS)
{

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/tid.c,v 1.34 2002/08/28 20:46:24 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/tid.c,v 1.35 2002/08/29 00:17:05 tgl Exp $
*
* NOTES
* input routine largely stolen from boxin().
@@ -226,9 +226,6 @@ currtid_byreloid(PG_FUNCTION_ARGS)
if (rel->rd_rel->relkind == RELKIND_VIEW)
return currtid_for_view(rel, tid);
if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
elog(ERROR, "currtid can't handle type relations");
ItemPointerCopy(tid, result);
heap_get_latest_tid(rel, SnapshotNow, result);
@@ -252,9 +249,6 @@ currtid_byrelname(PG_FUNCTION_ARGS)
if (rel->rd_rel->relkind == RELKIND_VIEW)
return currtid_for_view(rel, tid);
if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
elog(ERROR, "currtid can't handle type relations");
result = (ItemPointer) palloc(sizeof(ItemPointerData));
ItemPointerCopy(tid, result);

View File

@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.80 2002/08/26 17:53:59 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.81 2002/08/29 00:17:05 tgl Exp $
*
* NOTES
* Eventually, the index information should go through here, too.
@@ -1190,6 +1190,33 @@ get_typtype(Oid typid)
return '\0';
}
/*
* getTypeInputInfo
*
* Get info needed for converting values of a type to internal form
*/
void
getTypeInputInfo(Oid type, Oid *typInput, Oid *typElem)
{
HeapTuple typeTuple;
Form_pg_type pt;
typeTuple = SearchSysCache(TYPEOID,
ObjectIdGetDatum(type),
0, 0, 0);
if (!HeapTupleIsValid(typeTuple))
elog(ERROR, "getTypeInputInfo: Cache lookup of type %u failed", type);
pt = (Form_pg_type) GETSTRUCT(typeTuple);
if (!pt->typisdefined)
elog(ERROR, "Type \"%s\" is only a shell", NameStr(pt->typname));
*typInput = pt->typinput;
*typElem = pt->typelem;
ReleaseSysCache(typeTuple);
}
/*
* getTypeOutputInfo
*

View File

@@ -6,13 +6,18 @@
*
* Copyright (c) 2002, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/fmgr/funcapi.c,v 1.3 2002/08/29 00:17:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "funcapi.h"
#include "catalog/pg_type.h"
#include "utils/syscache.h"
/*
* init_MultiFuncCall
* Create an empty FuncCallContext data structure
@@ -99,8 +104,6 @@ per_MultiFuncCall(PG_FUNCTION_ARGS)
void
end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx)
{
MemoryContext oldcontext;
/* unbind from fcinfo */
fcinfo->flinfo->fn_extra = NULL;
@@ -108,32 +111,8 @@ end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx)
* Caller is responsible to free up memory for individual
* struct elements other than att_in_funcinfo and elements.
*/
oldcontext = MemoryContextSwitchTo(funcctx->fmctx);
if (funcctx->attinmeta != NULL)
pfree(funcctx->attinmeta);
pfree(funcctx);
MemoryContextSwitchTo(oldcontext);
}
void
get_type_metadata(Oid typeid, Oid *attinfuncid, Oid *attelem)
{
HeapTuple typeTuple;
Form_pg_type typtup;
typeTuple = SearchSysCache(TYPEOID,
ObjectIdGetDatum(typeid),
0, 0, 0);
if (!HeapTupleIsValid(typeTuple))
elog(ERROR, "get_type_metadata: Cache lookup of type %u failed", typeid);
typtup = (Form_pg_type) GETSTRUCT(typeTuple);
*attinfuncid = typtup->typinput;
*attelem = typtup->typelem;
ReleaseSysCache(typeTuple);
}

View File

@@ -5,7 +5,7 @@
* command, configuration file, and command line options.
* See src/backend/utils/misc/README for more information.
*
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.84 2002/08/26 17:53:59 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.85 2002/08/29 00:17:05 tgl Exp $
*
* Copyright 2000 by PostgreSQL Global Development Group
* Written by Peter Eisentraut <peter_e@gmx.net>.
@@ -2284,7 +2284,7 @@ ShowGUCConfigOption(const char *name)
tstate = begin_tup_output_tupdesc(dest, tupdesc);
/* Send it */
PROJECT_LINE_OF_TEXT(tstate, value);
do_text_output_oneline(tstate, value);
end_tup_output(tstate);
}
@@ -2462,7 +2462,7 @@ show_all_settings(PG_FUNCTION_ARGS)
if (call_cntr < max_calls) /* do when there is more left to send */
{
char **values;
char *values[2];
char *varname;
char *varval;
bool noshow;
@@ -2474,7 +2474,9 @@ show_all_settings(PG_FUNCTION_ARGS)
*/
do
{
varval = GetConfigOptionByNum(call_cntr, (const char **) &varname, &noshow);
varval = GetConfigOptionByNum(call_cntr,
(const char **) &varname,
&noshow);
if (noshow)
{
/* varval is a palloc'd copy, so free it */
@@ -2495,9 +2497,8 @@ show_all_settings(PG_FUNCTION_ARGS)
* This should be an array of C strings which will
* be processed later by the appropriate "in" functions.
*/
values = (char **) palloc(2 * sizeof(char *));
values[0] = pstrdup(varname);
values[1] = varval; /* varval is already a palloc'd copy */
values[0] = varname;
values[1] = varval;
/* build a tuple */
tuple = BuildTupleFromCStrings(attinmeta, values);
@@ -2506,10 +2507,8 @@ show_all_settings(PG_FUNCTION_ARGS)
result = TupleGetDatum(slot, tuple);
/* Clean up */
pfree(values[0]);
if (varval != NULL)
pfree(values[1]);
pfree(values);
pfree(varval);
SRF_RETURN_NEXT(funcctx, result);
}