use Carp::Clan qw/^DBIx::Class/;
use aliased 'DBIx::Class::ResultSource::Table';
use aliased 'DBIx::Class::ResultClass::HashRefInflator';
+use String::TT qw(strip tt);
use namespace::autoclean;
# how this works:
map $schema->source($_), $schema->sources;
confess "Couldn't find attached source for parent $parent_name - did you use load_classes? This module is only compatible with load_namespaces"
unless $parent;
+ $self->parent_source($parent); # so our parent is the one in this schema
}
# create the raw table source
method raw_source_name () {
my $base = $self->source_name;
- confess "Can't generate raw source name when we don't have a source_name"
+ confess "Can't generate raw source name for ${\$self->name} when we don't have a source_name"
unless $base;
return 'Raw::'.$base;
}
$source->primary_columns;
};
- *names_of = sub (@cols) { map $_->{name}, @cols };
+ *name_of = *names_of = sub (@cols) { map $_->{name}, @cols };
- *arglist = sub (@cols) {
- map join(' ', @{$_}{qw(name data_type)}), @cols;
+ *function_body = sub ($name, $args, $body_parts) {
+ my $arglist = join(
+ ', ',
+ map '_'.join(' ', @{$_}{qw(name data_type)}),
+ @$args
+ );
+ my $body = join("\n", '', map " $_;", @$body_parts);
+ return strip tt q{
+ CREATE OR REPLACE FUNCTION [% name %]
+ ([% arglist %])
+ RETURNS VOID AS $function$
+ BEGIN
+ [%- body %]
+ END;
+ $function$ LANGUAGE plpgsql;
+ };
};
}
+BEGIN {
+
+ use signatures;
+
+ *arg_hash = sub ($source) {
+ map +($_ => \(argify $_)), names_of body_cols $source;
+ };
+}
+
+method root_table () {
+ $self->parent_source
+ ? $self->parent_source->root_table
+ : $self->schema->source($self->raw_source_name)
+}
+
method view_definition () {
my $schema = $self->schema;
confess "Can't generate view without connected schema, sorry"
])
: ($table->name)),
[ (qualify_with $table, names_of @pk_cols), names_of @body_cols ],
- );
- return $select;
+ ).';';
+ my ($now, $next) = grep defined, $super_view, $table;
+ # NOTE: this assumes a single PK col called id with a sequence somewhere
+ # but nothing else -should- so fixing this should make everything work
+ my $insert_func =
+ function_body
+ $self->name.'_insert',
+ \@body_cols,
+ [
+ $sqla->insert( # INSERT INTO _tbl (foo, ...) VALUES (_foo, ...)
+ $now->name,
+ { arg_hash $now },
+ ),
+ ($next
+ ? $sqla->insert( # INSERT INTO super_view (id, ...)
+ # VALUES (currval('_root_tbl_id_seq'), ...)
+ $next->name,
+ {
+ (arg_hash $next),
+ id => \"currval('${\$self->root_table->name}_id_seq')",
+ }
+ )
+ : ()
+ )
+ ];
+ # note - similar to arg_hash but not quite enough to share code sanely
+ my $pk_where = { # id = _id AND id2 = _id2 ...
+ map +($_ => \"= ${\argify $_}"), names_of @pk_cols
+ };
+ my $update_func =
+ function_body
+ $self->name.'_update',
+ [ @pk_cols, @body_cols ],
+ [ map $sqla->update(
+ $_->name, # UPDATE foo
+ { arg_hash $_ }, # SET a = _a
+ $pk_where,
+ ), @sources
+ ];
+ my $delete_func =
+ function_body
+ $self->name.'_delete',
+ [ @pk_cols ],
+ [ map $sqla->delete($_->name, $pk_where), @sources ];
+ return join("\n\n", $select, $insert_func, $update_func, $delete_func);
}
1;