151 lines
4.8 KiB
Perl
151 lines
4.8 KiB
Perl
#!/usr/bin/perl
|
|
# CustIS Bug 61728 - external SQL interface to Bugzilla's bug tables
|
|
|
|
package FlushViews;
|
|
|
|
use strict;
|
|
use Bugzilla::User;
|
|
use Bugzilla::Search;
|
|
|
|
our @ISA = qw(Exporter);
|
|
our @EXPORT = qw(refresh_views);
|
|
|
|
sub refresh_views
|
|
{
|
|
refresh_some_views();
|
|
return 1;
|
|
}
|
|
|
|
# MySQL has a limitation on views! :-(
|
|
# Views in MySQL cannot include a subquery in the FROM clause.
|
|
# We bypass it by creating a view for every such subquery.
|
|
sub recurse_create_view
|
|
{
|
|
my ($dbh, $name, $sql, $index) = @_;
|
|
# We need recursive regular expressions, available from Perl 5.10.0
|
|
require 5.010;
|
|
my $myname = $name;
|
|
if (!$index)
|
|
{
|
|
my $i = 0;
|
|
$index = \$i;
|
|
}
|
|
else
|
|
{
|
|
$myname .= '_'.$$index;
|
|
}
|
|
# Match and replace subqueries in the FROM part of the query
|
|
$sql =~ s/(FROM|JOIN) \s* \(\s* SELECT((?:
|
|
[^\(\)\"\'\\]+ |
|
|
\"(?:(?:[^\"\\]+|\\[\"\\])*)\" |
|
|
\'(?:(?:[^\'\\]+|\\[\'\\])*)\' |
|
|
\( (?2) \)
|
|
)+) \)/($$index++), "$1 ".recurse_create_view($dbh, $name, "SELECT$2", $index)/gexiso;
|
|
$dbh->do("DROP VIEW IF EXISTS $myname");
|
|
$dbh->do("CREATE SQL SECURITY DEFINER VIEW $myname AS $sql");
|
|
return $myname;
|
|
}
|
|
|
|
# Refresh views, optionally only for $users = [ 'username@domain.org', ... ]
|
|
sub refresh_some_views
|
|
{
|
|
my ($users) = @_;
|
|
my %u;
|
|
for (@{$users || []})
|
|
{
|
|
$_ = lc $_;
|
|
s/[^a-z0-9]+/_/giso;
|
|
$_ = "_$_" if !/^[a-z]/;
|
|
$u{$_} = 1;
|
|
}
|
|
my $dbh = Bugzilla->dbh;
|
|
my $r = $dbh->real_table_list('view$%$bugs', 'VIEW');
|
|
# Save current user
|
|
my $old_user = Bugzilla->user;
|
|
for (@$r)
|
|
{
|
|
# Determine user
|
|
my (undef, $user, $query) = split /\$/, $_, -1;
|
|
!%u || $u{$user} or next;
|
|
my $q = $user;
|
|
$q =~ tr/_/%/;
|
|
my ($userid) = $dbh->selectrow_array('SELECT userid FROM profiles WHERE login_name LIKE ? ORDER BY userid LIMIT 1', undef, $q.'@%');
|
|
$userid or next;
|
|
my $userobj = Bugzilla::User->new($userid) or next;
|
|
# Modify current user (hack)
|
|
Bugzilla->request_cache->{user} = $userobj;
|
|
# Determine saved search
|
|
$q = $query;
|
|
$q =~ tr/_/%/;
|
|
($q) = $dbh->selectrow_array('SELECT name FROM namedqueries WHERE userid=? AND name LIKE ? LIMIT 1', undef, $userid, $q);
|
|
$q or next;
|
|
my $storedquery = Bugzilla::Search::LookupNamedQuery($q, $userid, 0) or next;
|
|
$storedquery = http_decode_query($storedquery);
|
|
# get SQL code
|
|
my $search = new Bugzilla::Search(
|
|
params => $storedquery,
|
|
fields => [ 'bug_id', grep { $_ ne 'bug_id' } split(/[ ,]+/, $storedquery->{columnlist} || '') ],
|
|
user => $userobj,
|
|
) or next;
|
|
# Re-create views
|
|
my $drop = "DROP VIEW IF EXISTS view\$$user\$$query\$";
|
|
my $create = "CREATE VIEW view\$$user\$$query\$";
|
|
my $bugid_query = $search->bugid_query;
|
|
my $bugids = "view\$$user\$$query\$bugids";
|
|
if ($dbh->isa('Bugzilla::DB::Mysql'))
|
|
{
|
|
$create = "CREATE SQL SECURITY DEFINER VIEW view\$$user\$$query\$";
|
|
recurse_create_view($dbh, $bugids, $bugid_query);
|
|
}
|
|
else
|
|
{
|
|
$dbh->do($drop.'bugids');
|
|
$dbh->do("CREATE VIEW $bugids AS $bugid_query");
|
|
}
|
|
my $sql = $search->getSQL;
|
|
$sql =~ s/\(\s*\Q$bugid_query\E\s*\)/$bugids/s;
|
|
$dbh->do($drop.'bugs');
|
|
$dbh->do($drop.'longdescs');
|
|
$dbh->do($drop.'bugs_activity');
|
|
$dbh->do($drop.'scrum_cards');
|
|
$dbh->do($create.'bugs AS '.$sql);
|
|
$dbh->do($create.'longdescs AS SELECT l.bug_id, u.login_name, l.bug_when, l.thetext, l.work_time FROM longdescs l INNER JOIN '.$bugids.' b ON b.bug_id=l.bug_id INNER JOIN profiles u ON u.userid=l.who'.($userobj->is_insider?'':' WHERE l.isprivate=0'));
|
|
$dbh->do($create.'bugs_activity AS SELECT a.bug_id, u.login_name, a.bug_when, f.name field_name, a.removed, a.added FROM bugs_activity a INNER JOIN '.$bugids.' b ON b.bug_id=a.bug_id INNER JOIN profiles u ON u.userid=a.who INNER JOIN fielddefs f ON f.id=a.fieldid');
|
|
$dbh->do($create.'scrum_cards AS SELECT s.* FROM scrum_cards s INNER JOIN '.$bugids.' b ON b.bug_id=s.bug_id');
|
|
}
|
|
# Restore current user
|
|
Bugzilla->request_cache->{user} = $old_user;
|
|
}
|
|
|
|
# hooks:
|
|
sub savedsearch_post_update
|
|
{
|
|
my ($args) = @_;
|
|
my $name = $args->{search}->user->login;
|
|
$name =~ s/\@.*$//so;
|
|
refresh_some_views([ $name ]);
|
|
return 1;
|
|
}
|
|
|
|
sub editusers_post_update_delete
|
|
{
|
|
my ($args) = @_;
|
|
my $name = $args->{userid};
|
|
if ($name)
|
|
{
|
|
$name = user_id_to_login($name);
|
|
$name =~ s/\@.*$//so;
|
|
refresh_some_views([ $name ]);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
sub install_before_final_checks
|
|
{
|
|
print "Refreshing Views...\n";
|
|
refresh_views();
|
|
}
|
|
|
|
1;
|
|
__END__
|