DBIx-Custom / lib / DBI / Custom.pm /
Newer Older
309 lines | 6.356kb
first commit
yuki-kimoto authored on 2009-10-13
1
package DBI::Custom;
2
use Object::Simple;
add test
yuki-kimoto authored on 2009-10-16
3

            
4
our $VERSION = '0.0101';
5

            
6
use Carp 'croak';
add some method
yuki-kimoto authored on 2009-10-14
7
use DBI;
first commit
yuki-kimoto authored on 2009-10-13
8

            
cleanup
yuki-kimoto authored on 2009-10-15
9
# Model
10
sub model : ClassAttr { auto_build => \&_inherit_model }
first commit
yuki-kimoto authored on 2009-10-13
11

            
cleanup
yuki-kimoto authored on 2009-10-15
12
# Inherit super class model
13
sub _inherit_model {
add test
yuki-kimoto authored on 2009-10-16
14
    my $class = shift;
cleanup
yuki-kimoto authored on 2009-10-15
15
    my $super = do {
16
        no strict 'refs';
17
        ${"${class}::ISA"}[0];
18
    };
19
    my $model = eval{$super->can('model')}
20
                         ? $super->model->clone
21
                         : $class->Object::Simple::new;
cleanup
yuki-kimoto authored on 2009-10-14
22
    
23
    $class->model($model);
first commit
yuki-kimoto authored on 2009-10-13
24
}
25

            
cleanup
yuki-kimoto authored on 2009-10-15
26
# New
27
sub new {
28
    my $self = shift->Object::Simple::new(@_);
29
    my $class = ref $self;
30
    return bless {%{$class->model->clone}, %{$self}}, $class;
first commit
yuki-kimoto authored on 2009-10-13
31
}
32

            
cleanup
yuki-kimoto authored on 2009-10-15
33
# Initialize modle
34
sub initialize_model {
35
    my ($class, $callback) = @_;
first commit
yuki-kimoto authored on 2009-10-13
36
    
cleanup
yuki-kimoto authored on 2009-10-15
37
    # Callback to initialize model
38
    $callback->($class->model);
first commit
yuki-kimoto authored on 2009-10-13
39
}
40

            
cleanup
yuki-kimoto authored on 2009-10-15
41
# Clone
42
sub clone {
cleanup
yuki-kimoto authored on 2009-10-14
43
    my $self = shift;
cleanup
yuki-kimoto authored on 2009-10-15
44
    my $new = $self->Object::Simple::new;
add test
yuki-kimoto authored on 2009-10-16
45
    $new->connect_info(%{$self->connect_info || {}});
cleanup
yuki-kimoto authored on 2009-10-15
46
    $new->filters(%{$self->filters || {}});
add test
yuki-kimoto authored on 2009-10-16
47
    $new->bind_filter($self->bind_filter);
48
    $new->fetch_filter($self->fetch_filter);
cleanup
yuki-kimoto authored on 2009-10-14
49
}
50

            
cleanup
yuki-kimoto authored on 2009-10-15
51
# Attribute
52
sub connect_info       : Attr { type => 'hash',  auto_build => sub { shift->connect_info({}) } }
cleanup
yuki-kimoto authored on 2009-10-15
53

            
add test
yuki-kimoto authored on 2009-10-16
54
sub bind_filter : Attr {}
55
sub fetch_filter : Attr {}
cleanup
yuki-kimoto authored on 2009-10-15
56

            
add test
yuki-kimoto authored on 2009-10-16
57
sub filters : Attr { type => 'hash', deref => 1, auto_build => sub { shift->filters({}) } }
cleanup
yuki-kimoto authored on 2009-10-15
58
sub add_filter { shift->filters(@_) }
59

            
cleanup
yuki-kimoto authored on 2009-10-15
60
sub dbh          : Attr { auto_build => sub { shift->connect } }
add test
yuki-kimoto authored on 2009-10-17
61
sub sql_template : Attr { auto_build => sub { shift->sql_template(DBI::Custom::SQLTemplate->new) } }
add test
yuki-kimoto authored on 2009-10-16
62

            
63
our %VALID_CONNECT_INFO = map {$_ => 1} qw/data_source user password options/;
cleanup
yuki-kimoto authored on 2009-10-14
64

            
add some method
yuki-kimoto authored on 2009-10-14
65
sub connect {
66
    my $self = shift;
67
    my $connect_info = $self->connect_info;
68
    
add test
yuki-kimoto authored on 2009-10-16
69
    foreach my $key (keys %{$self->connect_info}) {
add test
yuki-kimoto authored on 2009-10-17
70
        croak("connect_info '$key' is invald")
71
          unless $VALID_CONNECT_INFO{$key};
add test
yuki-kimoto authored on 2009-10-16
72
    }
73
    
add some method
yuki-kimoto authored on 2009-10-14
74
    my $dbh = DBI->connect(
add test
yuki-kimoto authored on 2009-10-16
75
        $connect_info->{data_source},
add some method
yuki-kimoto authored on 2009-10-14
76
        $connect_info->{user},
77
        $connect_info->{password},
78
        {
79
            RaiseError => 1,
80
            PrintError => 0,
81
            AutoCommit => 1,
82
            %{$connect_info->{options} || {} }
83
        }
84
    );
85
    
86
    $self->dbh($dbh);
87
}
first commit
yuki-kimoto authored on 2009-10-13
88

            
add test
yuki-kimoto authored on 2009-10-17
89
sub create_sql {
90
    my $self = shift;
91
    
92
    my ($sql, @bind) = $self->sql_template->create_sql(@_);
93
    
94
    return ($sql, @bind);
95
}
96

            
add some method
yuki-kimoto authored on 2009-10-14
97
sub query {
try varioud way
yuki-kimoto authored on 2009-10-17
98
    my ($self, $template, $values, $filter)  = @_;
99
    
100
    $filter ||= $self->bind_filter;
101
    
102
    my ($sql, @bind) = $self->creqte_sql($template, $values, $filter);
add test
yuki-kimoto authored on 2009-10-17
103
    $self->prepare($sql);
104
    $self->execute(@bind);
105
}
106

            
107
sub query_raw_sql {
108
    my ($self, $sql, @bind) = @_;
109
    $self->prepare($sql);
110
    $self->execute(@bind);
111
}
112

            
113
Object::Simple->build_class;
114

            
115
package DBI::Custom::SQLTemplate;
116
use Object::Simple;
117

            
try varioud way
yuki-kimoto authored on 2009-10-17
118
### Attributes;
119
sub tag_start : Attr { default => '{' }
120
sub tag_end   : Attr { default => '}' }
121
sub template : Attr {};
122
sub tree     : Attr { auto_build => sub { shift->tree([]) } }
123

            
124

            
add test
yuki-kimoto authored on 2009-10-17
125
sub create_sql {
try varioud way
yuki-kimoto authored on 2009-10-17
126
    my ($self, $template, $values, $filter)  = @_;
127
    
128
    $self->parse($template);
129
    
130
    my ($sql, @bind);
131
    
132
    return ($sql, @bind);
133
}
134

            
135
our $TAG_SYNTAX = <<'EOS';
136
[tag]            [expand]
137
{= name}         name = ?
138
{!= name}        name != ?
139

            
140
{< name}         name < ?
141
{> name}         name > ?
142
{>= name}        name >= ?
143
{<= name}        name <= ?
144

            
145
{like name}      name like ?
146
{in name}        name in [?, ?, ..]
147

            
148
{insert_values}  (key1, key2, key3) values (?, ?, ?)
149
{update_values}  set key1 = ?, key2 = ?, key3 = ?
150
EOS
151

            
152
our %VALID_TAG_NAMES = map {$_ => 1} qw/=/;
153
sub parse {
154
    my ($self, $template) = @_;
155
    $self->template($template);
156
    
157
    # Clean start;
158
    delete $self->{tree};
159
    
160
    # Tags
161
    my $tag_start = quotemeta $self->tag_start;
162
    my $tag_end   = quotemeta $self->tag_end;
first commit
yuki-kimoto authored on 2009-10-13
163
    
try varioud way
yuki-kimoto authored on 2009-10-17
164
    # Tokenize
165
    my $state = 'text';
166
    
167
    # Save original template
168
    my $original_template = $template;
169
    
170
    # Text
171
    while ($template =~ s/([^$tag_start]*?)$tag_start([^$tag_end].*?)$tag_end//sm) {
172
        my $text          = $1;
173
        my $tag  = $2;
174
        
175
        push @{$self->tree}, ['text', $text] if $text;
176
        
177
        if ($tag) {
178
            
179
            my ($tag_name, @params) = split /\s+/, $tag;
180
            
181
            croak("Tag name is empty in '$tag'.\n" .
182
                  "Tag Syntax\n$TAG_SYNTAX.\n" .
183
                  "Your SQL template is \n$original_template")
184
              unless length $tag_name;
185
            
186
            croak("Tag name '$tag_name' in '$tag' is invalid.\n" .
187
                  "Tag Syntax\n$TAG_SYNTAX.\n" .
188
                  "Your SQL template is \n$original_template")
189
              unless $VALID_TAG_NAMES{$tag_name}; 
190
            
191
            push @{$self->tree}, [$tag_name, @params];
192
        }
193
    }
194
    
195
    push @{$self->tree}, ['text', $template] if $template;
first commit
yuki-kimoto authored on 2009-10-13
196
}
197

            
add test
yuki-kimoto authored on 2009-10-17
198

            
199

            
200

            
try varioud way
yuki-kimoto authored on 2009-10-17
201

            
202

            
203

            
204

            
first commit
yuki-kimoto authored on 2009-10-13
205
Object::Simple->build_class;
206

            
207
=head1 NAME
208

            
add test
yuki-kimoto authored on 2009-10-17
209
DBI::Custom - Customizable simple DBI
first commit
yuki-kimoto authored on 2009-10-13
210

            
211
=head1 VERSION
212

            
add test
yuki-kimoto authored on 2009-10-16
213
Version 0.0101
first commit
yuki-kimoto authored on 2009-10-13
214

            
215
=cut
216

            
217
=head1 SYNOPSIS
218

            
add test
yuki-kimoto authored on 2009-10-16
219
  my $dbi = DBI::Custom->new;
