postgresql/src/backend/utils/adt/sets.c

174 lines
4.9 KiB
C
Raw Normal View History

/*-------------------------------------------------------------------------
*
* sets.c--
* Functions for sets, which are defined by queries.
* Example: a set is defined as being the result of the query
* retrieve (X.all)
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.6 1997/09/07 04:50:43 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include <stdio.h> /* for sprintf() */
#include <string.h>
#include "postgres.h"
#include "access/heapam.h"
#include "access/relscan.h"
#include "access/xact.h"
#include "catalog/pg_proc.h" /* for Form_pg_proc */
#include "utils/syscache.h" /* for PROOID */
#include "catalog/catname.h" /* for ProcedureRelationName */
#include "catalog/indexing.h" /* for Num_pg_proc_indices */
#include "storage/lmgr.h"
#include "utils/sets.h" /* for GENERICSETNAME */
#include "tcop/dest.h"
#include "fmgr.h"
extern CommandDest whereToSendOutput; /* defined in tcop/postgres.c */
/*
* SetDefine - converts query string defining set to an oid
*
* The query string is used to store the set as a function in
* pg_proc. The name of the function is then changed to use the
* OID of its tuple in pg_proc.
*/
Oid
SetDefine(char *querystr, char *typename)
{
Oid setoid;
char *procname = GENERICSETNAME;
char *fileName = "-";
char realprocname[16];
HeapTuple tup,
newtup = NULL;
Form_pg_proc proc;
Relation procrel;
int i;
Datum replValue[Natts_pg_proc];
char replNull[Natts_pg_proc];
char repl[Natts_pg_proc];
HeapScanDesc pg_proc_scan;
Buffer buffer;
ItemPointerData ipdata;
static ScanKeyData oidKey[1] = {
{0, ObjectIdAttributeNumber, ObjectIdEqualRegProcedure}};
setoid = ProcedureCreate(procname, /* changed below, after oid known */
true, /* returnsSet */
typename, /* returnTypeName */
"sql", /* languageName */
querystr, /* sourceCode */
fileName, /* fileName */
false, /* canCache */
true, /* trusted */
100, /* byte_pct */
0, /* perbyte_cpu */
0, /* percall_cpu */
100, /* outin_ratio */
NIL, /* argList */
whereToSendOutput);
/*
* Since we're still inside this command of the transaction, we can't
* see the results of the procedure definition unless we pretend we've
* started the next command. (Postgres's solution to the Halloween
* problem is to not allow you to see the results of your command
* until you start the next command.)
*/
CommandCounterIncrement();
tup = SearchSysCacheTuple(PROOID,
ObjectIdGetDatum(setoid),
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(WARN, "setin: unable to define set %s", querystr);
/*
* We can tell whether the set was already defined by checking the
* name. If it's GENERICSETNAME, the set is new. If it's "set<some
* oid>" it's already defined.
*/
proc = (Form_pg_proc) GETSTRUCT(tup);
if (!strcmp((char *) procname, (char *) &(proc->proname)))
{
/* make the real proc name */
sprintf(realprocname, "set%u", setoid);
/* set up the attributes to be modified or kept the same */
repl[0] = 'r';
for (i = 1; i < Natts_pg_proc; i++)
repl[i] = ' ';
replValue[0] = (Datum) realprocname;
for (i = 1; i < Natts_pg_proc; i++)
replValue[i] = (Datum) 0;
for (i = 0; i < Natts_pg_proc; i++)
replNull[i] = ' ';
/* change the pg_proc tuple */
procrel = heap_openr(ProcedureRelationName);
RelationSetLockForWrite(procrel);
fmgr_info(ObjectIdEqualRegProcedure,
&oidKey[0].sk_func,
&oidKey[0].sk_nargs);
oidKey[0].sk_argument = ObjectIdGetDatum(setoid);
pg_proc_scan = heap_beginscan(procrel,
0,
SelfTimeQual,
1,
oidKey);
tup = heap_getnext(pg_proc_scan, 0, &buffer);
if (HeapTupleIsValid(tup))
{
newtup = heap_modifytuple(tup,
buffer,
procrel,
replValue,
replNull,
repl);
/* XXX may not be necessary */
ItemPointerCopy(&tup->t_ctid, &ipdata);
setheapoverride(true);
heap_replace(procrel, &ipdata, newtup);
setheapoverride(false);
setoid = newtup->t_oid;
}
else
elog(WARN, "setin: could not find new set oid tuple");
heap_endscan(pg_proc_scan);
if (RelationGetRelationTupleForm(procrel)->relhasindex)
{
Relation idescs[Num_pg_proc_indices];
CatalogOpenIndices(Num_pg_proc_indices, Name_pg_proc_indices, idescs);
CatalogIndexInsert(idescs, Num_pg_proc_indices, procrel, newtup);
CatalogCloseIndices(Num_pg_proc_indices, idescs);
}
RelationUnsetLockForWrite(procrel);
heap_close(procrel);
}
return setoid;
}
/* This function is a placeholder. The parser uses the OID of this
* function to fill in the :funcid field of a set. This routine is
* never executed. At runtime, the OID of the actual set is substituted
* into the :funcid.
*/
int
seteval(Oid funcoid)
{
return 17;
}