/[cvs]/nfo/perl/libs/Data/Transfer/SyncStep.pm
ViewVC logotype

Contents of /nfo/perl/libs/Data/Transfer/SyncStep.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (show annotations)
Thu Oct 10 03:44:21 2002 UTC (21 years, 8 months ago) by cvsjoko
Branch: MAIN
CVS Tags: HEAD
+ new

1 #################################
2 #
3 # $Id$
4 #
5 # $Log$
6 #
7 #################################
8
9 package Data::Transfer::SyncStep;
10
11 #require Exporter;
12 #@ISA = qw( Exporter );
13 #@EXPORT = qw( syncSet2Table );
14
15 use strict;
16 use warnings;
17
18 use Data::Dumper;
19 use misc::HashExt;
20
21 # get logger instance
22 my $logger = Log::Dispatch::Config->instance;
23
24 sub new {
25 my $invocant = shift;
26 my $class = ref($invocant) || $invocant;
27 my $self = { @_ };
28 $logger->debug( __PACKAGE__ . "->new(@_)" );
29 return bless $self, $class;
30 }
31
32 sub _dumpCompact {
33 $Data::Dumper::Indent = 0;
34 my $result = Dumper(@_);
35 $Data::Dumper::Indent = 2;
36 return $result;
37 }
38
39 sub syncSet2Table {
40
41 my $self = shift;
42 my $args = shift;
43
44 my $tc = OneLineDumpHash->new( {} );
45
46
47 my @results;
48 if ($args->{objectSet}) {
49 # set of objects is already in $args
50 $logger->debug( __PACKAGE__ . "->syncSet2Table( objectSet => '" . $args->{objectSet} . "' )" );
51 @results = @{$args->{objectSet}};
52 } else {
53 # get set of objects from odbms by object name
54 $logger->debug( __PACKAGE__ . "->syncSet2Table( objectName => '" . $args->{objectName} . "' )" );
55 my $objects_set = $self->{L}->remote($args->{objectName});
56 @results = $self->{L}->select($objects_set);
57 }
58
59 # iterate through set
60 foreach my $obj (@results) {
61
62 # clone object (in case we have to modify it here)
63 my $objClone = $obj;
64
65 # exclude defined fields (simply delete from object)
66 foreach my $exField ( @{$args->{exclude}} ) {
67 delete $objClone->{$exField};
68 }
69
70 # calculate checksum for current object
71 my $oid = $self->{L}->id($objClone);
72
73 #my $objdump = $oid . "\n" . $objClone->quickdump();
74 my $objdump = $oid . "\n" . Dumper($objClone);
75
76 # TODO: $logger->dump( ... );
77 #$logger->debug( __PACKAGE__ . ": " . $objdump );
78 #$logger->dump( __PACKAGE__ . ": " . $objdump );
79
80 # build checksum for current object-dump
81 # md5-based fingerprint, base64 encoded (from Digest::MD5)
82 #my $checksum_cur = md5_base64($objdump) . '==';
83 # 32-bit integer "hash" value (maybe faster?) (from DBI)
84 my $checksum_cur = DBI::hash($objdump, 1);
85
86 # get checksum for current entry from rdbms
87 my $sql = "SELECT cs FROM $args->{sqlTable} WHERE $args->{sqlIdField}='$oid';";
88 #my $result = sendSql($sql);
89 my $result = $self->{R}->sendCommand($sql);
90 my $row = $result->getNextEntry();
91 my $checksum_remote = $row->{cs};
92
93 # determine if entry is "new" or "dirty"
94 my $bool_new = !$checksum_remote;
95 my $bool_dirty = $bool_new || $checksum_cur ne $checksum_remote || $args->{force};
96 print "c" if $main::args->{verbose};
97 if (!$bool_dirty) {
98 $tc->{in_sync}++;
99 next;
100 }
101
102 # field-structure for building sql
103 # mapping of sql-fieldnames to object-attributes
104 my $sqlmap;
105
106 # manually set ...
107 # ... object-id
108 $sqlmap->{$args->{sqlIdField}} = $self->{L}->id($objClone);
109 # ... checksum
110 $sqlmap->{cs} = $checksum_cur;
111
112
113 if ($args->{mapping}) {
114 # apply mapping from $args->{mapping} to $sqlmap
115 foreach my $key (keys %{$args->{mapping}}) {
116 my $map_right = $args->{mapping}->{$key};
117 #print "map: $map_right", "\n";
118 my $value;
119 # detect for callback
120 if (ref($map_right) eq 'CODE') {
121 $value = &$map_right($objClone);
122 } else {
123 $value = $objClone->{$map_right};
124 }
125 #$sqlmap->{$key} = $value;
126 $sqlmap->{$key} = $self->{R}->quoteSql($value);
127 }
128 }
129
130 if ($args->{mappingV2}) {
131
132 # apply mapping from $args->{mappingV2} to $sqlmap
133 foreach my $mapStep (@{$args->{mappingV2}}) {
134
135 # prepare left/right keys/values
136 my $left_key = $mapStep->{left};
137 my $left_val = _resolveMapStepExpr( $objClone, $mapStep->{left} );
138 my $right_key = $mapStep->{right};
139 my $right_val = ( $mapStep->{right} );
140 #print "map: $map_right", "\n";
141
142 if ($mapStep->{method}) {
143 if ($mapStep->{method} eq 'v:1') {
144 $left_val = $left_key;
145 }
146 }
147
148 #$sqlmap->{$key} = $value;
149 #if ( grep(!/$right_key/, @{$args->{exclude}}) ) {
150 $sqlmap->{$right_key} = $self->{R}->quoteSql($left_val);
151 #}
152 }
153 }
154
155 # TODO: $logger->dump( ... );
156 #$logger->debug( "sqlmap:" . "\n" . Dumper($sqlmap) );
157
158 my $sql_main;
159 if ($bool_new) {
160 $tc->{attempt_new}++;
161 $sql_main = $self->{R}->hash2Sql($args->{sqlTable}, $sqlmap, 'SQL_INSERT');
162 } else {
163 $tc->{attempt_modify}++;
164 $sql_main = $self->{R}->hash2Sql($args->{sqlTable}, $sqlmap, 'SQL_UPDATE', "$args->{sqlIdField}='$sqlmap->{$args->{sqlIdField}}'");
165 }
166
167 my $sqlHandle = $self->{R}->sendCommand($sql_main);
168 if (!$sqlHandle->err) {
169 $tc->{ok}++;
170 print "t" if $main::args->{verbose};
171 } else {
172 $tc->{error}++;
173 push( @{$tc->{error_per_row}}, {
174 statement => $sql_main,
175 state => $sqlHandle->state,
176 err => $sqlHandle->err,
177 errstr => $sqlHandle->errstr,
178 } );
179 #if ($args->{debug}) { print "sql-error with statement: $sql_main", "\n"; }
180 print "e" if $main::args->{verbose};
181 }
182
183 }
184 print "\n" if $main::args->{verbose};
185
186
187 # build user-message from some stats and log it via "sysevent"
188 # change logging level in case of an error
189
190 my $level = 'LEVEL_INFO';
191
192 my $msg;
193
194 # $msg .= "stats: ";
195 # $tc->{in_sync} && ($msg .= "in-sync: $tc->{in_sync}");
196 # $tc->{attempt_new} && ($msg .= " / " . "attempt-new: $tc->{attempt_new}");
197 # $tc->{attempt_modify} && ($msg .= " / " . "attempt-modify: $tc->{attempt_modify}");
198 # $tc->{ok} && ($msg .= " / " . "result-ok: $tc->{ok}");
199 # $tc->{error} && ($msg .= " / " . "result-error: $tc->{error}");
200
201 $msg .= "stats: $tc";
202
203 if ($tc->{error_per_row}) {
204 $msg .= "\n";
205 $level = 'LEVEL_NOTIFY';
206 $msg .= "errors:" . "\n";
207 $msg .= Dumper($tc->{error_per_row});
208 }
209
210 # todo!!!
211 #sysevent( { usermsg => $msg, level => $level }, $taskEvent );
212 $logger->info($msg);
213
214 return $tc;
215
216 }
217
218 sub _resolveMapStepExpr {
219
220 my $obj = shift;
221 my $expr = shift;
222
223 my $value;
224 # detect for callback (code-reference)
225 if (ref($expr) eq 'CODE') {
226 $value = &$expr($obj);
227 } elsif ($expr =~ m/->/) {
228 # use expr as complex object reference declaration (obj->subObj->subSubObj->0->attribute)
229 my $objPerlRefString = _mapStepExprToPerlRefString($expr);
230 #print "\n", "expr: $expr";
231 #print "\n", "objPerlRefString: $objPerlRefString";
232 $value = eval('$obj' . '->' . $objPerlRefString);
233 } else {
234 # use expr as simple scalar key (attributename)
235 $value = $obj->{$expr};
236 }
237
238 return $value;
239
240 }
241
242 sub _mapStepExprToPerlRefString {
243 my $expr = shift;
244
245 # split expression by dereference operators first
246 my @parts = split(/->/, $expr);
247
248 # wrap []'s around each part, if it consists of numeric characters only (=> numeric array-index),
249 # use {}'s, if there are word-characters in it (=> alphanumeric hash-key)
250 map {
251 m/^\d+$/ && ($_ = "[$_]") || ($_ = "{$_}");
252 } @parts;
253
254 # join parts with dereference operators together again and return built string
255 return join('->', @parts);
256 }
257
258
259 1;

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