99 *
1010 *
1111 * IDENTIFICATION
12- * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.35 1999/09/28 04:34:40 momjian Exp $
12+ * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.36 1999/10/02 21:33:24 tgl Exp $
1313 *
1414 * DESCRIPTION
1515 * The "DefineFoo" routines take the parse tree and pick out the
5353#include "utils/syscache.h"
5454
5555static char * defGetString (DefElem * def );
56+ static double defGetNumeric (DefElem * def );
5657static int defGetTypeLength (DefElem * def );
5758
5859#define DEFAULT_TYPDELIM ','
@@ -103,17 +104,26 @@ compute_return_type(const Node *returnType,
103104}
104105
105106
106-
107107static void
108- compute_full_attributes (const List * parameters ,int32 * byte_pct_p ,
108+ compute_full_attributes (List * parameters ,int32 * byte_pct_p ,
109109int32 * perbyte_cpu_p ,int32 * percall_cpu_p ,
110110int32 * outin_ratio_p ,bool * canCache_p )
111111{
112112/*--------------------------------------------------------------------------
113113 Interpret the parameters *parameters and return their contents as
114114 *byte_pct_p, etc.
115115
116- These are the full parameters of a C or internal function.
116+ These parameters supply optional information about a function.
117+ All have defaults if not specified.
118+
119+ Note: as of version 6.6, canCache is used (if set, the optimizer's
120+ constant-folder is allowed to pre-evaluate the function if all its
121+ inputs are constant). The other four are not used. They used to be
122+ used in the "expensive functions" optimizer, but that's been dead code
123+ for a long time.
124+
125+ Since canCache is useful for any function, we now allow attributes to be
126+ supplied for all functions regardless of language.
117127---------------------------------------------------------------------------*/
118128List * pl ;
119129
@@ -122,58 +132,33 @@ compute_full_attributes(const List *parameters, int32 *byte_pct_p,
122132* perbyte_cpu_p = PERBYTE_CPU ;
123133* percall_cpu_p = PERCALL_CPU ;
124134* outin_ratio_p = OUTIN_RATIO ;
135+ * canCache_p = false;
125136
126- foreach (pl ,( List * ) parameters )
137+ foreach (pl ,parameters )
127138{
128- ParamString * param = (ParamString * )lfirst (pl );
139+ DefElem * param = (DefElem * )lfirst (pl );
129140
130- if (strcasecmp (param -> name ,"iscachable" )== 0 )
141+ if (strcasecmp (param -> defname ,"iscachable" )== 0 )
131142* canCache_p = true;
132- else if (strcasecmp (param -> name ,"trusted" )== 0 )
143+ else if (strcasecmp (param -> defname ,"trusted" )== 0 )
133144{
134-
135145/*
136146 * we don't have untrusted functions any more. The 4.2
137147 * implementation is lousy anyway so I took it out. -ay 10/94
138148 */
139149elog (ERROR ,"untrusted function has been decommissioned." );
140150}
141- else if (strcasecmp (param -> name ,"byte_pct" )== 0 )
142- {
143-
144- /*
145- * * handle expensive function parameters
146- */
147- * byte_pct_p = atoi (param -> val );
148- }
149- else if (strcasecmp (param -> name ,"perbyte_cpu" )== 0 )
150- {
151- if (sscanf (param -> val ,"%d" ,perbyte_cpu_p )== 0 )
152- {
153- int count ;
154- char * ptr ;
155-
156- for (count = 0 ,ptr = param -> val ;* ptr != '\0' ;ptr ++ )
157- if (* ptr == '!' )
158- count ++ ;
159- * perbyte_cpu_p = (int )pow (10.0 , (double )count );
160- }
161- }
162- else if (strcasecmp (param -> name ,"percall_cpu" )== 0 )
163- {
164- if (sscanf (param -> val ,"%d" ,percall_cpu_p )== 0 )
165- {
166- int count ;
167- char * ptr ;
168-
169- for (count = 0 ,ptr = param -> val ;* ptr != '\0' ;ptr ++ )
170- if (* ptr == '!' )
171- count ++ ;
172- * percall_cpu_p = (int )pow (10.0 , (double )count );
173- }
174- }
175- else if (strcasecmp (param -> name ,"outin_ratio" )== 0 )
176- * outin_ratio_p = atoi (param -> val );
151+ else if (strcasecmp (param -> defname ,"byte_pct" )== 0 )
152+ * byte_pct_p = (int )defGetNumeric (param );
153+ else if (strcasecmp (param -> defname ,"perbyte_cpu" )== 0 )
154+ * perbyte_cpu_p = (int )defGetNumeric (param );
155+ else if (strcasecmp (param -> defname ,"percall_cpu" )== 0 )
156+ * percall_cpu_p = (int )defGetNumeric (param );
157+ else if (strcasecmp (param -> defname ,"outin_ratio" )== 0 )
158+ * outin_ratio_p = (int )defGetNumeric (param );
159+ else
160+ elog (NOTICE ,"Unrecognized function attribute '%s' ignored" ,
161+ param -> defname );
177162}
178163}
179164
@@ -215,8 +200,8 @@ interpret_AS_clause(const char *languageName, const List *as,
215200* probin_str_p = "-" ;
216201
217202if (lnext (as )!= NULL )
218- elog (ERROR ,"CREATE FUNCTION:parse error in ' AS%s, %s'. " ,
219- strVal ( lfirst ( as )), strVal ( lsecond ( as )) );
203+ elog (ERROR ,"CREATE FUNCTION:only one ASitem needed for %s language " ,
204+ languageName );
220205}
221206}
222207
@@ -246,39 +231,37 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest)
246231 * or "SQL"
247232 */
248233
234+ bool returnsSet ;
235+ /* The function returns a set of values, as opposed to a singleton. */
236+
237+ bool lanisPL = false;
238+
249239/*
250- * The following are attributes of the function, as expressed in the
251- * CREATE FUNCTION statement, where applicable.
240+ * The following are optional user-supplied attributes of the function.
252241 */
253242int32 byte_pct ,
254243perbyte_cpu ,
255244percall_cpu ,
256245outin_ratio ;
257246bool canCache ;
258- bool returnsSet ;
259-
260- bool lanisPL = false;
261-
262- /* The function returns a set of values, as opposed to a singleton. */
263247
264248
265249case_translate_language_name (stmt -> language ,languageName );
266250
267- compute_return_type (stmt -> returnType ,& prorettype ,& returnsSet );
268-
269251if (strcmp (languageName ,"C" )== 0 ||
270252strcmp (languageName ,"internal" )== 0 )
271253{
272- compute_full_attributes (stmt -> withClause ,
273- & byte_pct ,& perbyte_cpu ,& percall_cpu ,
274- & outin_ratio ,& canCache );
254+ if (!superuser ())
255+ elog (ERROR ,
256+ "Only users with Postgres superuser privilege are "
257+ "permitted to create a function "
258+ "in the '%s' language. Others may use the 'sql' language "
259+ "or the created procedural languages." ,
260+ languageName );
275261}
276262else if (strcmp (languageName ,"sql" )== 0 )
277263{
278- /* query optimizer groks sql, these are meaningless */
279- perbyte_cpu = percall_cpu = 0 ;
280- byte_pct = outin_ratio = 100 ;
281- canCache = false;
264+ /* No security check needed for SQL functions */
282265}
283266else
284267{
@@ -321,47 +304,34 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest)
321304}
322305
323306lanisPL = true;
324-
325- /*
326- * These are meaningless
327- */
328- perbyte_cpu = percall_cpu = 0 ;
329- byte_pct = outin_ratio = 100 ;
330- canCache = false;
331307}
332308
333- interpret_AS_clause ( languageName , stmt -> as ,& prosrc_str ,& probin_str );
309+ compute_return_type ( stmt -> returnType ,& prorettype ,& returnsSet );
334310
335- if (strcmp (languageName ,"sql" )!= 0 && lanisPL == false&& !superuser ())
336- elog (ERROR ,
337- "Only users with Postgres superuser privilege are permitted "
338- "to create a function "
339- "in the '%s' language. Others may use the 'sql' language "
340- "or the created procedural languages." ,
341- languageName );
342- /* Above does not return. */
343- else
344- {
311+ compute_full_attributes (stmt -> withClause ,
312+ & byte_pct ,& perbyte_cpu ,& percall_cpu ,
313+ & outin_ratio ,& canCache );
345314
346- /*
347- * And now that we have all the parameters, and know we're
348- * permitted to do so, go ahead and create the function.
349- */
350- ProcedureCreate (stmt -> funcname ,
351- returnsSet ,
352- prorettype ,
353- languageName ,
354- prosrc_str ,/* converted to text later */
355- probin_str ,/* converted to text later */
356- canCache ,
357- true,/* (obsolete "trusted") */
358- byte_pct ,
359- perbyte_cpu ,
360- percall_cpu ,
361- outin_ratio ,
362- stmt -> defArgs ,
363- dest );
364- }
315+ interpret_AS_clause (languageName ,stmt -> as ,& prosrc_str ,& probin_str );
316+
317+ /*
318+ * And now that we have all the parameters, and know we're
319+ * permitted to do so, go ahead and create the function.
320+ */
321+ ProcedureCreate (stmt -> funcname ,
322+ returnsSet ,
323+ prorettype ,
324+ languageName ,
325+ prosrc_str ,/* converted to text later */
326+ probin_str ,/* converted to text later */
327+ canCache ,
328+ true,/* (obsolete "trusted") */
329+ byte_pct ,
330+ perbyte_cpu ,
331+ percall_cpu ,
332+ outin_ratio ,
333+ stmt -> defArgs ,
334+ dest );
365335}
366336
367337
@@ -734,6 +704,25 @@ defGetString(DefElem *def)
734704return strVal (def -> arg );
735705}
736706
707+ static double
708+ defGetNumeric (DefElem * def )
709+ {
710+ if (def -> arg == NULL )
711+ elog (ERROR ,"Define: \"%s\" requires a numeric value" ,
712+ def -> defname );
713+ switch (nodeTag (def -> arg ))
714+ {
715+ case T_Integer :
716+ return (double )intVal (def -> arg );
717+ case T_Float :
718+ return floatVal (def -> arg );
719+ default :
720+ elog (ERROR ,"Define: \"%s\" requires a numeric value" ,
721+ def -> defname );
722+ }
723+ return 0 ;/* keep compiler quiet */
724+ }
725+
737726static int
738727defGetTypeLength (DefElem * def )
739728{