AtteanX-Store-DBI
view release on metacpan or search on metacpan
lib/AtteanX/Store/DBI.pm view on Meta::CPAN
}
}
foreach my $vdata (@vars) {
my ($var, $name) = @$vdata;
my $var_name = $rename_proj->( $var->value );
push(@select, [$table, $name, $var_name]) unless ($seen_vars{$var->value}++);
if (my $tt = $source_table_for_var{ $var->value }) {
push(@where_joins, ['=', $tt, [$table, $name]]);
} else {
$source_table_for_var{ $var->value } = [$table, $name];
}
}
}
foreach my $w (@where_joins) {
my ($op, $a, $b) = @$w;
my ($as, $bs) = map { sprintf('%s.%s', @$_) } ($a, $b);
push(@where, join(' ', $as, $op, $bs));
}
return AtteanX::Store::DBI::Plan->new(
store => $self,
select => \@select,
where => \@where,
tables => \@tables,
in_scope_variables => [@vars],
rename_mapping => \%rename_mapping,
bindings => \@bind,
variables => \%source_table_for_var,
);
}
return;
}
=item C<< cost_for_plan( $plan ) >>
Returns the estimated cost for a DBI-specific query plan, undef otherwise.
=cut
sub cost_for_plan {
my $self = shift;
my $plan = shift;
if ($plan->isa('AtteanX::Store::DBI::Plan')) {
return 1; # TODO: actually estimate cost here
}
return;
}
}
package AtteanX::Store::DBI::Plan 0.012 {
use Moo;
use Type::Tiny::Role;
use Types::Standard qw(HashRef ArrayRef InstanceOf Str);
use namespace::clean;
has store => (is => 'ro', isa => InstanceOf['AtteanX::Store::DBI'], required => 1);
has rename_mapping => (is => 'ro', isa => HashRef[Str], default => sub { +{} });
has variables => (is => 'ro', isa => HashRef, required => 1);
has bindings => (is => 'ro', isa => ArrayRef, required => 1);
has select => (is => 'ro', isa => ArrayRef, required => 1);
has where => (is => 'ro', isa => ArrayRef, required => 1);
has tables => (is => 'ro', isa => ArrayRef[ArrayRef[Str]], required => 1);
with 'Attean::API::BindingSubstitutionPlan', 'Attean::API::NullaryQueryTree';
sub plan_as_string {
my $self = shift;
my ($sql, @bind) = $self->sql();
return sprintf('DBI BGP { %s â (%s) }', $sql, join(', ', @bind));
}
sub sql {
my $self = shift;
my $bind = shift;
my $store = $self->store;
my $dbh = $store->dbh;
my @bind = @{ $self->bindings };
my @where = @{ $self->where };
if ($bind) {
foreach my $var ($bind->variables) {
my $id = $store->_get_term_id($bind->value($var));
return unless defined($id);
if (my $cdata = $self->variables->{ $var }) {
my ($table, $col) = @$cdata;
push(@where, sprintf("%s.%s = ?", $table, $col));
push(@bind, $id);
}
}
}
my @select = map { sprintf("%s.%s AS %s", map { $dbh->quote_identifier( $_ ) } @$_) } @{ $self->select };
unless (scalar(@select)) {
push(@select, '1');
}
my @sql;
push(@sql, 'SELECT');
push(@sql, join(', ', @select));
push(@sql, 'FROM');
push(@sql, join(', ', map { join(' ', @$_) } @{ $self->tables }));
if (scalar(@where)) {
push(@sql, 'WHERE');
push(@sql, join(' AND ', map { "($_)" } @where));
}
my $sql = join(" ", @sql);
return ($sql, @bind);
}
sub substitute_impl {
my $self = shift;
my $model = shift;
my ($sql, @bind) = $self->sql(@_);
my $store = $self->store;
my $dbh = $store->dbh;
# warn "TODO: generatee SQL for BGP: $sql\n";
# warn "======================================================================\n";
( run in 0.856 second using v1.01-cache-2.11-cpan-5735350b133 )