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

📄 table.pm

📁 普通的ETL工具
💻 PM
📖 第 1 页 / 共 3 页
字号:
# vim:ts=4 sw=4
# ----------------------------------------------------------------------------------------------------
#  Name		: ETL::Pequel3::Type::Table.pm
#  Created	: 2 June 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::Table;
require 5.005_62;
use strict;
use warnings;
use ETL::Pequel3::CodeStyler;
# ----------------------------------------------------------------------------------------------------
{
	package ETL::Pequel3::Type::Table::Abstract;
	use base qw(Class::STL::Element);
	use Class::STL::ClassMembers 
		qw( 
			catalogue
			err 
			properties 
			pequel_types 
			sorters
			table_number 
			fields 
			tname 
			field_map
			key_field 
			verify
			configuration
			used_by_list 
			use_list
			package_name
			load_function_name
			load_name 
			pequel_ref

			name 
			description
		), 
		Class::STL::ClassMembers::DataMember->new(name => 'xs_type', default => 'NMTOKEN'),
		Class::STL::ClassMembers::DataMember->new(name => 'fieldset_type', default => 'table_fields'),
		Class::STL::ClassMembers::DataMember->new(name => 'key_type', default => 'string'); #??? not used ???
	use Class::STL::ClassMembers::Constructor;
	use ETL::Pequel3::Error;
	sub new_extra
	{
		my $self = shift;
		use ETL::Pequel3::Catalogue;
		$self->catalogue(ETL::Pequel3::Catalogue->new());
		$self->err(ETL::Pequel3::Error->new()); 
		$self->properties(ETL::Pequel3::Type::Properties->new());
		defined($self->pequel_ref()->config())
			? $self->configuration($self->pequel_ref()->config())
			: $self->configuration(ETL::Pequel3::Type::Properties::User->new());
		$self->pequel_types(ETL::Pequel3::Type::PequelTypes::Catalogue->new());
		$self->sorters(ETL::Pequel3::Type::Sorters::Catalogue->new());

		$self->tname('_T_' . $self->name());
		use ETL::Pequel3::Type::FieldSet;
		$self->fields($self->catalogue()->fieldsets()->exists($self->fieldset_type())
			->new(table => $self, pequel_ref => $self->pequel_ref()));
		$self->used_by_list(stl::list());
		$self->use_list(stl::list());
		$self->package_name(ref($self));
		$self->load_function_name("load@{[ $self->tname() ]}");
		$self->load_name($self->package_name() . '::' . $self->load_function_name());
		return $self;
	}
	sub factory
	{
		my $self = shift;
		my %p = @_; # table_type, static, input_dataset, dataset_spec, ...
		return $self->new(%p);
	}
	sub prepare
	{
		my $self = shift;
		my $items = shift;
	}
	sub code_load_table
	{
		# virtual function
	}
	sub code_start
	{
		my $self = shift;
		my $c = shift || ETL::Pequel3::CodeStyler::Program::Perl->new();
		$c->code("our \$@{[ $self->tname() ]} =");
		$c->over();
			$c->code("\&@{[ $self->load_name() ]}();");
			$c->code("# ref to \%@{[ $self->tname() ]} hash");
		$c->back();
		return $c;
	}
	sub translate
	{
		my $self = shift;
		my $key_exp = shift; 
		my $field = shift; # || undef;
		my $show_synonyms = shift;
		my $target_obj = shift; #TODO: not best solution?
		my $c = ETL::Pequel3::CodeStyler::Program::Perl->new();
		if (defined($field) && !ref($field)) 
		{
			$field =~ s/^@{[ $self->name() ]}->//;
			my $f = $self->fields()->exists($field); 
			$self->err()->user_error(10302, "Unknown field '$field' for table '@{[ $self->name() ]}'")
				unless (defined($f) && ref($f));
			$field = $f;
		}
		if (defined($field)) 
		{
#>			$c->code($field->getvar($key_exp, $show_synonyms, $target_obj)); # update ref's to key-fields
			$c->code($field->getvar($key_exp, $show_synonyms));
			$target_obj->xref()->references($field) if (defined($target_obj) && $target_obj->can('xref'));
			$field->xref()->referenced_by($target_obj) if (defined($target_obj) && $field->can('xref'));
		} 
		else 
		{
			# !! this should never happen -- a field name is required !!
			# keyfld can be an expression eg: another macro
			my $key_eval = $key_exp =~ /[&\(|\[|,]/ ? "\@{[ $key_exp ]}" : $key_exp;
			$c->code('$$' . $self->tname() . '{qq{' . $key_eval . '}}');
		}
		return $c;
	}
	sub code_display_info
	{
		my $self = shift;
		my $c = shift || ETL::Pequel3::CodeStyler::Program::Perl->new();
		my $extra = shift;
		$c->comment("++++++ Table @{[ $self->name() ]} --> Type @{[ ref($self) ]} ++++++");
		$c->comment("++++++ $extra") if (defined($extra));
		return $c;
	}
	sub attach_sorter #--> External::Abstract ?? --> move to dataset
	{
		my $self = shift;
		my $key_type = shift;
		# TODO:Need to verify key_field exists!
		$self->input_dataset()->datasource()->sorter(
			$self->sorters()->exists($self->properties()->sorter())->new(
				uniq => 1,
				field_delimiter => $self->input_dataset()->can('field_delimiter')
					? $self->input_dataset()->field_delimiter() : undef,
				pequel_ref => $self->pequel_ref()
			)
		);
#<		# TODO: dataset-type to determine sorter: eg packed type no sorter...
		$self->input_dataset()->datasource()->sorter()->add(
			name => $self->key_field(),
			column => $self->fields()->exists($self->key_field())->ds_column(),
			pequel_type => $key_type,
			pequel_ref => $self->pequel_ref(),
		);
	}
}
# ----------------------------------------------------------------------------------------------------
{
	package ETL::Pequel3::Type::Table::Local::Data;
	use base qw(Class::STL::Element);
	use Class::STL::ClassMembers qw( key value );
	use Class::STL::ClassMembers::Constructor;
	sub new_extra
	{
		my $self = shift;
		$self->value([]) unless defined($self->value());
		return $self;
	}
}
# ----------------------------------------------------------------------------------------------------
{
	package ETL::Pequel3::Type::Table::Local;
	use base qw(ETL::Pequel3::Type::Table::Abstract);
	use Class::STL::ClassMembers qw( data ),
		Class::STL::ClassMembers::DataMember->new(name => 'description', default => "The F<local> table type can be used to create a table with the data declared within the I<pequel script>. The table data is declared within the I<items> with the F<key>, F<value> attribute pairs. The F<value> attribute consists of string of space delimited data values"),
		Class::STL::ClassMembers::DataMember->new(name => 'name', default => 'local');
	use Class::STL::ClassMembers::Constructor;
	sub new_extra
	{
		my $self = shift;
		$self->data(stl::list(element_type => 'ETL::Pequel3::Type::Table::Local::Data'));
		return $self;
	}
	sub factory
	{
		my $self = shift;
		my %p = @_; # table_type, static, input_dataset, dataset_spec, ...
		return $p{table_type} eq 'local' ? $self->new(%p) : 0;
	}
	sub code_load_table
	{
		my $self = shift;
		my $c = shift || ETL::Pequel3::CodeStyler::Program::Perl->new();
		return if ($c->jump("load@{[ $self->tname() ]}")); # ???
		$c->divider();
		$self->code_display_info($c, "@{[ __PACKAGE__ ]}");
		$c->open_block("{");
			$c->code("package " . $self->package_name() . ";");
			$c->code("sub @{[ $self->load_function_name() ]}");
			$c->open_block("{");
				$c->code("my \%@{[ $self->tname() ]} =");
				$c->code("(");
				$c->over();
					my $count=0;
					foreach my $d (sort { $a->key() cmp $b->key() } $self->data()->to_array())
					{
						$c->newline_on();
						$c->indent_off();
						$c->code(',') if (++$count > 1);
						$c->indent_on();
						$c->newline_off();
						$c->code("'@{[ $d->key() ]}' => ");
						($self->fields()->size() == 0)
							? $c->code("'@{[ $d->key() ]}'")
							: ($self->fields()->size() == 1)
								? $c->code("'@{[ ${$d->value()}[0] ]}'")
								: $c->code("['@{[ join(q{', '}, map($_, map(defined($_) ? $_ : '', @{$d->value()}))) ]}']");
					}
					$c->newline_on();
					$c->code("");
				$c->back();
				$c->code(");");
				$c->code('return \%' . $self->tname() . ';');
			$c->close_block();
		$c->close_block();
		return $c;
	}
	sub prepare
	{
		my $self = shift;
		my $items = shift;

		$self->fields()->map_fields($self->field_map());
		# Copy the data:
		foreach (grep(defined($_->key_value()), $items->to_array())) {
			$self->data()->push_back($self->data()->factory(
				key => $_->key_value(),
				value => $_->data_values()
			));
		}
	}
}
# ----------------------------------------------------------------------------------------------------
{
	package ETL::Pequel3::Type::Table::External::Abstract;

⌨️ 快捷键说明

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