9
9
*
10
10
*
11
11
* 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 $
13
13
*
14
14
* DESCRIPTION
15
15
* The "DefineFoo" routines take the parse tree and pick out the
53
53
#include "utils/syscache.h"
54
54
55
55
static char * defGetString (DefElem * def );
56
+ static double defGetNumeric (DefElem * def );
56
57
static int defGetTypeLength (DefElem * def );
57
58
58
59
#define DEFAULT_TYPDELIM ','
@@ -103,17 +104,26 @@ compute_return_type(const Node *returnType,
103
104
}
104
105
105
106
106
-
107
107
static void
108
- compute_full_attributes (const List * parameters ,int32 * byte_pct_p ,
108
+ compute_full_attributes (List * parameters ,int32 * byte_pct_p ,
109
109
int32 * perbyte_cpu_p ,int32 * percall_cpu_p ,
110
110
int32 * outin_ratio_p ,bool * canCache_p )
111
111
{
112
112
/*--------------------------------------------------------------------------
113
113
Interpret the parameters *parameters and return their contents as
114
114
*byte_pct_p, etc.
115
115
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.
117
127
---------------------------------------------------------------------------*/
118
128
List * pl ;
119
129
@@ -122,58 +132,33 @@ compute_full_attributes(const List *parameters, int32 *byte_pct_p,
122
132
* perbyte_cpu_p = PERBYTE_CPU ;
123
133
* percall_cpu_p = PERCALL_CPU ;
124
134
* outin_ratio_p = OUTIN_RATIO ;
135
+ * canCache_p = false;
125
136
126
- foreach (pl ,( List * ) parameters )
137
+ foreach (pl ,parameters )
127
138
{
128
- ParamString * param = (ParamString * )lfirst (pl );
139
+ DefElem * param = (DefElem * )lfirst (pl );
129
140
130
- if (strcasecmp (param -> name ,"iscachable" )== 0 )
141
+ if (strcasecmp (param -> defname ,"iscachable" )== 0 )
131
142
* canCache_p = true;
132
- else if (strcasecmp (param -> name ,"trusted" )== 0 )
143
+ else if (strcasecmp (param -> defname ,"trusted" )== 0 )
133
144
{
134
-
135
145
/*
136
146
* we don't have untrusted functions any more. The 4.2
137
147
* implementation is lousy anyway so I took it out. -ay 10/94
138
148
*/
139
149
elog (ERROR ,"untrusted function has been decommissioned." );
140
150
}
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 );
177
162
}
178
163
}
179
164
@@ -215,8 +200,8 @@ interpret_AS_clause(const char *languageName, const List *as,
215
200
* probin_str_p = "-" ;
216
201
217
202
if (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 );
220
205
}
221
206
}
222
207
@@ -246,39 +231,37 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest)
246
231
* or "SQL"
247
232
*/
248
233
234
+ bool returnsSet ;
235
+ /* The function returns a set of values, as opposed to a singleton. */
236
+
237
+ bool lanisPL = false;
238
+
249
239
/*
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.
252
241
*/
253
242
int32 byte_pct ,
254
243
perbyte_cpu ,
255
244
percall_cpu ,
256
245
outin_ratio ;
257
246
bool canCache ;
258
- bool returnsSet ;
259
-
260
- bool lanisPL = false;
261
-
262
- /* The function returns a set of values, as opposed to a singleton. */
263
247
264
248
265
249
case_translate_language_name (stmt -> language ,languageName );
266
250
267
- compute_return_type (stmt -> returnType ,& prorettype ,& returnsSet );
268
-
269
251
if (strcmp (languageName ,"C" )== 0 ||
270
252
strcmp (languageName ,"internal" )== 0 )
271
253
{
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 );
275
261
}
276
262
else if (strcmp (languageName ,"sql" )== 0 )
277
263
{
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 */
282
265
}
283
266
else
284
267
{
@@ -321,47 +304,34 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest)
321
304
}
322
305
323
306
lanisPL = true;
324
-
325
- /*
326
- * These are meaningless
327
- */
328
- perbyte_cpu = percall_cpu = 0 ;
329
- byte_pct = outin_ratio = 100 ;
330
- canCache = false;
331
307
}
332
308
333
- interpret_AS_clause ( languageName , stmt -> as ,& prosrc_str ,& probin_str );
309
+ compute_return_type ( stmt -> returnType ,& prorettype ,& returnsSet );
334
310
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 );
345
314
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 );
365
335
}
366
336
367
337
@@ -734,6 +704,25 @@ defGetString(DefElem *def)
734
704
return strVal (def -> arg );
735
705
}
736
706
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
+
737
726
static int
738
727
defGetTypeLength (DefElem * def )
739
728
{