From 2c4a3f6910cd0d840f2da6b448a03271a7add076 Mon Sep 17 00:00:00 2001 From: nasseeder1 Date: Mon, 23 Jan 2023 19:06:28 +0000 Subject: [PATCH] 93_DbLog: Syntaxcheck of DbLogValueFn attribute, Forum:#131777 git-svn-id: https://svn.fhem.de/fhem/trunk@27111 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 1 + fhem/FHEM/93_DbLog.pm | 115 ++++++++++++++++++++++++------------------ 2 files changed, 67 insertions(+), 49 deletions(-) diff --git a/fhem/CHANGED b/fhem/CHANGED index 98647cad7..c4aa7b270 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,6 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. + - change: 93_DbLog: Syntaxcheck of DbLogValueFn attribute, Forum:#131777 - change: 72_FRITZBOX: our Deklaration nach my (package global) - bugfix: 49_SSCAM: substitution of placeholder [$#]TIME corrected - bugfix: 93_DbRep: reduceLog -> Handling of field 'value' with NULL value, diff --git a/fhem/FHEM/93_DbLog.pm b/fhem/FHEM/93_DbLog.pm index c2fbe3707..6fc2a1a94 100644 --- a/fhem/FHEM/93_DbLog.pm +++ b/fhem/FHEM/93_DbLog.pm @@ -38,6 +38,7 @@ no if $] >= 5.017011, warnings => 'experimental::smartmatch'; # Version History intern by DS_Starter: my %DbLog_vNotesIntern = ( + "5.6.2" => "22.01.2023 check Syntax of DbLogValueFn attribute with Log output, Forum:#131777 ", "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 ", @@ -194,7 +195,7 @@ sub DbLog_Initialize { $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; @@ -409,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); } @@ -1229,33 +1216,25 @@ sub DbLog_Log { my $memcount = 0; my $re = $hash->{REGEXP}; - my $ts_0 = TimeNow(); # timestamp in SQL format YYYY-MM-DD hh:mm:ss - my $now = gettimeofday(); # get timestamp in seconds since epoch + my $ts_0 = TimeNow(); # timestamp in SQL format YYYY-MM-DD hh:mm:ss + my $now = gettimeofday(); # get timestamp in seconds since epoch my $DbLogExclude = AttrVal ($dev_name, 'DbLogExclude', undef); my $DbLogInclude = AttrVal ($dev_name, 'DbLogInclude', undef); my $DbLogValueFn = AttrVal ($dev_name, 'DbLogValueFn', ''); my $DbLogSelectionMode = AttrVal ($name, 'DbLogSelectionMode','Exclude'); my $value_fn = AttrVal ($name, 'valueFn', ''); - my $ctz = AttrVal ($name, 'convertTimezone', 'none'); # convert time zone + my $ctz = AttrVal ($name, 'convertTimezone', 'none'); # convert time zone my $async = AttrVal ($name, 'asyncMode', 0); 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 + eval { # one Transaction for (my $i = 0; $i < $max; $i++) { my $next = 0; my $event = $events->[$i]; @@ -2552,16 +2531,16 @@ sub _DbLog_SBP_connectDB { } } - if ($model eq 'SQLITE') { - my @dos = ("PRAGMA temp_store=MEMORY", - "PRAGMA synchronous=FULL", + if ($model eq 'SQLITE') { + my @dos = ("PRAGMA temp_store=MEMORY", + "PRAGMA synchronous=FULL", "PRAGMA journal_mode=$sltjm", "PRAGMA cache_size=$sltcs" ); - + for my $do (@dos) { - ($err, undef) = _DbLog_SBP_dbhDo ($name, $dbh, $do); - return ($err, q{}) if($err); + ($err, undef) = _DbLog_SBP_dbhDo ($name, $dbh, $do); + return ($err, q{}) if($err); } } @@ -3448,8 +3427,8 @@ sub _DbLog_SBP_onRun_deleteOldDays { my $st = [gettimeofday]; # SQL-Startzeit if(defined ($cmd)) { - (my $err, $numdel) = _DbLog_SBP_dbhDo ($name, $dbh, $cmd); - + (my $err, $numdel) = _DbLog_SBP_dbhDo ($name, $dbh, $cmd); + if ($err) { $dbh->disconnect(); delete $store->{dbh}; @@ -3462,9 +3441,9 @@ sub _DbLog_SBP_onRun_deleteOldDays { }; __DbLog_SBP_sendToParent ($subprocess, $ret); - return; + return; } - + $numdel = 0 if($numdel == 0E0); $error = __DbLog_SBP_commitOnly ($name, $dbh, $history); @@ -5042,7 +5021,7 @@ return ($err, @sr); # # param1: DbLog-hash # param2: SQL-Statement -# +# ########################################################################## sub DbLog_ExecSQL { my $hash = shift; @@ -5055,9 +5034,9 @@ sub DbLog_ExecSQL { my $name = $hash->{NAME}; Log3 ($name, 4, "DbLog $name - Backdoor executing: $sql"); - - ($err, my $sth) = _DbLog_SBP_dbhDo ($name, $dbh, $sql); - $sth = 0 if($err); + + ($err, my $sth) = _DbLog_SBP_dbhDo ($name, $dbh, $sql); + $sth = 0 if($err); __DbLog_SBP_commitOnly ($name, $dbh); __DbLog_SBP_disconnectOnly ($name, $dbh); @@ -7081,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 ################################################################ @@ -8878,7 +8895,7 @@ attr SMA_Energymeter DbLogValueFn
- +
- +