On 23/12/10 14:41, Jan Urbański wrote: > Here's a patch implementing a validator functoin mentioned in > http://archives.postgresql.org/pgsql-hackers/2010-12/msg01991.php. It's > an incremental patch on top of the plpython-refactor patch sent eariler. > > Git branch for this patch: > https://github.com/wulczer/postgres/tree/validator. > > Cheers, > Jan
Yes, here's a patch. Jan
diff --git a/src/include/catalog/pg_pltemplate.h b/src/include/catalog/pg_pltemplate.h index 6befcfa..2f1d8e1 100644 *** a/src/include/catalog/pg_pltemplate.h --- b/src/include/catalog/pg_pltemplate.h *************** DATA(insert ( "pltcl" t t "pltcl_call_h *** 72,79 **** DATA(insert ( "pltclu" f f "pltclu_call_handler" _null_ _null_ "$libdir/pltcl" _null_ )); DATA(insert ( "plperl" t t "plperl_call_handler" "plperl_inline_handler" "plperl_validator" "$libdir/plperl" _null_ )); DATA(insert ( "plperlu" f f "plperl_call_handler" "plperl_inline_handler" "plperl_validator" "$libdir/plperl" _null_ )); ! DATA(insert ( "plpythonu" f f "plpython_call_handler" "plpython_inline_handler" _null_ "$libdir/plpython" _null_ )); ! DATA(insert ( "plpython2u" f f "plpython_call_handler" "plpython_inline_handler" _null_ "$libdir/plpython2" _null_ )); ! DATA(insert ( "plpython3u" f f "plpython3_call_handler" "plpython3_inline_handler" _null_ "$libdir/plpython3" _null_ )); #endif /* PG_PLTEMPLATE_H */ --- 72,79 ---- DATA(insert ( "pltclu" f f "pltclu_call_handler" _null_ _null_ "$libdir/pltcl" _null_ )); DATA(insert ( "plperl" t t "plperl_call_handler" "plperl_inline_handler" "plperl_validator" "$libdir/plperl" _null_ )); DATA(insert ( "plperlu" f f "plperl_call_handler" "plperl_inline_handler" "plperl_validator" "$libdir/plperl" _null_ )); ! DATA(insert ( "plpythonu" f f "plpython_call_handler" "plpython_inline_handler" "plpython_validator" "$libdir/plpython" _null_ )); ! DATA(insert ( "plpython2u" f f "plpython_call_handler" "plpython_inline_handler" "plpython_validator" "$libdir/plpython2" _null_ )); ! DATA(insert ( "plpython3u" f f "plpython3_call_handler" "plpython3_inline_handler" "plpython3_validator" "$libdir/plpython3" _null_ )); #endif /* PG_PLTEMPLATE_H */ diff --git a/src/pl/plpython/expected/plpython_error.out b/src/pl/plpython/expected/plpython_error.out index 70890a8..a9e1f15 100644 *** a/src/pl/plpython/expected/plpython_error.out --- b/src/pl/plpython/expected/plpython_error.out *************** *** 1,6 **** --- 1,30 ---- -- test error handling, i forgot to restore Warn_restart in -- the trigger handler once. the errors and subsequent core dump were -- interesting. + /* Flat out Python syntax error + */ + CREATE FUNCTION python_syntax_error() RETURNS text + AS + '.syntaxerror' + LANGUAGE plpythonu; + ERROR: could not compile PL/Python function "python_syntax_error" + DETAIL: SyntaxError: invalid syntax (<string>, line 2) + /* With check_function_bodies = false the function should get defined + * and the error reported when called + */ + SET check_function_bodies = false; + CREATE FUNCTION python_syntax_error() RETURNS text + AS + '.syntaxerror' + LANGUAGE plpythonu; + SELECT python_syntax_error(); + ERROR: could not compile PL/Python function "python_syntax_error" + DETAIL: SyntaxError: invalid syntax (<string>, line 2) + /* Run the function twice to check if the hashtable entry gets cleaned up */ + SELECT python_syntax_error(); + ERROR: could not compile PL/Python function "python_syntax_error" + DETAIL: SyntaxError: invalid syntax (<string>, line 2) + RESET check_function_bodies; /* Flat out syntax error */ CREATE FUNCTION sql_syntax_error() RETURNS text diff --git a/src/pl/plpython/expected/plpython_record.out b/src/pl/plpython/expected/plpython_record.out index c8c4f9d..770f764 100644 *** a/src/pl/plpython/expected/plpython_record.out --- b/src/pl/plpython/expected/plpython_record.out *************** CREATE FUNCTION test_in_out_params_multi *** 47,52 **** --- 47,53 ---- second out text, third out text) AS $$ return first + '_record_in_to_out'; $$ LANGUAGE plpythonu; + ERROR: PL/Python functions cannot return type record CREATE FUNCTION test_inout_params(first inout text) AS $$ return first + '_inout'; $$ LANGUAGE plpythonu; *************** SELECT * FROM test_in_out_params('test_i *** 299,305 **** -- this doesn't work yet :-( SELECT * FROM test_in_out_params_multi('test_in'); ! ERROR: PL/Python functions cannot return type record SELECT * FROM test_inout_params('test_in'); first --------------- --- 300,309 ---- -- this doesn't work yet :-( SELECT * FROM test_in_out_params_multi('test_in'); ! ERROR: function test_in_out_params_multi(unknown) does not exist ! LINE 1: SELECT * FROM test_in_out_params_multi('test_in'); ! ^ ! HINT: No function matches the given name and argument types. You might need to add explicit type casts. SELECT * FROM test_inout_params('test_in'); first --------------- diff --git a/src/pl/plpython/expected/plpython_types.out b/src/pl/plpython/expected/plpython_types.out index 982005b..e74a400 100644 *** a/src/pl/plpython/expected/plpython_types.out --- b/src/pl/plpython/expected/plpython_types.out *************** PL/Python function "test_type_conversion *** 571,579 **** CREATE FUNCTION test_type_conversion_array_record() RETURNS type_record[] AS $$ return [None] $$ LANGUAGE plpythonu; - SELECT * FROM test_type_conversion_array_record(); ERROR: PL/Python functions cannot return type type_record[] DETAIL: PL/Python does not support conversion to arrays of row types. CREATE FUNCTION test_type_conversion_array_string() RETURNS text[] AS $$ return 'abc' $$ LANGUAGE plpythonu; --- 571,583 ---- CREATE FUNCTION test_type_conversion_array_record() RETURNS type_record[] AS $$ return [None] $$ LANGUAGE plpythonu; ERROR: PL/Python functions cannot return type type_record[] DETAIL: PL/Python does not support conversion to arrays of row types. + SELECT * FROM test_type_conversion_array_record(); + ERROR: function test_type_conversion_array_record() does not exist + LINE 1: SELECT * FROM test_type_conversion_array_record(); + ^ + HINT: No function matches the given name and argument types. You might need to add explicit type casts. CREATE FUNCTION test_type_conversion_array_string() RETURNS text[] AS $$ return 'abc' $$ LANGUAGE plpythonu; diff --git a/src/pl/plpython/expected/plpython_types_3.out b/src/pl/plpython/expected/plpython_types_3.out index eeb23b7..577c1ff 100644 *** a/src/pl/plpython/expected/plpython_types_3.out --- b/src/pl/plpython/expected/plpython_types_3.out *************** PL/Python function "test_type_conversion *** 571,579 **** CREATE FUNCTION test_type_conversion_array_record() RETURNS type_record[] AS $$ return [None] $$ LANGUAGE plpython3u; - SELECT * FROM test_type_conversion_array_record(); ERROR: PL/Python functions cannot return type type_record[] DETAIL: PL/Python does not support conversion to arrays of row types. CREATE FUNCTION test_type_conversion_array_string() RETURNS text[] AS $$ return 'abc' $$ LANGUAGE plpython3u; --- 571,583 ---- CREATE FUNCTION test_type_conversion_array_record() RETURNS type_record[] AS $$ return [None] $$ LANGUAGE plpython3u; ERROR: PL/Python functions cannot return type type_record[] DETAIL: PL/Python does not support conversion to arrays of row types. + SELECT * FROM test_type_conversion_array_record(); + ERROR: function test_type_conversion_array_record() does not exist + LINE 1: SELECT * FROM test_type_conversion_array_record(); + ^ + HINT: No function matches the given name and argument types. You might need to add explicit type casts. CREATE FUNCTION test_type_conversion_array_string() RETURNS text[] AS $$ return 'abc' $$ LANGUAGE plpython3u; diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c index 67eb0f3..ba310c0 100644 *** a/src/pl/plpython/plpython.c --- b/src/pl/plpython/plpython.c *************** typedef struct PLyResultObject *** 248,262 **** --- 248,265 ---- #if PY_MAJOR_VERSION >= 3 /* Use separate names to avoid clash in pg_pltemplate */ + #define plpython_validator plpython3_validator #define plpython_call_handler plpython3_call_handler #define plpython_inline_handler plpython3_inline_handler #endif /* exported functions */ + Datum plpython_validator(PG_FUNCTION_ARGS); Datum plpython_call_handler(PG_FUNCTION_ARGS); Datum plpython_inline_handler(PG_FUNCTION_ARGS); void _PG_init(void); + PG_FUNCTION_INFO_V1(plpython_validator); PG_FUNCTION_INFO_V1(plpython_call_handler); PG_FUNCTION_INFO_V1(plpython_inline_handler); *************** plpython_return_error_callback(void *arg *** 431,436 **** --- 434,478 ---- errcontext("while creating return value"); } + static bool + PLy_procedure_is_trigger(Form_pg_proc procStruct) + { + if (get_typtype(procStruct->prorettype) != TYPTYPE_PSEUDO) + return false; + + return (procStruct->prorettype == TRIGGEROID || + (procStruct->prorettype == OPAQUEOID && + procStruct->pronargs == 0)); + } + + Datum + plpython_validator(PG_FUNCTION_ARGS) + { + Oid funcoid = PG_GETARG_OID(0); + HeapTuple tuple; + Form_pg_proc procStruct; + bool is_trigger; + + if (!check_function_bodies) + { + PG_RETURN_VOID(); + } + + /* Get the new function's pg_proc entry */ + tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for function %u", funcoid); + procStruct = (Form_pg_proc) GETSTRUCT(tuple); + + is_trigger = PLy_procedure_is_trigger(procStruct); + + ReleaseSysCache(tuple); + + PLy_procedure_get(funcoid, is_trigger); + + PG_RETURN_VOID(); + } + Datum plpython_call_handler(PG_FUNCTION_ARGS) { diff --git a/src/pl/plpython/sql/plpython_error.sql b/src/pl/plpython/sql/plpython_error.sql index 5ca6849..6509257 100644 *** a/src/pl/plpython/sql/plpython_error.sql --- b/src/pl/plpython/sql/plpython_error.sql *************** *** 2,7 **** --- 2,30 ---- -- the trigger handler once. the errors and subsequent core dump were -- interesting. + /* Flat out Python syntax error + */ + CREATE FUNCTION python_syntax_error() RETURNS text + AS + '.syntaxerror' + LANGUAGE plpythonu; + + /* With check_function_bodies = false the function should get defined + * and the error reported when called + */ + SET check_function_bodies = false; + + CREATE FUNCTION python_syntax_error() RETURNS text + AS + '.syntaxerror' + LANGUAGE plpythonu; + + SELECT python_syntax_error(); + /* Run the function twice to check if the hashtable entry gets cleaned up */ + SELECT python_syntax_error(); + + RESET check_function_bodies; + /* Flat out syntax error */ CREATE FUNCTION sql_syntax_error() RETURNS text
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers