source: LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Sql/objects.pm @ 154

Last change on this file since 154 was 154, checked in by nanardon, 15 years ago
  • use same name for table column than ldap attr name
  • try to auto discovery inline field
  • Property svn:keywords set to Id Rev
File size: 8.8 KB
Line 
1package LATMOS::Accounts::Bases::Sql::objects;
2
3use 5.010000;
4use strict;
5use warnings;
6
7use base qw(LATMOS::Accounts::Bases::Objects);
8
9our $VERSION = (q$Rev$ =~ /^Rev: (\d+) /)[0];
10
11=head1 NAME
12
13LATMOS::Ad - Perl extension for blah blah blah
14
15=head1 SYNOPSIS
16
17  use LATMOS::Accounts::Bases;
18  my $base = LATMOS::Accounts::Bases->new('unix');
19  ...
20
21=head1 DESCRIPTION
22
23Account base access over standard unix file format.
24
25=head1 FUNCTIONS
26
27=cut
28
29=head2 new(%options)
30
31Create a new LATMOS::Ad object for windows AD $domain.
32
33domain / server: either the Ad domain or directly the server
34
35ldap_args is an optionnal list of arguments to pass to L<Net::LDAP>.
36
37=cut
38
39sub list {
40    my ($class, $base) = @_;
41
42    my $sth = $base->db->prepare_cached(
43        sprintf(
44            q{select %s as k from %s order by %s},
45            $base->db->quote_identifier($class->key_field),
46            $base->db->quote_identifier($class->object_table),
47            $base->db->quote_identifier($class->key_field),
48        )
49    );
50    $sth->execute;
51    my @keys;
52    while(my $res = $sth->fetchrow_hashref) {
53        push(@keys, $res->{k});
54    }
55    @keys
56}
57
58sub list_from_rev {
59    my ($class, $base, $rev) = @_;
60    my $sth = $base->db->prepare_cached(
61        sprintf(
62            q{select %s as k from %s where rev > ? order by %s},
63            $base->db->quote_identifier($class->key_field),
64            $base->db->quote_identifier($class->object_table),
65            $base->db->quote_identifier($class->key_field),
66        )
67    );
68    $sth->execute($rev);
69    my @keys;
70    while(my $res = $sth->fetchrow_hashref) {
71        push(@keys, $res->{k});
72    }
73    @keys
74}
75
76sub has_extended_attributes { 0 }
77
78sub _initial_fields {
79    my ($self, $for, $base) = @_;
80    $base ||= $self->base;
81    my $sth = $base->db->prepare_cached(
82        q{SELECT column_name FROM information_schema.columns
83          WHERE table_name = ?}
84    );
85    $sth->execute($self->object_table);
86    my @res;
87    while (my $res = $sth->fetchrow_hashref) {
88        if ($for =~ 'w') {
89            next if($res->{column_name} =~ /^(rev|date|create|ikey)$/);
90            next if($res->{column_name} eq $self->key_field);
91        }
92        push(@res, $res->{column_name});
93    }
94    my %fields = map { $_ => $_ } @res;
95    \%fields
96}
97
98sub _canonical_fields {
99    my ($class, $base, $for) = @_;
100    $for ||= 'rw';
101    my @attr;
102    if ($class->has_extended_attributes) {
103        my $sth = $base->db->prepare_cached(
104            sprintf(
105                q{select canonical from %s order by canonical},
106                $base->db->quote_identifier($class->object_table . '_attributes_list'),
107            )
108        );
109        $sth->execute;
110        while (my $res = $sth->fetchrow_hashref) {
111            push(@attr, $res->{canonical});
112        }
113    }
114    @attr, keys %{ $class->_inline_fields($for, $base) || {} }
115}
116
117sub _get_field_name_db {
118    my ($class, $c_field, $base) = @_;
119    $class->has_extended_attributes or return;
120    $class->object_table or return;
121    my $sth = $base->db->prepare_cached(
122        sprintf(
123            q{select ikey from %s where canonical = ?},
124            $base->db->quote_identifier($class->object_table . '_attributes_list'),
125        )
126    );
127    $sth->execute($c_field);
128   
129    my $res = $sth->fetchrow_hashref;
130    $sth->finish;
131    $res->{ikey}
132}
133
134sub _get_field_name {
135    my ($class, $c_field, $base, $for) = @_;
136    $c_field or return;
137    $for ||= 'rw';
138    my $inline = $class->_inline_fields($for, $base) || {};
139    return $inline->{$c_field}
140        ? $inline->{$c_field}
141        : $class->_get_field_name_db($c_field, $base);
142}
143
144sub new {
145    my ($class, $base, $id) = @_;
146    my $sth = $base->db->prepare_cached(
147        sprintf(q{select 1 from %s where %s = ?},
148            $base->db->quote_identifier($class->object_table),
149            $base->db->quote_identifier($class->key_field),
150        ),
151    );
152    my $count = $sth->execute($id);
153    $sth->finish;
154    $count == 1 or return;
155    bless({ _id => $id, _base => $base }, $class);
156}
157
158sub _create {
159    my ($class, $base, $id, %data) = @_;
160
161    # splitting inline from extended
162    my $inl = $class->_initial_fields('w', $base) || {};
163    my %inline = map { $inl->{$_} => 1 }  keys %{ $inl || {}};
164    my (%first, %second);
165    foreach (keys %data) {
166        if ($inline{$_}) {
167            $first{$_} = $data{$_};
168        } else {
169            $second{$_} = $data{$_};
170        }
171    }
172    $first{$class->key_field} = $id;
173
174    my $sth = $base->db->prepare(
175        sprintf(
176            q{insert into %s (%s) values (%s)},
177            $base->db->quote_identifier($class->object_table),
178            join(', ', map { $base->db->quote_identifier($_) } sort keys %first),
179            join(',', qw(?) x scalar(keys %first)),
180        )
181    );
182    $sth->execute(map { $first{$_} } sort keys %first) or return;
183
184    $class->new($base, $id)->set_fields(%second);
185
186    1;
187}
188
189sub _delete {
190    my ($class, $base, $id) = @_;
191
192    my $sthd = $base->db->prepare_cached(
193        sprintf(
194            q{delete from %s where %s = ?},
195            $base->db->quote_identifier($class->object_table),
196            $base->db->quote_identifier($class->key_field),
197        )
198    );
199    $sthd->execute($id);
200}
201
202sub db {
203    return $_[0]->base->db;
204}
205
206sub quote_object_table {
207    my ($self) = @_;
208    my $table = $self->object_table or return;
209    $self->db->quote_identifier($table);
210}
211sub quote_key_field { 
212    my ($self) = @_;
213    my $key_field = $self->key_field or return;
214    $self->db->quote_identifier($key_field);
215}
216
217sub get_field {
218    my ($self, $field) = @_;
219    my $inl = $self->_inline_fields('r') || {};
220    my %inline = map { $inl->{$_} => 1 }  keys %{ $inl || {}};
221    if ($inline{lc($field)}) {
222    my $sth = $self->db->prepare_cached(
223        sprintf(
224            q{select %s from %s where %s = ?},
225            $self->db->quote_identifier(lc($field)),
226            $self->quote_object_table,
227            $self->quote_key_field,
228        )
229    );
230    $sth->execute($self->id);
231    my $res = $sth->fetchrow_hashref;
232    $sth->finish;
233    return $res->{$field};
234    } elsif ($self->has_extended_attributes) { # else, then we mandatory have extend attr
235        my $sth = $self->db->prepare_cached(
236            sprintf(
237                q{select value from %s where id = ? and attr = ?},
238                $self->db->quote_identifier($self->object_table. '_attributes'),
239            )
240        );
241        $sth->execute($self->id, $field);
242        my $res = $sth->fetchrow_hashref;
243        $sth->finish;
244        return $res->{value};
245    }
246}
247
248sub set_fields {
249    my ($self, %data) = @_;
250    my @fields;
251    my @vals;
252    my %ext;
253    my $inl = $self->_inline_fields('w') || {};
254    my %inline = map { $inl->{$_} => 1 }  keys %{ $inl || {}};
255    foreach my $field (keys %data) {
256        my $oldval = $self->get_field($field);
257        next if (($data{$field} || '') eq ($oldval || ''));
258        if ($inline{$field}) {
259        # TODO check fields exists !
260        push(@fields, sprintf("%s = ?", $self->db->quote_identifier($field)));
261        push(@vals, $data{$field});
262        } else {
263            $ext{$field} = $data{$field};
264        }
265    }
266    if (@fields) {
267        my $sth = $self->db->prepare_cached(
268            sprintf(
269                q{update %s set %s where %s = ?},
270                $self->quote_object_table,
271                join(', ', @fields),
272                $self->quote_key_field,
273            )
274        );
275        $sth->execute(@vals, $self->id);
276    }
277   
278    if ($self->has_extended_attributes) {
279        my $sthd = $self->db->prepare_cached(
280            sprintf(
281                q{delete from %s where id = ? and attr = ?},
282                $self->db->quote_identifier($self->object_table. '_attributes'),
283            ),
284        );
285        my $sthx = $self->db->prepare_cached(
286            sprintf(
287                q{insert into %s (id, attr, value) values (?,?,?)},
288                $self->db->quote_identifier($self->object_table. '_attributes'),
289            )
290        );
291        my $sthu = $self->db->prepare_cached(
292            sprintf(
293                q{update %s set value = ? where id = ? and attr = ?},
294                $self->db->quote_identifier($self->object_table. '_attributes'),
295            )
296        );
297
298        foreach (keys %ext) {
299            if ($ext{$_}) {
300                $sthu->execute($ext{$_}, $self->id, $_) != 0 ||
301                $sthx->execute($self->id, $_, $ext{$_}) or return;
302            } else {
303                $sthd->execute($self->id, $_) or return;
304            }
305        }
306    }
307
308    1;
309}
310
3111;
312
313__END__
314
315=head1 SEE ALSO
316
317=head1 AUTHOR
318
319Olivier Thauvin, E<lt>olivier.thauvin@latmos.ipsl.frE<gt>
320
321=head1 COPYRIGHT AND LICENSE
322
323Copyright (C) 2008, 2009 CNRS SA/CETP/LATMOS
324
325This library is free software; you can redistribute it and/or modify
326it under the same terms as Perl itself, either Perl version 5.10.0 or,
327at your option, any later version of Perl 5 you may have available.
328
329
330=cut
Note: See TracBrowser for help on using the repository browser.