99 *
1010 *
1111 * IDENTIFICATION
12- * $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.3 2002/04/27 03:45:01 tgl Exp $
12+ * $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.4 2002/05/17 18:32:52 petere Exp $
1313 *
1414 * DESCRIPTION
1515 * These routines take the parse tree and pick out the
@@ -159,6 +159,104 @@ compute_parameter_types(List *argTypes, Oid languageOid,
159159return parameterCount ;
160160}
161161
162+
163+ /*
164+ * Dissect the list of options assembled in gram.y into function
165+ * attributes.
166+ */
167+
168+ static void
169+ compute_attributes_sql_style (const List * options ,
170+ List * * as ,
171+ char * * language ,
172+ char * volatility_p ,
173+ bool * strict_p ,
174+ bool * security_definer ,
175+ bool * implicit_cast )
176+ {
177+ const List * option ;
178+ DefElem * as_item = NULL ;
179+ DefElem * language_item = NULL ;
180+ DefElem * volatility_item = NULL ;
181+ DefElem * strict_item = NULL ;
182+ DefElem * security_item = NULL ;
183+ DefElem * implicit_item = NULL ;
184+
185+ foreach (option ,options )
186+ {
187+ DefElem * defel = (DefElem * )lfirst (option );
188+
189+ if (strcmp (defel -> defname ,"as" )== 0 )
190+ {
191+ if (as_item )
192+ elog (ERROR ,"conflicting or redundant options" );
193+ as_item = defel ;
194+ }
195+ else if (strcmp (defel -> defname ,"language" )== 0 )
196+ {
197+ if (language_item )
198+ elog (ERROR ,"conflicting or redundant options" );
199+ language_item = defel ;
200+ }
201+ else if (strcmp (defel -> defname ,"volatility" )== 0 )
202+ {
203+ if (volatility_item )
204+ elog (ERROR ,"conflicting or redundant options" );
205+ volatility_item = defel ;
206+ }
207+ else if (strcmp (defel -> defname ,"strict" )== 0 )
208+ {
209+ if (strict_item )
210+ elog (ERROR ,"conflicting or redundant options" );
211+ strict_item = defel ;
212+ }
213+ else if (strcmp (defel -> defname ,"security" )== 0 )
214+ {
215+ if (security_item )
216+ elog (ERROR ,"conflicting or redundant options" );
217+ security_item = defel ;
218+ }
219+ else if (strcmp (defel -> defname ,"implicit" )== 0 )
220+ {
221+ if (implicit_item )
222+ elog (ERROR ,"conflicting or redundant options" );
223+ implicit_item = defel ;
224+ }
225+ else
226+ elog (ERROR ,"invalid CREATE FUNCTION option" );
227+ }
228+
229+ if (as_item )
230+ * as = (List * )as_item -> arg ;
231+ else
232+ elog (ERROR ,"no function body specified" );
233+
234+ if (language_item )
235+ * language = strVal (language_item -> arg );
236+ else
237+ elog (ERROR ,"no language specified" );
238+
239+ if (volatility_item )
240+ {
241+ if (strcmp (strVal (volatility_item -> arg ),"immutable" )== 0 )
242+ * volatility_p = PROVOLATILE_IMMUTABLE ;
243+ else if (strcmp (strVal (volatility_item -> arg ),"stable" )== 0 )
244+ * volatility_p = PROVOLATILE_STABLE ;
245+ else if (strcmp (strVal (volatility_item -> arg ),"volatile" )== 0 )
246+ * volatility_p = PROVOLATILE_VOLATILE ;
247+ else
248+ elog (ERROR ,"invalid volatility" );
249+ }
250+
251+ if (strict_item )
252+ * strict_p = intVal (strict_item -> arg );
253+ if (security_item )
254+ * security_definer = intVal (security_item -> arg );
255+ if (implicit_item )
256+ * implicit_cast = intVal (implicit_item -> arg );
257+ }
258+
259+
162260/*-------------
163261 * Interpret the parameters *parameters and return their contents as
164262 * *byte_pct_p, etc.
@@ -183,23 +281,14 @@ compute_parameter_types(List *argTypes, Oid languageOid,
183281 *------------
184282 */
185283static void
186- compute_full_attributes (List * parameters ,
187- int32 * byte_pct_p ,int32 * perbyte_cpu_p ,
188- int32 * percall_cpu_p ,int32 * outin_ratio_p ,
189- bool * isImplicit_p ,bool * isStrict_p ,
190- char * volatility_p )
284+ compute_attributes_with_style (List * parameters ,
285+ int32 * byte_pct_p ,int32 * perbyte_cpu_p ,
286+ int32 * percall_cpu_p ,int32 * outin_ratio_p ,
287+ bool * isImplicit_p ,bool * isStrict_p ,
288+ char * volatility_p )
191289{
192290List * pl ;
193291
194- /* the defaults */
195- * byte_pct_p = BYTE_PCT ;
196- * perbyte_cpu_p = PERBYTE_CPU ;
197- * percall_cpu_p = PERCALL_CPU ;
198- * outin_ratio_p = OUTIN_RATIO ;
199- * isImplicit_p = false;
200- * isStrict_p = false;
201- * volatility_p = PROVOLATILE_VOLATILE ;
202-
203292foreach (pl ,parameters )
204293{
205294DefElem * param = (DefElem * )lfirst (pl );
@@ -290,12 +379,13 @@ interpret_AS_clause(Oid languageOid, const char *languageName, const List *as,
290379 * Execute a CREATE FUNCTION utility statement.
291380 */
292381void
293- CreateFunction (ProcedureStmt * stmt )
382+ CreateFunction (CreateFunctionStmt * stmt )
294383{
295384char * probin_str ;
296385char * prosrc_str ;
297386Oid prorettype ;
298387bool returnsSet ;
388+ char * language ;
299389char languageName [NAMEDATALEN ];
300390Oid languageOid ;
301391char * funcname ;
@@ -308,10 +398,12 @@ CreateFunction(ProcedureStmt *stmt)
308398percall_cpu ,
309399outin_ratio ;
310400bool isImplicit ,
311- isStrict ;
401+ isStrict ,
402+ security ;
312403char volatility ;
313404HeapTuple languageTuple ;
314405Form_pg_language languageStruct ;
406+ List * as_clause ;
315407
316408/* Convert list of names to a name and namespace */
317409namespaceId = QualifiedNameGetCreationNamespace (stmt -> funcname ,
@@ -322,8 +414,21 @@ CreateFunction(ProcedureStmt *stmt)
322414if (aclresult != ACLCHECK_OK )
323415aclcheck_error (aclresult ,get_namespace_name (namespaceId ));
324416
417+ /* defaults attributes */
418+ byte_pct = BYTE_PCT ;
419+ perbyte_cpu = PERBYTE_CPU ;
420+ percall_cpu = PERCALL_CPU ;
421+ outin_ratio = OUTIN_RATIO ;
422+ isImplicit = false;
423+ isStrict = false;
424+ volatility = PROVOLATILE_VOLATILE ;
425+
426+ /* override attributes from explicit list */
427+ compute_attributes_sql_style (stmt -> options ,
428+ & as_clause ,& language ,& volatility ,& isStrict ,& security ,& isImplicit );
429+
325430/* Convert language name to canonical case */
326- case_translate_language_name (stmt -> language ,languageName );
431+ case_translate_language_name (language ,languageName );
327432
328433/* Look up the language and validate permissions */
329434languageTuple = SearchSysCache (LANGNAME ,
@@ -363,12 +468,12 @@ CreateFunction(ProcedureStmt *stmt)
363468parameterCount = compute_parameter_types (stmt -> argTypes ,languageOid ,
364469parameterTypes );
365470
366- compute_full_attributes (stmt -> withClause ,
367- & byte_pct ,& perbyte_cpu ,& percall_cpu ,
368- & outin_ratio ,& isImplicit ,& isStrict ,
369- & volatility );
471+ compute_attributes_with_style (stmt -> withClause ,
472+ & byte_pct ,& perbyte_cpu ,& percall_cpu ,
473+ & outin_ratio ,& isImplicit ,& isStrict ,
474+ & volatility );
370475
371- interpret_AS_clause (languageOid ,languageName ,stmt -> as ,
476+ interpret_AS_clause (languageOid ,languageName ,as_clause ,
372477& prosrc_str ,& probin_str );
373478
374479/*