From a84b4b345f0fe8167d6ffede208f4995cb348cfd Mon Sep 17 00:00:00 2001 From: nasseeder1 Date: Sun, 20 Jan 2019 07:34:28 +0000 Subject: [PATCH] 93_DbRep: sqlCmd can handle SQL session variables, Forum:#96082 git-svn-id: https://svn.fhem.de/fhem/trunk@18345 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 1 + fhem/FHEM/93_DbRep.pm | 103 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 96 insertions(+), 8 deletions(-) diff --git a/fhem/CHANGED b/fhem/CHANGED index 1783f62fd..83ece2ec2 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. + - feature: 93_DbRep: sqlCmd can handle SQL session variables, Forum:#96082 - bugfix: 98_DOIFtools: remove Log in DOIFtoolsNextTimer - bugfix: 93_DbRep: V8.9.10, fix warnings Malformed UTF-8 character during importFromFile, Forum:#96056 diff --git a/fhem/FHEM/93_DbRep.pm b/fhem/FHEM/93_DbRep.pm index 371c11cc0..fbba016a2 100644 --- a/fhem/FHEM/93_DbRep.pm +++ b/fhem/FHEM/93_DbRep.pm @@ -57,6 +57,7 @@ no if $] >= 5.017011, warnings => 'experimental::smartmatch'; # Versions History intern our %DbRep_vNotesIntern = ( + "8.10.0" => "19.01.2019 sqlCmd, dbValue may input SQL session variables, Forum:#96082 ", "8.9.10" => "18.01.2019 fix warnings Malformed UTF-8 character during importFromFile, Forum:#96056 ", "8.9.9" => "06.01.2019 diffval_DoParse: 'ORDER BY TIMESTAMP' added to statements Forum:https://forum.fhem.de/index.php/topic,53584.msg882082.html#msg882082", "8.9.8" => "27.11.2018 minor fix in deviceRename, commandref revised ", @@ -130,6 +131,7 @@ our %DbRep_vNotesIntern = ( # Versions History extern: our %DbRep_vNotesExtern = ( + "8.10.0" => "19.01.2019 In commands sqlCmd, dbValue you may now use SQL session variables like \"SET \@open:=NULL,\@closed:=NULL; SELECT ...\", Forum:#96082", "8.9.0" => "07.11.2018 new command set delDoublets added. This command allows to delete multiple occuring identical records. ", "8.8.0" => "06.11.2018 new attribute 'fastStart'. Usually every DbRep-device is making a short connect to its database when " ."FHEM is restarted. When this attribute is set, the initial connect is done when the DbRep-device is doing its " @@ -944,7 +946,7 @@ sub DbRep_Get($@) { } } $i = 0; - foreach my $key (reverse sort(keys %hs)) { + foreach my $key (sort{$b<=>$a}(keys %hs)) { $val0 = $hs{$key}; $ret .= sprintf("$key $val0" ); $ret .= ""; @@ -969,7 +971,7 @@ sub DbRep_Get($@) { $ret .= ""; $ret .= ""; $i = 0; - foreach my $key (reverse sort(keys %DbRep_vNotesExtern)) { + foreach my $key (sort{$b<=>$a}(keys %DbRep_vNotesExtern)) { ($val0,$val1) = split(/\s/,$DbRep_vNotesExtern{$key},2); $ret .= sprintf("$key $val0 $val1" ); $ret .= ""; @@ -5559,11 +5561,30 @@ sub sqlCmd_DoParse($) { no warnings 'uninitialized'; my $sql = ($cmd =~ m/\;$/)?$cmd:$cmd.";"; + + # split SQL-Parameter Statement falls mitgegeben + # z.B. SET @open:=NULL, @closed:=NULL; Select ... + my $set; + if($cmd =~ /^SET.*;/i) { + $cmd =~ m/^(SET.*?;)(.*)/i; + $set = $1; + $sql = $2; + } + + if($set) { + Log3($name, 4, "DbRep $name - Set SQL session variables: $set"); + eval {$dbh->do($set);}; # @\RB = Resetbit wenn neues Selektionsintervall beginnt + } + if ($@) { + $err = encode_base64($@,""); + Log3 ($name, 2, "DbRep $name - ERROR - $@"); + $dbh->disconnect; + return "$name|''|$opt|$set|''|''|$err"; + } + # Allow inplace replacement of keywords for timings (use time attribute syntax) $sql =~ s/§timestamp_begin§/'$runtime_string_first'/g; $sql =~ s/§timestamp_end§/'$runtime_string_next'/g; - -# Debug "SQL :".$sql.":"; Log3($name, 4, "DbRep $name - SQL execute: $sql"); @@ -5577,7 +5598,6 @@ sub sqlCmd_DoParse($) { }; if ($@) { - # error bei sql-execute $err = encode_base64($@,""); Log3 ($name, 2, "DbRep $name - ERROR - $@"); $dbh->disconnect; @@ -5629,7 +5649,7 @@ sub sqlCmd_DoParse($) { $rt = $rt.",".$brt; - return "$name|$rowstring|$opt|$sql|$nrows|$rt|$err"; + return "$name|$rowstring|$opt|$cmd|$nrows|$rt|$err"; } #################################################################################################### @@ -9953,6 +9973,27 @@ sub DbRep_dbValue($$) { Log3 ($name, 4, "DbRep $name - -------- New selection --------- "); Log3 ($name, 4, "DbRep $name - Command: dbValue"); Log3 ($name, 4, "DbRep $name - SQL execute: $sql"); + + # split SQL-Parameter Statement falls mitgegeben + # z.B. SET @open:=NULL, @closed:=NULL; Select ... + my $set; + if($cmd =~ /^SET.*;/i) { + $cmd =~ m/^(SET.*?;)(.*)/i; + $set = $1; + $sql = $2; + } + + if($set) { + Log3($name, 4, "DbRep $name - Set SQL session variables: $set"); + eval {$dbh->do($set);}; # @\RB = Resetbit wenn neues Selektionsintervall beginnt + } + if ($@) { + $err = $@; + Log3 ($name, 2, "DbRep $name - $err"); + ReadingsSingleUpdateValue ($hash, "errortext", $err, 1); + ReadingsSingleUpdateValue ($hash, "state", "error", 1); + return ($err); + } # SQL-Startzeit my $st = [gettimeofday]; @@ -11294,6 +11335,8 @@ return; "allowDeletion" has to be set for security reason.
The statement doesn't consider limitations by attributes "device", "reading", "time.*" respectively "aggregation".
+ This command also accept the setting of SQL session variables like "SET @open:=NULL, + @closed:=NULL;".
If the attribute "timestamp_begin" respectively "timestamp_end" is assumed in the statement, it is possible to use placeholder "§timestamp_begin§" respectively "§timestamp_end§" on suitable place.

