Perl言語集合体

この例では、次のファイル名を使用している: 'Maxae.pm

コード

この例のコードは、すべての可能なデータ型を扱うため、C言語の集計例よりも若干長くなっている。

package Maxae;
use nzae::Ae;
use strict;
use autodie;
our @ISA = qw(nzae::Ae);
my $ae = Maxae->new();
$ae->run();
# The runUda function here is the exact function implemented for the Ae class
# Reproducing this function is not needed in user code to run an aggregate
# as it is inherited. The user can however override this function to have
# finer control on the running of the aggregate Ae
sub runUda
{
my $self = shift;
while(1)
{
my $aggregationType = $self->_getNextAggregation();
if ( $aggregationType == $self->getAggregateTypeInitialize() )
{
$self->_initializeState();
$self->_saveAggregateResult();
}
elsif ( $aggregationType == $self->getAggregateTypeAccumulate() )
{
$self->_accumulate($self->getState(), $self->getInputRow());
$self->_saveAggregateResult();
}
elsif ( $aggregationType == $self->getAggregateTypeMerge() )
{
$self->_merge($self->getState(), $self->getInputState());
$self->_saveAggregateResult();
}
elsif ( $aggregationType == $self->getAggregateTypeFinalResult() )
{
my $result = $self->_finalResult($self->getState());
$self->_setAggregateResult($result, 1);
$self->_saveAggregateResult();
}
elsif ( $aggregationType == $self->getAggregateTypeEnd() )
{
return;
}
elsif ( $aggregationType == $self->getAggregateTypeError() )
{
croak(nzae::Exceptions::AeInternalError->new("Error calling
nzaeAggNext(). Cause unknown."));
}
else
{
croak(nzae::Exceptions::AeInternalError->new("Received unknown
aggregation type."));
}
}
}
#the functions below need to be overridden by the user
#while writing an aggregate Ae
sub _initializeState
{
my $self = shift;
$self->_setState(0, -2147483647);
}
sub _accumulate
{
my $self = shift;
my @instate = shift;
my @row = shift;
my $state = pop(@instate);
if (scalar(@row) > 0)
{
if ( defined $row[0] )
{
unless (defined $state)
{
if (defined $row[0])
{
$state = $row[0];
}
}
elsif ( $state < $row[0] )
{
if (defined $row[0])
{
$state = $row[0];
}
}
}
}
unless (defined $state)
{
$state = -2147483647;
}
$self->_setState(0, $state);
}
sub _merge
{
my $self = shift;
my @instate = shift;
my @inputValues = shift;
my $state = pop(@instate);
for ( my $i = 0 ; $i < scalar(@inputValues); $i++ )
{
unless (defined $state)
{
$state = $inputValues[$i];
}
elsif ( $state < $inputValues[$i] )
{
$state = $inputValues[$i];
}
}
unless (defined $state)
{
$state = -2147483647;
}
$self->_setState(0, $state);
}
sub _finalResult
{
my $self = shift;
my @state = shift;
my $ret = defined $state[0]? $state[0] : -2147483647;
return $ret;
}
1;

この例では、'runUda関数がオーバーライドされている。 例のコメントにあるように、この関数はすでに'nzae::Aeクラスから継承されているので、ユーザーがオーバーライドする必要はない。 しかし、AEの動作をより細かく制御する必要がある場合は、この機能をオーバーライドすることができる。

まとめると、カスタマイズせずにUDAを書くには、次のような手順がある:
  1. Perlモジュールファイルを作成する。 上の例では'MaxAe.pmである。
  2. ファイルにある'nzae::Aeクラスをインポートしてインスタンス化する。
  3. autodieをインポートして、実行中に処理されなかった例外を処理する。
  4. _initializeState関数をオーバーライドして、登録ステップで定義した状態変数を初期化する。
  5. accumulateメソッドをオーバーライドして、データスライスごとの集計機能を実装します。
  6. mergeメソッドをオーバーライドして、各データスライスからの状態変数の集約を実装する。
  7. finalResultメソッドをオーバーライドして、マージされたステート変数を返す。
  8. nzae::Aeオブジェクトの 'run()メソッドを実行する。
  9. これはPerlモジュールなので、ファイル'MaxAe.pmの末尾に "1 "を付ける。

デプロイメント

スクリプトをデプロイする:
$NZ_EXPORT_DIR/ae/utilities/bin/compile_ae --language perl --version 3 \
--template deploy Maxae.pm;

登録

stateパラメータを使用して、サンプルを UDA として登録します:
$NZ_EXPORT_DIR/ae/utilities/bin/register_ae --language perl --version 3 \
--template uda --exe Maxae.pm --sig "maxaepl(int)" --return int4 \
--state "(int4)"

実行中

実行するには、まずダミーのテーブルを作成し、集約を実行する:
CREATE TABLE grp_test (grp int4, val int4);
CREATE TABLE
INSERT INTO grp_test VALUES (1, 1);
INSERT 0 1
INSERT INTO grp_test VALUES (1, 2);
INSERT 0 1
INSERT INTO grp_test VALUES (1, 3);
INSERT 0 1
INSERT INTO grp_test VALUES (2, 4);
INSERT 0 1
SELECT maxaepl(val) FROM grp_test;
MAXAEPL
---------
4
(1 row)
SELECT grp, maxaepl(val) FROM grp_test GROUP BY grp;
GRP | MAXAEPL
-----+---------
2 | 4
1 | 3
(2 rows)
SELECT grp, maxaepl(val) over (partition BY grp) FROM grp_test;
GRP | MAXAEPL
-----+---------
1 | 3
1 | 3
1 | 3
2 | 4
(4 rows)