-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsuggest.cgi
More file actions
executable file
·153 lines (130 loc) · 3.86 KB
/
Copy pathsuggest.cgi
File metadata and controls
executable file
·153 lines (130 loc) · 3.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use CGI qw(:standard);
use DBI;
use DBD::SQLite ();
binmode(STDOUT, ':encoding(UTF-8)');
my $DB_FILE = '/var/www/data/panels.db';
my $q = CGI->new;
my $type = lc($q->param('type') // '');
my $query = $q->param('q') // '';
my $limit = $q->param('limit') // 30;
$query =~ s/^\s+|\s+$//g;
$limit = 30 if $limit !~ /^\d+$/;
$limit = 100 if $limit > 100;
# JSON output
print $q->header(-type => 'application/json', -charset => 'utf-8');
sub json_escape {
my ($s) = @_;
$s //= '';
$s =~ s/\\/\\\\/g;
$s =~ s/"/\\"/g;
$s =~ s/\r/\\r/g;
$s =~ s/\n/\\n/g;
$s =~ s/\t/\\t/g;
return $s;
}
sub emit_json {
my (@items) = @_;
my $arr = join(",", map { '"' . json_escape($_) . '"' } @items);
print qq|{"items":[${arr}]}|;
}
if ($query eq '') { emit_json(); exit; }
my $dbh = DBI->connect(
"dbi:SQLite:dbname=$DB_FILE", "", "",
{
RaiseError => 1,
sqlite_unicode => 1,
AutoCommit => 1,
ReadOnly => 1,
sqlite_open_flags => DBD::SQLite::OPEN_READONLY(),
}
) or do { emit_json(); exit; };
my @items;
if ($type eq 'gene') {
# gene: prefix match (case-sensitivity depends on SQLite LIKE; ASCII names are fine)
my $sth = $dbh->prepare(<<'SQL');
SELECT gene
FROM variants
WHERE gene IS NOT NULL AND TRIM(gene) != ''
AND gene LIKE ?
GROUP BY gene
ORDER BY gene
LIMIT ?
SQL
$sth->execute($query . "%", $limit);
while (my ($v) = $sth->fetchrow_array) { push @items, $v; }
$sth->finish;
} elsif ($type eq 'protein') {
# protein: tolerate optional "p." prefix and collect candidates broadly
my $norm = $query;
$norm =~ s/^\s*p\.?\s*//i; # strip leading 'p.' / 'p' prefix
$norm =~ s/\s+//g;
my @patterns;
push @patterns, $query . "%";
push @patterns, $norm . "%";
push @patterns, "p." . $norm . "%";
push @patterns, "p" . $norm . "%";
my %seen; @patterns = grep { !$seen{$_}++ } @patterns;
my $or = join(" OR ", map { "protein_effect LIKE ?" } @patterns);
my $sql = "SELECT protein_effect
FROM variants
WHERE protein_effect IS NOT NULL AND TRIM(protein_effect) != ''
AND ($or)
GROUP BY protein_effect
ORDER BY protein_effect
LIMIT ?";
my $sth = $dbh->prepare($sql);
$sth->execute(@patterns, $limit);
while (my ($v) = $sth->fetchrow_array) { push @items, $v; }
$sth->finish;
} elsif ($type eq 'disease') {
# disease: collect candidates from three case columns (prefix first, also substring)
my $pat_prefix = $query . "%";
my $pat_like = "%" . $query . "%";
my $sql = <<'SQL';
SELECT val FROM (
SELECT disease AS val, 1 AS pri
FROM cases
WHERE disease IS NOT NULL AND TRIM(disease) != '' AND disease LIKE ?
UNION
SELECT tissue_of_origin AS val, 1 AS pri
FROM cases
WHERE tissue_of_origin IS NOT NULL AND TRIM(tissue_of_origin) != '' AND tissue_of_origin LIKE ?
UNION
SELECT pathology_diagnosis AS val, 1 AS pri
FROM cases
WHERE pathology_diagnosis IS NOT NULL AND TRIM(pathology_diagnosis) != '' AND pathology_diagnosis LIKE ?
UNION
SELECT disease AS val, 2 AS pri
FROM cases
WHERE disease IS NOT NULL AND TRIM(disease) != '' AND disease LIKE ?
UNION
SELECT tissue_of_origin AS val, 2 AS pri
FROM cases
WHERE tissue_of_origin IS NOT NULL AND TRIM(tissue_of_origin) != '' AND tissue_of_origin LIKE ?
UNION
SELECT pathology_diagnosis AS val, 2 AS pri
FROM cases
WHERE pathology_diagnosis IS NOT NULL AND TRIM(pathology_diagnosis) != '' AND pathology_diagnosis LIKE ?
)
GROUP BY val
ORDER BY pri, val
LIMIT ?
SQL
my $sth = $dbh->prepare($sql);
$sth->execute($pat_prefix, $pat_prefix, $pat_prefix,
$pat_like, $pat_like, $pat_like,
$limit);
while (my ($v) = $sth->fetchrow_array) { push @items, $v; }
$sth->finish;
} else {
# unknown type
$dbh->disconnect;
emit_json();
exit;
}
$dbh->disconnect;
emit_json(@items);