first commit
yuki-kimoto authored on 2009-10-13
220

            
add test
yuki-kimoto authored on 2009-10-16
221
=head1 METHODS
first commit
yuki-kimoto authored on 2009-10-13
222

            
add test
yuki-kimoto authored on 2009-10-16
223
=head2 add_filter
first commit
yuki-kimoto authored on 2009-10-13
224

            
add test
yuki-kimoto authored on 2009-10-16
225
=head2 bind_filter
first commit
yuki-kimoto authored on 2009-10-13
226

            
add test
yuki-kimoto authored on 2009-10-16
227
=head2 clone
first commit
yuki-kimoto authored on 2009-10-13
228

            
add test
yuki-kimoto authored on 2009-10-16
229
=head2 connect
first commit
yuki-kimoto authored on 2009-10-13
230

            
add test
yuki-kimoto authored on 2009-10-16
231
=head2 connect_info
first commit
yuki-kimoto authored on 2009-10-13
232

            
add test
yuki-kimoto authored on 2009-10-16
233
=head2 dbh
first commit
yuki-kimoto authored on 2009-10-13
234

            
add test
yuki-kimoto authored on 2009-10-16
235
=head2 fetch_filter
first commit
yuki-kimoto authored on 2009-10-13
236

            
add test
yuki-kimoto authored on 2009-10-16
237
=head2 filters
first commit
yuki-kimoto authored on 2009-10-13
238

            
add test
yuki-kimoto authored on 2009-10-16
239
=head2 initialize_model
first commit
yuki-kimoto authored on 2009-10-13
240

            
add test
yuki-kimoto authored on 2009-10-16
241
=head2 model
first commit
yuki-kimoto authored on 2009-10-13
242

            
add test
yuki-kimoto authored on 2009-10-16
243
=head2 new
244

            
245
=head2 query
first commit
yuki-kimoto authored on 2009-10-13
246

            
add test
yuki-kimoto authored on 2009-10-17
247
=head2 create_sql
248

            
249
=head2 query_raw_sql
250

            
251
=head2 sql_template
252

            
first commit
yuki-kimoto authored on 2009-10-13
253
=head1 AUTHOR
254

            
255
Yuki Kimoto, C<< <kimoto.yuki at gmail.com> >>
256

            
257
=head1 BUGS
258

            
259
Please report any bugs or feature requests to C<bug-dbi-custom at rt.cpan.org>, or through
260
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=DBI-Custom>.  I will be notified, and then you'll
261
automatically be notified of progress on your bug as I make changes.
262

            
263

            
264

            
265

            
266
=head1 SUPPORT
267

            
268
You can find documentation for this module with the perldoc command.
269

            
270
    perldoc DBI::Custom
271

            
272

            
273
You can also look for information at:
274

            
275
=over 4
276

            
277
=item * RT: CPAN's request tracker
278

            
279
L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=DBI-Custom>
280

            
281
=item * AnnoCPAN: Annotated CPAN documentation
282

            
283
L<http://annocpan.org/dist/DBI-Custom>
284

            
285
=item * CPAN Ratings
286

            
287
L<http://cpanratings.perl.org/d/DBI-Custom>
288

            
289
=item * Search CPAN
290

            
291
L<http://search.cpan.org/dist/DBI-Custom/>
292

            
293
=back
294

            
295

            
296
=head1 ACKNOWLEDGEMENTS
297

            
298

            
299
=head1 COPYRIGHT & LICENSE
300

            
301
Copyright 2009 Yuki Kimoto, all rights reserved.
302

            
303
This program is free software; you can redistribute it and/or modify it
304
under the same terms as Perl itself.
305

            
306

            
307
=cut
308

            
309
1; # End of DBI::Custom