line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Hailo::Storage::Schema; |
2
|
|
|
|
|
|
|
our $AUTHORITY = 'cpan:AVAR'; |
3
|
|
|
|
|
|
|
$Hailo::Storage::Schema::VERSION = '0.75'; |
4
|
29
|
|
|
29
|
|
373
|
use v5.10.0; |
|
29
|
|
|
|
|
110
|
|
5
|
29
|
|
|
29
|
|
156
|
use strict; |
|
29
|
|
|
|
|
72
|
|
|
29
|
|
|
|
|
24870
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
## Soup to spawn the database itself / create statement handles |
8
|
|
|
|
|
|
|
sub deploy { |
9
|
42
|
|
|
42
|
0
|
155
|
my (undef, $dbd, $dbh, $order) = @_; |
10
|
42
|
|
|
|
|
196
|
my @orders = (0 .. $order-1); |
11
|
|
|
|
|
|
|
|
12
|
42
|
|
|
|
|
151
|
my $int_primary_key = "INTEGER PRIMARY KEY AUTOINCREMENT"; |
13
|
42
|
50
|
|
|
|
164
|
$int_primary_key = "INTEGER PRIMARY KEY AUTO_INCREMENT" if $dbd eq "mysql"; |
14
|
42
|
50
|
|
|
|
123
|
$int_primary_key = "SERIAL UNIQUE" if $dbd eq "Pg"; |
15
|
|
|
|
|
|
|
|
16
|
42
|
|
|
|
|
90
|
my $text = 'TEXT'; |
17
|
42
|
50
|
|
|
|
157
|
$text = 'VARCHAR(255)' if $dbd eq 'mysql'; |
18
|
|
|
|
|
|
|
|
19
|
42
|
|
|
|
|
96
|
my $text_primary = 'TEXT NOT NULL PRIMARY KEY'; |
20
|
42
|
50
|
|
|
|
126
|
$text_primary = 'TEXT NOT NULL' if $dbd eq 'mysql'; |
21
|
|
|
|
|
|
|
|
22
|
42
|
|
|
|
|
91
|
my @tables; |
23
|
|
|
|
|
|
|
|
24
|
42
|
|
|
|
|
171
|
push @tables => <<"TABLE"; |
25
|
|
|
|
|
|
|
CREATE TABLE info ( |
26
|
|
|
|
|
|
|
attribute $text_primary, |
27
|
|
|
|
|
|
|
text TEXT NOT NULL |
28
|
|
|
|
|
|
|
); |
29
|
|
|
|
|
|
|
TABLE |
30
|
|
|
|
|
|
|
|
31
|
42
|
|
|
|
|
190
|
push @tables => <<"TABLE"; |
32
|
|
|
|
|
|
|
CREATE TABLE token ( |
33
|
|
|
|
|
|
|
id $int_primary_key, |
34
|
|
|
|
|
|
|
spacing INTEGER NOT NULL, |
35
|
|
|
|
|
|
|
text $text NOT NULL, |
36
|
|
|
|
|
|
|
count INTEGER NOT NULL |
37
|
|
|
|
|
|
|
); |
38
|
|
|
|
|
|
|
TABLE |
39
|
|
|
|
|
|
|
|
40
|
42
|
|
|
|
|
140
|
my $token_n = join ",\n ", map { "token${_}_id INTEGER NOT NULL REFERENCES token (id)" } @orders; |
|
85
|
|
|
|
|
408
|
|
41
|
42
|
|
|
|
|
184
|
push @tables => <<"TABLE"; |
42
|
|
|
|
|
|
|
CREATE TABLE expr ( |
43
|
|
|
|
|
|
|
id $int_primary_key, |
44
|
|
|
|
|
|
|
$token_n |
45
|
|
|
|
|
|
|
); |
46
|
|
|
|
|
|
|
TABLE |
47
|
|
|
|
|
|
|
|
48
|
42
|
|
|
|
|
137
|
push @tables => <<"TABLE"; |
49
|
|
|
|
|
|
|
CREATE TABLE next_token ( |
50
|
|
|
|
|
|
|
id $int_primary_key, |
51
|
|
|
|
|
|
|
expr_id INTEGER NOT NULL REFERENCES expr (id), |
52
|
|
|
|
|
|
|
token_id INTEGER NOT NULL REFERENCES token (id), |
53
|
|
|
|
|
|
|
count INTEGER NOT NULL |
54
|
|
|
|
|
|
|
); |
55
|
|
|
|
|
|
|
TABLE |
56
|
|
|
|
|
|
|
|
57
|
42
|
|
|
|
|
148
|
push @tables => <<"TABLE"; |
58
|
|
|
|
|
|
|
CREATE TABLE prev_token ( |
59
|
|
|
|
|
|
|
id $int_primary_key, |
60
|
|
|
|
|
|
|
expr_id INTEGER NOT NULL REFERENCES expr (id), |
61
|
|
|
|
|
|
|
token_id INTEGER NOT NULL REFERENCES token (id), |
62
|
|
|
|
|
|
|
count INTEGER NOT NULL |
63
|
|
|
|
|
|
|
); |
64
|
|
|
|
|
|
|
TABLE |
65
|
|
|
|
|
|
|
|
66
|
42
|
|
|
|
|
160
|
for my $i (@orders) { |
67
|
85
|
|
|
|
|
282
|
push @tables => "CREATE INDEX expr_token${i}_id on expr (token${i}_id);" |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
|
70
|
42
|
|
|
|
|
130
|
my $columns = join(', ', map { "token${_}_id" } @orders); |
|
85
|
|
|
|
|
262
|
|
71
|
42
|
|
|
|
|
146
|
push @tables => "CREATE INDEX expr_token_ids on expr ($columns);"; |
72
|
|
|
|
|
|
|
|
73
|
42
|
|
|
|
|
98
|
push @tables => 'CREATE INDEX token_text on token (text);'; |
74
|
42
|
|
|
|
|
128
|
push @tables => 'CREATE INDEX next_token_expr_id ON next_token (expr_id);'; |
75
|
42
|
|
|
|
|
90
|
push @tables => 'CREATE INDEX prev_token_expr_id ON prev_token (expr_id);'; |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
|
78
|
42
|
|
|
|
|
118
|
for (@tables) { |
79
|
463
|
|
|
|
|
85302
|
$dbh->do($_); |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
42
|
|
|
|
|
7441
|
return; |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
# create statement handle objects |
86
|
|
|
|
|
|
|
sub sth { |
87
|
50
|
|
|
50
|
0
|
262
|
my (undef, $dbd, $dbh, $order) = @_; |
88
|
50
|
|
|
|
|
211
|
my @orders = (0 .. $order-1); |
89
|
50
|
|
|
|
|
174
|
my @columns = map { "token${_}_id" } 0 .. $order-1; |
|
103
|
|
|
|
|
379
|
|
90
|
50
|
|
|
|
|
204
|
my $columns = join(', ', @columns); |
91
|
50
|
|
|
|
|
224
|
my @ids = join(', ', ('?') x @columns); |
92
|
50
|
|
|
|
|
181
|
my $ids = join(', ', @ids); |
93
|
|
|
|
|
|
|
|
94
|
50
|
|
|
|
|
106
|
my $q_rand = 'RANDOM()'; |
95
|
50
|
50
|
|
|
|
172
|
$q_rand = 'RAND()' if $dbd eq 'mysql'; |
96
|
|
|
|
|
|
|
|
97
|
50
|
|
|
|
|
150
|
my $q_rand_id = "(abs($q_rand) % (SELECT max(id) FROM expr))"; |
98
|
50
|
50
|
|
|
|
171
|
$q_rand_id = "(random()*id+1)::int" if $dbd eq 'Pg'; |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
my %state = ( |
101
|
|
|
|
|
|
|
set_info => qq[INSERT INTO info (attribute, text) VALUES (?, ?);], |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
random_expr => qq[SELECT * FROM expr WHERE id >= $q_rand_id LIMIT 1;], |
104
|
|
|
|
|
|
|
token_resolve => qq[SELECT id, count FROM token WHERE spacing = ? AND text = ?;], |
105
|
|
|
|
|
|
|
token_id => qq[SELECT id FROM token WHERE spacing = ? AND text = ?;], |
106
|
|
|
|
|
|
|
token_info => qq[SELECT spacing, text FROM token WHERE id = ?;], |
107
|
|
|
|
|
|
|
token_similar => qq[SELECT id, spacing, count FROM token WHERE text = ? ORDER BY $q_rand LIMIT 1;] , |
108
|
|
|
|
|
|
|
add_token => qq[INSERT INTO token (spacing, text, count) VALUES (?, ?, 0)], |
109
|
|
|
|
|
|
|
inc_token_count => qq[UPDATE token SET count = count + ? WHERE id = ?], |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
# ->stats() |
112
|
|
|
|
|
|
|
expr_total => qq[SELECT COUNT(*) FROM expr;], |
113
|
|
|
|
|
|
|
token_total => qq[SELECT COUNT(*) FROM token;], |
114
|
|
|
|
|
|
|
prev_total => qq[SELECT COUNT(*) FROM prev_token;], |
115
|
|
|
|
|
|
|
next_total => qq[SELECT COUNT(*) FROM next_token;], |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
# Defaults, overriden in SQLite |
118
|
|
|
|
|
|
|
last_expr_rowid => qq[SELECT id FROM expr ORDER BY id DESC LIMIT 1;], |
119
|
|
|
|
|
|
|
last_token_rowid => qq[SELECT id FROM token ORDER BY id DESC LIMIT 1;], |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
token_count => qq[SELECT count FROM token WHERE id = ?;], |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
add_expr => qq[INSERT INTO expr ($columns) VALUES ($ids)], |
124
|
50
|
|
|
|
|
358
|
expr_id => qq[SELECT id FROM expr WHERE ] . join(' AND ', map { "token${_}_id = ?" } @orders), |
|
103
|
|
|
|
|
1114
|
|
125
|
|
|
|
|
|
|
); |
126
|
|
|
|
|
|
|
|
127
|
50
|
|
|
|
|
201
|
for my $table (qw(next_token prev_token)) { |
128
|
|
|
|
|
|
|
$state{"${table}_links"} = qq[SELECT SUM(count) FROM $table WHERE expr_id = ?;], |
129
|
|
|
|
|
|
|
$state{"${table}_count"} = qq[SELECT count FROM $table WHERE expr_id = ? AND token_id = ?;], |
130
|
|
|
|
|
|
|
$state{"${table}_inc"} = qq[UPDATE $table SET count = count + ? WHERE expr_id = ? AND token_id = ?], |
131
|
|
|
|
|
|
|
$state{"${table}_add"} = qq[INSERT INTO $table (expr_id, token_id, count) VALUES (?, ?, ?);], |
132
|
100
|
|
|
|
|
1077
|
$state{"${table}_get"} = qq[SELECT token_id, count FROM $table WHERE expr_id = ?;], |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
|
135
|
50
|
|
|
|
|
162
|
for (@orders) { |
136
|
103
|
|
|
|
|
449
|
$state{"expr_by_token${_}_id"} = qq[SELECT * FROM expr WHERE token${_}_id = ? ORDER BY $q_rand LIMIT 1;]; |
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
# DBD specific queries / optimizations / munging |
140
|
50
|
50
|
|
|
|
230
|
if ($dbd eq 'SQLite') { |
141
|
|
|
|
|
|
|
# Optimize these for SQLite |
142
|
50
|
|
|
|
|
143
|
$state{expr_total} = qq[SELECT seq FROM sqlite_sequence WHERE name = 'expr';]; |
143
|
50
|
|
|
|
|
133
|
$state{token_total} = qq[SELECT seq FROM sqlite_sequence WHERE name = 'token';]; |
144
|
50
|
|
|
|
|
105
|
$state{prev_total} = qq[SELECT seq FROM sqlite_sequence WHERE name = 'prev_token';]; |
145
|
50
|
|
|
|
|
110
|
$state{next_total} = qq[SELECT seq FROM sqlite_sequence WHERE name = 'next_token';]; |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
# Sort to make error output easier to read if this fails. The |
149
|
|
|
|
|
|
|
# order doesn't matter. |
150
|
50
|
|
|
|
|
982
|
my @queries = sort keys %state; |
151
|
50
|
|
|
|
|
207
|
my %sth = map { $_ => $dbh->prepare($state{$_}) } @queries; |
|
1453
|
|
|
|
|
91057
|
|
152
|
|
|
|
|
|
|
|
153
|
50
|
|
|
|
|
5650
|
return \%sth; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
1; |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=head1 NAME |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
Hailo::Storage::Schema - Deploy the database schema Hailo uses |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
=head1 DESCRIPTION |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
Implements functions to create the database schema and prepared |
165
|
|
|
|
|
|
|
database queries L<Hailo::Storage> needs. |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
This class is internal to Hailo and has no public interface. |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
=head1 AUTHOR |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason <avar@cpan.org> |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
=head1 LICENSE AND COPYRIGHT |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
Copyright 2010 E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
This program is free software, you can redistribute it and/or modify |
178
|
|
|
|
|
|
|
it under the same terms as Perl itself. |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
=cut |