@@ -1385,6 +1385,136 @@ PLy_procedure_get(Oid fn_oid, bool is_trigger)
13851385 return entry -> proc ;
13861386}
13871387
1388+ /*
1389+ * Set up output conversion functions for a procedure
1390+ */
1391+ static void
1392+ PLy_procedure_output_conversion (PLyProcedure * proc , Form_pg_proc procStruct )
1393+ {
1394+ HeapTuple rvTypeTup ;
1395+ Form_pg_type rvTypeStruct ;
1396+
1397+ /* Get the return type */
1398+ rvTypeTup = SearchSysCache1 (TYPEOID ,
1399+ ObjectIdGetDatum (procStruct -> prorettype ));
1400+ if (!HeapTupleIsValid (rvTypeTup ))
1401+ elog (ERROR , "cache lookup failed for type %u" ,
1402+ procStruct -> prorettype );
1403+ rvTypeStruct = (Form_pg_type ) GETSTRUCT (rvTypeTup );
1404+
1405+ /* Disallow pseudotype result, except for void */
1406+ if (rvTypeStruct -> typtype == TYPTYPE_PSEUDO &&
1407+ procStruct -> prorettype != VOIDOID )
1408+ {
1409+ if (procStruct -> prorettype == TRIGGEROID )
1410+ ereport (ERROR ,
1411+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
1412+ errmsg ("trigger functions can only be called as triggers" )));
1413+ else
1414+ ereport (ERROR ,
1415+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
1416+ errmsg ("PL/Python functions cannot return type %s" ,
1417+ format_type_be (procStruct -> prorettype ))));
1418+ }
1419+
1420+ if (rvTypeStruct -> typtype == TYPTYPE_COMPOSITE )
1421+ {
1422+ /*
1423+ * Tuple: set up later, during first call to
1424+ * PLy_function_handler
1425+ */
1426+ proc -> result .out .d .typoid = procStruct -> prorettype ;
1427+ proc -> result .is_rowtype = 2 ;
1428+ }
1429+ else
1430+ {
1431+ /* Do the real work */
1432+ PLy_output_datum_func (& proc -> result , rvTypeTup );
1433+ }
1434+
1435+ ReleaseSysCache (rvTypeTup );
1436+ }
1437+
1438+ /*
1439+ * Set up output conversion functions for a procedure
1440+ */
1441+ static void
1442+ PLy_procedure_input_conversion (PLyProcedure * proc , HeapTuple procTup ,
1443+ Form_pg_proc procStruct )
1444+ {
1445+ Oid * types ;
1446+ char * * names ,
1447+ * modes ;
1448+ int i ,
1449+ pos ,
1450+ total ;
1451+
1452+ /* Extract argument type info from the pg_proc tuple */
1453+ total = get_func_arg_info (procTup , & types , & names , & modes );
1454+
1455+ /* Count number of in+inout args into proc->nargs */
1456+ if (modes == NULL )
1457+ proc -> nargs = total ;
1458+ else
1459+ {
1460+ /* proc->nargs was initialized to 0 above */
1461+ for (i = 0 ; i < total ; i ++ )
1462+ {
1463+ if (modes [i ] != PROARGMODE_OUT &&
1464+ modes [i ] != PROARGMODE_TABLE )
1465+ (proc -> nargs )++ ;
1466+ }
1467+ }
1468+
1469+ proc -> argnames = (char * * ) PLy_malloc0 (sizeof (char * ) * proc -> nargs );
1470+ for (i = pos = 0 ; i < total ; i ++ )
1471+ {
1472+ HeapTuple argTypeTup ;
1473+ Form_pg_type argTypeStruct ;
1474+
1475+ if (modes &&
1476+ (modes [i ] == PROARGMODE_OUT ||
1477+ modes [i ] == PROARGMODE_TABLE ))
1478+ continue ; /* skip OUT arguments */
1479+
1480+ Assert (types [i ] == procStruct -> proargtypes .values [pos ]);
1481+
1482+ argTypeTup = SearchSysCache1 (TYPEOID ,
1483+ ObjectIdGetDatum (types [i ]));
1484+ if (!HeapTupleIsValid (argTypeTup ))
1485+ elog (ERROR , "cache lookup failed for type %u" , types [i ]);
1486+ argTypeStruct = (Form_pg_type ) GETSTRUCT (argTypeTup );
1487+
1488+ /* Check argument type is OK, set up I/O function info */
1489+ switch (argTypeStruct -> typtype )
1490+ {
1491+ case TYPTYPE_PSEUDO :
1492+ /* Disallow pseudotype argument */
1493+ ereport (ERROR ,
1494+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
1495+ errmsg ("PL/Python functions cannot accept type %s" ,
1496+ format_type_be (types [i ]))));
1497+ break ;
1498+ case TYPTYPE_COMPOSITE :
1499+ /* We'll set IO funcs at first call */
1500+ proc -> args [pos ].is_rowtype = 2 ;
1501+ break ;
1502+ default :
1503+ PLy_input_datum_func (& (proc -> args [pos ]),
1504+ types [i ],
1505+ argTypeTup );
1506+ break ;
1507+ }
1508+
1509+ /* Get argument name */
1510+ proc -> argnames [pos ] = names ? PLy_strdup (names [i ]) : NULL ;
1511+
1512+ ReleaseSysCache (argTypeTup );
1513+
1514+ pos ++ ;
1515+ }
1516+ }
1517+
13881518/*
13891519 * Create a new PLyProcedure structure
13901520 */
@@ -1433,46 +1563,7 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
14331563 * but only if this isn't a trigger.
14341564 */
14351565 if (!is_trigger )
1436- {
1437- HeapTuple rvTypeTup ;
1438- Form_pg_type rvTypeStruct ;
1439-
1440- rvTypeTup = SearchSysCache1 (TYPEOID ,
1441- ObjectIdGetDatum (procStruct -> prorettype ));
1442- if (!HeapTupleIsValid (rvTypeTup ))
1443- elog (ERROR , "cache lookup failed for type %u" ,
1444- procStruct -> prorettype );
1445- rvTypeStruct = (Form_pg_type ) GETSTRUCT (rvTypeTup );
1446-
1447- /* Disallow pseudotype result, except for void */
1448- if (rvTypeStruct -> typtype == TYPTYPE_PSEUDO &&
1449- procStruct -> prorettype != VOIDOID )
1450- {
1451- if (procStruct -> prorettype == TRIGGEROID )
1452- ereport (ERROR ,
1453- (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
1454- errmsg ("trigger functions can only be called as triggers" )));
1455- else
1456- ereport (ERROR ,
1457- (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
1458- errmsg ("PL/Python functions cannot return type %s" ,
1459- format_type_be (procStruct -> prorettype ))));
1460- }
1461-
1462- if (rvTypeStruct -> typtype == TYPTYPE_COMPOSITE )
1463- {
1464- /*
1465- * Tuple: set up later, during first call to
1466- * PLy_function_handler
1467- */
1468- proc -> result .out .d .typoid = procStruct -> prorettype ;
1469- proc -> result .is_rowtype = 2 ;
1470- }
1471- else
1472- PLy_output_datum_func (& proc -> result , rvTypeTup );
1473-
1474- ReleaseSysCache (rvTypeTup );
1475- }
1566+ PLy_procedure_output_conversion (proc , procStruct );
14761567
14771568 /*
14781569 * Now get information required for input conversion of the
@@ -1482,79 +1573,7 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
14821573 * arguments.
14831574 */
14841575 if (procStruct -> pronargs )
1485- {
1486- Oid * types ;
1487- char * * names ,
1488- * modes ;
1489- int i ,
1490- pos ,
1491- total ;
1492-
1493- /* extract argument type info from the pg_proc tuple */
1494- total = get_func_arg_info (procTup , & types , & names , & modes );
1495-
1496- /* count number of in+inout args into proc->nargs */
1497- if (modes == NULL )
1498- proc -> nargs = total ;
1499- else
1500- {
1501- /* proc->nargs was initialized to 0 above */
1502- for (i = 0 ; i < total ; i ++ )
1503- {
1504- if (modes [i ] != PROARGMODE_OUT &&
1505- modes [i ] != PROARGMODE_TABLE )
1506- (proc -> nargs )++ ;
1507- }
1508- }
1509-
1510- proc -> argnames = (char * * ) PLy_malloc0 (sizeof (char * ) * proc -> nargs );
1511- for (i = pos = 0 ; i < total ; i ++ )
1512- {
1513- HeapTuple argTypeTup ;
1514- Form_pg_type argTypeStruct ;
1515-
1516- if (modes &&
1517- (modes [i ] == PROARGMODE_OUT ||
1518- modes [i ] == PROARGMODE_TABLE ))
1519- continue ; /* skip OUT arguments */
1520-
1521- Assert (types [i ] == procStruct -> proargtypes .values [pos ]);
1522-
1523- argTypeTup = SearchSysCache1 (TYPEOID ,
1524- ObjectIdGetDatum (types [i ]));
1525- if (!HeapTupleIsValid (argTypeTup ))
1526- elog (ERROR , "cache lookup failed for type %u" , types [i ]);
1527- argTypeStruct = (Form_pg_type ) GETSTRUCT (argTypeTup );
1528-
1529- /* check argument type is OK, set up I/O function info */
1530- switch (argTypeStruct -> typtype )
1531- {
1532- case TYPTYPE_PSEUDO :
1533- /* Disallow pseudotype argument */
1534- ereport (ERROR ,
1535- (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
1536- errmsg ("PL/Python functions cannot accept type %s" ,
1537- format_type_be (types [i ]))));
1538- break ;
1539- case TYPTYPE_COMPOSITE :
1540- /* we'll set IO funcs at first call */
1541- proc -> args [pos ].is_rowtype = 2 ;
1542- break ;
1543- default :
1544- PLy_input_datum_func (& (proc -> args [pos ]),
1545- types [i ],
1546- argTypeTup );
1547- break ;
1548- }
1549-
1550- /* get argument name */
1551- proc -> argnames [pos ] = names ? PLy_strdup (names [i ]) : NULL ;
1552-
1553- ReleaseSysCache (argTypeTup );
1554-
1555- pos ++ ;
1556- }
1557- }
1576+ PLy_procedure_input_conversion (proc , procTup , procStruct );
15581577
15591578 /*
15601579 * get the text of the function.
0 commit comments