1 /*-------------------------------------------------------------------------
4 * Functions for sets, which are defined by queries.
5 * Example: a set is defined as being the result of the query
8 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
9 * Portions Copyright (c) 1994, Regents of the University of California
13 * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.39 2001/10/02 21:39:35 tgl Exp $
15 *-------------------------------------------------------------------------
20 #include "access/heapam.h"
21 #include "catalog/catname.h"
22 #include "catalog/indexing.h"
23 #include "catalog/pg_proc.h"
24 #include "executor/executor.h"
25 #include "utils/fcache.h"
26 #include "utils/sets.h"
27 #include "utils/syscache.h"
31 * SetDefine - converts query string defining set to an oid
33 * We create an SQL function having the given querystring as its body.
34 * The name of the function is then changed to use the OID of its tuple
38 SetDefine(char *querystr, char *typename)
41 char *procname = GENERICSETNAME;
43 char realprocname[NAMEDATALEN];
49 Datum replValue[Natts_pg_proc];
50 char replNull[Natts_pg_proc];
51 char repl[Natts_pg_proc];
53 setoid = ProcedureCreate(procname, /* changed below, after oid known */
54 false, /* don't replace */
55 true, /* returnsSet */
56 typename, /* returnTypeName */
57 "sql", /* languageName */
58 querystr, /* sourceCode */
59 fileName, /* fileName */
61 false, /* canCache (assume unsafe) */
62 false, /* isStrict (irrelevant, no args) */
66 100, /* outin_ratio */
70 * Since we're still inside this command of the transaction, we can't
71 * see the results of the procedure definition unless we pretend we've
72 * started the next command. (Postgres's solution to the Halloween
73 * problem is to not allow you to see the results of your command
74 * until you start the next command.)
76 CommandCounterIncrement();
78 procrel = heap_openr(ProcedureRelationName, RowExclusiveLock);
80 tup = SearchSysCache(PROCOID,
81 ObjectIdGetDatum(setoid),
83 if (!HeapTupleIsValid(tup))
84 elog(ERROR, "SetDefine: unable to define set %s", querystr);
87 * We can tell whether the set was already defined by checking the
88 * name. If it's GENERICSETNAME, the set is new. If it's "set<some
89 * oid>" it's already defined.
91 proc = (Form_pg_proc) GETSTRUCT(tup);
92 if (strcmp(procname, NameStr(proc->proname)) == 0)
94 /* make the real proc name */
95 sprintf(realprocname, "set%u", setoid);
97 /* set up the attributes to be modified or kept the same */
99 for (i = 1; i < Natts_pg_proc; i++)
101 replValue[0] = (Datum) realprocname;
102 for (i = 1; i < Natts_pg_proc; i++)
103 replValue[i] = (Datum) 0;
104 for (i = 0; i < Natts_pg_proc; i++)
107 /* change the pg_proc tuple */
108 newtup = heap_modifytuple(tup,
114 simple_heap_update(procrel, &newtup->t_self, newtup);
116 setoid = newtup->t_data->t_oid;
118 if (RelationGetForm(procrel)->relhasindex)
120 Relation idescs[Num_pg_proc_indices];
122 CatalogOpenIndices(Num_pg_proc_indices, Name_pg_proc_indices, idescs);
123 CatalogIndexInsert(idescs, Num_pg_proc_indices, procrel, newtup);
124 CatalogCloseIndices(Num_pg_proc_indices, idescs);
126 heap_freetuple(newtup);
129 ReleaseSysCache(tup);
131 heap_close(procrel, RowExclusiveLock);
137 * This function executes set evaluation. The parser sets up a set reference
138 * as a call to this function with the OID of the set to evaluate as argument.
140 * We build a new fcache for execution of the set's function and run the
141 * function until it says "no mas". The fn_extra field of the call's
142 * FmgrInfo record is a handy place to hold onto the fcache. (Since this
143 * is a built-in function, there is no competing use of fn_extra.)
146 seteval(PG_FUNCTION_ARGS)
148 Oid funcoid = PG_GETARG_OID(0);
149 FunctionCachePtr fcache;
155 * If this is the first call, we need to set up the fcache for the
156 * target set's function.
158 fcache = (FunctionCachePtr) fcinfo->flinfo->fn_extra;
161 fcache = init_fcache(funcoid, 0, fcinfo->flinfo->fn_mcxt);
162 fcinfo->flinfo->fn_extra = (void *) fcache;
166 * Evaluate the function. NOTE: we need no econtext because there are
167 * no arguments to evaluate.
170 /* ExecMakeFunctionResult assumes these are initialized at call: */
172 isDone = ExprSingleResult;
174 result = ExecMakeFunctionResult(fcache,
176 NULL, /* no econtext, see above */
181 * If we're done with the results of this set function, get rid of its
182 * func cache so that we will start from the top next time. (Can you
183 * say "memory leak"? This feature is a crock anyway...)
185 if (isDone != ExprMultipleResult)
188 fcinfo->flinfo->fn_extra = NULL;
192 * Return isNull/isDone status.
194 fcinfo->isnull = isNull;
196 if (isDone != ExprSingleResult)
198 ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
200 if (rsi && IsA(rsi, ReturnSetInfo))
201 rsi->isDone = isDone;
203 elog(ERROR, "Set-valued function called in context that cannot accept a set");
206 PG_RETURN_DATUM(result);