2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-01-31 12:49:34 +00:00

93_DbRep: contrib v 8.46.2

git-svn-id: https://svn.fhem.de/fhem/trunk@25328 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2021-12-08 21:55:10 +00:00
parent cf5e5d2135
commit d2159b1a50

View File

@ -1,5 +1,5 @@
########################################################################################################## ##########################################################################################################
# $Id: 93_DbRep.pm 25280 2021-12-01 21:44:21Z DS_Starter $ # $Id: 93_DbRep.pm 25321 2021-12-07 22:46:22Z DS_Starter $
########################################################################################################## ##########################################################################################################
# 93_DbRep.pm # 93_DbRep.pm
# #
@ -57,6 +57,7 @@ no if $] >= 5.017011, warnings => 'experimental::smartmatch';
# Version History intern # Version History intern
my %DbRep_vNotesIntern = ( my %DbRep_vNotesIntern = (
"8.46.2" => "08.12.2021 Pragma query possible in sqlCmd. So far only 'set', get encoding info from database ",
"8.46.1" => "07.12.2021 some code improvements ", "8.46.1" => "07.12.2021 some code improvements ",
"8.46.0" => "06.12.2021 reduceLog options INCLUDE / EXCLUCE parse by parseParams ", "8.46.0" => "06.12.2021 reduceLog options INCLUDE / EXCLUCE parse by parseParams ",
"8.45.0" => "05.12.2021 revised userExitFn, fix average=day problem in reduceLog (Forum: https://forum.fhem.de/index.php/topic,53584.msg1177799.html#msg1177799) ", "8.45.0" => "05.12.2021 revised userExitFn, fix average=day problem in reduceLog (Forum: https://forum.fhem.de/index.php/topic,53584.msg1177799.html#msg1177799) ",
@ -452,7 +453,7 @@ sub DbRep_Define {
$hash->{NOTIFYDEV} = "global,".$name; # nur Events dieser Devices an DbRep_Notify weiterleiten $hash->{NOTIFYDEV} = "global,".$name; # nur Events dieser Devices an DbRep_Notify weiterleiten
my $dbconn = $defs{$a[2]}{dbconn}; my $dbconn = $defs{$a[2]}{dbconn};
$hash->{DATABASE} = (split(/;|=/, $dbconn))[1]; $hash->{DATABASE} = (split(/;|=/, $dbconn))[1];
$hash->{UTF8} = defined($defs{$a[2]}{UTF8}) ? $defs{$a[2]}{UTF8} : 0; $hash->{UTF8} = defined($defs{$a[2]}{UTF8}) ? $defs{$a[2]}{UTF8} : 0; # wird in DbRep_getInitData aus DB abgefragt und neu gesetzt
# Versionsinformationen setzen # Versionsinformationen setzen
DbRep_setVersionInfo($hash); DbRep_setVersionInfo($hash);
@ -971,6 +972,7 @@ sub DbRep_Get {
"svrinfo:noArg ". "svrinfo:noArg ".
"blockinginfo:noArg ". "blockinginfo:noArg ".
"minTimestamp:noArg ". "minTimestamp:noArg ".
"initData:noArg ".
(($dbmodel =~ /MYSQL/)?"storedCredentials:noArg ":""). (($dbmodel =~ /MYSQL/)?"storedCredentials:noArg ":"").
"sqlCmdBlocking:textField-long ". "sqlCmdBlocking:textField-long ".
(($dbmodel eq "MYSQL")?"dbstatus:noArg ":""). (($dbmodel eq "MYSQL")?"dbstatus:noArg ":"").
@ -1019,14 +1021,17 @@ sub DbRep_Get {
ReadingsSingleUpdateValue ($hash, "state", "running", 1); ReadingsSingleUpdateValue ($hash, "state", "running", 1);
DbRep_getblockinginfo($hash); DbRep_getblockinginfo($hash);
} }
elsif ($opt eq "minTimestamp") { elsif ($opt eq "minTimestamp" || $opt eq "initData") {
return "Dump is running - try again later !" if($hash->{HELPER}{RUNNING_BACKUP_CLIENT}); return "Dump is running - try again later !" if($hash->{HELPER}{RUNNING_BACKUP_CLIENT});
$hash->{LASTCMD} = $prop ? "$opt $prop" : "$opt"; $hash->{LASTCMD} = $prop ? "$opt $prop" : "$opt";
$hash->{HELPER}{IDRETRIES} = 3; # Anzahl wie oft versucht wird initiale Daten zu holen
DbRep_delread ($hash); DbRep_delread ($hash);
ReadingsSingleUpdateValue ($hash, "state", "running", 1); ReadingsSingleUpdateValue ($hash, "state", "running", 1);
$hash->{HELPER}{IDRETRIES} = 3; # Anzahl wie oft versucht wird initiale Daten zu holen
$prop = $prop?$prop:''; $prop //= '';
DbRep_firstconnect("$name|$opt|$prop|"); DbRep_firstconnect("$name|$opt|$prop");
} }
elsif ($opt =~ /sqlCmdBlocking|dbValue/) { elsif ($opt =~ /sqlCmdBlocking|dbValue/) {
return qq{get "$opt" needs at least an argument} if ( @a < 3 ); return qq{get "$opt" needs at least an argument} if ( @a < 3 );
@ -1662,7 +1667,7 @@ return;
} }
#################################################################################################### ####################################################################################################
# DatenDatenbankeigenschaften ermitteln # Datenbankeigenschaften ermitteln
#################################################################################################### ####################################################################################################
sub DbRep_getInitData { sub DbRep_getInitData {
my $paref = shift; my $paref = shift;
@ -1670,11 +1675,10 @@ sub DbRep_getInitData {
my $name = $paref->{name}; my $name = $paref->{name};
my $opt = $paref->{opt}; my $opt = $paref->{opt};
my $prop = $paref->{prop}; my $prop = $paref->{prop};
my $fret = $paref->{fret}; my $fret = $paref->{fret} // '';
my $database = $hash->{DATABASE}; my $database = $hash->{DATABASE};
my $mintsdef = "1970-01-01 01:00:00"; my $mintsdef = "1970-01-01 01:00:00";
my $idxstate = "";
my $bst = [gettimeofday]; # Background-Startzeit my $bst = [gettimeofday]; # Background-Startzeit
@ -1687,13 +1691,39 @@ sub DbRep_getInitData {
my $st = [gettimeofday]; # SQL-Startzeit my $st = [gettimeofday]; # SQL-Startzeit
# ältesten Datensatz der DB ermitteln # ältesten Datensatz der DB ermitteln
my $mints = qq{}; ######################################
eval { $mints = $dbh->selectrow_array("SELECT min(TIMESTAMP) FROM history;"); }; my $mints = qq{undefined - $mintsdef is used instead};
eval { $mints = $dbh->selectrow_array("SELECT min(TIMESTAMP) FROM history;") };
Log3 ($name, 4, "DbRep $name - Oldest timestamp determined: $mints");
$mints = $mints =~ /undefined/x ? $mintsdef : $mints;
# Encoding der Datenbank ermitteln
####################################
my $enc = qq{undefined};
my @se;
if($dbmodel =~ /MYSQL/) {
eval { @se = $dbh->selectrow_array("SHOW VARIABLES LIKE 'character_set_database';") };
$enc = @se ? uc($se[1]) : $enc;
}
elsif($dbmodel =~ /SQLITE/) {
eval { $enc = $dbh->selectrow_array("PRAGMA encoding;") };
}
elsif($dbmodel =~ /POSTGRESQL/) {
eval { $enc = $dbh->selectrow_array("select character_set_name from information_schema.character_sets;") };
}
Log3 ($name, 4, "DbRep $name - Encoding of database determined: $enc");
# Report_Idx Status ermitteln # Report_Idx Status ermitteln
my ($ava,$sqlava); ##############################
my $idxstate = '';
my $idx = "Report_Idx"; my $idx = "Report_Idx";
my ($ava,$sqlava);
if($dbmodel =~ /MYSQL/) { if($dbmodel =~ /MYSQL/) {
$sqlava = "SHOW INDEX FROM history where Key_name='$idx';"; $sqlava = "SHOW INDEX FROM history where Key_name='$idx';";
} }
@ -1712,26 +1742,31 @@ sub DbRep_getInitData {
else { else {
if($hash->{LASTCMD} ne "minTimestamp") { if($hash->{LASTCMD} ne "minTimestamp") {
if($ava) { if($ava) {
$idxstate = "Index $idx exists"; $idxstate = qq{Index $idx exists};
Log3($name, 3, "DbRep $name - $idxstate. Check ok"); Log3($name, 3, "DbRep $name - $idxstate. Check ok");
} }
else { else {
$idxstate = "Index $idx doesn't exist. Please create the index by \"set $name index recreate_Report_Idx\" command !"; $idxstate = qq{Index $idx doesn't exist. Please create the index by "set $name index recreate_Report_Idx" command !};
Log3($name, 3, "DbRep $name - WARNING - $idxstate"); Log3($name, 3, "DbRep $name - WARNING - $idxstate");
} }
} }
} }
# effektive Userrechte in MYSQL ermitteln # effektive Userrechte in MYSQL ermitteln
my ($grants,$sth,@uniq); ##########################################
my $grants = '';
my ($sth,@uniq);
if($dbmodel =~ /MYSQL/) { if($dbmodel =~ /MYSQL/) {
eval {$sth = $dbh->prepare("SHOW GRANTS FOR CURRENT_USER();"); $sth->execute();}; eval {$sth = $dbh->prepare("SHOW GRANTS FOR CURRENT_USER();");
$sth->execute();
};
if($@) { if($@) {
Log3($name, 2, "DbRep $name - WARNING - user rights couldn't be determined: ".$@); Log3($name, 2, "DbRep $name - WARNING - user rights couldn't be determined: ".$@);
} }
else { else {
my $row = ""; my $row = "";
while (my @line = $sth->fetchrow_array()) { while (my @line = $sth->fetchrow_array()) {
for my $l (@line) { for my $l (@line) {
next if($l !~ /(\s+ON \*\.\*\s+|\s+ON `$database`)/ ); next if($l !~ /(\s+ON \*\.\*\s+|\s+ON `$database`)/ );
@ -1750,9 +1785,9 @@ sub DbRep_getInitData {
} }
@uniq = keys %seen; @uniq = keys %seen;
$grants = join(",",@uniq); $grants = join ",", @uniq;
Log3 ($name, 4, "DbRep $name - all grants: $grants"); Log3 ($name, 4, "DbRep $name - Grants determined: $grants");
} }
} }
@ -1760,11 +1795,10 @@ sub DbRep_getInitData {
my $rt = tv_interval($st); # SQL-Laufzeit ermitteln my $rt = tv_interval($st); # SQL-Laufzeit ermitteln
Log3 ($name, 5, "DbRep $name - minimum timestamp found in database: $mints"); $enc = encode_base64($enc, "");
$mints = encode_base64($mints, "");
$mints = $mints ? encode_base64($mints, "") : encode_base64($mintsdef, "");
$idxstate = encode_base64($idxstate, ""); $idxstate = encode_base64($idxstate, "");
$grants = encode_base64($grants, "") if($grants); $grants = encode_base64($grants, "");
my $brt = tv_interval($bst); # Background-Laufzeit ermitteln my $brt = tv_interval($bst); # Background-Laufzeit ermitteln
@ -1773,7 +1807,7 @@ sub DbRep_getInitData {
$opt = DbRep_trim ($opt) if($opt); $opt = DbRep_trim ($opt) if($opt);
$prop = DbRep_trim ($prop) if($prop); $prop = DbRep_trim ($prop) if($prop);
return "$name|$mints|$rt|0|$opt|$prop|$fret|$idxstate|$grants"; return "$name|$mints|$rt|0|$opt|$prop|$fret|$idxstate|$grants|$enc";
} }
#################################################################################################### ####################################################################################################
@ -1781,20 +1815,19 @@ return "$name|$mints|$rt|0|$opt|$prop|$fret|$idxstate|$grants";
#################################################################################################### ####################################################################################################
sub DbRep_getInitDataDone { sub DbRep_getInitDataDone {
my $string = shift; my $string = shift;
my @a = split("\\|",$string); my @a = split "\\|", $string;
my $hash = $defs{$a[0]}; my $hash = $defs{$a[0]};
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $mints = decode_base64($a[1]); my $mints = decode_base64($a[1]);
my $bt = $a[2]; my $bt = $a[2];
my ($rt,$brt) = split(",", $bt); my ($rt,$brt) = split ",", $bt;
my $err = $a[3] ? decode_base64($a[3]) : undef; my $err = $a[3] ? decode_base64($a[3]) : undef;
my $opt = $a[4]; my $opt = $a[4];
my $prop = $a[5]; my $prop = $a[5];
my $fret; my $fret = $a[6] ? \&{$a[6]} : undef;
$fret = \&{$a[6]} if($a[6]); my $idxstate = decode_base64($a[7]);
my $grants = $a[8] ? decode_base64($a[8]) : '';
my $idxstate = $a[7] ? decode_base64($a[7]) : ""; my $enc = decode_base64($a[9]);
my $grants = $a[8] ? decode_base64($a[8]) : "";
my $dbloghash = $defs{$hash->{HELPER}{DBLOGDEVICE}}; my $dbloghash = $defs{$hash->{HELPER}{DBLOGDEVICE}};
my $dbconn = $dbloghash->{dbconn}; my $dbconn = $dbloghash->{dbconn};
@ -1809,19 +1842,30 @@ sub DbRep_getInitDataDone {
else { else {
Log3 ($name, 3, "DbRep $name - Initial data information retrieved - total time used: ".sprintf("%.4f",$brt)." seconds"); Log3 ($name, 3, "DbRep $name - Initial data information retrieved - total time used: ".sprintf("%.4f",$brt)." seconds");
my $state = ($hash->{LASTCMD} eq "minTimestamp")?"done":"connected"; my $state = ($hash->{LASTCMD} =~ /minTimestamp|initData/x) ? "done" : "connected";
$state = qq{invalid timestamp "$mints" found in database - please delete it} if($mints =~ /^0000-00-00.*$/); $state = qq{invalid timestamp "$mints" found in database - please delete it} if($mints =~ /^0000-00-00.*$/);
readingsBeginUpdate ($hash); readingsBeginUpdate ($hash);
ReadingsBulkUpdateValue ($hash, "timestamp_oldest_dataset", $mints) if($hash->{LASTCMD} eq "minTimestamp");
ReadingsBulkUpdateValue ($hash, "index_state", $idxstate) if($hash->{LASTCMD} ne "minTimestamp"); if($hash->{LASTCMD} eq "minTimestamp") {
ReadingsBulkUpdateValue ($hash, "timestamp_oldest_dataset", $mints);
}
else {
ReadingsBulkUpdateValue ($hash, "dbEncoding", $enc);
ReadingsBulkUpdateValue ($hash, "indexState", $idxstate);
ReadingsBulkUpdateValue ($hash, "timestamp_oldest_dataset", $mints);
ReadingsBulkUpdateValue ($hash, "userRights", $grants) if($grants);
}
ReadingsBulkUpdateTimeState ($hash,$brt,$rt,$state); ReadingsBulkUpdateTimeState ($hash,$brt,$rt,$state);
readingsEndUpdate ($hash, 1); readingsEndUpdate ($hash, 1);
Log3 ($name, 3, "DbRep $name - Connectiontest to db $dbconn successful") if($hash->{LASTCMD} ne "minTimestamp"); Log3 ($name, 3, "DbRep $name - Connectiontest to db $dbconn successful") if($hash->{LASTCMD} !~ /minTimestamp|initData/x);
$hash->{HELPER}{MINTS} = $mints; $hash->{HELPER}{MINTS} = $mints;
$hash->{HELPER}{GRANTS} = $grants if($grants); $hash->{HELPER}{GRANTS} = $grants if($grants);
$hash->{UTF8} = $enc =~ /UTF-?8/x ? 1 : 0;
} }
Log3 ($name, 5, qq{DbRep $name - getInitData finished PID "$hash->{HELPER}{RUNNING_PID}{pid}"}); Log3 ($name, 5, qq{DbRep $name - getInitData finished PID "$hash->{HELPER}{RUNNING_PID}{pid}"});
@ -1888,7 +1932,7 @@ sub DbRep_dbConnect {
} }
} }
Log3 ($name, 4, "DbRep $name - Database connect - user: ".($dbuser ? $dbuser : 'no').", UTF8 option set: ".($utf8 ? 'yes' : 'no')); Log3 ($name, 4, "DbRep $name - Database connect - user: ".($dbuser ? $dbuser : 'no').", UTF-8 option set: ".($utf8 ? 'yes' : 'no'));
eval { $dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, eval { $dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0,
RaiseError => 1, RaiseError => 1,
@ -3563,18 +3607,14 @@ sub maxval_DoParse {
my ($string) = @_; my ($string) = @_;
my ($name,$device,$reading,$prop,$ts) = split("\\§", $string); my ($name,$device,$reading,$prop,$ts) = split("\\§", $string);
my $hash = $defs{$name}; my $hash = $defs{$name};
my $dbloghash = $defs{$hash->{HELPER}{DBLOGDEVICE}};
my $dbconn = $dbloghash->{dbconn}; my ($sql,$sth);
my $dbuser = $dbloghash->{dbuser};
my $dblogname = $dbloghash->{NAME};
my $dbpassword = $attr{"sec$dblogname"}{secret};
my ($dbh,$sql,$sth,$err);
# Background-Startzeit # Background-Startzeit
my $bst = [gettimeofday]; my $bst = [gettimeofday];
eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1, AutoInactiveDestroy => 1 });}; my ($err,$dbh,$dbmodel) = DbRep_dbConnect($name, 0);
if ($@) { if ($err) {
$err = encode_base64($@,""); $err = encode_base64($@,"");
Log3 ($name, 2, "DbRep $name - $@"); Log3 ($name, 2, "DbRep $name - $@");
return "$name|''|$device|$reading|''|$err|''"; return "$name|''|$device|$reading|''|$err|''";
@ -3596,7 +3636,7 @@ sub maxval_DoParse {
# DB-Abfrage zeilenweise für jeden Array-Eintrag # DB-Abfrage zeilenweise für jeden Array-Eintrag
my @row_array; my @row_array;
foreach my $row (@ts) { for my $row (@ts) {
my @a = split("#", $row); my @a = split("#", $row);
my $runtime_string = $a[0]; my $runtime_string = $a[0];
my $runtime_string_first = $a[1]; my $runtime_string_first = $a[1];
@ -3818,18 +3858,14 @@ sub minval_DoParse {
my ($string) = @_; my ($string) = @_;
my ($name,$device,$reading,$prop,$ts) = split("\\§", $string); my ($name,$device,$reading,$prop,$ts) = split("\\§", $string);
my $hash = $defs{$name}; my $hash = $defs{$name};
my $dbloghash = $defs{$hash->{HELPER}{DBLOGDEVICE}};
my $dbconn = $dbloghash->{dbconn}; my ($sql,$sth);
my $dbuser = $dbloghash->{dbuser};
my $dblogname = $dbloghash->{NAME};
my $dbpassword = $attr{"sec$dblogname"}{secret};
my ($dbh,$sql,$sth,$err);
# Background-Startzeit # Background-Startzeit
my $bst = [gettimeofday]; my $bst = [gettimeofday];
eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1, AutoInactiveDestroy => 1 });}; my ($err,$dbh,$dbmodel) = DbRep_dbConnect($name, 0);
if ($@) { if ($err) {
$err = encode_base64($@,""); $err = encode_base64($@,"");
Log3 ($name, 2, "DbRep $name - $@"); Log3 ($name, 2, "DbRep $name - $@");
return "$name|''|$device|$reading|''|$err|''"; return "$name|''|$device|$reading|''|$err|''";
@ -4073,28 +4109,18 @@ sub diffval_DoParse {
my $string = shift; my $string = shift;
my ($name,$device,$reading,$prop,$ts) = split("\\§", $string); my ($name,$device,$reading,$prop,$ts) = split("\\§", $string);
my $hash = $defs{$name}; 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 $dbpassword = $attr{"sec$dblogname"}{secret};
my ($dbh,$sql,$sth,$err,$selspec); my ($sql,$sth,$selspec);
# Background-Startzeit # Background-Startzeit
my $bst = [gettimeofday]; my $bst = [gettimeofday];
eval { $dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, my ($err,$dbh,$dbmodel) = DbRep_dbConnect($name, 0);
RaiseError => 1, if ($err) {
AutoInactiveDestroy => 1 $err = encode_base64($@, "");
}
); 1;
}
or do { $err = encode_base64($@,"");
Log3 ($name, 2, "DbRep $name - $@"); Log3 ($name, 2, "DbRep $name - $@");
return "$name|''|$device|$reading|''|''|''|$err|''"; return "$name|''|$device|$reading|''|''|''|$err|''";
}; }
# only for this block because of warnings if details of readings are not set # only for this block because of warnings if details of readings are not set
no warnings 'uninitialized'; no warnings 'uninitialized';
@ -4641,16 +4667,19 @@ sub del_DoParse {
my $string = shift; my $string = shift;
my ($name,$table,$device,$reading,$runtime_string_first,$runtime_string_next) = split("\\|", $string); my ($name,$table,$device,$reading,$runtime_string_first,$runtime_string_next) = split("\\|", $string);
my $hash = $defs{$name}; my $hash = $defs{$name};
my $dbloghash = $defs{$hash->{HELPER}{DBLOGDEVICE}};
my $dbconn = $dbloghash->{dbconn}; my ($sql,$sth,$rows);
my $dbuser = $dbloghash->{dbuser};
my $dblogname = $dbloghash->{NAME};
my $dbpassword = $attr{"sec$dblogname"}{secret};
my ($dbh,$sql,$sth,$err,$rows);
# Background-Startzeit # Background-Startzeit
my $bst = [gettimeofday]; my $bst = [gettimeofday];
my ($err,$dbh,$dbmodel) = DbRep_dbConnect($name, 0);
if ($err) {
$err = encode_base64($@,"");
Log3 ($name, 2, "DbRep $name - $@");
return "$name|''|''|$err|''|''|''";
}
# ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef) # ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef)
my ($IsTimeSet,$IsAggrSet) = DbRep_checktimeaggr($hash); my ($IsTimeSet,$IsAggrSet) = DbRep_checktimeaggr($hash);
Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet"); Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet");
@ -4660,16 +4689,9 @@ sub del_DoParse {
# SQL zusammenstellen für DB-Operation # SQL zusammenstellen für DB-Operation
if ($IsTimeSet || $IsAggrSet) { if ($IsTimeSet || $IsAggrSet) {
$sql = DbRep_createDeleteSql($hash,$table,$device,$reading,$runtime_string_first,$runtime_string_next,''); $sql = DbRep_createDeleteSql($hash,$table,$device,$reading,$runtime_string_first,$runtime_string_next,'');
} else {
$sql = DbRep_createDeleteSql($hash,$table,$device,$reading,undef,undef,'');
} }
else {
eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1, AutoCommit => 1, AutoInactiveDestroy => 1 });}; $sql = DbRep_createDeleteSql($hash,$table,$device,$reading,undef,undef,'');
if ($@) {
$err = encode_base64($@,"");
Log3 ($name, 2, "DbRep $name - $@");
return "$name|''|''|$err|''|''|''";
} }
$sth = $dbh->prepare($sql); $sth = $dbh->prepare($sql);
@ -4910,21 +4932,14 @@ sub currentfillup_Push {
my ($name,$device,$reading,$runtime_string_first,$runtime_string_next) = split("\\|", $string); my ($name,$device,$reading,$runtime_string_first,$runtime_string_next) = split("\\|", $string);
my $hash = $defs{$name}; my $hash = $defs{$name};
my $dbloghash = $defs{$hash->{HELPER}{DBLOGDEVICE}}; my $dbloghash = $defs{$hash->{HELPER}{DBLOGDEVICE}};
my $dbconn = $dbloghash->{dbconn};
my $dbuser = $dbloghash->{dbuser};
my $dblogname = $dbloghash->{NAME};
my $dbpassword = $attr{"sec$dblogname"}{secret};
my $utf8 = $hash->{UTF8} // 0;
my ($err,$sth,$sql,$selspec,$addon,@dwc,@rwc); my ($sth,$sql,$selspec,$addon,@dwc,@rwc);
# Background-Startzeit # Background-Startzeit
my $bst = [gettimeofday]; my $bst = [gettimeofday];
my $dbh; my ($err,$dbh,$dbmodel) = DbRep_dbConnect($name, 0);
eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1, AutoCommit => 1, AutoInactiveDestroy => 1, mysql_enable_utf8 => $utf8 });}; if ($err) {
if ($@) {
$err = encode_base64($@,""); $err = encode_base64($@,"");
Log3 ($name, 2, "DbRep $name - $@"); Log3 ($name, 2, "DbRep $name - $@");
return "$name|''|''|$err|''|''"; return "$name|''|''|$err|''|''";
@ -6091,44 +6106,40 @@ sub expfile_DoParse {
my $string = shift; my $string = shift;
my ($name, $device, $reading, $rsf, $file, $ts) = split("\\§", $string); my ($name, $device, $reading, $rsf, $file, $ts) = split("\\§", $string);
my $hash = $defs{$name}; my $hash = $defs{$name};
my $dbloghash = $defs{$hash->{HELPER}{DBLOGDEVICE}};
my $dbconn = $dbloghash->{dbconn};
my $dbuser = $dbloghash->{dbuser};
my $dblogname = $dbloghash->{NAME};
my $dbpassword = $attr{"sec$dblogname"}{secret};
my $utf8 = $hash->{UTF8} // 0;
my ($dbh,$sth,$sql); my ($sth,$sql);
my $err=0;
# Background-Startzeit # Background-Startzeit
my $bst = [gettimeofday]; my $bst = [gettimeofday];
eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1, AutoInactiveDestroy => 1, mysql_enable_utf8 => $utf8 });}; my ($err,$dbh,$dbmodel) = DbRep_dbConnect($name, 0);
if ($err) {
if ($@) {
$err = encode_base64($@,""); $err = encode_base64($@,"");
Log3 ($name, 2, "DbRep $name - $@"); Log3 ($name, 2, "DbRep $name - $@");
return "$name|''|''|$err|''|''|''"; return "$name|''|''|$err|''|''|''";
} }
my $ml; my $ml;
my $part = "."; my $part = ".";
if($file =~ /MAXLINES=/) { if($file =~ /MAXLINES=/) {
my ($arrayref, $hashref) = parseParams($file); my ($arrayref, $hashref) = parseParams($file);
my @a = @{$arrayref}; my @a = @{$arrayref};
my %h = %{$hashref}; my %h = %{$hashref};
$file = $a[0]; $file = $a[0];
if(!$file) { if(!$file) {
($arrayref, undef) = parseParams(AttrVal($name,"expimpfile","")); ($arrayref, undef) = parseParams(AttrVal($name,"expimpfile",""));
@a = @{$arrayref}; @a = @{$arrayref};
$file = $a[0]; $file = $a[0];
} }
$ml = $h{MAXLINES}; $ml = $h{MAXLINES};
if($ml !~ /^\d+$/) { if($ml !~ /^\d+$/) {
undef $ml; undef $ml;
} else { }
else {
$part = "_part1."; $part = "_part1.";
} }
} }
@ -6145,7 +6156,8 @@ sub expfile_DoParse {
if (open(FH, ">", $outfile)) { if (open(FH, ">", $outfile)) {
binmode (FH); binmode (FH);
} else { }
else {
$err = encode_base64("could not open ".$outfile.": ".$!,""); $err = encode_base64("could not open ".$outfile.": ".$!,"");
return "$name|''|''|$err|''|''|''"; return "$name|''|''|$err|''|''|''";
} }
@ -6166,8 +6178,10 @@ sub expfile_DoParse {
my ($nrows,$frows) = (0,0); my ($nrows,$frows) = (0,0);
my $p = 2; my $p = 2;
my $addon = "ORDER BY TIMESTAMP"; my $addon = "ORDER BY TIMESTAMP";
no warnings 'uninitialized'; no warnings 'uninitialized';
foreach my $row (@ts) {
for my $row (@ts) {
my @a = split("#", $row); my @a = split("#", $row);
my $runtime_string = $a[0]; my $runtime_string = $a[0];
my $runtime_string_first = $a[1]; my $runtime_string_first = $a[1];
@ -6196,16 +6210,20 @@ sub expfile_DoParse {
# Anzahl der Datensätze # Anzahl der Datensätze
$nrows++; $nrows++;
$frows++; $frows++;
if($ml && $frows >= $ml) { if($ml && $frows >= $ml) {
Log3 ($name, 3, "DbRep $name - Number of exported datasets from $hash->{DATABASE} to file $outfile: ".$frows); Log3 ($name, 3, "DbRep $name - Number of exported datasets from $hash->{DATABASE} to file $outfile: ".$frows);
close(FH); close(FH);
$outfile = $f."_part$p.".$e; $outfile = $f."_part$p.".$e;
if (open(FH, ">", $outfile)) { if (open(FH, ">", $outfile)) {
binmode (FH); binmode (FH);
} else { }
else {
$err = encode_base64("could not open ".$outfile.": ".$!,""); $err = encode_base64("could not open ".$outfile.": ".$!,"");
return "$name|''|''|$err|''|''|''"; return "$name|''|''|$err|''|''|''";
} }
$p++; $p++;
$frows = 0; $frows = 0;
} }
@ -6285,23 +6303,14 @@ sub impfile_Push {
my ($name, $rsf, $file) = split("\\|", $string); my ($name, $rsf, $file) = split("\\|", $string);
my $hash = $defs{$name}; my $hash = $defs{$name};
my $dbloghash = $defs{$hash->{HELPER}{DBLOGDEVICE}}; my $dbloghash = $defs{$hash->{HELPER}{DBLOGDEVICE}};
my $dbconn = $dbloghash->{dbconn};
my $dbuser = $dbloghash->{dbuser};
my $dblogname = $dbloghash->{NAME};
my $dbmodel = $dbloghash->{MODEL};
my $dbpassword = $attr{"sec$dblogname"}{secret};
my $utf8 = $hash->{UTF8} // 0;
my $err = 0;
my $sth; my $sth;
# Background-Startzeit # Background-Startzeit
my $bst = [gettimeofday]; my $bst = [gettimeofday];
my $dbh; my ($err,$dbh,$dbmodel) = DbRep_dbConnect($name, 0);
eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1, AutoCommit => 1, AutoInactiveDestroy => 1, mysql_enable_utf8 => $utf8 });}; if ($err) {
if ($@) {
$err = encode_base64($@,""); $err = encode_base64($@,"");
Log3 ($name, 2, "DbRep $name - $@"); Log3 ($name, 2, "DbRep $name - $@");
return "$name|''|''|$err|''"; return "$name|''|''|$err|''";
@ -6487,37 +6496,30 @@ sub sqlCmd_DoParse {
my $string = shift; my $string = shift;
my ($name, $opt, $runtime_string_first, $runtime_string_next, $cmd) = split("\\|", $string); my ($name, $opt, $runtime_string_first, $runtime_string_next, $cmd) = split("\\|", $string);
my $hash = $defs{$name}; my $hash = $defs{$name};
my $dbloghash = $defs{$hash->{HELPER}{DBLOGDEVICE}};
my $dbconn = $dbloghash->{dbconn};
my $dbuser = $dbloghash->{dbuser};
my $dblogname = $dbloghash->{NAME};
my $dbpassword = $attr{"sec$dblogname"}{secret};
my $utf8 = $hash->{UTF8} // 0;
my $srs = AttrVal($name, "sqlResultFieldSep", "|"); my $srs = AttrVal($name, "sqlResultFieldSep", "|");
my $device = AttrVal($name, "device", undef); my $device = AttrVal($name, "device", undef);
my $reading = AttrVal($name, "reading", undef); my $reading = AttrVal($name, "reading", undef);
my ($err,$dbh,@pms);
# Background-Startzeit # Background-Startzeit
my $bst = [gettimeofday]; my $bst = [gettimeofday];
($err,$dbh) = DbRep_dbConnect($name, 0); my ($err,$dbh,$dbmodel) = DbRep_dbConnect($name, 0);
if ($err) { if ($err) {
$err = encode_base64($err,""); $err = encode_base64($err,"");
return "$name|''|$opt|$cmd|''|''|$err"; return "$name|''|$opt|$cmd|''|''|$err";
} }
# only for this block because of warnings if details of readings are not set
no warnings 'uninitialized'; no warnings 'uninitialized';
$cmd =~ s/\;\;/ESC_ESC_ESC/gx; # ersetzen von escapeten ";" (;;) $cmd =~ s/\;\;/ESC_ESC_ESC/gx; # ersetzen von escapeten ";" (;;)
my $sql = ($cmd =~ m/\;$/) ? $cmd : $cmd.";"; my $sql = $cmd =~ m/\;$/ ? $cmd : $cmd.";";
# Set Session Variablen "SET" oder PRAGMA aus Attribut "sqlCmdVars" # Set Session Variablen "SET" oder PRAGMA aus Attribut "sqlCmdVars"
my @pms;
my $vars = AttrVal($name, "sqlCmdVars", ""); my $vars = AttrVal($name, "sqlCmdVars", "");
if ($vars) { if ($vars) {
@pms = split(";",$vars); @pms = split(";",$vars);
@ -6527,10 +6529,10 @@ sub sqlCmd_DoParse {
} }
$pm = ltrim($pm).";"; $pm = ltrim($pm).";";
$pm =~ s/ESC_ESC_ESC/;/gx; # wiederherstellen von escapeten ";" -> umwandeln von ";;" in ";" $pm =~ s/ESC_ESC_ESC/;/gx; # wiederherstellen von escapeten ";" -> umwandeln von ";;" in ";"
Log3($name, 4, "DbRep $name - Set VARIABLE or PRAGMA: $pm"); Log3($name, 4, "DbRep $name - Set VARIABLE or PRAGMA: $pm");
eval {$dbh->do($pm);};
if ($@) { eval { $dbh->do($pm) } or do { $err = encode_base64($@, "");
$err = encode_base64($@,"");
Log3 ($name, 2, "DbRep $name - ERROR - $@"); Log3 ($name, 2, "DbRep $name - ERROR - $@");
$dbh->disconnect; $dbh->disconnect;
return "$name|''|$opt|$sql|''|''|$err"; return "$name|''|$opt|$sql|''|''|$err";
@ -6556,9 +6558,7 @@ sub sqlCmd_DoParse {
Log3($name, 4, "DbRep $name - Set SQL session variable: $pm"); Log3($name, 4, "DbRep $name - Set SQL session variable: $pm");
eval {$dbh->do($pm);}; eval { $dbh->do($pm) } or do { $err = encode_base64($@, "");
if ($@) {
$err = encode_base64($@,"");
Log3 ($name, 2, "DbRep $name - ERROR - $@"); Log3 ($name, 2, "DbRep $name - ERROR - $@");
$dbh->disconnect; $dbh->disconnect;
return "$name|''|$opt|$sql|''|''|$err"; return "$name|''|$opt|$sql|''|''|$err";
@ -6569,12 +6569,12 @@ sub sqlCmd_DoParse {
# Abarbeitung aller Pragmas vor einem SQLite Statement, SQL wird extrahiert # Abarbeitung aller Pragmas vor einem SQLite Statement, SQL wird extrahiert
# wenn Pragmas im SQL vorangestellt sind # wenn Pragmas im SQL vorangestellt sind
if($cmd =~ /^\s*PRAGMA.*;/i) { if($cmd =~ /^\s*PRAGMA.*;/i) {
@pms = split(";",$cmd); @pms = split ";", $cmd;
$sql = q{}; $sql = q{};
for my $pm (@pms) { for my $pm (@pms) {
if($pm !~ /PRAGMA/i) { if($pm !~ /PRAGMA.*=/i) { # PRAGMA ohne "=" werden als SQL-Statement mit Abfrageergebnis behandelt
$sql .= $pm.";"; $sql .= $pm.";";
next; next;
} }
@ -6584,9 +6584,7 @@ sub sqlCmd_DoParse {
Log3($name, 4, "DbRep $name - Exec PRAGMA Statement: $pm"); Log3($name, 4, "DbRep $name - Exec PRAGMA Statement: $pm");
eval {$dbh->do($pm);}; eval { $dbh->do($pm) } or do { $err = encode_base64($@, "");
if ($@) {
$err = encode_base64($@,"");
Log3 ($name, 2, "DbRep $name - ERROR - $@"); Log3 ($name, 2, "DbRep $name - ERROR - $@");
$dbh->disconnect; $dbh->disconnect;
return "$name|''|$opt|$sql|''|''|$err"; return "$name|''|$opt|$sql|''|''|$err";
@ -6611,9 +6609,7 @@ sub sqlCmd_DoParse {
Log3($name, 4, "DbRep $name - Exec PREPARE statement: $pm"); Log3($name, 4, "DbRep $name - Exec PREPARE statement: $pm");
eval {$dbh->do($pm);}; eval { $dbh->do($pm) } or do { $err = encode_base64($@, "");
if ($@) {
$err = encode_base64($@,"");
Log3 ($name, 2, "DbRep $name - ERROR - $@"); Log3 ($name, 2, "DbRep $name - ERROR - $@");
$dbh->disconnect; $dbh->disconnect;
return "$name|''|$opt|$sql|''|''|$err"; return "$name|''|$opt|$sql|''|''|$err";
@ -6638,14 +6634,12 @@ sub sqlCmd_DoParse {
eval {$sth = $dbh->prepare($sql); eval {$sth = $dbh->prepare($sql);
$r = $sth->execute(); $r = $sth->execute();
}; }
or do { $err = encode_base64($@, "");
if ($@) {
$err = encode_base64($@,"");
Log3 ($name, 2, "DbRep $name - ERROR - $@"); Log3 ($name, 2, "DbRep $name - ERROR - $@");
$dbh->disconnect; $dbh->disconnect;
return "$name|''|$opt|$sql|''|''|$err"; return "$name|''|$opt|$sql|''|''|$err";
} };
my (@rows,$row,@head); my (@rows,$row,@head);
my $nrows = 0; my $nrows = 0;
@ -6667,7 +6661,6 @@ sub sqlCmd_DoParse {
# Anzahl der Datensätze # Anzahl der Datensätze
$nrows++; $nrows++;
} }
} else { } else {
$nrows = $sth->rows; $nrows = $sth->rows;
eval {$dbh->commit() if(!$dbh->{AutoCommit});}; eval {$dbh->commit() if(!$dbh->{AutoCommit});};
@ -12144,12 +12137,12 @@ sub DbRep_setVersionInfo {
if($modules{$type}{META}{x_prereqs_src} && !$hash->{HELPER}{MODMETAABSENT}) { if($modules{$type}{META}{x_prereqs_src} && !$hash->{HELPER}{MODMETAABSENT}) {
# META-Daten sind vorhanden # META-Daten sind vorhanden
$modules{$type}{META}{version} = "v".$v; # Version aus META.json überschreiben, Anzeige mit {Dumper $modules{SMAPortal}{META}} $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 25280 2021-12-01 21:44:21Z DS_Starter $ im Kopf komplett! vorhanden ) if($modules{$type}{META}{x_version}) { # {x_version} ( nur gesetzt wenn $Id: 93_DbRep.pm 25321 2021-12-07 22:46:22Z DS_Starter $ im Kopf komplett! vorhanden )
$modules{$type}{META}{x_version} =~ s/1.1.1/$v/g; $modules{$type}{META}{x_version} =~ s/1.1.1/$v/g;
} else { } else {
$modules{$type}{META}{x_version} = $v; $modules{$type}{META}{x_version} = $v;
} }
return $@ unless (FHEM::Meta::SetInternals($hash)); # FVERSION wird gesetzt ( nur gesetzt wenn $Id: 93_DbRep.pm 25280 2021-12-01 21:44:21Z DS_Starter $ im Kopf komplett! vorhanden ) return $@ unless (FHEM::Meta::SetInternals($hash)); # FVERSION wird gesetzt ( nur gesetzt wenn $Id: 93_DbRep.pm 25321 2021-12-07 22:46:22Z DS_Starter $ im Kopf komplett! vorhanden )
if(__PACKAGE__ eq "FHEM::$type" || __PACKAGE__ eq $type) { if(__PACKAGE__ eq "FHEM::$type" || __PACKAGE__ eq $type) {
# es wird mit Packages gearbeitet -> Perl übliche Modulversion setzen # es wird mit Packages gearbeitet -> Perl übliche Modulversion setzen
# mit {<Modul>->VERSION()} im FHEMWEB kann Modulversion abgefragt werden # mit {<Modul>->VERSION()} im FHEMWEB kann Modulversion abgefragt werden