@@ -11316,6 +11359,25 @@ return;
  • set <name> sqlCmd update history set TIMESTAMP=TIMESTAMP,VALUE='Val' WHERE VALUE='TestValue'
  • set <name> sqlCmd select * from history where DEVICE = "Test"
  • set <name> sqlCmd insert into history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES ('2017-05-09 17:00:14','Test','manuell','manuell','Tes§e','TestValue','°C')
  • + +
    + + Here you can see an example of a more complex statement (MySQL) with setting SQL session + variables:

    + +
    @@ -11531,6 +11593,8 @@ return; Executes the specified SQL-statement in blocking manner. Because of its mode of operation this function is particular convenient for user own perl scripts.
    The input accepts multi line commands and delivers multi line results as well. + This command also accept the setting of SQL session variables like "SET @open:=NULL, + @closed:=NULL;".
    If several fields are selected and passed back, the fieds are separated by the separator defined by attribute "sqlResultFieldSep" (default "|"). Several result lines are separated by newline ("\n").
    @@ -13604,6 +13668,8 @@ sub bdump { Attribut "allowDeletion" gesetzt sein.
    Bei der Ausführung dieses Kommandos werden keine Einschränkungen durch gesetzte Attribute "device", "reading", "time.*" bzw. "aggregation" berücksichtigt.
    + Dieses Kommando akzeptiert ebenfalls das Setzen von SQL Session Variablen wie z.B. + "SET @open:=NULL, @closed:=NULL;".
    Sollen die im Modul gesetzten Attribute "timestamp_begin" bzw. "timestamp_end" im Statement berücksichtigt werden, können die Platzhalter "§timestamp_begin§" bzw. "§timestamp_end§" dafür verwendet werden.

    @@ -13627,7 +13693,26 @@ sub bdump {
  • set <name> sqlCmd select * from history where DEVICE = "Test"
  • set <name> sqlCmd insert into history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES ('2017-05-09 17:00:14','Test','manuell','manuell','Tes§e','TestValue','°C')
  • -
    +
    + + Nachfolgend noch ein Beispiel für ein komplexeres Statement (MySQL) unter Mitgabe von + SQL Session Variablen:

    + + +
    Das Ergebnis des Statements wird im Reading "SqlResult" dargestellt. Die Ergebnis-Formatierung kann durch das Attribut "sqlResultFormat" ausgewählt, sowie der verwendete @@ -13848,7 +13933,9 @@ sub bdump {
  • dbValue <SQL-Statement> - Führt das angegebene SQL-Statement blockierend aus. Diese Funktion ist durch ihre Arbeitsweise speziell für den Einsatz in benutzerspezifischen Scripten geeignet.
    - Die Eingabe akzeptiert Mehrzeiler und gibt ebenso mehrzeilige Ergebisse zurück. + Die Eingabe akzeptiert Mehrzeiler und gibt ebenso mehrzeilige Ergebisse zurück. + Dieses Kommando akzeptiert ebenfalls das Setzen von SQL Session Variablen wie z.B. + "SET @open:=NULL, @closed:=NULL;".
    Werden mehrere Felder selektiert und zurückgegeben, erfolgt die Feldtrennung mit dem Trenner des Attributes "sqlResultFieldSep" (default "|"). Mehrere Ergebniszeilen werden mit Newline ("\n") separiert.