/[cvs]/nfo/perl/libs/Tangram/Hash.pm
ViewVC logotype

Annotation of /nfo/perl/libs/Tangram/Hash.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (hide annotations)
Sun Nov 24 23:57:35 2002 UTC (21 years, 11 months ago) by joko
Branch: MAIN
Changes since 1.1: +63 -69 lines
+ patched version from Tangram 2.05

1 joko 1.1 # (c) Sound Object Logic 2000-2001
2    
3     use strict;
4    
5     package Tangram::Hash;
6    
7     use Tangram::AbstractHash;
8     use base qw( Tangram::AbstractHash );
9    
10     use Carp;
11    
12     sub reschema
13     {
14     my ($self, $members, $class, $schema) = @_;
15    
16     foreach my $member (keys %$members)
17     {
18     my $def = $members->{$member};
19    
20     unless (ref($def))
21     {
22     $def = { class => $def };
23     $members->{$member} = $def;
24     }
25    
26     $def->{table} ||= $schema->{normalize}->($def->{class} . "_$member", 'tablename');
27     $def->{coll} ||= 'coll';
28     $def->{item} ||= 'item';
29     $def->{slot} ||= 'slot';
30     $def->{quote} = !exists $def->{key_type} || $def->{key_type} eq 'string' ? "'" : '';
31     }
32    
33     return keys %$members;
34     }
35    
36 joko 1.2 sub defered_save {
37     my ($self, $obj, $field, $storage) = @_;
38    
39     my $coll_id = $storage->export_object($obj);
40    
41     my ($table, $coll_col, $item_col, $slot_col) = @{ $self }{ qw( table coll item slot ) };
42     my $Q = $self->{quote};
43    
44     my $coll = $obj->{$field};
45    
46     my $old_state = $self->get_load_state($storage, $obj, $field) || {};
47    
48     my %removed = %$old_state;
49     delete @removed{ keys %$coll };
50     my @free = keys %removed;
51    
52     my %new_state;
53    
54     foreach my $slot (keys %$coll)
55     {
56     my $item_id = $storage->export_object($coll->{$slot});
57    
58     if (exists $old_state->{$slot})
59     {
60     # key already exists
61    
62     if ($item_id != $old_state->{$slot})
63     {
64     # val has changed
65     $storage->sql_do(
66     "UPDATE $table SET $item_col = $item_id WHERE $coll_col = $coll_id AND $slot_col = $Q$slot$Q" );
67     }
68     }
69     else
70 joko 1.1 {
71 joko 1.2 # key does not exist
72    
73     if (@free)
74 joko 1.1 {
75 joko 1.2 # recycle an existing line
76     my $rslot = shift @free;
77     $storage->sql_do(
78     "UPDATE $table SET $slot_col = $Q$slot$Q, $item_col = $item_id WHERE $coll_col = $coll_id AND $slot_col = $Q$rslot$Q" );
79 joko 1.1 }
80 joko 1.2 else
81 joko 1.1 {
82 joko 1.2 # insert a new line
83     $storage->sql_do(
84     "INSERT INTO $table ($coll_col, $item_col, $slot_col) VALUES ($coll_id, $item_id, $Q$slot$Q)" );
85 joko 1.1 }
86     }
87 joko 1.2
88     $new_state{$slot} = $item_id;
89    
90     } # foreach my $slot (keys %$coll)
91    
92     # remove lines in excess
93    
94     if (@free)
95     {
96     @free = map { "$Q$_$Q" } @free if $Q;
97     $storage->sql_do( "DELETE FROM $table WHERE $coll_col = $coll_id AND $slot_col IN (@free)" );
98     }
99    
100     $self->set_load_state($storage, $obj, $field, \%new_state );
101     $storage->tx_on_rollback( sub { $self->set_load_state($storage, $obj, $field, $old_state) } );
102     }
103 joko 1.1
104    
105     sub erase
106     {
107     my ($self, $storage, $obj, $members, $coll_id) = @_;
108    
109     foreach my $member (keys %$members)
110     {
111     my $def = $members->{$member};
112    
113     my $table = $def->{table} || $def->{class} . "_$member";
114     my $coll_col = $def->{coll} || 'coll';
115    
116     my $sql = "DELETE FROM $table WHERE $coll_col = $coll_id";
117     $storage->sql_do($sql);
118     }
119     }
120    
121     sub cursor # ?? factorize ??
122     {
123     my ($self, $def, $storage, $obj, $member) = @_;
124    
125     my $cursor = Tangram::CollCursor->new($storage, $def->{class}, $storage->{db});
126    
127 joko 1.2 my $coll_id = $storage->export_object($obj);
128 joko 1.1 my $coll_tid = $storage->alloc_table;
129     my $table = $def->{table};
130 joko 1.2 my $item_tid = $cursor->{TARGET}->object->root_table;
131 joko 1.1 my $coll_col = $def->{coll};
132     my $item_col = $def->{item};
133     my $slot_col = $def->{slot};
134     $cursor->{-coll_tid} = $coll_tid;
135     $cursor->{-coll_cols} = "t$coll_tid.$slot_col";
136     $cursor->{-coll_from} = "$table t$coll_tid";
137     $cursor->{-coll_where} = "t$coll_tid.$coll_col = $coll_id AND t$coll_tid.$item_col = t$item_tid.id";
138    
139     return $cursor;
140     }
141    
142     sub query_expr
143     {
144     my ($self, $obj, $members, $tid) = @_;
145     map { Tangram::CollExpr->new($obj, $_); } values %$members;
146     }
147    
148     sub remote_expr
149     {
150     my ($self, $obj, $tid) = @_;
151     Tangram::CollExpr->new($obj, $self);
152     }
153    
154     sub prefetch
155     {
156     q{
157     my ($self, $storage, $def, $coll, $class, $member, $filter) = @_;
158    
159     my $ritem = $storage->remote($def->{class});
160    
161     # first retrieve the collection-side ids of all objects satisfying $filter
162     # empty the corresponding prefetch array
163    
164     my $ids = $storage->my_select_data( cols => [ $coll->{id} ], filter => $filter );
165     my $prefetch = $storage->{PREFETCH}{$class}{$member} ||= {}; # weakref
166    
167     while (my $id = $ids->fetchrow)
168     {
169     $prefetch->{$id} = []
170     }
171    
172     undef $ids;
173    
174     # now fetch the items
175    
176     my $cursor = Tangram::Cursor->new($storage, $ritem, $storage->{db});
177     my $includes = $coll->{$member}->includes($ritem);
178    
179     # also retrieve collection-side id and index of elmt in sequence
180     $cursor->retrieve($coll->{id},
181     Tangram::Number->expr("t$includes->{link_tid}.$def->{slot}" ) );
182    
183     $cursor->select($filter ? $filter & $includes : $includes);
184    
185     while (my $item = $cursor->current)
186     {
187     my ($coll_id, $slot) = $cursor->residue;
188     $prefetch->{$coll_id}[$slot] = $item;
189     $cursor->next;
190     }
191    
192     } # skipped
193     }
194    
195     $Tangram::Schema::TYPES{hash} = Tangram::Hash->new;
196    
197     1;

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed