use aliased 'DBIx::Class::ResultSource::Table';
use aliased 'DBIx::Class::ResultClass::HashRefInflator';
use String::TT qw(strip tt);
+use Scalar::Util qw(blessed);
use namespace::autoclean;
# how this works:
};
*qualify_with = sub ($source, @names) {
- map join('.', $source->name, $_), @names;
+ my $name = blessed($source) ? $source->name : $source;
+ map join('.', $name, $_), @names;
};
*body_cols = sub ($source) {
$source->primary_columns;
};
- *name_of = *names_of = sub (@cols) { map $_->{name}, @cols };
+ *names_of = sub (@cols) { map $_->{name}, @cols };
*function_body = sub ($name, $args, $body_parts) {
my $arglist = join(
$function$ LANGUAGE plpgsql;
};
};
-
}
BEGIN {
*arg_hash = sub ($source) {
map +($_ => \(argify $_)), names_of body_cols $source;
};
+
+ *rule_body = sub ($on, $to, $oldlist, $newlist) {
+ my $arglist = join(', ',
+ (qualify_with 'OLD', names_of @$oldlist),
+ (qualify_with 'NEW', names_of @$newlist),
+ );
+ $to = $to->name if blessed($to);
+ return strip tt q{
+ CREATE RULE _[% to %]_[% on %]_rule AS
+ ON [% on | upper %] TO [% to %]
+ DO INSTEAD (
+ SELECT _[% to %]_[% on %]([% arglist %])
+ );
+ };
+ };
}
method root_table () {
push(@sources, $super_view) if defined($super_view);
my @body_cols = map body_cols($_), @sources;
my @pk_cols = pk_cols $self;
+
+ # SELECT statement
+
my $select = $sqla->select(
($super_view
? ([ # FROM _tbl _tbl
: ($table->name)),
[ (qualify_with $table, names_of @pk_cols), names_of @body_cols ],
).';';
+
my ($now, $next) = grep defined, $super_view, $table;
+
+ # INSERT function
+
# 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 =
: ()
)
];
+
# 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
};
+
+ # UPDATE function
+
my $update_func =
function_body
$self->name.'_update',
$pk_where,
), @sources
];
+
+ # DELETE function
+
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);
+
+ my @rules = (
+ (rule_body insert => $self, [], \@body_cols),
+ (rule_body update => $self, \@pk_cols, \@body_cols),
+ (rule_body delete => $self, \@pk_cols, []),
+ );
+ return join("\n\n", $select, $insert_func, $update_func, $delete_func, @rules);
}
1;