line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Class::ReluctantORM::SchemaCache; |
2
|
1
|
|
|
1
|
|
6
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
37
|
|
3
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
50
|
|
4
|
|
|
|
|
|
|
our $SCHEMA_CACHE; |
5
|
|
|
|
|
|
|
our $DEBUG = 0; |
6
|
|
|
|
|
|
|
|
7
|
1
|
|
|
1
|
|
6
|
use Carp; |
|
1
|
|
|
|
|
98
|
|
|
1
|
|
|
|
|
74
|
|
8
|
1
|
|
|
1
|
|
6
|
use Class::ReluctantORM::Utilities qw(conditional_load_subdir read_file write_file json_encode json_decode); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
149
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
our @POLICY_CLASSES; |
11
|
|
|
|
|
|
|
BEGIN { |
12
|
1
|
|
|
1
|
|
10
|
@POLICY_CLASSES = conditional_load_subdir(__PACKAGE__); |
13
|
|
|
|
|
|
|
} |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
=head2 @policy_names = Class::ReluctantORM::SchemaCache->policy_names() |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
Returns a list of available caching policies. |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=cut |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
sub policy_names { |
22
|
0
|
|
|
0
|
1
|
|
return map { s/Class::ReluctantORM::SchemaCache:://; $_ } @POLICY_CLASSES; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
} |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
=head2 $cache = Class::ReluctantORM::SchemaCache->instance(); |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
Returns a Class::ReluctantORM::SchemaCache object, implementing the policy specified by the Class::ReluctantORM global option schema_cache_policy. This is a singleton object. |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
=cut |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
sub instance { |
33
|
0
|
0
|
|
0
|
1
|
|
if ($SCHEMA_CACHE) { return $SCHEMA_CACHE; } |
|
0
|
|
|
|
|
|
|
34
|
0
|
|
|
|
|
|
my $class = 'Class::ReluctantORM::SchemaCache::' . Class::ReluctantORM->get_global_option('schema_cache_policy'); |
35
|
0
|
|
|
|
|
|
return $SCHEMA_CACHE = $class->new(); |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
=head2 $hashref = $cache->read_columns_for_table($namespace, $table_name); |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
Looks in the cache, and returns a hashref mapping lowercased column names to database-cased column names. If there is no hit, undef is returned. Pass an empty string if the database does not support namespaces. |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
=cut |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
sub read_columns_for_table { |
45
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
46
|
0
|
|
|
|
|
|
my ($namespace, $table_name) = @_; |
47
|
0
|
|
0
|
|
|
|
return $self->{__databag}{$namespace || '(none)'}{$table_name}{cols}; |
48
|
|
|
|
|
|
|
} |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=head2 $cache->store_columns_for_table($namespace, $table_name, $hashref); |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
Stores to the cache a hashref mapping lowercased column names to database-cased column names. The cache file is immediately updated. Pass an empty string if the database does not support namespaces. |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=cut |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
sub store_columns_for_table { |
57
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
58
|
0
|
|
|
|
|
|
my ($namespace, $table_name, $data) = @_; |
59
|
0
|
|
0
|
|
|
|
$self->{__databag}{$namespace || '(none)'}{$table_name}{cols} = $data; |
60
|
0
|
|
|
|
|
|
$self->write_cache_file(); |
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
=head2 $arrayref = $cache->read_primary_keys_for_table($namespace, $table_name); |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
Looks in the cache, and returns an arrayref listing the lowercased column names of the primary key columns, if any, in the order reported by the database. If there is no hit, undef is returned. Pass an empty string if the database does not support namespaces. |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=cut |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
sub read_primary_keys_for_table { |
70
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
71
|
0
|
|
|
|
|
|
my ($namespace, $table_name) = @_; |
72
|
0
|
|
0
|
|
|
|
return $self->{__databag}{$namespace || '(none)'}{$table_name}{pk}; |
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=head2 $cache->store_primary_keys_for_table($namespace, $table_name, $arrayref); |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
Stores to the cache an arrayref listing lowercased column names of the primary keys. The cache file is immediately updated. Pass an empty string if the database does not support namespaces. |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
=cut |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
sub store_primary_keys_for_table { |
82
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
83
|
0
|
|
|
|
|
|
my ($namespace, $table_name, $data) = @_; |
84
|
0
|
|
0
|
|
|
|
$self->{__databag}{$namespace || '(none)'}{$table_name}{pk} = $data; |
85
|
0
|
|
|
|
|
|
$self->write_cache_file(); |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
=head2 $cache->clear(); |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
Clears the cache by deleting the cache file. |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
=cut |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
sub clear { |
95
|
0
|
|
|
0
|
1
|
|
my $cache = shift; |
96
|
0
|
|
|
|
|
|
my $filename = Class::ReluctantORM->get_global_option('schema_cache_file'); |
97
|
0
|
0
|
0
|
|
|
|
if ($filename && -e $filename) { |
98
|
0
|
0
|
|
|
|
|
unless (unlink ($filename)) { |
99
|
0
|
|
|
|
|
|
carp ("Could not delete $filename to clear schema cache"); |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
sub databag { |
105
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
106
|
0
|
|
|
|
|
|
return $self->{__databag}; |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub read_cache_file { |
110
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
111
|
0
|
|
|
|
|
|
my $filename = Class::ReluctantORM->get_global_option('schema_cache_file'); |
112
|
|
|
|
|
|
|
|
113
|
0
|
0
|
0
|
|
|
|
unless ($filename && -e $filename) { |
114
|
|
|
|
|
|
|
# No cache file; treat all as misses |
115
|
0
|
|
|
|
|
|
$self->{__databag} = {}; |
116
|
0
|
|
|
|
|
|
return; |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
0
|
|
|
|
|
|
my $raw = read_file($filename); |
120
|
0
|
|
|
|
|
|
$self->{__databag} = json_decode($raw); |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
sub write_cache_file { |
124
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
125
|
0
|
|
|
|
|
|
my $filename = Class::ReluctantORM->get_global_option('schema_cache_file'); |
126
|
0
|
0
|
|
|
|
|
return unless $filename; |
127
|
|
|
|
|
|
|
|
128
|
0
|
|
|
|
|
|
my $raw = json_encode($self->{__databag}); |
129
|
|
|
|
|
|
|
|
130
|
0
|
|
|
|
|
|
write_file($filename, $raw); |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=head2 $cache->notify_sql_error($@) |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
Informs the cache that an error has occurred. It may or may not be schema-cache related. |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
Default does nothing. |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=cut |
141
|
|
|
|
|
|
|
|
142
|
0
|
|
|
0
|
1
|
|
sub notify_sql_error { } |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
1; |