-
-
Notifications
You must be signed in to change notification settings - Fork 27
/
Cache.pm6
103 lines (85 loc) · 3.15 KB
/
Cache.pm6
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
use v6.d;
use Red::Database;
use Red::Driver;
use Red::AST;
use Red::AST::Select;
use Red::AST::Infix;
use Red::AST::Value;
use Red::AST::LastInsertedRow;
use Red::Statement;
unit role Red::Driver::Cache does Red::Driver;
method schema-reader {}
proto cache($, $) is export { * }
multi cache(Str $cache, Str $driver) {
cache $cache => \(), $driver => \()
}
multi cache(Pair $cache-pair, Str $driver) {
cache $cache-pair, $driver => \()
}
multi cache(Str $cache, Pair $driver-pair) {
cache $cache => \(), $driver-pair
}
multi cache(Str $cache, Red::Driver $driver) {
cache $cache => \(), $driver
}
multi cache(Pair (Str :key($cache-driver), Capture :value($cache-conf)), Red::Driver $driver) {
my $cache = "Red::Driver::Cache::$cache-driver";
require ::($cache);
::($cache).new: :$driver, |$cache-conf
}
multi cache(
Pair (Str :key($cache-driver), Capture :value($cache-conf)),
Pair (Str :key($driver-name), Capture :value($driver-conf))
) is export {
my $driver = database $driver-name, |$driver-conf;
my $cache = "Red::Driver::Cache::$cache-driver";
require ::($cache);
::($cache).new: :$driver, |$cache-conf
}
multi method get-from-cache(Red::AST) { ... }
multi method set-on-cache(Red::AST, @) { ... }
has Red::Driver $.driver is required;
multi method default-type-for(Red::Column $a --> Str:D) { $!driver.default-type-for($a) }
multi method is-valid-table-name(|c) { $!driver.is-valid-table-name(|c) }
multi method type-by-name(|c) { $!driver.type-by-name(|c) }
multi method inflate(|c) { $!driver.inflate(|c) }
multi method deflate(|c) { $!driver.deflate(|c) }
multi method prepare(Str $_) { $!driver.prepare($_) }
multi method translate(Red::AST $ast, $context?) { $!driver.translate($ast, $context) }
my class CachedStatement does Red::Statement {
has Red::AST $.ast is required;
has Iterator $.iterator is required;
method stt-exec($stt, *@bind) { }
method stt-row($stt) { $!iterator.pull-one }
}
my class Statement does Red::Statement {
has Red::AST $.ast is required;
has Red::Statement $.stt is required;
has Iterator $.iterator;
method stt-exec($stt, *@bind) {
my @data;
$!stt.stt-exec: $!stt, |@bind;
while my $row = $!stt.row {
@data.push: $row
}
note "setting data on cache" if $*RED-CACHE-DEBUG;
$!driver.set-on-cache: $!ast, @data;
$!iterator = @data.iterator
}
method stt-row($stt) { $!iterator.pull-one }
}
multi method prepare(Red::AST::Select $ast ) {
CATCH {
default {
return $!driver.prepare: $ast
}
}
with self.get-from-cache: $ast {
PRE .^can: "iterator";
note "getting data from cache" if $*RED-CACHE-DEBUG;
return CachedStatement.new: :driver(self), :iterator(.iterator), :$ast
}
do for $!driver.prepare: $ast -> $stt {
Statement.new: :driver(self), :$stt, :$ast
}
}