mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-02-25 09:55:38 +00:00
93_DbLog: contrib 5.6.2
git-svn-id: https://svn.fhem.de/fhem/trunk@27105 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
db66e5bc54
commit
5306857e06
@ -1,5 +1,5 @@
|
||||
############################################################################################################################################
|
||||
# $Id: 93_DbLog.pm 26923 2023-01-10 10:28:14Z DS_Starter $
|
||||
# $Id: 93_DbLog.pm 27082 2023-01-18 22:08:25Z DS_Starter $
|
||||
#
|
||||
# 93_DbLog.pm
|
||||
# written by Dr. Boris Neubert 2007-12-30
|
||||
@ -8,7 +8,7 @@
|
||||
# modified and maintained by Tobias Faust since 2012-06-26 until 2016
|
||||
# e-mail: tobias dot faust at online dot de
|
||||
#
|
||||
# redesigned and maintained 2016-2023 by DS_Starter with credits by: JoeAllb, DeeSpe
|
||||
# redesigned and maintained 2016-2023 by DS_Starter
|
||||
# e-mail: heiko dot maaz at t-online dot de
|
||||
#
|
||||
# reduceLog() created by Claudiu Schuster (rapster) adapted by DS_Starter
|
||||
@ -38,14 +38,17 @@ no if $] >= 5.017011, warnings => 'experimental::smartmatch';
|
||||
|
||||
# Version History intern by DS_Starter:
|
||||
my %DbLog_vNotesIntern = (
|
||||
"5.5.12" => "10.01.2023 changed routine _DbLog_SBP_onRun_LogBulk ",
|
||||
"5.6.2" => "22.01.2023 check Syntax of DbLogValueFn attribute with Log output ",
|
||||
"5.6.1" => "16.01.2023 rewrite sub _DbLog_SBP_connectDB, rewrite sub DbLog_ExecSQL, _DbLog_SBP_onRun_deleteOldDays ",
|
||||
"5.6.0" => "11.01.2023 rename attribute 'bulkInsert' to 'insertMode' ",
|
||||
"5.5.12" => "10.01.2023 changed routine _DbLog_SBP_onRun_LogSequential, edit CommandRef ",
|
||||
"5.5.11" => "09.01.2023 more code rework / structured subroutines ",
|
||||
"5.5.10" => "07.01.2023 more code rework (_DbLog_SBP_checkDiscDelpars) and others, use dbh quote in _DbLog_SBP_onRun_LogBulk ".
|
||||
"5.5.10" => "07.01.2023 more code rework (_DbLog_SBP_checkDiscDelpars) and others, use dbh quote in _DbLog_SBP_onRun_LogSequential ".
|
||||
"configCheck changed to use only one db connect + measuring the connection time, universal DBHU ",
|
||||
"5.5.9" => "28.12.2022 optimize \$hash->{HELPER}{TH}, \$hash->{HELPER}{TC}, mode in Define ".
|
||||
"Forum: https://forum.fhem.de/index.php/topic,130588.msg1254073.html#msg1254073 ",
|
||||
"5.5.8" => "27.12.2022 two-line output of long state messages, define LONGRUN_PID threshold ",
|
||||
"5.5.7" => "20.12.2022 cutted _DbLog_SBP_onRun_Log into _DbLog_SBP_onRun_LogArray and _DbLog_SBP_onRun_LogBulk ".
|
||||
"5.5.7" => "20.12.2022 cutted _DbLog_SBP_onRun_Log into _DbLog_SBP_onRun_LogArray and _DbLog_SBP_onRun_LogSequential ".
|
||||
"__DbLog_SBP_onRun_LogCurrent, __DbLog_SBP_fieldArrays, some bugfixes, add drivers to configCheck, edit comref ",
|
||||
"5.5.6" => "12.12.2022 Serialize with Storable instead of JSON, more code rework ",
|
||||
"5.5.5" => "11.12.2022 Array Log -> may be better error processing ",
|
||||
@ -147,7 +150,6 @@ sub DbLog_Initialize {
|
||||
$hash->{ShutdownFn} = "DbLog_Shutdown";
|
||||
$hash->{AttrList} = "addStateEvent:0,1 ".
|
||||
"asyncMode:1,0 ".
|
||||
"bulkInsert:1,0 ".
|
||||
"commitMode:basic_ta:on,basic_ta:off,ac:on_ta:on,ac:on_ta:off,ac:off_ta:on ".
|
||||
"cacheEvents:2,1,0 ".
|
||||
"cacheLimit ".
|
||||
@ -158,14 +160,13 @@ sub DbLog_Initialize {
|
||||
"convertTimezone:UTC,none ".
|
||||
"DbLogSelectionMode:Exclude,Include,Exclude/Include ".
|
||||
"DbLogType:Current,History,Current/History,SampleFill/History ".
|
||||
"SQLiteJournalMode:WAL,off ".
|
||||
"SQLiteCacheSize ".
|
||||
"dbSchema ".
|
||||
"defaultMinInterval:textField-long ".
|
||||
"disable:1,0 ".
|
||||
"excludeDevs ".
|
||||
"expimpdir ".
|
||||
"exportCacheAppend:1,0 ".
|
||||
"insertMode:1,0 ".
|
||||
"noSupportPK:1,0 ".
|
||||
"noNotifyDev:1,0 ".
|
||||
"showproctime:1,0 ".
|
||||
@ -174,6 +175,8 @@ sub DbLog_Initialize {
|
||||
"syncEvents:1,0 ".
|
||||
"syncInterval ".
|
||||
"showNotifyTime:1,0 ".
|
||||
"SQLiteJournalMode:WAL,off ".
|
||||
"SQLiteCacheSize ".
|
||||
"traceFlag:SQL,CON,ENC,DBD,TXN,ALL ".
|
||||
"traceLevel:0,1,2,3,4,5,6,7 ".
|
||||
"timeout ".
|
||||
@ -190,6 +193,9 @@ sub DbLog_Initialize {
|
||||
$hash->{SVG_sampleDataFn} = "DbLog_sampleDataFn";
|
||||
$hash->{prioSave} = 1; # Prio-Flag für save Reihenfolge, Forum: https://forum.fhem.de/index.php/topic,130588.msg1249277.html#msg1249277
|
||||
|
||||
$hash->{AttrRenameMap} = { "bulkInsert" => "insertMode",
|
||||
};
|
||||
|
||||
eval { FHEM::Meta::InitMod( __FILE__, $hash ) }; # für Meta.pm (https://forum.fhem.de/index.php/topic,97589.0.html)
|
||||
|
||||
return;
|
||||
@ -404,22 +410,8 @@ sub DbLog_Attr {
|
||||
return qq{"$aName" is not valid for database model "$hash->{MODEL}"};
|
||||
}
|
||||
|
||||
if( $aName eq 'valueFn' ) {
|
||||
my %specials= (
|
||||
"%TIMESTAMP" => $name,
|
||||
"%LASTTIMESTAMP" => $name,
|
||||
"%DEVICE" => $name,
|
||||
"%DEVICETYPE" => $name,
|
||||
"%EVENT" => $name,
|
||||
"%READING" => $name,
|
||||
"%VALUE" => $name,
|
||||
"%LASTVALUE" => $name,
|
||||
"%UNIT" => $name,
|
||||
"%IGNORE" => $name,
|
||||
"%CN" => $name
|
||||
);
|
||||
|
||||
my $err = perlSyntaxCheck($aVal, %specials);
|
||||
if($aName =~ /[Vv]alueFn/) {
|
||||
my ($err, $func) = DbLog_checkSyntaxValueFn ($name, $aVal);
|
||||
return $err if($err);
|
||||
}
|
||||
|
||||
@ -1236,19 +1228,11 @@ sub DbLog_Log {
|
||||
my $clim = AttrVal ($name, 'cacheLimit', $dblog_cachedef);
|
||||
my $ce = AttrVal ($name, 'cacheEvents', 0);
|
||||
|
||||
if( $DbLogValueFn =~ m/^\s*(\{.*\})\s*$/s ) { # Funktion aus Device spezifischer DbLogValueFn validieren
|
||||
$DbLogValueFn = $1;
|
||||
}
|
||||
else {
|
||||
$DbLogValueFn = '';
|
||||
}
|
||||
($err, $DbLogValueFn) = DbLog_checkSyntaxValueFn ($name, $DbLogValueFn, $dev_name); # Funktion aus Device spezifischer DbLogValueFn validieren
|
||||
$DbLogValueFn = '' if($err);
|
||||
|
||||
if( $value_fn =~ m/^\s*(\{.*\})\s*$/s ) { # Funktion aus Attr valueFn validieren
|
||||
$value_fn = $1;
|
||||
}
|
||||
else {
|
||||
$value_fn = '';
|
||||
}
|
||||
($err, $value_fn) = DbLog_checkSyntaxValueFn ($name, $value_fn); # Funktion aus Attr valueFn validieren
|
||||
$value_fn = '' if($err);
|
||||
|
||||
eval { # one Transaction
|
||||
for (my $i = 0; $i < $max; $i++) {
|
||||
@ -2206,10 +2190,10 @@ sub DbLog_SBP_onRun {
|
||||
## Event Logging
|
||||
#########################################################
|
||||
if ($operation =~ /log_/xs) {
|
||||
my $bi = $memc->{bi}; # Bulk-Insert 0|1
|
||||
my $im = $memc->{im}; # Insert-Mode 0|1
|
||||
|
||||
if ($bi) {
|
||||
_DbLog_SBP_onRun_LogBulk ( { subprocess => $subprocess,
|
||||
if ($im) {
|
||||
_DbLog_SBP_onRun_LogSequential ( { subprocess => $subprocess,
|
||||
name => $name,
|
||||
memc => $memc,
|
||||
store => $store,
|
||||
@ -2469,6 +2453,10 @@ return $doNext;
|
||||
# PrintError - handle attribute tells DBI to call the Perl warn( ) function
|
||||
# (which typically results in errors being printed to the screen
|
||||
# when encountered)
|
||||
#
|
||||
# For maximum reliability and for robustness against database corruption,
|
||||
# SQLite should always be run with its default synchronous setting of FULL.
|
||||
# https://sqlite.org/howtocorrupt.html
|
||||
###################################################################################
|
||||
sub _DbLog_SBP_connectDB {
|
||||
my $paref = shift;
|
||||
@ -2533,27 +2521,56 @@ sub _DbLog_SBP_connectDB {
|
||||
if($utf8) {
|
||||
if($model eq "MYSQL") {
|
||||
$dbh->{mysql_enable_utf8} = 1;
|
||||
$dbh->do('set names "UTF8"');
|
||||
($err, undef) = _DbLog_SBP_dbhDo ($name, $dbh, 'set names "UTF8"');
|
||||
return ($err, q{}) if($err);
|
||||
}
|
||||
|
||||
if($model eq "SQLITE") {
|
||||
$dbh->do('PRAGMA encoding="UTF-8"');
|
||||
($err, undef) = _DbLog_SBP_dbhDo ($name, $dbh, 'PRAGMA encoding="UTF-8"');
|
||||
return ($err, q{}) if($err);
|
||||
}
|
||||
}
|
||||
|
||||
if ($model eq 'SQLITE') {
|
||||
$dbh->do("PRAGMA temp_store=MEMORY");
|
||||
$dbh->do("PRAGMA synchronous=FULL"); # For maximum reliability and for robustness against database corruption,
|
||||
# SQLite should always be run with its default synchronous setting of FULL.
|
||||
# https://sqlite.org/howtocorrupt.html
|
||||
my @dos = ("PRAGMA temp_store=MEMORY",
|
||||
"PRAGMA synchronous=FULL",
|
||||
"PRAGMA journal_mode=$sltjm",
|
||||
"PRAGMA cache_size=$sltcs"
|
||||
);
|
||||
|
||||
$dbh->do("PRAGMA journal_mode=$sltjm");
|
||||
$dbh->do("PRAGMA cache_size=$sltcs");
|
||||
for my $do (@dos) {
|
||||
($err, undef) = _DbLog_SBP_dbhDo ($name, $dbh, $do);
|
||||
return ($err, q{}) if($err);
|
||||
}
|
||||
}
|
||||
|
||||
return ($err, $dbh);
|
||||
}
|
||||
|
||||
####################################################################################################
|
||||
# einfaches Sdbh->do, return ERROR-String wenn Fehler bzw. die Anzahl der betroffenen Zeilen
|
||||
####################################################################################################
|
||||
sub _DbLog_SBP_dbhDo {
|
||||
my $name = shift;
|
||||
my $dbh = shift;
|
||||
my $sql = shift;
|
||||
my $info = shift // "simple do statement: $sql";
|
||||
|
||||
my $err = q{};
|
||||
my $rv = q{};
|
||||
|
||||
Log3 ($name, 4, "DbLog $name - $info");
|
||||
|
||||
eval{ $rv = $dbh->do($sql);
|
||||
1;
|
||||
}
|
||||
or do { $err = $@;
|
||||
Log3 ($name, 2, "DbLog $name - ERROR - $@");
|
||||
};
|
||||
|
||||
return ($err, $rv);
|
||||
}
|
||||
|
||||
############################################################################
|
||||
# Datenbank Ping
|
||||
# ohne alarm (timeout) bleibt ping hängen wenn DB nicht
|
||||
@ -2592,11 +2609,37 @@ sub _DbLog_SBP_pingDB {
|
||||
return $bool;
|
||||
}
|
||||
|
||||
############################################################################
|
||||
# DBH set
|
||||
# PrintError = 1, RaiseError = 0
|
||||
############################################################################
|
||||
sub _DbLog_SBP_dbhPrintError {
|
||||
my $dbh = shift;
|
||||
|
||||
$dbh->{PrintError} = 1;
|
||||
$dbh->{RaiseError} = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
############################################################################
|
||||
# DBH set
|
||||
# PrintError = 0, RaiseError = 1
|
||||
############################################################################
|
||||
sub _DbLog_SBP_dbhRaiseError {
|
||||
my $dbh = shift;
|
||||
|
||||
$dbh->{PrintError} = 0;
|
||||
$dbh->{RaiseError} = 1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#################################################################
|
||||
# SubProcess - Log-Routine
|
||||
# Bulk-Insert
|
||||
#################################################################
|
||||
sub _DbLog_SBP_onRun_LogBulk {
|
||||
sub _DbLog_SBP_onRun_LogSequential {
|
||||
my $paref = shift;
|
||||
|
||||
my $subprocess = $paref->{subprocess};
|
||||
@ -2715,9 +2758,8 @@ sub _DbLog_SBP_onRun_LogBulk {
|
||||
|
||||
$error = __DbLog_SBP_beginTransaction ($name, $dbh, $useta);
|
||||
|
||||
if(!$useta) { # generate errstr wenn keine TA
|
||||
$dbh->{PrintError} = 1;
|
||||
$dbh->{RaiseError} = 0;
|
||||
if(!$useta) { # keine Transaktion: generate errstr, keine Ausnahme
|
||||
_DbLog_SBP_dbhPrintError ($dbh);
|
||||
}
|
||||
|
||||
eval { for my $ds (@ins) {
|
||||
@ -2728,7 +2770,6 @@ sub _DbLog_SBP_onRun_LogBulk {
|
||||
Log3 ($name, 2, "DbLog $name - ERROR in >$operation< - ".$sth_ih->errstr);
|
||||
}
|
||||
else {
|
||||
#$rv = 0 if($rv eq "0E0");
|
||||
$ins_hist += $rv;
|
||||
}
|
||||
}
|
||||
@ -2747,6 +2788,7 @@ sub _DbLog_SBP_onRun_LogBulk {
|
||||
Log3 ($name, 2, "DbLog $name - Transaction is switched off. Transferred data is lost.");
|
||||
}
|
||||
|
||||
_DbLog_SBP_dbhRaiseError ($dbh);
|
||||
__DbLog_SBP_rollbackOnly ($name, $dbh, $history);
|
||||
|
||||
$ret = {
|
||||
@ -2759,14 +2801,11 @@ sub _DbLog_SBP_onRun_LogBulk {
|
||||
|
||||
__DbLog_SBP_sendToParent ($subprocess, $ret);
|
||||
|
||||
$dbh->{PrintError} = 0;
|
||||
$dbh->{RaiseError} = 1;
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
$dbh->{PrintError} = 0;
|
||||
$dbh->{RaiseError} = 1;
|
||||
_DbLog_SBP_dbhRaiseError ($dbh);
|
||||
__DbLog_SBP_commitOnly ($name, $dbh, $history);
|
||||
|
||||
if($ins_hist == $ceti) {
|
||||
Log3 ($name, 4, "DbLog $name - $ins_hist of $ceti events inserted into table $history".($usepkh ? " using PK on columns $pkh" : ""));
|
||||
@ -2779,8 +2818,6 @@ sub _DbLog_SBP_onRun_LogBulk {
|
||||
Log3 ($name, 2, "DbLog $name - WARNING - only ".$ins_hist." of $ceti events inserted into table $history");
|
||||
}
|
||||
}
|
||||
|
||||
__DbLog_SBP_commitOnly ($name, $dbh, $history);
|
||||
}
|
||||
|
||||
if ($operation eq 'importCachefile') {
|
||||
@ -2954,11 +2991,14 @@ sub _DbLog_SBP_onRun_LogArray {
|
||||
|
||||
$error = __DbLog_SBP_beginTransaction ($name, $dbh, $useta);
|
||||
|
||||
eval {
|
||||
($tuples, $rows) = $sth_ih->execute_array( { ArrayTupleStatus => \@tuple_status } );
|
||||
};
|
||||
if(!$useta) { # keine Transaktion: generate errstr, keine Ausnahme
|
||||
_DbLog_SBP_dbhPrintError ($dbh);
|
||||
}
|
||||
|
||||
if ($@) {
|
||||
eval { ($tuples, $rows) = $sth_ih->execute_array( { ArrayTupleStatus => \@tuple_status } );
|
||||
1;
|
||||
}
|
||||
or do {
|
||||
$error = $@;
|
||||
$nins_hist = $ceti;
|
||||
|
||||
@ -2966,18 +3006,31 @@ sub _DbLog_SBP_onRun_LogArray {
|
||||
|
||||
if($useta) {
|
||||
$rowlback = $cdata; # nicht gespeicherte Datensätze nur zurück geben wenn Transaktion ein
|
||||
__DbLog_SBP_rollbackOnly ($name, $dbh, $history);
|
||||
|
||||
Log3 ($name, 4, "DbLog $name - Transaction is switched on. Transferred data is returned to the cache.");
|
||||
}
|
||||
else {
|
||||
__DbLog_SBP_commitOnly ($name, $dbh, $history);
|
||||
Log3 ($name, 4, "DbLog $name - Transaction is switched off. Some or all of the transferred data will be lost. Note the following information.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
_DbLog_SBP_dbhRaiseError ($dbh);
|
||||
__DbLog_SBP_rollbackOnly ($name, $dbh, $history);
|
||||
|
||||
$ret = {
|
||||
name => $name,
|
||||
msg => $error,
|
||||
ot => 0,
|
||||
oper => $operation,
|
||||
rowlback => $rowlback
|
||||
};
|
||||
|
||||
__DbLog_SBP_sendToParent ($subprocess, $ret);
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
_DbLog_SBP_dbhRaiseError ($dbh);
|
||||
__DbLog_SBP_commitOnly ($name, $dbh, $history);
|
||||
}
|
||||
|
||||
no warnings 'uninitialized';
|
||||
|
||||
@ -2987,7 +3040,7 @@ sub _DbLog_SBP_onRun_LogArray {
|
||||
|
||||
next if($status); # $status ist "1" wenn insert ok
|
||||
|
||||
Log3 ($name, 4, "DbLog $name - Insert into $history rejected".($usepkh ? " (possible PK violation) " : " ")."- TS: $timestamp[$tuple], Device: $device[$tuple], Reading: $reading[$tuple]");
|
||||
Log3 ($name, 4, "DbLog $name - Insert into $history rejected".($usepkh ? " (possible PK violation) " : " ")."->\nTS: $timestamp[$tuple], Device: $device[$tuple], Reading: $reading[$tuple]");
|
||||
|
||||
$event[$tuple] =~ s/\|/_ESC_/gxs; # escape Pipe "|"
|
||||
$reading[$tuple] =~ s/\|/_ESC_/gxs;
|
||||
@ -3273,7 +3326,7 @@ sub __DbLog_SBP_logLogmodes {
|
||||
my $name = $paref->{name};
|
||||
my $useta = $paref->{useta};
|
||||
my $dbh = $store->{dbh};
|
||||
my $bi = $memc->{bi}; # Bulk-Insert 0|1
|
||||
my $im = $memc->{im}; # Insert-Mode 0|1
|
||||
my $DbLogType = $memc->{DbLogType}; # Log-Ziele
|
||||
my $operation = $memc->{operation} // 'unknown'; # aktuell angeforderte Operation (log, etc.)
|
||||
|
||||
@ -3283,7 +3336,7 @@ sub __DbLog_SBP_logLogmodes {
|
||||
Log3 ($name, 4, "DbLog $name - Operation: $operation");
|
||||
Log3 ($name, 5, "DbLog $name - DbLogType: $DbLogType");
|
||||
Log3 ($name, 4, "DbLog $name - AutoCommit: $ac, Transaction: $tm");
|
||||
Log3 ($name, 4, "DbLog $name - Insert mode: ".($bi ? "Bulk" : "Array"));
|
||||
Log3 ($name, 4, "DbLog $name - Insert mode: ".($im ? "Sequential" : "Array"));
|
||||
|
||||
return;
|
||||
}
|
||||
@ -3374,26 +3427,22 @@ sub _DbLog_SBP_onRun_deleteOldDays {
|
||||
my $st = [gettimeofday]; # SQL-Startzeit
|
||||
|
||||
if(defined ($cmd)) {
|
||||
eval { $numdel = $dbh->do($cmd);
|
||||
1;
|
||||
}
|
||||
or do { $error = $@;
|
||||
|
||||
Log3 ($name, 2, "DbLog $name - Error table $history - $error");
|
||||
(my $err, $numdel) = _DbLog_SBP_dbhDo ($name, $dbh, $cmd);
|
||||
|
||||
if ($err) {
|
||||
$dbh->disconnect();
|
||||
delete $store->{dbh};
|
||||
|
||||
$ret = {
|
||||
name => $name,
|
||||
msg => $error,
|
||||
msg => $err,
|
||||
ot => 0,
|
||||
oper => $operation
|
||||
};
|
||||
|
||||
__DbLog_SBP_sendToParent ($subprocess, $ret);
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
$numdel = 0 if($numdel == 0E0);
|
||||
$error = __DbLog_SBP_commitOnly ($name, $dbh, $history);
|
||||
@ -3491,7 +3540,7 @@ return;
|
||||
# $memc->{arguments} -> $infile
|
||||
# $memc->{operation} -> 'importCachefile'
|
||||
# $memc->{DbLogType} -> 'history'
|
||||
# $memc->{bi} -> 0
|
||||
# $memc->{im} -> 0
|
||||
#
|
||||
#################################################################
|
||||
sub _DbLog_SBP_onRun_importCachefile {
|
||||
@ -3546,7 +3595,7 @@ sub _DbLog_SBP_onRun_importCachefile {
|
||||
Log3 ($name, 3, "DbLog $name - $msg");
|
||||
|
||||
$memc->{DbLogType} = 'history'; # nur history-Insert !
|
||||
$memc->{bi} = 0; # Array-Insert !
|
||||
$memc->{im} = 0; # Array-Insert !
|
||||
|
||||
($error, $nins_hist, $rowlback) = _DbLog_SBP_onRun_LogArray ( { subprocess => $subprocess,
|
||||
name => $name,
|
||||
@ -4186,32 +4235,6 @@ sub __DbLog_SBP_disconnectOnly {
|
||||
return $err;
|
||||
}
|
||||
|
||||
#################################################################
|
||||
# erstellt SQL für Insert Daten in die HISTORY! Tabelle
|
||||
#################################################################
|
||||
sub __DbLog_SBP_sqlInsHistory {
|
||||
my $table = shift;
|
||||
my $model = shift;
|
||||
my $usepkh = shift;
|
||||
|
||||
my $sql;
|
||||
|
||||
if ($usepkh && $model eq 'MYSQL') {
|
||||
$sql = "INSERT IGNORE INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES ";
|
||||
}
|
||||
elsif ($usepkh && $model eq 'SQLITE') {
|
||||
$sql = "INSERT OR IGNORE INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES ";
|
||||
}
|
||||
elsif ($usepkh && $model eq 'POSTGRESQL') {
|
||||
$sql = "INSERT INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES ";
|
||||
}
|
||||
else { # ohne PK
|
||||
$sql = "INSERT INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES ";
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
#################################################################
|
||||
# erstellt Statement Handle für Insert Daten in die
|
||||
# angegebene Tabelle
|
||||
@ -4453,7 +4476,7 @@ sub DbLog_SBP_sendLogData {
|
||||
$memc->{nsupk} = AttrVal ($name, 'noSupportPK', 0);
|
||||
$memc->{tl} = AttrVal ($name, 'traceLevel', 0);
|
||||
$memc->{tf} = AttrVal ($name, 'traceFlag', 'SQL');
|
||||
$memc->{bi} = AttrVal ($name, 'bulkInsert', 0);
|
||||
$memc->{im} = AttrVal ($name, 'insertMode', 0);
|
||||
$memc->{verbose} = AttrVal ($name, 'verbose', 3);
|
||||
$memc->{operation} = $oper;
|
||||
|
||||
@ -4492,7 +4515,7 @@ sub DbLog_SBP_sendCommand {
|
||||
$memc->{nsupk} = AttrVal ($name, 'noSupportPK', 0);
|
||||
$memc->{tl} = AttrVal ($name, 'traceLevel', 0);
|
||||
$memc->{tf} = AttrVal ($name, 'traceFlag', 'SQL');
|
||||
$memc->{bi} = AttrVal ($name, 'bulkInsert', 0);
|
||||
$memc->{im} = AttrVal ($name, 'insertMode', 0);
|
||||
$memc->{verbose} = AttrVal ($name, 'verbose', 3);
|
||||
$memc->{operation} = $oper;
|
||||
$memc->{arguments} = $arg;
|
||||
@ -5012,7 +5035,8 @@ sub DbLog_ExecSQL {
|
||||
|
||||
Log3 ($name, 4, "DbLog $name - Backdoor executing: $sql");
|
||||
|
||||
my $sth = DbLog_ExecSQL1($hash, $dbh, $sql);
|
||||
($err, my $sth) = _DbLog_SBP_dbhDo ($name, $dbh, $sql);
|
||||
$sth = 0 if($err);
|
||||
|
||||
__DbLog_SBP_commitOnly ($name, $dbh);
|
||||
__DbLog_SBP_disconnectOnly ($name, $dbh);
|
||||
@ -5020,24 +5044,6 @@ sub DbLog_ExecSQL {
|
||||
return $sth;
|
||||
}
|
||||
|
||||
sub DbLog_ExecSQL1 {
|
||||
my $hash = shift;
|
||||
my $dbh = shift;
|
||||
my $sql = shift;
|
||||
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
my $sth;
|
||||
|
||||
eval { $sth = $dbh->do($sql); };
|
||||
if($@) {
|
||||
Log3 ($name, 2, "DbLog $name - ERROR: $@");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $sth;
|
||||
}
|
||||
|
||||
################################################################
|
||||
#
|
||||
# GET Funktion
|
||||
@ -5944,25 +5950,25 @@ sub DbLog_configcheck {
|
||||
### Check Betriebsmodus
|
||||
#######################################################################
|
||||
my $mode = $hash->{MODE};
|
||||
my $bi = AttrVal($name, 'bulkInsert', 0);
|
||||
my $im = AttrVal($name, 'insertMode', 0);
|
||||
my $sfx = AttrVal("global", 'language', 'EN');
|
||||
$sfx = $sfx eq "EN" ? "" : "_$sfx";
|
||||
|
||||
$check .= "<u><b>Result of insert mode check</u></b><br><br>";
|
||||
|
||||
if (!$bi) {
|
||||
$bi = "Array";
|
||||
$check .= "Insert mode of DbLog-device $name is: $bi <br>";
|
||||
$check .= "Rating: ".$ok."<br>";
|
||||
$rec = "Setting attribute \"bulkInsert\" to \"1\" may result a higher write performance in most cases. ";
|
||||
$rec .= "Feel free to try this mode.";
|
||||
}
|
||||
else {
|
||||
$bi = "Bulk";
|
||||
$check .= "Insert mode of DbLog-device $name is: $bi <br>";
|
||||
if (!$im) {
|
||||
$im = "Array";
|
||||
$check .= "Insert mode of DbLog-device $name is: $im <br>";
|
||||
$check .= "Rating: ".$ok."<br>";
|
||||
$rec = "settings o.k.";
|
||||
}
|
||||
else {
|
||||
$im = "Sequential";
|
||||
$check .= "Insert mode of DbLog-device $name is: $im <br>";
|
||||
$check .= "Rating: ".$ok."<br>";
|
||||
$rec = qq(Setting attribute "insertMode" to "0" (or delete it) may result a higher write performance in most cases. );
|
||||
$rec .= "Feel free to try this mode.";
|
||||
}
|
||||
$check .= "<b>Recommendation:</b> $rec <br><br>";
|
||||
|
||||
### Check Plot Erstellungsmodus
|
||||
@ -7054,6 +7060,44 @@ sub DbLog_checkUsePK {
|
||||
return ($upkh,$upkc,$pkh,$pkc);
|
||||
}
|
||||
|
||||
################################################################
|
||||
# Syntaxcheck von Attr valueFn und DbLogValueFn
|
||||
# Rückgabe von Error oder der gesäuberten Funktion
|
||||
################################################################
|
||||
sub DbLog_checkSyntaxValueFn {
|
||||
my $name = shift;
|
||||
my $func = shift;
|
||||
my $devname = shift // q{};
|
||||
|
||||
my $err = q{};
|
||||
|
||||
if ($func !~ m/^\s*(\{.*\})\s*$/s) {
|
||||
return "Error while syntax checking. The function has to be enclosed by curly brackets.";
|
||||
}
|
||||
|
||||
my %specials= (
|
||||
"%TIMESTAMP" => $name,
|
||||
"%LASTTIMESTAMP" => $name,
|
||||
"%DEVICE" => $name,
|
||||
"%DEVICETYPE" => $name,
|
||||
"%EVENT" => $name,
|
||||
"%READING" => $name,
|
||||
"%VALUE" => $name,
|
||||
"%LASTVALUE" => $name,
|
||||
"%UNIT" => $name,
|
||||
"%IGNORE" => $name,
|
||||
"%CN" => $name
|
||||
);
|
||||
|
||||
$err = perlSyntaxCheck ($func, %specials);
|
||||
|
||||
Log3 ($name, 1, "DbLog $name - Syntaxcheck <$devname> attribute DbLogValueFn: \n".$err) if($err && $devname);
|
||||
|
||||
$func =~ s/^\s*(\{.*\})\s*$/$1/s;
|
||||
|
||||
return ($err, $func);
|
||||
}
|
||||
|
||||
################################################################
|
||||
# Routine für FHEMWEB Detailanzeige
|
||||
################################################################
|
||||
@ -7551,13 +7595,13 @@ sub DbLog_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{DbLog}{META}}
|
||||
if($modules{$type}{META}{x_version}) { # {x_version} ( nur gesetzt wenn $Id: 93_DbLog.pm 26923 2022-12-29 10:28:14Z DS_Starter $ im Kopf komplett! vorhanden )
|
||||
if($modules{$type}{META}{x_version}) { # {x_version} ( nur gesetzt wenn $Id: 93_DbLog.pm 27082 2023-01-18 22:08:25Z DS_Starter $ im Kopf komplett! vorhanden )
|
||||
$modules{$type}{META}{x_version} =~ s/1\.1\.1/$v/xsg;
|
||||
}
|
||||
else {
|
||||
$modules{$type}{META}{x_version} = $v;
|
||||
}
|
||||
return $@ unless (FHEM::Meta::SetInternals($hash)); # FVERSION wird gesetzt ( nur gesetzt wenn $Id: 93_DbLog.pm 26923 2022-12-29 10:28:14Z DS_Starter $ im Kopf komplett! vorhanden )
|
||||
return $@ unless (FHEM::Meta::SetInternals($hash)); # FVERSION wird gesetzt ( nur gesetzt wenn $Id: 93_DbLog.pm 27082 2023-01-18 22:08:25Z DS_Starter $ im Kopf komplett! vorhanden )
|
||||
if(__PACKAGE__ eq "FHEM::$type" || __PACKAGE__ eq $type) {
|
||||
# es wird mit Packages gearbeitet -> Perl übliche Modulversion setzen
|
||||
# mit {<Modul>->VERSION()} im FHEMWEB kann Modulversion abgefragt werden
|
||||
@ -8357,8 +8401,7 @@ return;
|
||||
<tr><td> </td><td>In principle, the data is immediately available in the database. </td></tr>
|
||||
<tr><td> </td><td>Very little to no data is lost when FHEM crashes. </td></tr>
|
||||
<tr><td> </td><td><b>Disadvantages:</b> </td></tr>
|
||||
<tr><td> </td><td>The data is only short cached and will be lost if the database is unavailable or malfunctions. </td></tr>
|
||||
<tr><td> </td><td>Alternative storage in the file system is not supported. </td></tr>
|
||||
<tr><td> </td><td>An alternative storage in the file system (in case of database problems) is not supported. </td></tr>
|
||||
<tr><td> </td><td> </td></tr>
|
||||
<tr><td> 1 - </td><td><b>Asynchroner Log-Modus.</b> The data to be logged is first cached in a memory cache and written to the database </td></tr>
|
||||
<tr><td> </td><td>depending on a <a href="#DbLog-attr-syncInterval">time interval</a> or <a href="#DbLog-attr-cacheLimit">fill level</a> of the cache. </td></tr>
|
||||
@ -8376,25 +8419,6 @@ return;
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<a id="DbLog-attr-bulkInsert"></a>
|
||||
<li><b>bulkInsert</b>
|
||||
<ul>
|
||||
<code>attr <device> bulkInsert [1|0] </code><br><br>
|
||||
|
||||
Toggles the insert mode between "Array" and "Bulk". <br>
|
||||
The bulk mode leads to a considerable performance increase when inserting a large number of data records into the
|
||||
history table, especially in asynchronous mode.
|
||||
To get the full performance increase, in this case the attribute "DbLogType" should <b>not</b> contain the
|
||||
current table. <br>
|
||||
In contrast, the "Array" mode has the advantage over "Bulk" that faulty data records are extracted and reported in the
|
||||
log file. <br>
|
||||
(default: 0=Array)
|
||||
</ul>
|
||||
</ul>
|
||||
</li>
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<a id="DbLog-attr-commitMode"></a>
|
||||
<li><b>commitMode</b>
|
||||
@ -8872,6 +8896,30 @@ attr SMA_Energymeter DbLogValueFn
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<a id="DbLog-attr-insertMode"></a>
|
||||
<li><b>insertMode</b>
|
||||
<ul>
|
||||
<code>attr <device> insertMode [1|0] </code><br><br>
|
||||
|
||||
Toggles the insert mode of the database interface. <br><br>
|
||||
|
||||
<ul>
|
||||
<table>
|
||||
<colgroup> <col width=5%> <col width=95%> </colgroup>
|
||||
<tr><td> 0 - </td><td>The data is passed as an array to the database interface. </td></tr>
|
||||
<tr><td> </td><td>It is in most cases the most performant way to insert a lot of data into the database at once. </td></tr>
|
||||
<tr><td> 1 - </td><td>The records are passed sequentially to the database interface and inserted into the DB. </td></tr>
|
||||
</table>
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
(default: 0)
|
||||
</ul>
|
||||
</ul>
|
||||
</li>
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<a id="DbLog-attr-noNotifyDev"></a>
|
||||
<li><b>noNotifyDev</b>
|
||||
@ -10018,8 +10066,7 @@ attr SMA_Energymeter DbLogValueFn
|
||||
<tr><td> </td><td>Die Daten stehen im Prinzip sofort in der Datenbank zur Verfügung. </td></tr>
|
||||
<tr><td> </td><td>Bei einem Absturz von FHEM gehen sehr wenige bis keine Daten verloren. </td></tr>
|
||||
<tr><td> </td><td><b>Nachteile:</b> </td></tr>
|
||||
<tr><td> </td><td>Die Daten werden nur kurz zwischengespeichert und gehen verloren wenn die Datenbank nicht verfügbar ist </td></tr>
|
||||
<tr><td> </td><td>oder fehlerhaft arbeitet. Eine alternative Speicherung im Filesystem wird nicht unterstützt. </td></tr>
|
||||
<tr><td> </td><td>Eine alternative Speicherung im Filesystem (bei Datenbankproblemen) wird nicht unterstützt. </td></tr>
|
||||
<tr><td> </td><td> </td></tr>
|
||||
<tr><td> </td><td> </td></tr>
|
||||
<tr><td> 1 - </td><td><b>Asynchroner Log-Modus.</b> Die zu loggenden Daten werden zunächst in einem Memory Cache zwischengespeichert </td></tr>
|
||||
@ -10038,24 +10085,6 @@ attr SMA_Energymeter DbLogValueFn
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<a id="DbLog-attr-bulkInsert"></a>
|
||||
<li><b>bulkInsert</b>
|
||||
<ul>
|
||||
<code>attr <device> bulkInsert [1|0] </code><br><br>
|
||||
|
||||
Schaltet den Insert-Modus zwischen "Array" und "Bulk" um. <br>
|
||||
Der Bulk Modus führt beim Insert von sehr vielen Datensätzen in die history-Tabelle zu einer erheblichen
|
||||
Performancesteigerung vor allem im asynchronen Mode. Um die volle Performancesteigerung zu erhalten, sollte in
|
||||
diesem Fall das Attribut "DbLogType" <b>nicht</b> die current-Tabelle enthalten. <br>
|
||||
Demgegenüber hat der Modus "Array" gegenüber "Bulk" den Vorteil, dass fehlerhafte Datensätze extrahiert und im
|
||||
Logfile reported werden. <br>
|
||||
(default: 0=Array)
|
||||
</ul>
|
||||
</ul>
|
||||
</li>
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<a id="DbLog-attr-cacheEvents"></a>
|
||||
<li><b>cacheEvents</b>
|
||||
@ -10553,6 +10582,30 @@ attr SMA_Energymeter DbLogValueFn
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<a id="DbLog-attr-insertMode"></a>
|
||||
<li><b>insertMode</b>
|
||||
<ul>
|
||||
<code>attr <device> insertMode [1|0] </code><br><br>
|
||||
|
||||
Schaltet den Insert-Modus der Datenbankschnittstelle um. <br><br>
|
||||
|
||||
<ul>
|
||||
<table>
|
||||
<colgroup> <col width=5%> <col width=95%> </colgroup>
|
||||
<tr><td> 0 - </td><td>Die Daten werden als Array der Datenbankschnittstelle übergeben. </td></tr>
|
||||
<tr><td> </td><td>Es ist in den meisten Fällen der performanteste Weg viele Daten auf einmal in die Datenbank einzufügen. </td></tr>
|
||||
<tr><td> 1 - </td><td>Die Datensätze werden sequentiell der Datenbankschnittstelle übergeben und in die DB eingefügt. </td></tr>
|
||||
</table>
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
(default: 0)
|
||||
</ul>
|
||||
</ul>
|
||||
</li>
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<a id="DbLog-attr-noNotifyDev"></a>
|
||||
<li><b>noNotifyDev</b>
|
||||
|
Loading…
x
Reference in New Issue
Block a user