2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-21 07:56:03 +00:00

93_DbRep: contrib V 8.53.8

git-svn-id: https://svn.fhem.de/fhem/trunk@28672 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2024-03-17 10:05:59 +00:00
parent 1c0bf47281
commit f1f99a99be

View File

@ -1,5 +1,5 @@
########################################################################################################## ##########################################################################################################
# $Id: 93_DbRep.pm 28621 2024-03-08 23:25:01Z DS_Starter $ # $Id: 93_DbRep.pm 28668 2024-03-16 20:01:55Z DS_Starter $
########################################################################################################## ##########################################################################################################
# 93_DbRep.pm # 93_DbRep.pm
# #
@ -59,6 +59,11 @@ no if $] >= 5.017011, warnings => 'experimental::smartmatch';
# Version History intern # Version History intern
my %DbRep_vNotesIntern = ( my %DbRep_vNotesIntern = (
"8.53.8" => "17.03.2024 sqlCmdBlocking able to use sql Keywords (§timestamp_end§ etc.) ",
"8.53.7" => "16.03.2024 prevent some attribute evaluation as long as init_done is not set ",
"8.53.6" => "15.03.2024 change verbose level of DbRep_beforeproc, DbRep_afterproc to 3 ",
"8.53.5" => "11.03.2024 some changes for MariaDB Perl driver usage, change DbRep_dbConnect".
"support compression between client and server ",
"8.53.4" => "09.03.2024 Ready for support of MariaDB Perl driver ", "8.53.4" => "09.03.2024 Ready for support of MariaDB Perl driver ",
"8.53.3" => "06.03.2024 delete attribute allowDeletion, multiCmd: executeBeforeProc, executeAfterProc as attributes ". "8.53.3" => "06.03.2024 delete attribute allowDeletion, multiCmd: executeBeforeProc, executeAfterProc as attributes ".
"Set: all commands are executable even if \$dbloghash->{HELPER}{REOPEN_RUNS_UNTIL}is set ". "Set: all commands are executable even if \$dbloghash->{HELPER}{REOPEN_RUNS_UNTIL}is set ".
@ -498,7 +503,6 @@ 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; # wird in DbRep_getInitData aus DB abgefragt und neu gesetzt
DbRep_setVersionInfo ($hash); # Versionsinformationen setzen DbRep_setVersionInfo ($hash); # Versionsinformationen setzen
DbRep_initSQLcmdCache ($name); # SQL Kommando Cache initialisieren DbRep_initSQLcmdCache ($name); # SQL Kommando Cache initialisieren
@ -1465,7 +1469,7 @@ sub DbRep_Get {
return $ret; return $ret;
} }
else { else {
return "$getlist"; return $getlist;
} }
return; return;
@ -1562,19 +1566,9 @@ sub DbRep_Attr {
} }
} }
if ($aName eq "fetchValueFn") { if ($aName eq "device") {
if($cmd eq "set") { my $awdev = $aVal;
my $VALUE = "Hello"; DbRep_modAssociatedWith ($hash,$cmd,$awdev);
if( $aVal =~ m/^\s*(\{.*\})\s*$/s ) { # Funktion aus Attr validieren
$aVal = $1;
}
else {
$aVal = "";
}
return "Your function does not match the form \"{<function>}\"" if(!$aVal);
eval $aVal;
return "Bad function: $@" if($@);
}
} }
if ($aName eq "sqlCmdHistoryLength") { if ($aName eq "sqlCmdHistoryLength") {
@ -1587,37 +1581,6 @@ sub DbRep_Attr {
} }
} }
if ($aName eq "userExitFn") {
if($cmd eq "set") {
if(!$aVal) {
return "Usage of $aName is wrong. The function has to be specified as \"<UserExitFn> [reading:value]\" ";
}
if ($aVal =~ m/^\s*(\{.*\})\s*$/xs) { # unnamed Funktion direkt in userExitFn mit {...}
$aVal = $1;
my ($NAME,$READING,$VALUE) = ('','','');
eval $aVal;
return $@ if ($@);
}
}
}
if ($aName =~ /executeAfterProc|executeBeforeProc/xs) {
if($cmd eq "set") {
if ($aVal =~ m/^\s*(\{.*\}|{.*|.*})\s*$/xs && $aVal !~ /{".*"}/xs) {
$aVal = $1;
my $fdv = __DbRep_fhemDefVars ();
my ($today, $hms, $we) = ($fdv->{today}, $fdv->{hms}, $fdv->{we});
my ($sec, $min, $hour) = ($fdv->{sec}, $fdv->{min}, $fdv->{hour});
my ($mday, $month, $year) = ($fdv->{mday}, $fdv->{month}, $fdv->{year});
my ($wday, $yday, $isdst) = ($fdv->{wday}, $fdv->{yday}, $fdv->{isdst});
eval $aVal;
return $@ if ($@);
}
}
}
if ($aName eq "role") { if ($aName eq "role") {
if ($cmd eq "set") { if ($cmd eq "set") {
if ($aVal eq "Agent") { if ($aVal eq "Agent") {
@ -1646,18 +1609,56 @@ sub DbRep_Attr {
delete($attr{$name}{icon}) if($do eq "Client"); delete($attr{$name}{icon}) if($do eq "Client");
} }
if($aName eq "device") { if ($cmd eq 'set') {
my $awdev = $aVal; if ($aName eq 'fetchValueFn' && $init_done) {
DbRep_modAssociatedWith ($hash,$cmd,$awdev); my $VALUE = "Hello";
if ( $aVal =~ m/^\s*(\{.*\})\s*$/s ) { # Funktion aus Attr validieren
$aVal = $1;
}
else {
$aVal = "";
}
return "Your function does not match the form \"{<function>}\"" if(!$aVal);
eval $aVal;
return "Bad function: $@" if($@);
}
if ($aName eq 'userExitFn' && $init_done) {
if (!$aVal) {
return "Usage of $aName is wrong. The function has to be specified as \"<UserExitFn> [reading:value]\" ";
}
if ($aVal =~ m/^\s*(\{.*\})\s*$/xs) { # unnamed Funktion direkt in userExitFn mit {...}
$aVal = $1;
my ($NAME,$READING,$VALUE) = ('','','');
eval $aVal;
return $@ if($@);
}
}
if ($aName =~ /executeAfterProc|executeBeforeProc/xs && $init_done) {
if ($aVal =~ m/^\s*(\{.*\}|{.*|.*})\s*$/xs && $aVal !~ /{".*"}/xs) {
$aVal = $1;
my $fdv = __DbRep_fhemDefVars ();
my ($today, $hms, $we) = ($fdv->{today}, $fdv->{hms}, $fdv->{we});
my ($sec, $min, $hour) = ($fdv->{sec}, $fdv->{min}, $fdv->{hour});
my ($mday, $month, $year) = ($fdv->{mday}, $fdv->{month}, $fdv->{year});
my ($wday, $yday, $isdst) = ($fdv->{wday}, $fdv->{yday}, $fdv->{isdst});
eval $aVal;
return $@ if ($@);
}
} }
if ($cmd eq "set") {
if ($aName =~ /valueFilter/) { if ($aName =~ /valueFilter/) {
eval { "Hallo" =~ m/$aVal/ }; eval { "Hallo" =~ m/$aVal/ };
return "Bad regexp: $@" if($@); return "Bad regexp: $@" if($@);
} }
if ($aName eq "autoForward") { if ($aName eq "autoForward" && $init_done) {
my $em = "Usage of $aName is wrong. The function has to be specified as ". my $em = "Usage of $aName is wrong. The function has to be specified as ".
"\"{ <destination-device> => \"<source-reading (Regex)> => [=> destination-reading]\" }\". ". "\"{ <destination-device> => \"<source-reading (Regex)> => [=> destination-reading]\" }\". ".
"The specification can be made in several lines separated by comma."; "The specification can be made in several lines separated by comma.";
@ -1840,11 +1841,11 @@ sub DbRep_Attr {
} }
if ($aName eq "ftpUse") { if ($aName eq "ftpUse") {
delete($attr{$name}{ftpUseSSL}); delete $attr{$name}{ftpUseSSL};
} }
if ($aName eq "ftpUseSSL") { if ($aName eq "ftpUseSSL") {
delete($attr{$name}{ftpUse}); delete $attr{$name}{ftpUse};
} }
if ($aName eq "useAdminCredentials" && $aVal) { if ($aName eq "useAdminCredentials" && $aVal) {
@ -2010,12 +2011,18 @@ sub DbRep_firstconnect {
RemoveInternalTimer ($hash, "DbRep_firstconnect"); RemoveInternalTimer ($hash, "DbRep_firstconnect");
return if(IsDisabled($name)); return if(IsDisabled($name));
if ($init_done == 1) { if ($init_done) {
my $dbloghash = $defs{$hash->{HELPER}{DBLOGDEVICE}}; my $dbloghash = $defs{$hash->{HELPER}{DBLOGDEVICE}};
my $dbconn = $dbloghash->{dbconn}; my $dbconn = $dbloghash->{dbconn};
my $dbuser = $dbloghash->{dbuser}; my $dbuser = $dbloghash->{dbuser};
my $fadef = $hash->{MODEL} eq "Client" ? 1 : 0; # fastStart default immer 1 für Clients (0 für Agenten) my $fadef = $hash->{MODEL} eq "Client" ? 1 : 0; # fastStart default immer 1 für Clients (0 für Agenten)
delete $hash->{COMPRESSION};
delete $hash->{UTF8};
$hash->{COMPRESSION} = $dbloghash->{COMPRESSION} if(defined $dbloghash->{COMPRESSION});
$hash->{UTF8} = $dbloghash->{UTF8} if(defined $dbloghash->{UTF8});
if (AttrVal($name, "fastStart", $fadef) && $prop eq "onBoot" ) { if (AttrVal($name, "fastStart", $fadef) && $prop eq "onBoot" ) {
DbRep_setLastCmd ($name, "initial database connect stopped due to attribute 'fastStart'"); DbRep_setLastCmd ($name, "initial database connect stopped due to attribute 'fastStart'");
@ -2173,7 +2180,7 @@ sub DbRep_getInitData {
$err = q{}; $err = q{};
return "$name|$err|$mints|$rt|$opt|$prop|$fret|$idxstate|$grants|$enc|$encc"; return "$name|$err|$mints|$rt|$opt|$prop|$fret|$idxstate|$grants|$enc|$encc|$dbmodel";
} }
#################################################################################################### ####################################################################################################
@ -2268,6 +2275,7 @@ sub DbRep_getInitDataDone {
my $grants = $a[8] ? decode_base64($a[8]) : ''; my $grants = $a[8] ? decode_base64($a[8]) : '';
my $enc = $a[9] ? decode_base64($a[9]) : ''; my $enc = $a[9] ? decode_base64($a[9]) : '';
my $encc = $a[10] ? decode_base64($a[10]) : ''; my $encc = $a[10] ? decode_base64($a[10]) : '';
my $dbmodel = $a[11];
my $hash = $defs{$name}; my $hash = $defs{$name};
@ -2301,6 +2309,7 @@ sub DbRep_getInitDataDone {
} }
else { else {
ReadingsBulkUpdateValue ($hash, "dbEncoding", $enc); ReadingsBulkUpdateValue ($hash, "dbEncoding", $enc);
ReadingsBulkUpdateValue ($hash, "dbModel", $dbmodel);
ReadingsBulkUpdateValue ($hash, "connectionEncoding", $encc) if($encc); ReadingsBulkUpdateValue ($hash, "connectionEncoding", $encc) if($encc);
ReadingsBulkUpdateValue ($hash, "indexState", $idxstate); ReadingsBulkUpdateValue ($hash, "indexState", $idxstate);
ReadingsBulkUpdateValue ($hash, "timestamp_oldest_dataset", $mints); ReadingsBulkUpdateValue ($hash, "timestamp_oldest_dataset", $mints);
@ -2314,7 +2323,6 @@ sub DbRep_getInitDataDone {
$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/xi ? 1 : 0;
} }
return if(!$fret); return if(!$fret);
@ -7005,8 +7013,10 @@ sub DbRep_sqlCmdBlocking {
my $hash = $defs{$name}; my $hash = $defs{$name};
my $srs = AttrVal ($name, 'sqlResultFieldSep', '|'); my $srs = AttrVal ($name, 'sqlResultFieldSep', '|');
my $to = AttrVal ($name, 'timeout', $dbrep_deftobl); my $to = AttrVal ($name, 'timeout', $dbrep_deftobl);
my $reading = AttrVal ($name, 'reading', '%');
my $device = AttrVal ($name, 'device', '%');
my ($ret); my $ret;
my ($err, $dbh, $dbmodel) = DbRep_dbConnect ($name); my ($err, $dbh, $dbmodel) = DbRep_dbConnect ($name);
if ($err) { if ($err) {
@ -7014,8 +7024,20 @@ sub DbRep_sqlCmdBlocking {
return $err; return $err;
} }
$cmd =~ s/\;\;/ESC_ESC_ESC/gx; # ersetzen von escapeten ";" (;;) my ($IsTimeSet, $IsAggrSet, $aggregation) = DbRep_checktimeaggr ($hash);
my ($runtime_string_first, $runtime_string_next);
if ($IsTimeSet || $IsAggrSet) {
(undef, undef, $runtime_string_first, $runtime_string_next) = DbRep_createTimeArray ($hash, $aggregation, 'sqlCmdBlocking');
}
else {
Log3 ($name, 4, "DbRep $name - Timestamp begin human readable: not set");
Log3 ($name, 4, "DbRep $name - Timestamp end human readable: not set");
}
Log3 ($name, 4, "DbRep $name - Aggregation: $aggregation");
$cmd =~ s/\;\;/ESC_ESC_ESC/gx; # ersetzen von escapeten ";" (;;)
$cmd .= ";" if ($cmd !~ m/\;$/x); $cmd .= ";" if ($cmd !~ m/\;$/x);
my $sql = $cmd; my $sql = $cmd;
@ -7048,6 +7070,21 @@ sub DbRep_sqlCmdBlocking {
return $err; return $err;
} }
# Ersetzung von Schlüsselwörtern für Timing, Gerät, Lesen (unter Verwendung der Attributsyntax)
($err, $sql) = _DbRep_sqlReplaceKeywords ( { hash => $hash,
sql => $sql,
device => $device,
reading => $reading,
dbmodel => $dbmodel,
rsf => $runtime_string_first,
rsn => $runtime_string_next
}
);
if ($err) {
_DbRep_sqlBlckgErrorState ($hash, $err);
return $err;
}
my $st = [gettimeofday]; # SQL-Startzeit my $st = [gettimeofday]; # SQL-Startzeit
my $totxt = qq{Timeout occured (limit: $to seconds). You may be able to adjust the "Timeout" attribute.}; my $totxt = qq{Timeout occured (limit: $to seconds). You may be able to adjust the "Timeout" attribute.};
@ -8281,8 +8318,6 @@ sub DbRep_mysql_DumpClientSide {
my $bst = [gettimeofday]; # Background-Startzeit my $bst = [gettimeofday]; # Background-Startzeit
Log3 ($name, 3, "DbRep $name - Starting dump of database '$dbname'");
## Beginn Dump ## Beginn Dump
################# #################
undef %db_tables; undef %db_tables;
@ -8301,6 +8336,8 @@ sub DbRep_mysql_DumpClientSide {
my ($err, $dbh, $dbmodel) = DbRep_dbConnect($name, 0); my ($err, $dbh, $dbmodel) = DbRep_dbConnect($name, 0);
return "$name|$err" if($err); return "$name|$err" if($err);
Log3 ($name, 3, "DbRep $name - Starting dump of database '$dbname' (model: $dbmodel)");
$dbh->{mysql_enable_utf8} = 0 if($dbmodel =~ /MYSQL/xs); # Dump Performance !!! Forum: https://forum.fhem.de/index.php/topic,53584.msg1204535.html#msg1204535 $dbh->{mysql_enable_utf8} = 0 if($dbmodel =~ /MYSQL/xs); # Dump Performance !!! Forum: https://forum.fhem.de/index.php/topic,53584.msg1204535.html#msg1204535
my $st = [gettimeofday]; # SQL-Startzeit my $st = [gettimeofday]; # SQL-Startzeit
@ -8308,7 +8345,7 @@ sub DbRep_mysql_DumpClientSide {
($err, $sth) = DbRep_prepareExecuteQuery ($name, $dbh, "SELECT VERSION()"); # Mysql-Version ermitteln ($err, $sth) = DbRep_prepareExecuteQuery ($name, $dbh, "SELECT VERSION()"); # Mysql-Version ermitteln
return "$name|$err" if($err); return "$name|$err" if($err);
my @mysql_version = $sth->fetchrow; my @mysql_version = $sth->fetchrow_array;
my @v = split(/\./,$mysql_version[0]); my @v = split(/\./,$mysql_version[0]);
my $collation = ''; my $collation = '';
my $dbcharset = ''; my $dbcharset = '';
@ -8317,7 +8354,7 @@ sub DbRep_mysql_DumpClientSide {
($err, $sth) = DbRep_prepareExecuteQuery ($name, $dbh, qq(SHOW VARIABLES LIKE 'collation_database')); ($err, $sth) = DbRep_prepareExecuteQuery ($name, $dbh, qq(SHOW VARIABLES LIKE 'collation_database'));
return "$name|$err" if($err); return "$name|$err" if($err);
@ar = $sth->fetchrow; @ar = $sth->fetchrow_array;
if ($ar[1]) { if ($ar[1]) {
$collation = $ar[1]; $collation = $ar[1];
@ -8331,7 +8368,7 @@ sub DbRep_mysql_DumpClientSide {
($err, $sth) = DbRep_prepareExecuteQuery ($name, $dbh, "SHOW VARIABLES LIKE 'dbcharset'"); # get standard encoding of MySQl-Server ($err, $sth) = DbRep_prepareExecuteQuery ($name, $dbh, "SHOW VARIABLES LIKE 'dbcharset'"); # get standard encoding of MySQl-Server
return "$name|$err" if($err); return "$name|$err" if($err);
@ar = $sth->fetchrow; @ar = $sth->fetchrow_array;
if ($ar[1]) { if ($ar[1]) {
$dbcharset = $ar[1]; $dbcharset = $ar[1];
@ -8540,7 +8577,7 @@ sub DbRep_mysql_DumpClientSide {
($err, $sth) = DbRep_prepareExecuteQuery ($name, $dbh, qq(SHOW CREATE DATABASE IF NOT EXISTS $dbname)); ($err, $sth) = DbRep_prepareExecuteQuery ($name, $dbh, qq(SHOW CREATE DATABASE IF NOT EXISTS $dbname));
return "$name|$err" if($err); return "$name|$err" if($err);
my $db_create = $sth->fetchrow; my $db_create = $sth->fetchrow_array;
DbRep_clearConn (undef, $sth); DbRep_clearConn (undef, $sth);
@ -8589,7 +8626,7 @@ sub DbRep_mysql_DumpClientSide {
($err, $sth) = DbRep_prepareExecuteQuery ($name, $dbh, qq(SHOW CREATE TABLE `$tablename`)); ($err, $sth) = DbRep_prepareExecuteQuery ($name, $dbh, qq(SHOW CREATE TABLE `$tablename`));
return "$name|$err" if($err); return "$name|$err" if($err);
@ctab = $sth->fetchrow; @ctab = $sth->fetchrow_array;
DbRep_clearConn (undef, $sth); DbRep_clearConn (undef, $sth);
$part = $ctab[1].";"; $part = $ctab[1].";";
@ -8626,7 +8663,7 @@ sub DbRep_mysql_DumpClientSide {
$fieldlist = "("; $fieldlist = "(";
while (@ar = $sth->fetchrow) { # build fieldlist while (@ar = $sth->fetchrow_array) { # build fieldlist
$fieldlist .= "`".$ar[0]."`,"; $fieldlist .= "`".$ar[0]."`,";
} }
@ -8649,7 +8686,7 @@ sub DbRep_mysql_DumpClientSide {
($err, $sth) = DbRep_prepareExecuteQuery ($name, $dbh, $sql_daten); ($err, $sth) = DbRep_prepareExecuteQuery ($name, $dbh, $sql_daten);
return "$name|$err" if($err); return "$name|$err" if($err);
while ( @ar = $sth->fetchrow) { # Start the insert while (@ar = $sth->fetchrow_array) { # Start the insert
if ($first_insert == 0) { if ($first_insert == 0) {
$part = "\n$insert"; $part = "\n$insert";
} }
@ -8666,7 +8703,6 @@ sub DbRep_mysql_DumpClientSide {
if ($memory_limit > 0 && length($sql_text) > $memory_limit) { if ($memory_limit > 0 && length($sql_text) > $memory_limit) {
($err, $filesize) = DbRep_WriteToDumpFile ($sql_text, $sql_file); ($err, $filesize) = DbRep_WriteToDumpFile ($sql_text, $sql_file);
# Log3 ($name, 5, "DbRep $name - Memory limit '$memory_limit' exceeded. Wrote to '$sql_file'. Filesize: '"._DbRep_byteOutput($filesize)."'");
$sql_text = ""; $sql_text = "";
} }
} }
@ -8674,6 +8710,8 @@ sub DbRep_mysql_DumpClientSide {
DbRep_clearConn (undef, $sth); DbRep_clearConn (undef, $sth);
} }
($err, $filesize) = DbRep_WriteToDumpFile ($sql_text, $sql_file) if($sql_text);
$sql_text .= "\n/*!40000 ALTER TABLE `$tablename` ENABLE KEYS */;\n"; $sql_text .= "\n/*!40000 ALTER TABLE `$tablename` ENABLE KEYS */;\n";
} }
@ -8808,7 +8846,7 @@ sub DbRep_mysql_DumpServerSide {
return "$name|$err" if ($err); return "$name|$err" if ($err);
} }
Log3 ($name, 3, "DbRep $name - Starting dump of database '$dbname', table '$table'"); Log3 ($name, 3, "DbRep $name - Starting dump of database '$dbname', table '$table' (model: $dbmodel)");
# Startzeit ermitteln # Startzeit ermitteln
my ($Sekunden, $Minuten, $Stunden, $Monatstag, $Monat, $Jahr, $Wochentag, $Jahrestag, $Sommerzeit) = localtime(time); my ($Sekunden, $Minuten, $Stunden, $Monatstag, $Monat, $Jahr, $Wochentag, $Jahrestag, $Sommerzeit) = localtime(time);
@ -8913,7 +8951,7 @@ sub DbRep_sqlite_Dump {
$dbname = (split /[\/]/, $dbname)[-1]; $dbname = (split /[\/]/, $dbname)[-1];
Log3 ($name, 3, "DbRep $name - Starting dump of database '$dbname'"); Log3 ($name, 3, "DbRep $name - Starting dump of database '$dbname' (model: $dbmodel)");
# Startzeit ermitteln # Startzeit ermitteln
my ($Sekunden, $Minuten, $Stunden, $Monatstag, $Monat, $Jahr, $Wochentag, $Jahrestag, $Sommerzeit) = localtime(time); my ($Sekunden, $Minuten, $Stunden, $Monatstag, $Monat, $Jahr, $Wochentag, $Jahrestag, $Sommerzeit) = localtime(time);
@ -11662,18 +11700,18 @@ return $sql;
sub DbRep_dbConnect { sub DbRep_dbConnect {
my $name = shift; my $name = shift;
my $uac = shift // AttrVal ($name, "useAdminCredentials", 0); my $uac = shift // AttrVal ($name, "useAdminCredentials", 0);
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 $dbconn = $dbloghash->{dbconn};
my $dbuser = $dbloghash->{dbuser}; my $dbuser = $dbloghash->{dbuser};
my $dblogname = $dbloghash->{NAME}; my $dblogname = $dbloghash->{NAME};
my $dbmodel = $dbloghash->{MODEL}; my $model = $dbloghash->{MODEL};
my $compression = $dbloghash->{COMPRESSION};
my $dbpassword = $attr{"sec$dblogname"}{secret}; my $dbpassword = $attr{"sec$dblogname"}{secret};
my $utf8 = $hash->{UTF8} // 0; my $utf8 = $dbloghash->{UTF8};
my $err = q{};
my $dbh; my $dbh;
my $err = q{};
if ($uac) { if ($uac) {
my ($success,$admusername,$admpassword) = DbRep_getcredentials ($hash, "adminCredentials"); my ($success,$admusername,$admpassword) = DbRep_getcredentials ($hash, "adminCredentials");
@ -11689,8 +11727,12 @@ sub DbRep_dbConnect {
} }
} }
Log3 ($name, 4, "DbRep $name - Database Model: $model");
Log3 ($name, 4, "DbRep $name - Database connect - user: ".($dbuser ? $dbuser : 'no').", UTF-8 option set: ".($utf8 ? 'yes' : 'no')); Log3 ($name, 4, "DbRep $name - Database connect - user: ".($dbuser ? $dbuser : 'no').", UTF-8 option set: ".($utf8 ? 'yes' : 'no'));
$dbconn .= ';mysql_compression=1' if($compression && $model eq 'MYSQL');
$dbconn .= ';mariadb_compression=1' if($compression && $model eq 'MARIADB');
eval { $dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, eval { $dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0,
RaiseError => 1, RaiseError => 1,
AutoCommit => 1, AutoCommit => 1,
@ -11703,9 +11745,14 @@ sub DbRep_dbConnect {
return $err; return $err;
}; };
if ($utf8) { return $DBI::errstr if($DBI::errstr);
if ($dbmodel =~ /MYSQL|MARIADB/xs) {
$dbh->{mysql_enable_utf8} = 1 if($dbmodel =~ /MYSQL/xs); # MariaDB kennt kein mysql_enable_utf8 if ($model =~ /MYSQL/xs) {
$dbh->{mysql_enable_utf8} = 1 if($utf8);
if ($compression) {
Log3 ($name, 4, "DbRep $name - Communication between Client and Server will be compressed");
}
($err, my @se) = DbRep_prepareExec2Array ($name, $dbh, "SHOW VARIABLES LIKE 'collation_database'"); ($err, my @se) = DbRep_prepareExec2Array ($name, $dbh, "SHOW VARIABLES LIKE 'collation_database'");
return $err if ($err); return $err if ($err);
@ -11723,12 +11770,29 @@ sub DbRep_dbConnect {
} }
} }
if ($dbmodel eq "SQLITE") { if ($model =~ /MARIADB/xs) {
$dbh->do('PRAGMA encoding="UTF-8"'); if ($compression) {
Log3 ($name, 4, "DbRep $name - Communication between Client and Server will be compressed");
} }
} }
return ($err, $dbh, $dbmodel); if ($model eq 'SQLITE') {
if ($utf8) {
($err, undef) = DbRep_dbhDo ($name, $dbh, 'PRAGMA encoding="UTF-8"');
return $err if ($err);
}
my @dos = ("PRAGMA temp_store=MEMORY",
"PRAGMA synchronous=FULL",
);
for my $do (@dos) {
($err, undef) = DbRep_dbhDo ($name, $dbh, $do);
return $err if ($err);
}
}
return ($err, $dbh, $model);
} }
#################################################################################################### ####################################################################################################
@ -12272,7 +12336,7 @@ sub DbRep_autoForward {
my $hash = $defs{$name}; my $hash = $defs{$name};
my $av = AttrVal ($name, 'autoForward', ''); my $av = AttrVal ($name, 'autoForward', '');
return if(!$av); return if(!$av || !$init_done);
$av =~ m/^\{(.*)\}/s; $av =~ m/^\{(.*)\}/s;
$av = $1; $av = $1;
@ -12612,13 +12676,13 @@ sub DbRep_beforeproc {
if ($fn) { if ($fn) {
Log3 ($name, 3, "DbRep $name - execute command before $cmd: '$fn' "); Log3 ($name, 3, "DbRep $name - execute command before $cmd: '$fn' ");
my $err = _DbRep_procCode ($hash, $fn); my $msg = _DbRep_procCode ($hash, $fn);
if ($err) { if ($msg) {
Log3 ($name, 2, "DbRep $name - command message before $cmd: \"$err\" "); Log3 ($name, 3, "DbRep $name - command message before $cmd: \"$msg\" ");
my $erread = "Warning - message from command before $cmd appeared"; my $erread = "Warning - message from command before $cmd appeared";
ReadingsSingleUpdateValue ($hash, "before_".$cmd."_message", $err, 1); ReadingsSingleUpdateValue ($hash, "before_".$cmd."_message", $msg, 1);
ReadingsSingleUpdateValue ($hash, "state", $erread, 1); ReadingsSingleUpdateValue ($hash, "state", $erread, 1);
} }
} }
@ -12634,8 +12698,6 @@ sub DbRep_afterproc {
my $cmd = shift // q{process}; my $cmd = shift // q{process};
my $bfile = shift // q{}; my $bfile = shift // q{};
my ($err,$erread);
my $name = $hash->{NAME}; my $name = $hash->{NAME};
$cmd = (split " ", $cmd)[0]; $cmd = (split " ", $cmd)[0];
my $sval = ReadingsVal ($name, 'state', ''); my $sval = ReadingsVal ($name, 'state', '');
@ -12644,14 +12706,14 @@ sub DbRep_afterproc {
if ($fn) { if ($fn) {
Log3 ($name, 3, "DbRep $name - execute command after $cmd: '$fn' "); Log3 ($name, 3, "DbRep $name - execute command after $cmd: '$fn' ");
$err = _DbRep_procCode ($hash, $fn); my $msg = _DbRep_procCode ($hash, $fn);
if ($err) { if ($msg) {
Log3 ($name, 2, qq{DbRep $name - command message after $cmd: >$err<}); Log3 ($name, 3, qq{DbRep $name - command message after $cmd: >$msg<});
$erread = $sval eq 'error' ? $sval : qq(WARNING - $cmd finished, but message after command appeared); my $erread = $sval eq 'error' ? $sval : qq(WARNING - $cmd finished, but message after command appeared);
ReadingsSingleUpdateValue ($hash, 'after_'.$cmd.'_message', $err, 1); ReadingsSingleUpdateValue ($hash, 'after_'.$cmd.'_message', $msg, 1);
ReadingsSingleUpdateValue ($hash, 'state', $erread, 1); ReadingsSingleUpdateValue ($hash, 'state', $erread, 1);
return $erread; return $erread;
@ -14461,12 +14523,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 28621 2024-03-08 23:25:01Z DS_Starter $ im Kopf komplett! vorhanden ) if($modules{$type}{META}{x_version}) { # {x_version} ( nur gesetzt wenn $Id: 93_DbRep.pm 28668 2024-03-16 20:01:55Z 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 28621 2024-03-08 23:25:01Z DS_Starter $ im Kopf komplett! vorhanden ) return $@ unless (FHEM::Meta::SetInternals($hash)); # FVERSION wird gesetzt ( nur gesetzt wenn $Id: 93_DbRep.pm 28668 2024-03-16 20:01:55Z 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
@ -16550,13 +16612,15 @@ return;
<ul><ul> <ul><ul>
<a id="DbRep-get-blockinginfo"></a> <a id="DbRep-get-blockinginfo"></a>
<li><b> blockinginfo </b> - list the current system wide running background processes (BlockingCalls) together with their informations. <li><b> blockinginfo </b> <br>
List the current system wide running background processes (BlockingCalls) together with their informations.
If character string is too long (e.g. arguments) it is reported shortened. If character string is too long (e.g. arguments) it is reported shortened.
</li> </li>
<br><br> <br><br>
<a id="DbRep-get-dbstatus"></a> <a id="DbRep-get-dbstatus"></a>
<li><b> dbstatus </b> - lists global information about MySQL server status (e.g. informations related to cache, threads, bufferpools, etc. ). <li><b> dbstatus </b> <br>
Lists global information about MySQL server status (e.g. informations related to cache, threads, bufferpools, etc. ).
Initially all available informations are reported. Using the attribute <a href="#DbRep-attr-showStatus">showStatus</a> the quantity of Initially all available informations are reported. Using the attribute <a href="#DbRep-attr-showStatus">showStatus</a> the quantity of
results can be limited to show only the desired values. Further detailed informations of items meaning are results can be limited to show only the desired values. Further detailed informations of items meaning are
explained <a href="http://dev.mysql.com/doc/refman/5.7/en/server-status-variables.html">here</a>. <br><br> explained <a href="http://dev.mysql.com/doc/refman/5.7/en/server-status-variables.html">here</a>. <br><br>
@ -16571,7 +16635,8 @@ return;
<br><br> <br><br>
<a id="DbRep-get-dbvars"></a> <a id="DbRep-get-dbvars"></a>
<li><b> dbvars </b> - lists global informations about MySQL system variables. Included are e.g. readings related to InnoDB-Home, datafile path, <li><b> dbvars </b> <br>
Lists global informations about MySQL system variables. Included are e.g. readings related to InnoDB-Home, datafile path,
memory- or cache-parameter and so on. The Output reports initially all available informations. Using the memory- or cache-parameter and so on. The Output reports initially all available informations. Using the
attribute <a href="#DbRep-attr-showVariables">showVariables</a> the quantity of results can be limited to show only the desired values. attribute <a href="#DbRep-attr-showVariables">showVariables</a> the quantity of results can be limited to show only the desired values.
Further detailed informations of items meaning are explained Further detailed informations of items meaning are explained
@ -16587,7 +16652,8 @@ return;
<br><br> <br><br>
<a id="DbRep-get-initData"></a> <a id="DbRep-get-initData"></a>
<li><b> initData </b> - Determines some database properties relevant for the module function. <li><b> initData </b> <br>
Determines some database properties relevant for the module function.
The command is executed implicitly at the first database connection. The command is executed implicitly at the first database connection.
</li> </li>
<br><br> <br><br>
@ -18084,8 +18150,8 @@ return;
<tr><td> <b>device</b> </td><td>: einschließen oder ausschließen von Datensätzen die &lt;device&gt; enthalten </td></tr> <tr><td> <b>device</b> </td><td>: einschließen oder ausschließen von Datensätzen die &lt;device&gt; enthalten </td></tr>
<tr><td> <b>reading</b> </td><td>: einschließen oder ausschließen von Datensätzen die &lt;reading&gt; enthalten </td></tr> <tr><td> <b>reading</b> </td><td>: einschließen oder ausschließen von Datensätzen die &lt;reading&gt; enthalten </td></tr>
<tr><td> <b>time.*</b> </td><td>: eine Reihe von Attributen zur Zeitabgrenzung </td></tr> <tr><td> <b>time.*</b> </td><td>: eine Reihe von Attributen zur Zeitabgrenzung </td></tr>
<tr><td> executeBeforeProc </td><td>: ausführen FHEM Kommando (oder Perl-Routine) vor Ausführung </td></tr> <tr><td> <b>executeBeforeProc</b> </td><td>: ausführen FHEM Kommando (oder Perl-Routine) vor Ausführung </td></tr>
<tr><td> executeAfterProc </td><td>: ausführen FHEM Kommando (oder Perl-Routine) nach Ausführung </td></tr> <tr><td> <b>executeAfterProc</b> </td><td>: ausführen FHEM Kommando (oder Perl-Routine) nach Ausführung </td></tr>
<tr><td> <b>readingNameMap</b> </td><td>: die entstehenden Ergebnisreadings werden partiell umbenannt </td></tr> <tr><td> <b>readingNameMap</b> </td><td>: die entstehenden Ergebnisreadings werden partiell umbenannt </td></tr>
<tr><td> <b>valueFilter</b> </td><td>: ein zusätzliches REGEXP um die Datenselektion zu steuern. Der REGEXP wird auf das Datenbankfeld 'VALUE' angewendet. </td></tr> <tr><td> <b>valueFilter</b> </td><td>: ein zusätzliches REGEXP um die Datenselektion zu steuern. Der REGEXP wird auf das Datenbankfeld 'VALUE' angewendet. </td></tr>
</table> </table>
@ -19678,16 +19744,19 @@ return;
<ul><ul> <ul><ul>
<a id="DbRep-get-blockinginfo"></a> <a id="DbRep-get-blockinginfo"></a>
<li><b> blockinginfo </b> - Listet die aktuell systemweit laufenden Hintergrundprozesse (BlockingCalls) mit ihren Informationen auf. <li><b> blockinginfo </b> <br>
Listet die aktuell systemweit laufenden Hintergrundprozesse (BlockingCalls) mit ihren Informationen auf.
Zu lange Zeichenketten (z.B. Argumente) werden gekürzt ausgeschrieben. Zu lange Zeichenketten (z.B. Argumente) werden gekürzt ausgeschrieben.
</li> </li>
<br><br> <br><br>
<a id="DbRep-get-dbstatus"></a> <a id="DbRep-get-dbstatus"></a>
<li><b> dbstatus </b> - Listet globale Informationen zum MySQL Serverstatus (z.B. Informationen zum Cache, Threads, Bufferpools, etc. ). <li><b> dbstatus </b> <br>
Listet globale Informationen zum MySQL Serverstatus (z.B. Informationen zum Cache, Threads, Bufferpools, etc. ).
Es werden zunächst alle verfügbaren Informationen berichtet. Mit dem Attribut <a href="#DbRep-attr-showStatus">showStatus</a> kann die Es werden zunächst alle verfügbaren Informationen berichtet. Mit dem Attribut <a href="#DbRep-attr-showStatus">showStatus</a> kann die
Ergebnismenge eingeschränkt werden, um nur gewünschte Ergebnisse abzurufen. Detailinformationen zur Bedeutung der einzelnen Readings Ergebnismenge eingeschränkt werden, um nur gewünschte Ergebnisse abzurufen. Detailinformationen zur Bedeutung der einzelnen Readings
sind <a href="http://dev.mysql.com/doc/refman/5.7/en/server-status-variables.html">hier</a> verfügbar. <br><br> sind <a href="http://dev.mysql.com/doc/refman/5.7/en/server-status-variables.html">hier</a> verfügbar.
<br><br>
<ul> <ul>
<b>Beispiel</b> <br> <b>Beispiel</b> <br>
@ -19699,7 +19768,8 @@ return;
<br><br> <br><br>
<a id="DbRep-get-dbvars"></a> <a id="DbRep-get-dbvars"></a>
<li><b> dbvars </b> - Zeigt die globalen Werte der MySQL Systemvariablen. Enthalten sind zum Beispiel Angaben zum InnoDB-Home, dem Datafile-Pfad, <li><b> dbvars </b> <br>
Zeigt die globalen Werte der MySQL Systemvariablen. Enthalten sind zum Beispiel Angaben zum InnoDB-Home, dem Datafile-Pfad,
Memory- und Cache-Parameter, usw. Die Ausgabe listet zunächst alle verfügbaren Informationen auf. Mit dem Attribut Memory- und Cache-Parameter, usw. Die Ausgabe listet zunächst alle verfügbaren Informationen auf. Mit dem Attribut
<a href="#DbRep-attr-showVariables">showVariables</a> kann die Ergebnismenge eingeschränkt werden um nur gewünschte Ergebnisse <a href="#DbRep-attr-showVariables">showVariables</a> kann die Ergebnismenge eingeschränkt werden um nur gewünschte Ergebnisse
abzurufen. Weitere Informationen zur Bedeutung der ausgegebenen Variablen sind abzurufen. Weitere Informationen zur Bedeutung der ausgegebenen Variablen sind
@ -19715,7 +19785,8 @@ return;
<br><br> <br><br>
<a id="DbRep-get-initData"></a> <a id="DbRep-get-initData"></a>
<li><b> initData </b> - Ermittelt einige für die Funktion des Moduls relevante Datenbankeigenschaften. <li><b> initData </b> <br>
Ermittelt einige für die Funktion des Moduls relevante Datenbankeigenschaften.
Der Befehl wird bei der ersten Datenbankverbindung implizit ausgeführt. Der Befehl wird bei der ersten Datenbankverbindung implizit ausgeführt.
</li> </li>
<br><br> <br><br>