From d74f0d54c569cd9e04978907f78683cce9881e15 Mon Sep 17 00:00:00 2001 From: nasseeder1 Date: Thu, 12 Jan 2023 19:58:49 +0000 Subject: [PATCH] 93_DbRep: contrib 8.51.2 git-svn-id: https://svn.fhem.de/fhem/trunk@27037 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/contrib/DS_Starter/93_DbRep.pm | 1197 ++++++++++++++------------- 1 file changed, 633 insertions(+), 564 deletions(-) diff --git a/fhem/contrib/DS_Starter/93_DbRep.pm b/fhem/contrib/DS_Starter/93_DbRep.pm index 18f6d46a4..f940e659b 100644 --- a/fhem/contrib/DS_Starter/93_DbRep.pm +++ b/fhem/contrib/DS_Starter/93_DbRep.pm @@ -1,5 +1,5 @@ ########################################################################################################## -# $Id: 93_DbRep.pm 26940 2023-01-02 20:22:51Z DS_Starter $ +# $Id: 93_DbRep.pm 27031 2023-01-11 23:20:18Z DS_Starter $ ########################################################################################################## # 93_DbRep.pm # @@ -59,6 +59,9 @@ no if $] >= 5.017011, warnings => 'experimental::smartmatch'; # Version History intern my %DbRep_vNotesIntern = ( + "8.51.2" => "12.01.2023 rewrite sub DbRep_OutputWriteToDB ", + "8.51.1" => "11.01.2023 write TYPE uppercase with writeToDB option, Commandref edited, fix add SQL Cache History ". + "set PRAGMA auto_vacuum = FULL when execute SQLite vacuum command", "8.51.0" => "02.01.2023 online formatting of sqlCmd, sqlCmdHistory, sqlSpecial, Commandref edited, get dbValue removed ". "sqlCmdBlocking customized like sqlCmd, bugfix avgTimeWeightMean ", "8.50.10" => "01.01.2023 Commandref edited ", @@ -1317,8 +1320,9 @@ sub DbRep_Get { elsif ($opt eq "minTimestamp" || $opt eq "initData") { return "Dump is running - try again later !" if($hash->{HELPER}{RUNNING_BACKUP_CLIENT}); - $hash->{HELPER}{IDRETRIES} = 3; # Anzahl wie oft versucht wird initiale Daten zu holen + $hash->{HELPER}{IDRETRIES} = 3; # Anzahl wie oft versucht wird initiale Daten zu holen + DbRep_delread ($hash); DbRep_setLastCmd (@a); ReadingsSingleUpdateValue ($hash, "state", "running", 1); @@ -3505,7 +3509,7 @@ sub DbRep_averval { } $dt = $tn - $to; - $sum += $val1*($dt/$tsum) if($tsum); + $sum += $val1 * ($dt/$tsum) if($tsum); $val1 = $val; $to = $tn; @@ -3515,25 +3519,31 @@ sub DbRep_averval { } my $aval = (DbRep_checktimeaggr($hash))[2]; + if($aval eq "hour") { - @rsf = split(/[ :]/,$runtime_string_first); - @rsn = split(/[ :]/,$runtime_string_next); + @rsf = split /[ :]/,$runtime_string_first; + @rsn = split /[ :]/,$runtime_string_next; $arrstr .= $runtime_string."#".$sum."#".$rsf[0]."_".$rsf[1]."|"; } elsif ($aval eq "minute") { - @rsf = split(/[ :]/,$runtime_string_first); - @rsn = split(/[ :]/,$runtime_string_next); + @rsf = split /[ :]/,$runtime_string_first; + @rsn = split /[ :]/,$runtime_string_next; $arrstr .= $runtime_string."#".$sum."#".$rsf[0]."_".$rsf[1]."-".$rsf[2]."|"; } else { - @rsf = split(" ",$runtime_string_first); - @rsn = split(" ",$runtime_string_next); + @rsf = split " ",$runtime_string_first; + @rsn = split " ",$runtime_string_next; $arrstr .= $runtime_string."#".$sum."#".$rsf[0]."|"; } - @wsf = split(" ",$runtime_string_first); - @wsn = split(" ",$runtime_string_next); - $wrstr .= $runtime_string."#".$sum."#".$wsf[0]."_".$wsf[1]."#".$wsn[0]."_".$wsn[1]."|"; # Kombi zum Rückschreiben in die DB + #@wsf = split " ",$runtime_string_first; + #@wsn = split " ",$runtime_string_next; + + $runtime_string_first =~ s/\s/_/xs; + $runtime_string_next =~ s/\s/_/xs; + + #$wrstr .= $runtime_string."#".$sum."#".$wsf[0]."_".$wsf[1]."#".$wsn[0]."_".$wsn[1]."|"; # Kombi zum Rückschreiben in die DB + $wrstr .= $runtime_string."#".$sum."#".$runtime_string_first."#".$runtime_string_next."|"; # Kombi zum Rückschreiben in die DB } } @@ -4349,7 +4359,7 @@ sub DbRep_diffval { $runtime_string = encode_base64($runtime_string,""); if($dbmodel eq "OLDMYSQLVER") { # Forum: https://forum.fhem.de/index.php/topic,130697.0.html - $err = DbRep_dbhDo ($name, $dbh, "set \@V:= 0, \@diff:= 0, \@diffTotal:= 0, \@RB:= 1;"); # @\RB = Resetbit wenn neues Selektionsintervall beginnt + ($err, undef) = DbRep_dbhDo ($name, $dbh, "set \@V:= 0, \@diff:= 0, \@diffTotal:= 0, \@RB:= 1;"); # @\RB = Resetbit wenn neues Selektionsintervall beginnt return "$name|$err" if ($err); } @@ -4966,13 +4976,13 @@ sub DbRep_insert { my ($sth,$sql,$irow); # insert into $table mit/ohne primary key - if ($usepkh && $dbloghash->{MODEL} eq 'MYSQL') { + if ($usepkh && $dbmodel eq 'MYSQL') { $sql = "INSERT IGNORE INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"; } - elsif ($usepkh && $dbloghash->{MODEL} eq 'SQLITE') { + elsif ($usepkh && $dbmodel eq 'SQLITE') { $sql = "INSERT OR IGNORE INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"; } - elsif ($usepkh && $dbloghash->{MODEL} eq 'POSTGRESQL') { + elsif ($usepkh && $dbmodel eq 'POSTGRESQL') { $sql = "INSERT INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?) ON CONFLICT DO NOTHING"; } else { @@ -6880,7 +6890,7 @@ sub _DbRep_setSessAttrVars { $pm = ltrim($pm).';'; $pm =~ s/ESC_ESC_ESC/;/gx; # wiederherstellen von escapeten ";" -> umwandeln von ";;" in ";" - my $err = DbRep_dbhDo ($name, $dbh, $pm, "Set VARIABLE or PRAGMA: $pm"); + (my $err, undef) = DbRep_dbhDo ($name, $dbh, $pm, "Set VARIABLE or PRAGMA: $pm"); return $err if ($err); } } @@ -6910,7 +6920,7 @@ sub _DbRep_setSessVars { $pm = ltrim($pm).';'; $pm =~ s/ESC_ESC_ESC/;/gx; # wiederherstellen von escapeten ";" -> umwandeln von ";;" in ";" - my $err = DbRep_dbhDo ($name, $dbh, $pm, "Set SQL session variable: $pm"); + (my $err, undef) = DbRep_dbhDo ($name, $dbh, $pm, "Set SQL session variable: $pm"); return $err if ($err); } } @@ -6940,7 +6950,7 @@ sub _DbRep_setSessPragma { $pm = ltrim($pm).';'; $pm =~ s/ESC_ESC_ESC/;/gx; # wiederherstellen von escapeten ";" -> umwandeln von ";;" in ";" - my $err = DbRep_dbhDo ($name, $dbh, $pm, "Exec PRAGMA Statement: $pm"); + (my $err, undef) = DbRep_dbhDo ($name, $dbh, $pm, "Exec PRAGMA Statement: $pm"); return $err if ($err); } } @@ -6972,7 +6982,7 @@ sub _DbRep_execSessPrepare { $pm = ltrim($pm).';'; $pm =~ s/ESC_ESC_ESC/;/gx; # wiederherstellen von escapeten ";" -> umwandeln von ";;" in ";" - my $err = DbRep_dbhDo ($name, $dbh, $pm, "Exec PREPARE statement: $pm"); + (my $err, undef) = DbRep_dbhDo ($name, $dbh, $pm, "Exec PREPARE statement: $pm"); return $err if ($err); } } @@ -7078,7 +7088,7 @@ sub DbRep_sqlCmdDone { delete($hash->{HELPER}{RUNNING_PID}); - my $tmpsql = delete $data{DbRep}{$name}{sqlcache}{temp}; # SQL incl. Formatierung aus Zwischenspeicher holen + my $tmpsql = $data{DbRep}{$name}{sqlcache}{temp}; # SQL incl. Formatierung aus Zwischenspeicher holen my ($erread, $state) = DbRep_afterproc ($hash, $hash->{LASTCMD}); # Befehl nach Procedure ausführen if ($err) { @@ -7090,6 +7100,8 @@ sub DbRep_sqlCmdDone { return; } + + DbRep_addSQLcmdCache ($name); # Drop-Down Liste bisherige sqlCmd-Befehle füllen und in Key-File sichern my ($rt,$brt) = split ",", $bt; my $srf = AttrVal($name, "sqlResultFormat", "separated"); @@ -7103,8 +7115,6 @@ sub DbRep_sqlCmdDone { ReadingsBulkUpdateValue ($hash, 'sqlCmd', $tmpsql); ReadingsBulkUpdateValue ($hash, 'sqlResultNumRows', $nrows); - DbRep_addSQLcmdCache ($name); # Drop-Down Liste bisherige sqlCmd-Befehle füllen und in Key-File sichern - if ($srf eq "sline") { $rowstring =~ s/§/]|[/g; $rowstring =~ s/\|°escaped°\|/§/g; @@ -7211,7 +7221,7 @@ sub DbRep_dbmeta { # due to incompatible changes made in MyQL 5.7.5, see http://johnemb.blogspot.de/2014/09/adding-or-removing-individual-sql-modes.html if($dbmodel eq "MYSQL") { - $err = DbRep_dbhDo ($name, $dbh, "SET sql_mode=(SELECT REPLACE(\@\@sql_mode,'ONLY_FULL_GROUP_BY',''));"); + ($err, undef) = DbRep_dbhDo ($name, $dbh, "SET sql_mode=(SELECT REPLACE(\@\@sql_mode,'ONLY_FULL_GROUP_BY',''));"); return "$name|$err" if ($err); } @@ -7760,7 +7770,12 @@ sub DbRep_optimizeTables { Log3 ($name, 3, "DbRep $name - Size of database $dbname before optimize (MB): $db_MB_start"); - $query ="VACUUM"; + $query = "PRAGMA auto_vacuum = FULL;"; + + $err = _DbRep_setSessPragma ($name, $dbh, \$query); + return "$name|$err" if ($err); + + $query = "VACUUM"; ($err, $sth) = DbRep_prepareExecuteQuery ($name, $dbh, $query, "VACUUM database $dbname...."); return "$name|$err" if ($err); @@ -10992,6 +11007,32 @@ sub DbRep_resolveDevspecs { return ($devs,$devswc); } +###################################################################################### +# Erstelle Insert SQL-Schema für Tabelle mit/ohne primary key +###################################################################################### +sub DbRep_createInsertSQLscheme { + my $table = shift; + my $dbmodel = shift; + my $usepkh = shift; + + my $sql; + + if ($usepkh && $dbmodel eq 'MYSQL') { + $sql = "INSERT IGNORE INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"; + } + elsif ($usepkh && $dbmodel eq 'SQLITE') { + $sql = "INSERT OR IGNORE INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"; + } + elsif ($usepkh && $dbmodel eq 'POSTGRESQL') { + $sql = "INSERT INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?) ON CONFLICT DO NOTHING"; + } + else { + $sql = "INSERT INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"; + } + +return $sql; +} + ###################################################################################### # Connect zur Datenbank herstellen # @@ -11139,7 +11180,7 @@ return ($err, $sth, $result); } #################################################################################################### -# einfaches Sdbh->do, return ERROR-String wenn Fehler +# einfaches Sdbh->do, return ERROR-String wenn Fehler bzw. die Anzahl der betroffenen Zeilen #################################################################################################### sub DbRep_dbhDo { my $name = shift; @@ -11148,19 +11189,44 @@ sub DbRep_dbhDo { my $info = shift // "simple do statement: $sql"; my $err = q{}; - - my $sth; + my $rv = q{}; Log3 ($name, 4, "DbRep $name - $info"); - eval{ $dbh->do($sql); + eval{ $rv = $dbh->do($sql); + 1; } or do { $err = encode_base64($@,""); Log3 ($name, 2, "DbRep $name - ERROR - $@"); $dbh->disconnect; }; -return $err; +return ($err, $rv); +} + +#################################################################################################### +# führt ein sth execute aus +# return ERROR oder die Anzahl der betroffenen Zeilen +#################################################################################################### +sub DbRep_sthExecOnly { + my $name = shift; + my $sth = shift; + my $arg = shift; + + my $err = q{}; + my $rv = q{}; + + my @args = split ",", $arg; + + eval{ $rv = $sth->execute(@args); + } + or do { $err = encode_base64($@,""); + Log3 ($name, 2, "DbRep $name - ERROR - $@"); + }; + + $rv = 0 if($rv eq "0E0"); + +return ($err, $rv); } #################################################################################################### @@ -12687,66 +12753,71 @@ return \%ncp; # Funktionsergebnisse in Datenbank schreiben #################################################################################################### sub DbRep_OutputWriteToDB { - my ($name,$device,$reading,$wrstr,$optxt) = @_; + my $name = shift; + my $device = shift; + my $reading = shift; + my $wrstr = shift; + my $optxt = shift; # Operation Kürzel + my $hash = $defs{$name}; my $dbloghash = $defs{$hash->{HELPER}{DBLOGDEVICE}}; - my $dbconn = $dbloghash->{dbconn}; - my $dbuser = $dbloghash->{dbuser}; my $dblogname = $dbloghash->{NAME}; - my $dbmodel = $dbloghash->{MODEL}; - my $DbLogType = AttrVal($dblogname, "DbLogType", "History"); - my $supk = AttrVal($dblogname, "noSupportPK", 0); - my $dbpassword = $attr{"sec$dblogname"}{secret}; - my $utf8 = $hash->{UTF8} // 0; + my $DbLogType = AttrVal ($dblogname, 'DbLogType', 'History'); + my $supk = AttrVal ($dblogname, 'noSupportPK', 0); + $device =~ s/[^A-Za-z\/\d_\.-]/\//g; $reading =~ s/[^A-Za-z\/\d_\.-]/\//g; - my $type = "calculated"; - my $event = "calculated"; - my $unit = ""; + my $type = 'calculated'; + my $event = 'calculated'; + my $unit = qq{}; my $wrt = 0; my $irowdone = 0; - my $ndp = AttrVal($name, "numDecimalPlaces", $dbrep_defdecplaces); + my $ndp = AttrVal ($name, 'numDecimalPlaces', $dbrep_defdecplaces); - my ($dbh,$sth_ih,$sth_uh,$sth_ic,$sth_uc,$err,$value,$date,$time,$hour,$minute,$ndate,$ntime,$rsf,$rsn,@row_array); + my ($dbh,$sth_ih,$sth_ic,$err,$value,$date,$time,$hour,$minute,$ndate,$ntime,$rsf,$rsn,@wr_arr); my ($timestamp,$year,$mon,$mday,$t1,$corr); if(!$dbloghash->{HELPER}{COLSET}) { - $err = "No result of \"$hash->{LASTCMD}\" to database written. Cause: column width in \"$hash->{DEF}\" isn't set"; + $err = qq(No result of "$hash->{LASTCMD}" to database written. Cause: column width in "$hash->{DEF}" isn't set); + Log3 ($name, 2, "DbRep $name - ERROR - $err"); + $err = encode_base64($err,""); + return ($err,$wrt,$irowdone); } no warnings 'uninitialized'; - my $aggr = (DbRep_checktimeaggr($hash))[2]; - $reading = $optxt."_".$aggr."_".AttrVal($name, "readingNameMap", $reading); + my $aggr = (DbRep_checktimeaggr ($hash))[2]; + $reading = $optxt."_".$aggr."_".AttrVal ($name, 'readingNameMap', $reading); - $type = $defs{$device}{TYPE} if($defs{$device}); # $type vom Device ableiten + $type = uc($defs{$device}{TYPE}) if($defs{$device}); # $type vom Device übernehmen if($optxt =~ /avg|sum/) { - my @arr = split("\\|", $wrstr); + my @arr = split "\\|", $wrstr; my $ele = $#arr; # Nr des letzten Elements my $i = 0; for my $row (@arr) { - my @a = split("#", $row); + my @a = split "#", $row; my $runtime_string = $a[0]; # Aggregations-Alias (nicht benötigt) $value = defined($a[1]) ? (looks_like_number($a[1]) ? sprintf("%.${ndp}f",$a[1]) : undef) : undef; # in Version 8.40.0 geändert $rsf = $a[2]; # Runtime String first - Datum / Zeit für DB-Speicherung - ($date,$time) = split("_",$rsf); + ($date,$time) = split "_", $rsf; $time =~ s/-/:/g if($time); $rsn = $a[3]; # Runtime String next - Datum / Zeit für DB-Speicherung - ($ndate,$ntime) = split("_",$rsn); + ($ndate,$ntime) = split "_", $rsn; $ntime =~ s/-/:/g if($ntime); if($aggr =~ /no|day|week|month|year/) { $time = "00:00:01" if($time !~ /^(\d{2}):(\d{2}):(\d{2})$/ || $hash->{LASTCMD} =~ /\bwriteToDB(Single)*?\b/); # https://forum.fhem.de/index.php/topic,105787.msg1013920.html#msg1013920 $ntime = "23:59:59" if($ntime !~ /^(\d{2}):(\d{2}):(\d{2})$/ || $hash->{LASTCMD} =~ /\bwriteToDB(Single)*?\b/); - ($year,$mon,$mday) = split("-", $ndate); - $corr = ($i != $ele) ? 86400 : 0; + + ($year,$mon,$mday) = split "-", $ndate; + $corr = $i != $ele ? 86400 : 0; $t1 = fhemTimeLocal(59, 59, 23, $mday, $mon-1, $year-1900)-$corr; - ($ndate,undef) = split(" ",FmtDateTime($t1)); + ($ndate,undef) = split " ", FmtDateTime($t1); } elsif ($aggr =~ /minute|hour/) { ($hour,$minute) = split ":", $time; @@ -12760,36 +12831,29 @@ sub DbRep_OutputWriteToDB { $time = "$hour:00:01" if($time !~ /^(\d{2}):(\d{2}):(\d{2})$/ || $hash->{LASTCMD} =~ /\bwriteToDB(Single)*?\b/); # https://forum.fhem.de/index.php/topic,105787.msg1013920.html#msg1013920 $ntime = "$hour:59:59" if($ntime !~ /^(\d{2}):(\d{2}):(\d{2})$/ || $hash->{LASTCMD} =~ /\bwriteToDB(Single)*?\b/); } - - if ($ntime eq "23:59:59") { - ($year,$mon,$mday) = split("-", $ndate); - $t1 = fhemTimeLocal(59, 59, 23, $mday, $mon-1, $year-1900)-86400; - ($ndate,undef) = split(" ",FmtDateTime($t1)); - } } if (defined $value) { - # Daten auf maximale Länge beschneiden (DbLog-Funktion !) ($device,$type,$event,$reading,$value,$unit) = DbLog_cutCol($dbloghash,$device,$type,$event,$reading,$value,$unit); if($i == 0) { - push(@row_array, "$date $time|$device|$type|$event|$reading|$value|$unit") if($hash->{LASTCMD} !~ /\bwriteToDBSingle\b/); - push(@row_array, "$ndate $ntime|$device|$type|$event|$reading|$value|$unit"); + push @wr_arr, "$date $time|$device|$type|$event|$reading|$value|$unit" if($hash->{LASTCMD} !~ /\bwriteToDBSingle\b/); + push @wr_arr, "$ndate $ntime|$device|$type|$event|$reading|$value|$unit"; } else { if ($aggr =~ /no|day|week|month|year/) { - ($year,$mon,$mday) = split("-", $date); + ($year,$mon,$mday) = split "-", $date; $t1 = fhemTimeLocal(01, 00, 00, $mday, $mon-1, $year-1900); - ($date,$time) = split(" ",FmtDateTime($t1)); + ($date,$time) = split " ", FmtDateTime($t1); } elsif ($aggr =~ /hour/) { - ($year,$mon,$mday) = split("-", $date); + ($year,$mon,$mday) = split "-", $date; $t1 = fhemTimeLocal(01, 00, $hour, $mday, $mon-1, $year-1900); - ($date,$time) = split(" ",FmtDateTime($t1)); + ($date,$time) = split " ", FmtDateTime($t1); } - push(@row_array, "$date $time|$device|$type|$event|$reading|$value|$unit") if($hash->{LASTCMD} !~ /\bwriteToDBSingle\b/); - push(@row_array, "$ndate $ntime|$device|$type|$event|$reading|$value|$unit"); + push @wr_arr, "$date $time|$device|$type|$event|$reading|$value|$unit" if($hash->{LASTCMD} !~ /\bwriteToDBSingle\b/); + push @wr_arr, "$ndate $ntime|$device|$type|$event|$reading|$value|$unit"; } } $i++; @@ -12797,14 +12861,14 @@ sub DbRep_OutputWriteToDB { } if($optxt =~ /min|max|diff/) { - my %rh = split("§", $wrstr); + my %rh = split "§", $wrstr; for my $key (sort(keys(%rh))) { - my @k = split("\\|",$rh{$key}); - $value = defined($k[1])?sprintf("%.${ndp}f",$k[1]):undef; - $rsf = $k[2]; # Datum / Zeit für DB-Speicherung + my @k = split "\\|", $rh{$key}; + $value = defined($k[1]) ? sprintf("%.${ndp}f",$k[1]) : undef; + $rsf = $k[2]; # Datum / Zeit für DB-Speicherung - ($date,$time) = split("_",$rsf); + ($date,$time) = split "_", $rsf; $time =~ s/-/:/g if($time); if($time !~ /^(\d{2}):(\d{2}):(\d{2})$/) { @@ -12819,140 +12883,107 @@ sub DbRep_OutputWriteToDB { } } if ($value) { - # Daten auf maximale Länge beschneiden (DbLog-Funktion !) ($device,$type,$event,$reading,$value,$unit) = DbLog_cutCol($dbloghash,$device,$type,$event,$reading,$value,$unit); - push(@row_array, "$date $time|$device|$type|$event|$reading|$value|$unit"); + push @wr_arr, "$date $time|$device|$type|$event|$reading|$value|$unit"; + } + } + } + + return ($err,$wrt,$irowdone) if(!@wr_arr); + + #Log3 ($name, 2, "DbRep $name - data for write: \n". Dumper @wr_arr); + #return; + + # Schreibzyklus + ################## + ($err, $dbh, my $dbmodel) = DbRep_dbConnect ($name, 0); + return ($err,$wrt,$irowdone) if ($err); + + # check ob PK verwendet wird, @usepkx?Anzahl der Felder im PK:0 wenn kein PK, $pkx?Namen der Felder:none wenn kein PK + my ($usepkh,$usepkc,$pkh,$pkc); + + if (!$supk) { + ($usepkh,$usepkc,$pkh,$pkc) = DbRep_checkUsePK($hash,$dbloghash,$dbh); + } + else { + Log3 ($name, 5, "DbRep $name -> Primary Key usage suppressed by attribute noSupportPK in DbLog >$dblogname<"); + } + + my $sql = DbRep_createInsertSQLscheme ('history', $dbmodel, $usepkh); + + ($err, $sth_ih) = DbRep_prepareOnly ($name, $dbh, $sql); + return ($err,$wrt,$irowdone) if ($err); + + $sql = DbRep_createInsertSQLscheme ('current', $dbmodel, $usepkh); + + ($err, $sth_ic) = DbRep_prepareOnly ($name, $dbh, $sql); + return ($err,$wrt,$irowdone) if ($err); + + $err = DbRep_beginDatabaseTransaction ($name, $dbh); + return ($err,$wrt,$irowdone) if ($err); + + my $wst = [gettimeofday]; # SQL-Startzeit + + my $ihs = 0; + my $uhs = 0; + + for my $row (@wr_arr) { + my @a = split "\\|", $row; + + $timestamp = $a[0]; + $device = $a[1]; + $type = $a[2]; + $event = $a[3]; + $reading = $a[4]; + $value = $a[5]; + $unit = $a[6] // q{}; + + if (lc($DbLogType) =~ m(history) ) { + my ($rv_uh, $rv_ih); + + ($err, $rv_uh) = DbRep_dbhDo ($name, $dbh, qq(UPDATE history SET TIMESTAMP="$timestamp", DEVICE="$device", READING="$reading", TYPE="$type", EVENT="$event", VALUE="$value", UNIT="$unit" WHERE TIMESTAMP="$timestamp" AND DEVICE="$device" AND READING="$reading";)); + return ($err,$wrt,$irowdone) if ($err); + + $uhs += $rv_uh if($rv_uh); + + Log3 ($name, 4, "DbRep $name - UPDATE history: $row, RESULT: $rv_uh"); + + if ($rv_uh == 0) { + ($err, $rv_ih) = DbRep_sthExecOnly ($name, $sth_ih, "$timestamp,$device,$type,$event,$reading,$value,$unit"); + if ($err) { + $dbh->disconnect; + return ($err,$wrt,$irowdone); + } + + $ihs += $rv_ih if($rv_ih); + + Log3 ($name, 4, "DbRep $name - INSERT history: $row, RESULT: $rv_ih"); + } + } + + if (lc($DbLogType) =~ m(current) ) { + my $rv_uc; + + ($err, $rv_uc) = DbRep_dbhDo ($name, $dbh, qq(UPDATE current SET TIMESTAMP="$timestamp", DEVICE="$device", READING="$reading", TYPE="$type", EVENT="$event", VALUE="$value", UNIT="$unit" WHERE DEVICE="$device" AND READING="$reading";)); + return ($err,$wrt,$irowdone) if ($err); + + if ($rv_uc == 0) { + $err = DbRep_sthExecOnly ($name, $sth_ic, "$timestamp,$device,$type,$event,$reading,$value,$unit"); } } } - if (@row_array) { # Schreibzyklus aktivieren - eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1, AutoCommit => 1, mysql_enable_utf8 => $utf8 });}; - if ($@) { - $err = $@; - Log3 ($name, 2, "DbRep $name - ERROR - $@"); - $err = encode_base64($err,""); - return ($err,$wrt,$irowdone); - } + $err = DbRep_commitOnly ($name, $dbh); + return ($err,$wrt,$irowdone) if ($err); - # check ob PK verwendet wird, @usepkx?Anzahl der Felder im PK:0 wenn kein PK, $pkx?Namen der Felder:none wenn kein PK - my ($usepkh,$usepkc,$pkh,$pkc); + $dbh->disconnect; - if (!$supk) { - ($usepkh,$usepkc,$pkh,$pkc) = DbRep_checkUsePK($hash,$dbloghash,$dbh); - } - else { - Log3 ($hash->{NAME}, 5, "DbRep $name -> Primary Key usage suppressed by attribute noSupportPK in DbLog \"$dblogname\""); - } + Log3 ($name, 3, "DbRep $name - number of lines updated in >$dblogname<: $uhs"); + Log3 ($name, 3, "DbRep $name - number of lines inserted into >$dblogname<: $ihs"); + + $irowdone = $ihs + $uhs; - if (lc($DbLogType) =~ m(history)) { # INSERT history mit/ohne primary key - if ($usepkh && $dbloghash->{MODEL} eq 'MYSQL') { - eval { $sth_ih = $dbh->prepare_cached("INSERT IGNORE INTO history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"); }; - } - elsif ($usepkh && $dbloghash->{MODEL} eq 'SQLITE') { - eval { $sth_ih = $dbh->prepare_cached("INSERT OR IGNORE INTO history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"); }; - } - elsif ($usepkh && $dbloghash->{MODEL} eq 'POSTGRESQL') { - eval { $sth_ih = $dbh->prepare_cached("INSERT INTO history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?) ON CONFLICT DO NOTHING"); }; - } - else { - eval { $sth_ih = $dbh->prepare_cached("INSERT INTO history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"); }; - } - if ($@) { - $err = $@; - Log3 ($name, 2, "DbRep $name - ERROR - $@"); - $err = encode_base64($err,""); - return ($err,$wrt,$irowdone); - } - } - - if (lc($DbLogType) =~ m(current) ) { # INSERT current mit/ohne primary key - if ($usepkc && $hash->{MODEL} eq 'MYSQL') { - eval { $sth_ic = $dbh->prepare("INSERT IGNORE INTO current (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"); }; - } - elsif ($usepkc && $hash->{MODEL} eq 'SQLITE') { - eval { $sth_ic = $dbh->prepare("INSERT OR IGNORE INTO current (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"); }; - } - elsif ($usepkc && $hash->{MODEL} eq 'POSTGRESQL') { - eval { $sth_ic = $dbh->prepare("INSERT INTO current (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?) ON CONFLICT DO NOTHING"); }; - } - else { - # old behavior - eval { $sth_ic = $dbh->prepare("INSERT INTO current (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"); }; - } - if ($@) { - $err = $@; - Log3 ($name, 2, "DbRep $name - ERROR - $@"); - $err = encode_base64($err,""); - return ($err,$wrt,$irowdone); - } - } - - eval { $dbh->begin_work() if($dbh->{AutoCommit}); }; - if ($@) { - Log3($name, 2, "DbRep $name - ERROR - $@"); - } - - # SQL-Startzeit - my $wst = [gettimeofday]; - - my $ihs = 0; - my $uhs = 0; - - for my $row (@row_array) { - my @a = split("\\|",$row); - $timestamp = $a[0]; - $device = $a[1]; - $type = $a[2]; - $event = $a[3]; - $reading = $a[4]; - $value = $a[5]; - $unit = $a[6]; - - eval { - # update oder insert history - if (lc($DbLogType) =~ m(history) ) { - my $rv_uh = $dbh->do("UPDATE history SET TIMESTAMP=\"$timestamp\", DEVICE=\"$device\", READING=\"$reading\", TYPE=\"$type\", EVENT=\"$event\", VALUE=\"$value\", UNIT=\"$unit\" WHERE TIMESTAMP=\"$timestamp\" AND DEVICE=\"$device\" AND READING=\"$reading\""); - $uhs += $rv_uh if($rv_uh); - - Log3 ($hash->{NAME}, 4, "DbRep $name - UPDATE history: $row, RESULT: $rv_uh"); - - if ($rv_uh == 0) { - my $rv_ih = $sth_ih->execute($timestamp,$device,$type,$event,$reading,$value,$unit); - $ihs += $rv_ih if($rv_ih); - Log3 $hash->{NAME}, 4, "DbRep $name - INSERT history: $row, RESULT: $rv_ih"; - } - } - # update oder insert current - if (lc($DbLogType) =~ m(current) ) { - my $rv_uc = $dbh->do("UPDATE current SET TIMESTAMP=\"$timestamp\", DEVICE=\"$device\", READING=\"$reading\", TYPE=\"$type\", EVENT=\"$event\", VALUE=\"$value\", UNIT=\"$unit\" WHERE DEVICE=\"$device\" AND READING=\"$reading\""); - if ($rv_uc == 0) { - $sth_ic->execute($timestamp,$device,$type,$event,$reading,$value,$unit); - } - } - }; - - if ($@) { - $err = $@; - Log3 ($name, 2, "DbRep $name - ERROR - $@"); - $dbh->rollback; - $dbh->disconnect; - $err = encode_base64($err,""); - return ($err,$wrt,0); - } - } - - eval {$dbh->commit() if(!$dbh->{AutoCommit});}; - - $dbh->disconnect; - - Log3 ($hash->{NAME}, 3, "DbRep $name - number of lines updated in \"$dblogname\": $uhs"); - Log3 ($hash->{NAME}, 3, "DbRep $name - number of lines inserted into \"$dblogname\": $ihs"); - $irowdone = $ihs + $uhs; - - # SQL-Laufzeit ermitteln - $wrt = tv_interval($wst); - } + $wrt = tv_interval($wst); # SQL-Laufzeit ermitteln return ($err,$wrt,$irowdone); } @@ -13410,12 +13441,12 @@ sub DbRep_setVersionInfo { if($modules{$type}{META}{x_prereqs_src} && !$hash->{HELPER}{MODMETAABSENT}) { # META-Daten sind vorhanden $modules{$type}{META}{version} = "v".$v; # Version aus META.json überschreiben, Anzeige mit {Dumper $modules{SMAPortal}{META}} - if($modules{$type}{META}{x_version}) { # {x_version} ( nur gesetzt wenn $Id: 93_DbRep.pm 26940 2023-01-01 20:22:51Z DS_Starter $ im Kopf komplett! vorhanden ) + if($modules{$type}{META}{x_version}) { # {x_version} ( nur gesetzt wenn $Id: 93_DbRep.pm 27031 2023-01-11 23:20:18Z DS_Starter $ im Kopf komplett! vorhanden ) $modules{$type}{META}{x_version} =~ s/1.1.1/$v/g; } else { $modules{$type}{META}{x_version} = $v; } - return $@ unless (FHEM::Meta::SetInternals($hash)); # FVERSION wird gesetzt ( nur gesetzt wenn $Id: 93_DbRep.pm 26940 2023-01-01 20:22:51Z DS_Starter $ im Kopf komplett! vorhanden ) + return $@ unless (FHEM::Meta::SetInternals($hash)); # FVERSION wird gesetzt ( nur gesetzt wenn $Id: 93_DbRep.pm 27031 2023-01-11 23:20:18Z DS_Starter $ im Kopf komplett! vorhanden ) if(__PACKAGE__ eq "FHEM::$type" || __PACKAGE__ eq $type) { # es wird mit Packages gearbeitet -> Perl übliche Modulversion setzen # mit {->VERSION()} im FHEMWEB kann Modulversion abgefragt werden @@ -14222,172 +14253,174 @@ return;
-
  • dumpMySQL [clientSide | serverSide] - - creates a dump of the connected MySQL database.
    - Depending from selected option the dump will be created on Client- or on Server-Side.
    - The variants differs each other concerning the executing system, the creating location, the usage of - attributes, the function result and the needed hardware ressources.
    - The option "clientSide" e.g. needs more powerful FHEM-Server hardware, but saves all available - tables inclusive possibly created views.
    - With attribute "dumpCompress" a compression of dump file after creation can be switched on. -

    +
  • dumpMySQL [clientSide | serverSide]

    + + Creates a dump of the connected MySQL database.
    + Depending from selected option the dump will be created on Client- or on Server-Side.
    + The variants differs each other concerning the executing system, the creating location, the usage of + attributes, the function result and the needed hardware ressources.
    + The option "clientSide" e.g. needs more powerful FHEM-Server hardware, but saves all available + tables inclusive possibly created views.
    + With attribute "dumpCompress" a compression of dump file after creation can be switched on. +

    -
      - Option clientSide
      - The dump will be created by client (FHEM-Server) and will be saved in FHEM log-directory by - default. - The target directory can be set by attribute dumpDirLocal and has to be - writable by the FHEM process.
      - Before executing the dump a table optimization can be processed optionally (see attribute - "optimizeTablesBeforeDump") as well as a FHEM-command (attribute "executeBeforeProc"). - After the dump a FHEM-command can be executed as well (see attribute "executeAfterProc").

      +
        + Option clientSide
        + The dump will be created by client (FHEM-Server) and will be saved in FHEM log-directory ((typical /opt/fhem/log/)) by + default. + The target directory can be set by attribute dumpDirLocal and has to be + writable by the FHEM process.
        + Before executing the dump a table optimization can be processed optionally (see attribute + "optimizeTablesBeforeDump") as well as a FHEM-command (attribute "executeBeforeProc"). + After the dump a FHEM-command can be executed as well (see attribute "executeAfterProc").

        - Note:
        - To avoid FHEM from blocking, you have to operate DbLog in asynchronous mode if the table - optimization want to be used !


        + Note:
        + To avoid FHEM from blocking, you have to operate DbLog in asynchronous mode if the table + optimization want to be used !


        - By the attributes dumpMemlimit and - dumpSpeed the run-time behavior of the function can be - controlled to optimize the performance and demand of ressources.

        + By the attributes dumpMemlimit and + dumpSpeed the run-time behavior of the function can be + controlled to optimize the performance and demand of ressources.

        - The attributes relevant for function "dumpMySQL clientSide" are:

        -
          - - - - - - - - - - - -
          dumpComment : User comment in head of dump file
          dumpCompress : compress of dump files after creation
          dumpDirLocal : the local destination directory for dump file creation
          dumpMemlimit : limits memory usage
          dumpSpeed : limits CPU utilization
          dumpFilesKeep : number of dump files to keep
          executeBeforeProc : execution of FHEM command (or Perl-routine) before dump
          executeAfterProc : execution of FHEM command (or Perl-routine) after dump
          optimizeTablesBeforeDump : table optimization before dump
          -
        -
        + The attributes relevant for function "dumpMySQL clientSide" are:

        +
          + + + + + + + + + + + +
          dumpComment : User comment in head of dump file
          dumpCompress : compress of dump files after creation
          dumpDirLocal : the local destination directory for dump file creation
          dumpMemlimit : limits memory usage
          dumpSpeed : limits CPU utilization
          dumpFilesKeep : number of dump files to keep
          executeBeforeProc : execution of FHEM command (or Perl-routine) before dump
          executeAfterProc : execution of FHEM command (or Perl-routine) after dump
          optimizeTablesBeforeDump : table optimization before dump
          +
        +
        - After a successfull finished dump the old dumpfiles are deleted and only the number of files - defined by attribute "dumpFilesKeep" (default: 3) remain in the target directory - "dumpDirLocal". If "dumpFilesKeep = 0" is set, all - dumpfiles (also the current created file), are deleted. This setting can be helpful, if FTP transmission is used - and the created dumps are only keep remain in the FTP destination directory.

        + After a successfull finished dump the old dumpfiles are deleted and only the number of files + defined by attribute "dumpFilesKeep" (default: 3) remain in the target directory + "dumpDirLocal". If "dumpFilesKeep = 0" is set, all + dumpfiles (also the current created file), are deleted. This setting can be helpful, if FTP transmission is used + and the created dumps are only keep remain in the FTP destination directory.

        - The naming convention of dump files is: <dbname>_<date>_<time>.sql[.gzip]

        + The naming convention of dump files is: <dbname>_<date>_<time>.sql[.gzip]

        - To rebuild the database from a dump file the command:

        + To rebuild the database from a dump file the command:

        -
          - set <name> restoreMySQL <filename>

          -
        +
          + set <name> restoreMySQL <filename>

          +
        - can be used.

        + can be used.

        - The created dumpfile (uncompressed) can imported on the MySQL-Server by:

        + The created dumpfile (uncompressed) can imported on the MySQL-Server by:

        -
          - mysql -u <user> -p <dbname> < <filename>.sql

          -
        +
          + mysql -u <user> -p <dbname> < <filename>.sql

          +
        - as well to restore the database from dump file.


        + as well to restore the database from dump file.


        - Option serverSide
        - The dump will be created on the MySQL-Server and will be saved in its Home-directory - by default.
        - The whole history-table (not the current-table) will be exported CSV-formatted without - any restrictions.
        + Option serverSide
        + The dump will be created on the MySQL-Server and will be saved in its Home-directory + by default.
        + The whole history-table (not the current-table) will be exported CSV-formatted without + any restrictions.
        - Before executing the dump a table optimization can be processed optionally (see attribute - "optimizeTablesBeforeDump") as well as a FHEM-command (attribute "executeBeforeProc").

        + Before executing the dump a table optimization can be processed optionally (see attribute + "optimizeTablesBeforeDump") as well as a FHEM-command (attribute "executeBeforeProc").

        - Note:
        - To avoid FHEM from blocking, you have to operate DbLog in asynchronous mode if the table - optimization is used !


        + Note:
        + To avoid FHEM from blocking, you have to operate DbLog in asynchronous mode if the table + optimization is used !


        - After the dump a FHEM-command can be executed as well (see attribute "executeAfterProc").

        + After the dump a FHEM-command can be executed as well (see attribute "executeAfterProc").

        - The attributes relevant for function "dumpMySQL serverSide" are:

        -
          - - - - - - - - - -
          dumpDirRemote : destination directory of dump file on remote server
          dumpCompress : compress of dump files after creation
          dumpDirLocal : the local mounted directory dumpDirRemote
          dumpFilesKeep : number of dump files to keep
          executeBeforeProc : execution of FHEM command (or Perl-routine) before dump
          executeAfterProc : execution of FHEM command (or Perl-routine) after dump
          optimizeTablesBeforeDump : table optimization before dump
          -
        -
        + The attributes relevant for function "dumpMySQL serverSide" are:

        +
          + + + + + + + + + +
          dumpDirRemote : destination directory of dump file on remote server
          dumpCompress : compress of dump files after creation
          dumpDirLocal : the local mounted directory dumpDirRemote
          dumpFilesKeep : number of dump files to keep
          executeBeforeProc : execution of FHEM command (or Perl-routine) before dump
          executeAfterProc : execution of FHEM command (or Perl-routine) after dump
          optimizeTablesBeforeDump : table optimization before dump
          +
        +
        - The target directory can be set by dumpDirRemote attribute. - It must be located on the MySQL-Host and has to be writable by the MySQL-server process.
        - The used database user must have the FILE privilege (see Wiki).

        + The target directory can be set by dumpDirRemote attribute. + It must be located on the MySQL-Host and has to be writable by the MySQL-server process.
        + The used database user must have the FILE privilege (see Wiki).

        - Note:
        - If the internal version management of DbRep should be used and the size of the created dumpfile be - reported, you have to mount the remote MySQL-Server directory "dumpDirRemote" on the client - and publish it to the DbRep-device by fill out the dumpDirLocal attribute.
        - Same is necessary if ftp transfer after dump is to be used (attribute "ftpUse" respectively "ftpUseSSL"). -

        + Note:
        + If the internal version management of DbRep should be used and the size of the created dumpfile be + reported, you have to mount the remote MySQL-Server directory "dumpDirRemote" on the client + and publish it to the DbRep-device by fill out the dumpDirLocal attribute.
        + Same is necessary if ftp transfer after dump is to be used (attribute "ftpUse" respectively "ftpUseSSL"). +

        -
          - Example:
          - attr <name> dumpDirRemote /volume1/ApplicationBackup/dumps_FHEM/
          - attr <name> dumpDirLocal /sds1/backup/dumps_FHEM/
          - attr <name> dumpFilesKeep 2

          +
            + Example:
            + attr <name> dumpDirRemote /volume1/ApplicationBackup/dumps_FHEM/
            + attr <name> dumpDirLocal /sds1/backup/dumps_FHEM/
            + attr <name> dumpFilesKeep 2

            - # The dump will be created remote on the MySQL-Server in directory - '/volume1/ApplicationBackup/dumps_FHEM/'.
            - # The internal version management searches in local mounted directory '/sds1/backup/dumps_FHEM/' - for present dumpfiles and deletes these files except the last two versions.
            -
            -
          + # The dump will be created remote on the MySQL-Server in directory + '/volume1/ApplicationBackup/dumps_FHEM/'.
          + # The internal version management searches in local mounted directory '/sds1/backup/dumps_FHEM/' + for present dumpfiles and deletes these files except the last two versions.
          +
          +
        - If the internal version management is used, after a successfull finished dump old dumpfiles will - be deleted and only the number of attribute "dumpFilesKeep" (default: 3) would remain in target - directory "dumpDirLocal" (the mounted "dumpDirRemote"). - In that case FHEM needs write permissions to the directory "dumpDirLocal".

        + If the internal version management is used, after a successfull finished dump old dumpfiles will + be deleted and only the number of attribute "dumpFilesKeep" (default: 3) would remain in target + directory "dumpDirLocal" (the mounted "dumpDirRemote"). + In that case FHEM needs write permissions to the directory "dumpDirLocal".

        - The naming convention of dump files is: <dbname>_<date>_<time>.csv[.gzip]

        + The naming convention of dump files is: <dbname>_<date>_<time>.csv[.gzip]

        - You can start a restore of table history from serverSide-Backup by command:

        -
          - set <name> <restoreMySQL> <filename>.csv[.gzip]

          -
        + You can start a restore of table history from serverSide-Backup by command:

        +
          + set <name> <restoreMySQL> <filename>.csv[.gzip]

          +
        -

        +

        - FTP-Transfer after Dump
        - If those possibility is be used, the attribute ftpUse or - ftpUseSSL has to be set. The latter if encoding for FTP is to be used. - The module also carries the version control of dump files in FTP-destination by attribute - "ftpDumpFilesKeep".
        - Further attributes are:

        + FTP-Transfer after Dump
        + If those possibility is be used, the attribute ftpUse or + ftpUseSSL has to be set. The latter if encoding for FTP is to be used. + The module also carries the version control of dump files in FTP-destination by attribute + "ftpDumpFilesKeep".
        + Further attributes are:

        -
          - - - - - - - - - - - - - -
          ftpUse : FTP Transfer after dump will be switched on (without SSL encoding)
          ftpUser : User for FTP-server login, default: anonymous
          ftpUseSSL : FTP Transfer with SSL encoding after dump
          ftpDebug : debugging of FTP communication for diagnostics
          ftpDir : directory on FTP-server in which the file will be send into (default: "/")
          ftpDumpFilesKeep : leave the number of dump files in FTP-destination <ftpDir> (default: 3)
          ftpPassive : set if passive FTP is to be used
          ftpPort : FTP-Port, default: 21
          ftpPwd : password of FTP-User, not set by default
          ftpServer : name or IP-address of FTP-server. absolutely essential !
          ftpTimeout : timeout of FTP-connection in seconds (default: 30).
          -
        -
        -
        -
      - -
      +
        + + + + + + + + + + + + + +
        ftpUse : FTP Transfer after dump will be switched on (without SSL encoding)
        ftpUser : User for FTP-server login, default: anonymous
        ftpUseSSL : FTP Transfer with SSL encoding after dump
        ftpDebug : debugging of FTP communication for diagnostics
        ftpDir : directory on FTP-server in which the file will be send into (default: "/")
        ftpDumpFilesKeep : leave the number of dump files in FTP-destination <ftpDir> (default: 3)
        ftpPassive : set if passive FTP is to be used
        ftpPort : FTP-Port, default: 21
        ftpPwd : password of FTP-User, not set by default
        ftpServer : name or IP-address of FTP-server. absolutely essential !
        ftpTimeout : timeout of FTP-connection in seconds (default: 30).
        +
      +
      +
      + +
    +
  • +
  • dumpSQLite - creates a dump of the connected SQLite database.
    This function uses the SQLite Online Backup API and allow to create a consistent backup of the @@ -15249,48 +15282,63 @@ return;

    - The relevant attributes to control this function are:

    + The following attributes are relevant for this function:

      - - - - -
      executeBeforeProc : execution of FHEM command (or Perl-routine) before operation
      executeAfterProc : execution of FHEM command (or Perl-routine) after operation
      + + + + +
      executeBeforeProc : execution of FHEM command (or Perl-routine) before operation
      executeAfterProc : execution of FHEM command (or Perl-routine) after operation


  • -
  • vacuum - optimize tables in the connected database (SQLite, PostgreSQL).
    - Before and after an optimization it is possible to execute a FHEM command. - (please see attributes executeBeforeProc, executeAfterProc) -

    + +
  • vacuum

    + + Optimizes the tables in the connected database (SQLite, PostgreSQL).
    + Especially for SQLite databases it is strongly recommended to temporarily close the connection of the relevant DbLog + device to the database (see DbLog reopen command). +
    +
    + + The following attributes are relevant for this function:

    -
      - Note:
      - Even though the function itself is designed non-blocking, make sure the assigned DbLog-device - is operating in asynchronous mode to avoid FHEM from blocking.

      - -

    +
      + + + + +
      executeBeforeProc : execution of FHEM command (or Perl-routine) before operation
      executeAfterProc : execution of FHEM command (or Perl-routine) after operation
      +
    +
    +
    -
    - + Hinweis:
    + When the vacuum command is executed, the PRAGMA auto_vacuum = FULL is automatically applied to SQLite databases. +
  • +
    - For all evaluation variants (except sqlCmd,deviceRename,readingRename) applies:
    - In addition to the needed reading the device can be complemented to restrict the datasets for reporting / function. - If no time limit attribute is set but aggregation is set, the period from the oldest dataset in database to the current - date/time will be used as selection criterion. If the oldest dataset wasn't identified, then '1970-01-01 01:00:00' is used - as start date (see get <name> "minTimestamp" also). - If both time limit attribute and aggregation isn't set, the selection on database is runnung without timestamp criterion. -

    +
    + + - Note:
    + For all evaluation variants (except sqlCmd,deviceRename,readingRename) applies:
    + In addition to the needed reading the device can be complemented to restrict the datasets for reporting / function. + If no time limit attribute is set but aggregation is set, the period from the oldest dataset in database to the current + date/time will be used as selection criterion. If the oldest dataset wasn't identified, then '1970-01-01 01:00:00' is used + as start date (see get <name> "minTimestamp" also). + If both time limit attribute and aggregation isn't set, the selection on database is runnung without timestamp criterion. +

    - If you are in detail view it could be necessary to refresh the browser to see the result of operation as soon in DeviceOverview section "state = done" will be shown. + Note:
    -

    + If you are in detail view it could be necessary to refresh the browser to see the result of operation as soon in DeviceOverview section "state = done" will be shown. + +

    @@ -15922,29 +15970,31 @@ sub bdump { new operation starts
    -
  • seqDoubletsVariance <positive variance [negative variance] [EDGE=negative|positive]>
    - Accepted variance for the command "set <name> delSeqDoublets".
    - The value of this attribute describes the variance up to consecutive numeric values (VALUE) of - datasets are handled as identical. If only one numeric value is declared, it is used as - postive as well as negative variance and both form the "deletion corridor". - Optional a second numeric value for a negative variance, separated by blank,can be - declared. - Always absolute, i.e. positive numeric values, have to be declared.
    - If the supplement "EDGE=negative" is declared, values at a negative edge (e.g. when - value is changed from 4.0 -> 1.0) are not deleted although they are in the "deletion corridor". - Equivalent is valid with "EDGE=positive" for the positive edge (e.g. the change - from 1.2 -> 2.8). -

    +
  • seqDoubletsVariance <positive variance [negative variance] [EDGE=negative|positive]>

    + + Accepted variance for the command "set <name> delSeqDoublets".
    + The value of this attribute describes the variance up to consecutive numeric values (VALUE) of + datasets are handled as identical. If only one numeric value is declared, it is used as + postive as well as negative variance and both form the "deletion corridor". + Optional a second numeric value for a negative variance, separated by blank,can be + declared. + Always absolute, i.e. positive numeric values, have to be declared.
    + If the supplement "EDGE=negative" is declared, values at a negative edge (e.g. when + value is changed from 4.0 -> 1.0) are not deleted although they are in the "deletion corridor". + Equivalent is valid with "EDGE=positive" for the positive edge (e.g. the change + from 1.2 -> 2.8). +

    -
      - Examples:
      - attr <name> seqDoubletsVariance 0.0014
      - attr <name> seqDoubletsVariance 1.45
      - attr <name> seqDoubletsVariance 3.0 2.0
      - attr <name> seqDoubletsVariance 1.5 EDGE=negative
      -
    -

    -
  • + +
    +
    +
  • showproctime - if set, the reading "sql_processing_time" shows the required execution time (in seconds) @@ -17087,172 +17137,174 @@ return;

  • -
  • dumpMySQL [clientSide | serverSide] - - erstellt einen Dump der angeschlossenen MySQL-Datenbank.
    - Abhängig von der ausgewählten Option wird der Dump auf der Client- bzw. Serverseite erstellt.
    - Die Varianten unterscheiden sich hinsichtlich des ausführenden Systems, des Erstellungsortes, der - Attributverwendung, des erzielten Ergebnisses und der benötigten Hardwareressourcen.
    - Die Option "clientSide" benötigt z.B. eine leistungsfähigere Hardware des FHEM-Servers, sichert aber alle - Tabellen inklusive eventuell angelegter Views.
    - Mit dem Attribut "dumpCompress" kann eine Komprimierung der erstellten Dumpfiles eingeschaltet werden. -

    +
  • dumpMySQL [clientSide | serverSide]

    + + Erstellt einen Dump der angeschlossenen MySQL-Datenbank.
    + Abhängig von der ausgewählten Option wird der Dump auf der Client- bzw. Serverseite erstellt.
    + Die Varianten unterscheiden sich hinsichtlich des ausführenden Systems, des Erstellungsortes, der + Attributverwendung, des erzielten Ergebnisses und der benötigten Hardwareressourcen.
    + Die Option "clientSide" benötigt z.B. eine leistungsfähigere Hardware des FHEM-Servers, sichert aber alle + Tabellen inklusive eventuell angelegter Views.
    + Mit dem Attribut "dumpCompress" kann eine Komprimierung der erstellten Dumpfiles eingeschaltet werden. +

    -
      - Option clientSide
      - Der Dump wird durch den Client (FHEM-Rechner) erstellt und per default im log-Verzeichnis des Clients - gespeichert. - Das Zielverzeichnis kann mit dem Attribut dumpDirLocal verändert werden und muß auf - dem Client durch FHEM beschreibbar sein.
      - Vor dem Dump kann eine Tabellenoptimierung (Attribut "optimizeTablesBeforeDump") oder ein FHEM-Kommando - (Attribut "executeBeforeProc") optional zugeschaltet werden. - Nach dem Dump kann ebenfalls ein FHEM-Kommando (siehe Attribut "executeAfterProc") ausgeführt werden.

      +
        + Option clientSide
        + Der Dump wird durch den Client (FHEM-Rechner) erstellt und per default im log-Verzeichnis des Clients + (typisch /opt/fhem/log/) gespeichert. + Das Zielverzeichnis kann mit dem Attribut dumpDirLocal verändert werden und muß auf + dem Client durch FHEM beschreibbar sein.
        + Vor dem Dump kann eine Tabellenoptimierung (Attribut "optimizeTablesBeforeDump") oder ein FHEM-Kommando + (Attribut "executeBeforeProc") optional zugeschaltet werden. + Nach dem Dump kann ebenfalls ein FHEM-Kommando (siehe Attribut "executeAfterProc") ausgeführt werden.

        - Achtung !
        - Um ein Blockieren von FHEM zu vermeiden, muß DbLog im asynchronen Modus betrieben werden wenn die - Tabellenoptimierung verwendet wird !


        + Achtung !
        + Um ein Blockieren von FHEM zu vermeiden, muß DbLog im asynchronen Modus betrieben werden wenn die + Tabellenoptimierung verwendet wird !


        - Über die Attribute dumpMemlimit und dumpSpeed - kann das Laufzeitverhalten der - Funktion beeinflusst werden um eine Optimierung bezüglich Performance und Ressourcenbedarf zu erreichen.

        + Über die Attribute dumpMemlimit und dumpSpeed + kann das Laufzeitverhalten der + Funktion beeinflusst werden um eine Optimierung bezüglich Performance und Ressourcenbedarf zu erreichen.

        - Die für "dumpMySQL clientSide" relevanten Attribute sind:

        -
          - - - - - - - - - - - -
          dumpComment : User-Kommentar im Dumpfile
          dumpCompress : Komprimierung des Dumpfiles nach der Erstellung
          dumpDirLocal : das lokale Zielverzeichnis für die Erstellung des Dump
          dumpMemlimit : Begrenzung der Speicherverwendung
          dumpSpeed : Begrenzung die CPU-Belastung
          dumpFilesKeep : Anzahl der aufzubwahrenden Dumpfiles
          executeBeforeProc : ausführen FHEM Kommando (oder Perl-Routine) vor dem Dump
          executeAfterProc : ausführen FHEM Kommando (oder Perl-Routine) nach dem Dump
          optimizeTablesBeforeDump : Tabelloptimierung vor dem Dump ausführen
          -
        -
        + Die für "dumpMySQL clientSide" relevanten Attribute sind:

        +
          + + + + + + + + + + + +
          dumpComment : User-Kommentar im Dumpfile
          dumpCompress : Komprimierung des Dumpfiles nach der Erstellung
          dumpDirLocal : das lokale Zielverzeichnis für die Erstellung des Dump
          dumpMemlimit : Begrenzung der Speicherverwendung
          dumpSpeed : Begrenzung die CPU-Belastung
          dumpFilesKeep : Anzahl der aufzubwahrenden Dumpfiles
          executeBeforeProc : ausführen FHEM Kommando (oder Perl-Routine) vor dem Dump
          executeAfterProc : ausführen FHEM Kommando (oder Perl-Routine) nach dem Dump
          optimizeTablesBeforeDump : Tabelloptimierung vor dem Dump ausführen
          +
        +
        - Nach einem erfolgreichen Dump werden alte Dumpfiles gelöscht und nur die Anzahl Files, definiert durch - das Attribut "dumpFilesKeep" (default: 3), verbleibt im Zielverzeichnis "dumpDirLocal". Falls "dumpFilesKeep = 0" - gesetzt ist, werden alle Dumpfiles (auch das aktuell erstellte File), gelöscht. - Diese Einstellung kann sinnvoll sein, wenn FTP aktiviert ist - und die erzeugten Dumps nur im FTP-Zielverzeichnis erhalten bleiben sollen.

        + Nach einem erfolgreichen Dump werden alte Dumpfiles gelöscht und nur die Anzahl Files, definiert durch + das Attribut "dumpFilesKeep" (default: 3), verbleibt im Zielverzeichnis "dumpDirLocal". Falls "dumpFilesKeep = 0" + gesetzt ist, werden alle Dumpfiles (auch das aktuell erstellte File), gelöscht. + Diese Einstellung kann sinnvoll sein, wenn FTP aktiviert ist + und die erzeugten Dumps nur im FTP-Zielverzeichnis erhalten bleiben sollen.

        - Die Namenskonvention der Dumpfiles ist: <dbname>_<date>_<time>.sql[.gzip]

        + Die Namenskonvention der Dumpfiles ist: <dbname>_<date>_<time>.sql[.gzip]

        - Um die Datenbank aus dem Dumpfile wiederherzustellen kann das Kommmando:

        + Um die Datenbank aus dem Dumpfile wiederherzustellen kann das Kommmando:

        -
          - set <name> restoreMySQL <filename>

          -
        +
          + set <name> restoreMySQL <filename>

          +
        - verwendet werden.

        + verwendet werden.

        - Das erzeugte Dumpfile (unkomprimiert) kann ebenfalls mit:

        + Das erzeugte Dumpfile (unkomprimiert) kann ebenfalls mit:

        -
          - mysql -u <user> -p <dbname> < <filename>.sql

          -
        +
          + mysql -u <user> -p <dbname> < <filename>.sql

          +
        - auf dem MySQL-Server ausgeführt werden um die Datenbank aus dem Dump wiederherzustellen.

        -
        + auf dem MySQL-Server ausgeführt werden um die Datenbank aus dem Dump wiederherzustellen.

        +
        - Option serverSide
        - Der Dump wird durch den MySQL-Server erstellt und per default im Home-Verzeichnis des MySQL-Servers - gespeichert.
        - Es wird die gesamte history-Tabelle (nicht current-Tabelle) im CSV-Format ohne - Einschränkungen exportiert.
        - Vor dem Dump kann eine Tabellenoptimierung (Attribut "optimizeTablesBeforeDump") - optional zugeschaltet werden .

        + Option serverSide
        + Der Dump wird durch den MySQL-Server erstellt und per default im Home-Verzeichnis des MySQL-Servers + gespeichert.
        + Es wird die gesamte history-Tabelle (nicht current-Tabelle) im CSV-Format ohne + Einschränkungen exportiert.
        + Vor dem Dump kann eine Tabellenoptimierung (Attribut "optimizeTablesBeforeDump") + optional zugeschaltet werden .

        - Achtung !
        - Um ein Blockieren von FHEM zu vermeiden, muß DbLog im asynchronen Modus betrieben werden wenn die - Tabellenoptimierung verwendet wird !


        + Achtung !
        + Um ein Blockieren von FHEM zu vermeiden, muß DbLog im asynchronen Modus betrieben werden wenn die + Tabellenoptimierung verwendet wird !


        - Vor und nach dem Dump kann ein FHEM-Kommando (siehe Attribute "executeBeforeProc", "executeAfterProc") ausgeführt - werden.

        + Vor und nach dem Dump kann ein FHEM-Kommando (siehe Attribute "executeBeforeProc", "executeAfterProc") ausgeführt + werden.

        - Die für "dumpMySQL serverSide" relevanten Attribute sind:

        -
          - - - - - - - - - -
          dumpDirRemote : das Erstellungsverzeichnis des Dumpfile auf dem entfernten Server
          dumpCompress : Komprimierung des Dumpfiles nach der Erstellung
          dumpDirLocal : Directory des lokal gemounteten dumpDirRemote-Verzeichnisses
          dumpFilesKeep : Anzahl der aufzubwahrenden Dumpfiles
          executeBeforeProc : ausführen FHEM Kommando (oder Perl-Routine) vor dem Dump
          executeAfterProc : ausführen FHEM Kommando (oder Perl-Routine) nach dem Dump
          optimizeTablesBeforeDump : Tabelloptimierung vor dem Dump ausführen
          -
        -
        + Die für "dumpMySQL serverSide" relevanten Attribute sind:

        +
          + + + + + + + + + +
          dumpDirRemote : das Erstellungsverzeichnis des Dumpfile auf dem entfernten Server
          dumpCompress : Komprimierung des Dumpfiles nach der Erstellung
          dumpDirLocal : Directory des lokal gemounteten dumpDirRemote-Verzeichnisses
          dumpFilesKeep : Anzahl der aufzubwahrenden Dumpfiles
          executeBeforeProc : ausführen FHEM Kommando (oder Perl-Routine) vor dem Dump
          executeAfterProc : ausführen FHEM Kommando (oder Perl-Routine) nach dem Dump
          optimizeTablesBeforeDump : Tabelloptimierung vor dem Dump ausführen
          +
        +
        - Das Zielverzeichnis kann mit dem Attribut dumpDirRemote verändert werden. - Es muß sich auf dem MySQL-Host gefinden und durch den MySQL-Serverprozess beschreibbar sein.
        - Der verwendete Datenbankuser benötigt das FILE Privileg (siehe Wiki).

        + Das Zielverzeichnis kann mit dem Attribut dumpDirRemote verändert werden. + Es muß sich auf dem MySQL-Host gefinden und durch den MySQL-Serverprozess beschreibbar sein.
        + Der verwendete Datenbankuser benötigt das FILE Privileg (siehe Wiki).

        - Hinweis:
        - Soll die interne Versionsverwaltung und die Dumpfilekompression des Moduls genutzt, sowie die Größe des erzeugten - Dumpfiles ausgegeben werden, ist das Verzeichnis "dumpDirRemote" des MySQL-Servers auf dem Client zu mounten - und im Attribut dumpDirLocal dem DbRep-Device bekannt zu machen.
        - Gleiches gilt wenn der FTP-Transfer nach dem Dump genutzt werden soll (Attribut "ftpUse" bzw. "ftpUseSSL"). -

        + Hinweis:
        + Soll die interne Versionsverwaltung und die Dumpfilekompression des Moduls genutzt, sowie die Größe des erzeugten + Dumpfiles ausgegeben werden, ist das Verzeichnis "dumpDirRemote" des MySQL-Servers auf dem Client zu mounten + und im Attribut dumpDirLocal dem DbRep-Device bekannt zu machen.
        + Gleiches gilt wenn der FTP-Transfer nach dem Dump genutzt werden soll (Attribut "ftpUse" bzw. "ftpUseSSL"). +

        -
          - Beispiel:
          - attr <name> dumpDirRemote /volume1/ApplicationBackup/dumps_FHEM/
          - attr <name> dumpDirLocal /sds1/backup/dumps_FHEM/
          - attr <name> dumpFilesKeep 2

          +
            + Beispiel:
            + attr <name> dumpDirRemote /volume1/ApplicationBackup/dumps_FHEM/
            + attr <name> dumpDirLocal /sds1/backup/dumps_FHEM/
            + attr <name> dumpFilesKeep 2

            - # Der Dump wird remote auf dem MySQL-Server im Verzeichnis '/volume1/ApplicationBackup/dumps_FHEM/' - erstellt.
            - # Die interne Versionsverwaltung sucht im lokal gemounteten Verzeichnis '/sds1/backup/dumps_FHEM/' - vorhandene Dumpfiles und löscht diese bis auf die zwei letzten Versionen.
            -
            -
          + # Der Dump wird remote auf dem MySQL-Server im Verzeichnis '/volume1/ApplicationBackup/dumps_FHEM/' + erstellt.
          + # Die interne Versionsverwaltung sucht im lokal gemounteten Verzeichnis '/sds1/backup/dumps_FHEM/' + vorhandene Dumpfiles und löscht diese bis auf die zwei letzten Versionen.
          +
          +
        - Wird die interne Versionsverwaltung genutzt, werden nach einem erfolgreichen Dump alte Dumpfiles gelöscht - und nur die Anzahl "dumpFilesKeep" (default: 3) verbleibt im Zielverzeichnis "dumpDirRemote". - FHEM benötigt in diesem Fall Schreibrechte auf dem Verzeichnis "dumpDirLocal".

        + Wird die interne Versionsverwaltung genutzt, werden nach einem erfolgreichen Dump alte Dumpfiles gelöscht + und nur die Anzahl "dumpFilesKeep" (default: 3) verbleibt im Zielverzeichnis "dumpDirRemote". + FHEM benötigt in diesem Fall Schreibrechte auf dem Verzeichnis "dumpDirLocal".

        - Die Namenskonvention der Dumpfiles ist: <dbname>_<date>_<time>.csv[.gzip]

        + Die Namenskonvention der Dumpfiles ist: <dbname>_<date>_<time>.csv[.gzip]

        - Ein Restore der Datenbank aus diesem Backup kann durch den Befehl:

        -
          - set <name> <restoreMySQL> <filename>.csv[.gzip]

          -
        + Ein Restore der Datenbank aus diesem Backup kann durch den Befehl:

        +
          + set <name> <restoreMySQL> <filename>.csv[.gzip]

          +
        - gestartet werden.

        + gestartet werden.

        - FTP Transfer nach Dump
        - Wenn diese Möglichkeit genutzt werden soll, ist das Attribut ftpUse oder - "ftpUseSSL" zu setzen. Letzteres gilt wenn eine verschlüsselte Übertragung genutzt werden soll.
        - Das Modul übernimmt ebenfalls die Versionierung der Dumpfiles im FTP-Zielverzeichnis mit Hilfe des Attributes - "ftpDumpFilesKeep". - Für die FTP-Übertragung relevante Attribute sind:

        + FTP Transfer nach Dump
        + Wenn diese Möglichkeit genutzt werden soll, ist das Attribut ftpUse oder + "ftpUseSSL" zu setzen. Letzteres gilt wenn eine verschlüsselte Übertragung genutzt werden soll.
        + Das Modul übernimmt ebenfalls die Versionierung der Dumpfiles im FTP-Zielverzeichnis mit Hilfe des Attributes + "ftpDumpFilesKeep". + Für die FTP-Übertragung relevante Attribute sind:

        -
          - - - - - - - - - - - - - -
          ftpUse : FTP Transfer nach dem Dump wird eingeschaltet (ohne SSL Verschlüsselung)
          ftpUser : User zur Anmeldung am FTP-Server, default: anonymous
          ftpUseSSL : FTP Transfer mit SSL Verschlüsselung nach dem Dump wird eingeschaltet
          ftpDebug : Debugging des FTP Verkehrs zur Fehlersuche
          ftpDir : Verzeichnis auf dem FTP-Server in welches das File übertragen werden soll (default: "/")
          ftpDumpFilesKeep : Es wird die angegebene Anzahl Dumpfiles im <ftpDir> belassen (default: 3)
          ftpPassive : setzen wenn passives FTP verwendet werden soll
          ftpPort : FTP-Port, default: 21
          ftpPwd : Passwort des FTP-Users, default nicht gesetzt
          ftpServer : Name oder IP-Adresse des FTP-Servers. notwendig !
          ftpTimeout : Timeout für die FTP-Verbindung in Sekunden (default: 30).
          -
        -
        -
        +
          + + + + + + + + + + + + + +
          ftpUse : FTP Transfer nach dem Dump wird eingeschaltet (ohne SSL Verschlüsselung)
          ftpUser : User zur Anmeldung am FTP-Server, default: anonymous
          ftpUseSSL : FTP Transfer mit SSL Verschlüsselung nach dem Dump wird eingeschaltet
          ftpDebug : Debugging des FTP Verkehrs zur Fehlersuche
          ftpDir : Verzeichnis auf dem FTP-Server in welches das File übertragen werden soll (default: "/")
          ftpDumpFilesKeep : Es wird die angegebene Anzahl Dumpfiles im <ftpDir> belassen (default: 3)
          ftpPassive : setzen wenn passives FTP verwendet werden soll
          ftpPort : FTP-Port, default: 21
          ftpPwd : Passwort des FTP-Users, default nicht gesetzt
          ftpServer : Name oder IP-Adresse des FTP-Servers. notwendig !
          ftpTimeout : Timeout für die FTP-Verbindung in Sekunden (default: 30).
          +
        +
        +
        -
      -
      +
    +
  • +
  • dumpSQLite - erstellt einen Dump der angeschlossenen SQLite-Datenbank.
    Diese Funktion nutzt die SQLite Online Backup API und ermöglicht es konsistente Backups der SQLite-DB @@ -18150,21 +18202,35 @@ return;
  • -
  • vacuum - optimiert die Tabellen in der angeschlossenen Datenbank (SQLite, PostgreSQL).
    - Vor und nach der Optimierung kann ein FHEM-Kommando ausgeführt werden. - (siehe Attribute executeBeforeProc, - executeAfterProc) -

    +
  • vacuum

    + + Optimiert die Tabellen in der angeschlossenen Datenbank (SQLite, PostgreSQL).
    + Insbesondere für SQLite Datenbanken ist unbedingt empfehlenswert die Verbindung des relevanten DbLog-Devices zur + Datenbank vorübergehend zu schließen (siehe DbLog reopen Kommando). +
    +
    + + Für diese Funktion sind folgende Attribute relevant:

    -
      - Hinweis:
      - Obwohl die Funktion selbst non-blocking ausgelegt ist, muß das zugeordnete DbLog-Device - im asynchronen Modus betrieben werden um ein Blockieren von FHEM zu vermeiden.

      - -

    +
      + + + + +
      executeBeforeProc : ausführen FHEM Kommando (oder Perl-Routine) vor Start des Befehls
      executeAfterProc : ausführen FHEM Kommando (oder Perl-Routine) nach Ende des Befehls
      +
    +
    +
    -
    - + Hinweis:
    + Bei der Ausführung des vacuum Kommandos wird bei SQLite Datenbanken automatisch das PRAGMA auto_vacuum = FULL + angewendet. +
  • +
    + +
    + + Für alle Auswertungsvarianten (Ausnahme sqlCmd,deviceRename,readingRename) gilt:
    Zusätzlich zu dem auszuwertenden Reading kann das Device mit angegeben werden um das Reporting nach diesen Kriterien einzuschränken. @@ -18534,6 +18600,7 @@ sub dbval {
  • dumpDirLocal

    +
      Zielverzeichnis für die Erstellung von Dumps mit "dumpMySQL clientSide" oder "dumpSQLite".
      @@ -18819,30 +18886,32 @@ sub bdump {
      -
    • seqDoubletsVariance <positive Abweichung [negative Abweichung] [EDGE=negative|positive]>
      - Akzeptierte Abweichung für das Kommando "set <name> delSeqDoublets".
      - Der Wert des Attributs beschreibt die Abweichung bis zu der aufeinanderfolgende numerische - Werte (VALUE) von Datensätzen als gleich angesehen werden sollen. - Ist in "seqDoubletsVariance" nur ein Zahlenwert angegeben, wird er sowohl als positive als - auch negative Abweichung verwendet und bilden den "Löschkorridor". - Optional kann ein zweiter Zahlenwert für eine negative Abweichung, getrennt durch - Leerzeichen, angegeben werden. - Es sind immer absolute, d.h. positive Zahlenwerte anzugeben.
      - Ist der Zusatz "EDGE=negative" angegeben, werden Werte an einer negativen Flanke - (z.B. beim Wechel von 4.0 -> 1.0) nicht gelöscht auch wenn sie sich im "Löschkorridor" - befinden. Entsprechendes gilt bei "EDGE=positive" für die positive Flanke (z.B. beim Wechel - von 1.2 -> 2.8). -

      +
    • seqDoubletsVariance <positive Abweichung [negative Abweichung] [EDGE=negative|positive]>

      + + Akzeptierte Abweichung für das Kommando "set <name> delSeqDoublets".
      + Der Wert des Attributs beschreibt die Abweichung bis zu der aufeinanderfolgende numerische + Werte (VALUE) von Datensätzen als gleich angesehen werden sollen. + Ist in "seqDoubletsVariance" nur ein Zahlenwert angegeben, wird er sowohl als positive als + auch negative Abweichung verwendet und bilden den "Löschkorridor". + Optional kann ein zweiter Zahlenwert für eine negative Abweichung, getrennt durch + Leerzeichen, angegeben werden. + Es sind immer absolute, d.h. positive Zahlenwerte anzugeben.
      + Ist der Zusatz "EDGE=negative" angegeben, werden Werte an einer negativen Flanke + (z.B. beim Wechel von 4.0 -> 1.0) nicht gelöscht auch wenn sie sich im "Löschkorridor" + befinden. Entsprechendes gilt bei "EDGE=positive" für die positive Flanke (z.B. beim Wechel + von 1.2 -> 2.8). +

      -
        - Beispiele:
        - attr <name> seqDoubletsVariance 0.0014
        - attr <name> seqDoubletsVariance 1.45
        - attr <name> seqDoubletsVariance 3.0 2.0
        - attr <name> seqDoubletsVariance 1.5 EDGE=negative
        -
      -

      -
    • +
        + Beispiele:
        + attr <name> seqDoubletsVariance 0.0014
        + attr <name> seqDoubletsVariance 1.45
        + attr <name> seqDoubletsVariance 3.0 2.0
        + attr <name> seqDoubletsVariance 1.5 EDGE=negative
        +
      +
      +
      +
    • showproctime - wenn gesetzt, zeigt das Reading "sql_processing_time" die benötigte Abarbeitungszeit (in Sekunden)