Perl language scalar function

The following example shows a simple scalar function that sums a set of numbers. The example uses the following file name: ApplyOp.pm

Code

  1. Name the example class by using the Perl package command:
    package ApplyOp;
  2. Import the nzae::Ae package and define the example class as a child class of the nzae::Ae class.
    use nzae::Ae;
    our @ISA = qw(nzae::Ae);
  3. Define the class. As in the Python examples, the base class handles most of the work. Typically the new() method is called to initialize the class, and the run() method is then called. The run() method calls the appropriate derived function. For UDF-based AEs such as this one, the _getFunctionResult() function must be overridden, as it gets called once for each row of input by default:
    package ApplyOp;
    use strict;
    use autodie;
    use nzae::Ae;
    our @ISA = qw(nzae::Ae);
    my $ae = ApplyOp->new();
    $ae->run();
    sub _getFunctionResult(@)
    {
    #User defined function code goes here
    }
    1;
  4. Add the custom Perl code. In this UDF, a string operator is passed in, which is either a plus sign (+) to add or an asterisk (*) to multiply, and two integers. The code returns either the product or the sum of the integers. In SQL, a simple version of this can be called by either:
    SELECT applyopPl('+', 3, 5);
    or
    SELECT applyopPl('*', 3, 5);
    While the mentioned example has only one input, the NPS system deals with streams of input. Therefore, the NPS system is more likely to use:
    SELECT applyopPl(mytable.operator, mytable.value1, mytable.value2) FROM mytable;

    In the first example, the NPS system takes the constants, "+", 3, and 5 and turns them into a stream of length 1 containing three elements. One row is "seen" by getFunctionResult() with the three elements in it. In addition, as in Perl convention, the calling object is passed in as the first argument to the function. This is picked up by the function by using the variable $self. Internally, all the mentioned cases are handled in the same manner and the assumption can be made that there are multiple inputs to the applyop AE.

  5. Enter custom code to handle one row of input, as loop handling input is needed to hand off one row to the function at a time:
    package ApplyOp;
    use nzae::Ae;
    use strict;
    use autodie;
    our @ISA = qw(nzae::Ae);
    my $ae = ApplyOp->new();
    $ae->run();
    sub _getFunctionResult(@)
    {
    my $self = shift;
    # BREAK APART OUR ROW OF INPUT.
    my ($operator, $leftInput, $rightInput) = @_;
    # HANDLE ADDITION.
    if ($operator eq "+")
    {
    return $leftInput + $rightInput;
    }
    # HANDLE MULTIPLICATION.
    if ($operator eq "*")
    {
    return $leftInput * $rightInput;
    }
    # ERROR ON ALL OTHER.
    croak(nzae::Exceptions::AeInternalError->new("Unhandled operator to ApplyOp: '" .
    $operator . "'."));
    }
    1;

    The croak function reports the error to the SQL user and, if logging is enabled, returns a trace to the line of error.

    You can use the cluck function in place of croak for writing warnings to the log file. To catch any unhandled exceptions automatically, use autodie. Die and warn can also be used to report a single-line error or warning, if logging is turned on. Die errors out the execution of the AE. Set log level by using the --level option during registration. What is returned by _getFunctionResult() is the result of the SQL operation, and because this is run as a UDF, there can be only one column in the result.

    In summary, to write a UDF adding only the actual functionality without customizing the methods for running it, follow the steps:
    1. Create a Perl module file (ApplyOp.pm in the mentioned example).
    2. Import and instantiate the nzae::Ae class in the file.
    3. Import autodie to handle unhandled exceptions during execution.
    4. Override _getFunctionResult to implement customized functionality for UDF. Handle errors to be returned to the user by using the croak() method.
    5. Execute the run() method of the nzae::Ae object.
    6. Since this is a Perl module, add a “1” at the end of the file ApplyOp.pm.

    When the code is complete, it must be deployed and registered.

Compilation

Perl AEs do not require compilation.

Deployment

Although Perl AEs do not require compilation, they must be deployed. The compile_ae command is still used with the --template deployment option to deploy the script to the default location on the shared export drive.
$NZ_EXPORT_DIR/ae/utilities/bin/compile_ae --language perl --version 3 \
--template deploy ApplyOp.pm

Registration

Register the Perl file:
$NZ_EXPORT_DIR/ae/utilities/bin/register_ae --language perl --version 3 \
--template udf --exe ApplyOp.pm --sig "applyopPl(varchar(1), int4, int4)"\
--return int4

Running

The AE can now be run in SQL on the system database:
SELECT applyopPl('+', 4, 10);
APPLYOPPL
-----------
14
(1 row)
Note that to validate types in _getFunctionResult(), the croak() method is called. The following example triggers an error:
SELECT applyopPl('-', 1, 2);
ERROR: Unhandled operator to ApplyOp: '-'. at
/nz/export/ae/applications/system/admin/ApplyOp.pm line 28