⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aggregates.pm

📁 普通的ETL工具
💻 PM
📖 第 1 页 / 共 3 页
字号:
# vim:ts=4 sw=4
# ----------------------------------------------------------------------------------------------------
#  Name		: ETL::Pequel3::Type::Aggregates.pm
#  Created	: 8 May 2006
#  Author	: Mario Gaffiero (gaffie)
#
# Copyright 1999-2007 Mario Gaffiero.
# 
# This file is part of Pequel(TM).
# 
# Pequel is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
# 
# Pequel is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with Pequel; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
# ----------------------------------------------------------------------------------------------------
# Modification History
# When          Version     Who     What
# ----------------------------------------------------------------------------------------------------
package ETL::Pequel3::Type::Aggregates;
require 5.005_62;
use strict;
use warnings;
# ----------------------------------------------------------------------------------------------------
{
	package ETL::Pequel3::Type::Aggregates::Abstract;
	use base qw(Class::STL::Element);
	use Class::STL::ClassMembers 
		qw( 
			name 
			err
			properties 
			pequel_types
			hash 
			configuration
			use_list
			output_field
			requires_input_field
			pequel_ref
			xref
			description
		),
		Class::STL::ClassMembers::DataMember->new(name => 'print_info', default => 1),
		Class::STL::ClassMembers::DataMember->new(name => 'xs_type', default => 'NMTOKEN'),
		Class::STL::ClassMembers::DataMember->new(name => 'valid_types', default => 'string'),
		Class::STL::ClassMembers::DataMember->new(name => 'require_input_field', default => 1);
	use Class::STL::ClassMembers::Constructor;
	use Class::CodeStyler;
	sub new_extra
	{
		my $self = shift;
		$self->err(ETL::Pequel3::Error->new());
		$self->configuration($self->pequel_ref()->config()) if (defined($self->pequel_ref()));
		use ETL::Pequel3::Type::Properties;
		$self->properties(ETL::Pequel3::Type::Properties->new());
		use ETL::Pequel3::Type::PequelTypes;
		$self->pequel_types(ETL::Pequel3::Type::PequelTypes::Catalogue->new());
		$self->err()->user_error(10900, "Aggregate '@{[ 
			$self->name() ]}' -- required attribute 'output_field' is undefined!")
			if (!defined($self->output_field()));
		$self->err()->user_error(10900, "Aggregate '@{[ 
				$self->name() 
			]}' -- required attribute 'input_field' is undefined for output field '@{[ 
				$self->output_field()->name() 
			]}'!")
			if ($self->require_input_field() && !defined($self->output_field()->input_field()));
		$self->hash(defined($self->configuration()) && $self->configuration()->hash() == 1 ? '{$_HKEY}' : '');
#TODO	$self->hash($self->configuration()->hash() == 1 ? '{$@{[ $self->properties()->hkey_vname() ]}}' : '');
		use ETL::Pequel3::Type::Dates;
		use ETL::Pequel3::Type::FieldSet;
		$self->use_list(ETL::Pequel3::Type::FieldSet::OutputFields->new());
		$self->data($self->name());
		use ETL::Pequel3::CrossRef;
		$self->xref(ETL::Pequel3::CrossRef->new(
			target_obj => $self, 
			target_name => $self->name(), 
			pequel_ref => $self->pequel_ref(),
			@_,
		));
		return $self;
	}
    sub code_init
	{ 
		my $self = shift; 
		my $c = shift || ETL::CodeStyler::Program::Perl->new();
		return $c;
	}
    sub code_reset
	{ 
		my $self = shift; 
		my $c = shift || Class::CodeStyler::Program::Perl->new();
		return $c;
	}
    sub code_output_final
	{ 
		my $self = shift; 
		my $c = shift || Class::CodeStyler::Program::Perl->new();
		return $c;
	}
    sub code_output 
	{ 
		my $self = shift; 
		my $c = shift || Class::CodeStyler::Program::Perl->new();
		return $c;
	}
	sub prinfo
	{
		my $self = shift; 
		return $self->print_info() ? "# ~@{[ $self->name() ]}(@{[ $self->output_field()->name() ]})" : '';
	}
	sub xml_schema
	{
		my $self = shift;
		my $xsd = shift;
		my $xml_node = shift || $xsd->schema_root();
		return if ($xsd->exists('element', $self->name(), $xml_node));
		$xsd->comment($xml_node, "Aggregate Type: @{[ $self->name() ]}"); 
		my $element = $xsd->xs_element($xml_node, 'name' => $self->name());
		if ($xsd->configuration()->xmlschema_annotation() && defined($self->description()) 
			&& $self->description() ne '') 
		{
			my $doc = $xsd->xs_documentation($xsd->xs_annotation($element), 'xml:lang' => 'en');
			$xsd->text($doc, $self->description());
		}
		my $valid_types = $xsd->xs_element($xsd->xs_all($xsd->xs_complexType($element)),
			'name', 'valid_types'
		);
		my $choice = $xsd->xs_choice($xsd->xs_complexType($valid_types));
		foreach (split(/[|]/, $self->valid_types())) {
			$xsd->xs_element($choice, 'name' => $_);
		}
	}
}
# ----------------------------------------------------------------------------------------------------
{
	package ETL::Pequel3::Type::Aggregates::Sum;
	use base qw(ETL::Pequel3::Type::Aggregates::Abstract);
	use Class::STL::ClassMembers 
		Class::STL::ClassMembers::DataMember->new(name => 'name', default => 'sum'),
		Class::STL::ClassMembers::DataMember->new(name => 'description', default => 'Accumulate the total for all values in the group.'),
		Class::STL::ClassMembers::DataMember->new(name => 'valid_types', default => 'amount|numeric|date');
	use Class::STL::ClassMembers::Constructor;
    sub code_output
	{ 
		my $self = shift; 
		my $c = shift || ETL::Pequel3::CodeStyler::Program::Perl->new();
		my $if = $self->output_field()->input_field()->getvar();
		$c->code("@{[ $self->output_field()->getvar() ]} += $if");
		$c->over();
		$c->code("unless");
		$c->open_block("(");
			$c->code("!defined($if)");
			$c->code("|| $if eq ''");
		$c->close_block();
		$c->code(";@{[ $self->prinfo() ]}"); #??? if ($self->properties()->no_nulls() == 1);
		$c->back();
		return $c;
	}
}
# ----------------------------------------------------------------------------------------------------
{
	package ETL::Pequel3::Type::Aggregates::SumDistinct;
	use base qw(ETL::Pequel3::Type::Aggregates::Abstract);
	use Class::STL::ClassMembers 
		Class::STL::ClassMembers::DataMember->new(name => 'name', default => 'sum_distinct'),
		Class::STL::ClassMembers::DataMember->new(name => 'description', default => 'Accumulate the total for unique values for field-name in the group.'),
		Class::STL::ClassMembers::DataMember->new(name => 'valid_types', default => 'amount|numeric|date');
	use Class::STL::ClassMembers::Constructor;
    sub code_init
	{ 
		my $self = shift; 
		my $c = shift || ETL::Pequel3::CodeStyler::Program::Perl->new();
		$c->code("my \%SUM_DISTINCT_KEYS_@{[ $self->output_field()->name() ]}; @{[ $self->prinfo() ]}");
		return $c;
	}
    sub code_reset
	{ 
		my $self = shift; 
		my $c = shift || ETL::Pequel3::CodeStyler::Program::Perl->new();
		$c->code("\%SUM_DISTINCT_KEYS_@{[ $self->output_field()->name() ]} = (); @{[ $self->prinfo() ]}");
		return $c;
	}
    sub code_output
	{ 
		my $self = shift; 
		my $c = shift || ETL::Pequel3::CodeStyler::Program::Perl->new();
		my $of = "@{[ $self->output_field()->name() ]}@{[ $self->hash() ]}";
		my $if = $self->output_field()->input_field()->getvar();
		$c->code("@{[ $self->output_field()->getvar() ]} += $if");
		$c->over();
		$c->code("if");
		$c->open_block("(");
			$c->code("$if ne ''");
			$c->code("&& ++\$SUM_DISTINCT_KEYS_$of\{qq{$if}} == 1");
		$c->close_block();
		$c->code(";@{[ $self->prinfo() ]}");
		$c->back();
		return $c;
	}
}
# ----------------------------------------------------------------------------------------------------
{
	package ETL::Pequel3::Type::Aggregates::ValuesUniq;
	use base qw(ETL::Pequel3::Type::Aggregates::Abstract);
	use Class::STL::ClassMembers 
		Class::STL::ClassMembers::DataMember->new(name => 'name', default => 'values_uniq'),
		Class::STL::ClassMembers::DataMember->new(name => 'description', default => 'Output the list of unique values in the group.');
	use Class::STL::ClassMembers::Constructor;
    sub code_init
	{ 
		my $self = shift; 
		my $c = shift || ETL::CodeStyler::Program::Perl->new();
		$c->code("my \%VALUES_UNIQ_@{[ $self->output_field()->name() ]};@{[ $self->prinfo() ]}");
		return $c;
	}
    sub code_reset
	{ 
		my $self = shift; 
		my $c = shift || ETL::Pequel3::CodeStyler::Program::Perl->new();
		$c->code("\%VALUES_UNIQ_@{[ $self->output_field()->name() ]} = ();@{[ $self->prinfo() ]}");
		return $c;
	}
    sub code_output_final
	{ 
		my $self = shift; 
		my $c = shift || ETL::Pequel3::CodeStyler::Program::Perl->new();
		my $of = "@{[ $self->output_field()->name() ]}@{[ $self->hash() ]}";
		my $delim = $self->properties()->default_list_delimiter();
		$c->code("@{[ $self->output_field()->getvar() ]} = ");
		$c->over();
			$c->code("join");
			$c->open_block("(");
				$c->code("qq{$delim},");
				$c->newline_off();
				$c->code("grep(length, sort keys ");
				$self->hash() eq ''
					? $c->code("\%VALUES_UNIQ_$of")
					: $c->code("\%{\$VALUES_UNIQ_$of}"); # hash
				$c->newline_on();
				$c->code(")"); #grep
			$c->close_block();
			$c->code(";@{[ $self->prinfo() ]}");
		$c->back();
		return $c;
	}
    sub code_output
	{ 
		my $self = shift; 
		my $c = shift || ETL::Pequel3::CodeStyler::Program::Perl->new();
		my $of = "@{[ $self->output_field()->name() ]}@{[ $self->hash() ]}";
		my $if = $self->output_field()->input_field()->getvar();
		my $delim = $self->properties()->default_list_delimiter();
		if ($self->output_field()->input_field()->pequel_type()->name() eq 'array')
		{
			$c->code("map");
			$c->open_block("(");
				$c->code("\$VALUES_UNIQ_$of\{\$_}++,");
				$c->code("split(/\\s*$delim\\s*/, $if)");
			$c->close_block();
			$c->code(";@{[ $self->prinfo() ]}");
		}
		else
		{
			$c->code("\$VALUES_UNIQ_$of\{qq{$if}}++;@{[ $self->prinfo() ]}");
		}
		return $c;
	}
}
# ----------------------------------------------------------------------------------------------------
{
	package ETL::Pequel3::Type::Aggregates::ValuesAll;
	use base qw(ETL::Pequel3::Type::Aggregates::Abstract);
	use Class::STL::ClassMembers 
		Class::STL::ClassMembers::DataMember->new(name => 'name', default => 'values_all'),
		Class::STL::ClassMembers::DataMember->new(name => 'description', default => 'Output the list of all values in the group.');
	use Class::STL::ClassMembers::Constructor;
    sub code_init
	{ 
		my $self = shift; 
		my $c = shift || ETL::CodeStyler::Program::Perl->new();
		$c->code("my @{[ $self->hash() eq '' ? '@' : '%' ]}VALUES_ALL_@{[ 
			$self->output_field()->name() ]};@{[ $self->prinfo() ]}");
		return $c;
	}
    sub code_reset
	{ 
		my $self = shift; 
		my $c = shift || ETL::Pequel3::CodeStyler::Program::Perl->new();
		$c->code("@{[ $self->hash() eq '' ? '@' : '%' ]}VALUES_ALL_@{[ 
			$self->output_field()->name() ]} = ();@{[ $self->prinfo() ]}");
		return $c;
	}
    sub code_output_final
	{ 
		my $self = shift; 
		my $c = shift || ETL::Pequel3::CodeStyler::Program::Perl->new();
		my $of = "@{[ $self->output_field()->name() ]}@{[ $self->hash() ]}";
		my $delim = $self->properties()->default_list_delimiter();
		$c->code("@{[ $self->output_field()->getvar() ]} = ");
		$c->over();
			$c->code("join");
			$c->open_block("(");
				$c->code("qq{$delim},");
				$c->newline_off();
				$c->code("grep(length, ");
				$self->hash() eq ''
					? $c->code("\@VALUES_ALL_$of")
					: $c->code("\@{\$VALUES_ALL_$of}"); # hash
				$c->newline_on();
				$c->code(")"); #grep
			$c->close_block();
			$c->code(";@{[ $self->prinfo() ]}");
		$c->back();
		return $c;
	}
    sub code_output
	{ 
		my $self = shift; 
		my $c = shift || ETL::Pequel3::CodeStyler::Program::Perl->new();
		my $of = "@{[ $self->output_field()->name() ]}@{[ $self->hash() ]}";
		my $if = $self->output_field()->input_field()->getvar();
		my $delim = $self->properties()->default_list_delimiter();
		$c->code("push");
		$c->open_block("(");
			$c->code($self->hash() eq '' ? "\@VALUES_ALL_$of, " : "\@{\$VALUES_ALL_$of}, ");
			$self->output_field()->input_field()->pequel_type()->name() eq 'array'
				? $c->code("split(/\\s*$delim\\s*/, $if)")
				: $c->code("qq{$if}");
		$c->close_block();
		$c->code(";@{[ $self->prinfo() ]}");
		return $c;
	}
}
# ----------------------------------------------------------------------------------------------------
{
	package ETL::Pequel3::Type::Aggregates::Count;
	use base qw(ETL::Pequel3::Type::Aggregates::Abstract);
	use Class::STL::ClassMembers 
		Class::STL::ClassMembers::DataMember->new(name => 'name', default => 'count'),
		Class::STL::ClassMembers::DataMember->new(name => 'description', default => 'Output the count of records in the group.');
	use Class::STL::ClassMembers::Constructor;
    sub code_output
	{ 
		my $self = shift; 
		my $c = shift || ETL::Pequel3::CodeStyler::Program::Perl->new();
		my $if = $self->output_field()->input_field()->getvar();
		$c->code("@{[ $self->output_field()->getvar() ]}++");
		$c->over();
		$c->code("if (defined($if));@{[ $self->prinfo() ]}");
		$c->back();
		return $c;
	}
}
# ----------------------------------------------------------------------------------------------------
{
	package ETL::Pequel3::Type::Aggregates::Distinct;
	use base qw(ETL::Pequel3::Type::Aggregates::Abstract);
	use Class::STL::ClassMembers 
		Class::STL::ClassMembers::DataMember->new(name => 'name', default => 'distinct'),
		Class::STL::ClassMembers::DataMember->new(name => 'valid_types', default => 'amount|numeric');
	use Class::STL::ClassMembers::Constructor;
    sub code_init
	{ 
		my $self = shift; 
		my $c = shift || ETL::CodeStyler::Program::Perl->new();
		$c->code("my \%DISTINCT_@{[ $self->output_field()->name() ]};@{[ $self->prinfo() ]}");
		return $c;
	}
    sub code_reset
	{ 
		my $self = shift; 
		my $c = shift || ETL::Pequel3::CodeStyler::Program::Perl->new();
		$c->code("\%DISTINCT_@{[ $self->output_field()->name() ]} = ();@{[ $self->prinfo() ]}");
		return $c;
	}
    sub code_output

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -