From 618987d5810a0b87efebcfc8c33e03c7e28cb113 Mon Sep 17 00:00:00 2001 From: tobiasfaust <> Date: Thu, 31 Jan 2013 04:03:12 +0000 Subject: [PATCH] 93_DbLog.pm: MySQL: neue Definition eines Indices auf history zur schnelleren Generierung von Plots, SQL darauf angepasst git-svn-id: https://svn.fhem.de/fhem/trunk@2614 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/93_DbLog.pm | 327 ++++++++++---------- fhem/contrib/dblog/db_create_mysql.sql | 2 +- fhem/contrib/dblog/db_create_postgresql.sql | 4 +- 3 files changed, 168 insertions(+), 165 deletions(-) diff --git a/fhem/FHEM/93_DbLog.pm b/fhem/FHEM/93_DbLog.pm index 7808866ec..d18fc5e18 100644 --- a/fhem/FHEM/93_DbLog.pm +++ b/fhem/FHEM/93_DbLog.pm @@ -535,179 +535,181 @@ DbLog_Get($@) $sqlspec{all} = ""; } - for(my $i=0; $i[0]."|".$readings[$i]->[1]."') - AND TIMESTAMP > $sqlspec{from_timestamp} - AND TIMESTAMP < $sqlspec{to_timestamp} - ORDER BY TIMESTAMP"; + my $stm= "SELECT + $sqlspec{get_timestamp}, + DEVICE, + READING, + VALUE + $sqlspec{all} + FROM history + WHERE 1=1 + AND $sqlspec{reading_clause} = ('".$readings[$i]->[0]."|".$readings[$i]->[1]."') + AND DEVICE = '".$readings[$i]->[0]."' + AND READING = '".$readings[$i]->[1]."' + AND TIMESTAMP > $sqlspec{from_timestamp} + AND TIMESTAMP < $sqlspec{to_timestamp} + ORDER BY TIMESTAMP"; - Log GetLogLevel($hash->{NAME},5), "Executing $stm"; + Log GetLogLevel($hash->{NAME},5), "Executing $stm"; - my $sth= $dbh->prepare($stm) || - return "Cannot prepare statement $stm: $DBI::errstr"; - my $rc= $sth->execute() || - return "Cannot execute statement $stm: $DBI::errstr"; + my $sth= $dbh->prepare($stm) || + return "Cannot prepare statement $stm: $DBI::errstr"; + my $rc= $sth->execute() || + return "Cannot execute statement $stm: $DBI::errstr"; - if(uc($outf) eq "ALL") { - $retval .= "Timestamp: Device, Type, Event, Reading, Value, Unit\n"; - $retval .= "=====================================================\n"; - } - while( ($sql_timestamp,$sql_dev,$sql_reading,$sql_value, $type, $event, $unit)= $sth->fetchrow_array) { - $writeout = 0; - $out_value = ""; - $out_tstamp = ""; - - ############ Auswerten des 5. Parameters: Regexp ################### - if($readings[$i]->[4] && $readings[$i]->[4]) { - #evaluate - my $val = $sql_value; - eval("$readings[$i]->[4]"); - $sql_value = $val; - if($@) {Log 3, "DbLog: Fehler in der übergebenen Funktion: <".$readings[$i]->[4].">, Fehler: $@";} - $out_tstamp = $sql_timestamp; - $writeout=1; - } - - ############ Auswerten des 4. Parameters: function ################### - if($readings[$i]->[3] && $readings[$i]->[3] eq "int") { - #nur den integerwert uebernehmen falls zb value=15°C - $out_value = $1 if($sql_value =~ m/^(\d+).*/o); - $out_tstamp = $sql_timestamp; - $writeout=1; - - } elsif ($readings[$i]->[3] && $readings[$i]->[3] =~ m/^int(\d+).*/o) { - #?bernehme den Dezimalwert mit den angegebenen Stellen an Nachkommastellen - $out_value = $1 if($sql_value =~ m/^([-\.\d]+).*/o); - $out_tstamp = $sql_timestamp; - $writeout=1; - - } elsif ($readings[$i]->[3] && $readings[$i]->[3] eq "delta-h") { - #Berechnung eines Stundenwertes - %tstamp = DbLog_explode_datetime($sql_timestamp, ()); - if($lastd[$i] eq "undef") { - %lasttstamp = DbLog_explode_datetime($sql_timestamp, ()); - } else { - %lasttstamp = DbLog_explode_datetime($lastd[$i], ()); - } - if("$tstamp{hour}" ne "$lasttstamp{hour}") { - # Aenderung der stunde, Berechne Delta - $out_value = sprintf("%0.1f", $maxval - $minval); - $out_tstamp = DbLog_implode_datetime($lasttstamp{year}, $lasttstamp{month}, $lasttstamp{day}, $lasttstamp{hour}, "30", "00"); - $minval = 999999; - $maxval = -999999; - $writeout=1; - } - } elsif ($readings[$i]->[3] && $readings[$i]->[3] eq "delta-d") { - #Berechnung eines Tageswertes - %tstamp = DbLog_explode_datetime($sql_timestamp, ()); - if($lastd[$i] eq "undef") { - %lasttstamp = DbLog_explode_datetime($sql_timestamp, ()); - } else { - %lasttstamp = DbLog_explode_datetime($lastd[$i], ()); - } - if("$tstamp{day}" ne "$lasttstamp{day}") { - # Aenderung des Tages, Berechne Delta - $out_value = sprintf("%0.1f", $maxval - $minval); - $out_tstamp = DbLog_implode_datetime($lasttstamp{year}, $lasttstamp{month}, $lasttstamp{day}, "00", "00", "00"); - $minval = 999999; - $maxval = -999999; - $writeout=1; - } - } else { - $out_value = $sql_value; - $out_tstamp = $sql_timestamp; - $writeout=1; - } - - ###################### Ausgabe ########################### - if($writeout) { - if(uc($outf) eq "ALL") { - $retval .= sprintf("%s: %s, %s, %s, %s, %s, %s\n", $out_tstamp, $sql_dev, $type, $event, $sql_reading, $out_value, $unit); - } else { - $out_tstamp =~ s/\ /_/g; #needed by generating plots - $retval .= "$out_tstamp $out_value\n"; - } - } - - if(defined($sql_value) || $sql_value =~ m/^[-\.\d]+$/o){ - #nur setzen wenn nummerisch - $min[$i] = $sql_value if($sql_value < $min[$i]); - $max[$i] = $sql_value if($sql_value > $max[$i]);; - $sum[$i] += $sql_value; - $minval = $sql_value if($sql_value < $minval); - $maxval = $sql_value if($sql_value > $maxval); - } else { - $min[$i] = 0; - $max[$i] = 0; - $sum[$i] = 0; - $minval = 0; - $maxval = 0; - } - $cnt[$i]++; - $lastv[$i] = $sql_value; - $lastd[$i] = $sql_timestamp; - - } #while fetchrow - - ######## den letzten Abschlusssatz rausschreiben ########## - if($readings[$i]->[3] && ($readings[$i]->[3] eq "delta-h" || $readings[$i]->[3] eq "delta-d")) { - $out_value = sprintf("%0.1f", $maxval - $minval); - $out_tstamp = DbLog_implode_datetime($lasttstamp{year}, $lasttstamp{month}, $lasttstamp{day}, $lasttstamp{hour}, "30", "00") if($readings[$i]->[3] eq "delta-h"); - $out_tstamp = DbLog_implode_datetime($lasttstamp{year}, $lasttstamp{month}, $lasttstamp{day}, "00", "00", "00") if($readings[$i]->[3] eq "delta-d"); if(uc($outf) eq "ALL") { - $retval .= sprintf("%s: %s %s %s %s %s %s\n", $out_tstamp, $sql_dev, $type, $event, $sql_reading, $out_value, $unit); - } else { - $out_tstamp =~ s/\ /_/g; #needed by generating plots - $retval .= "$out_tstamp $out_value\n"; - } - } - # DatenTrenner setzen - $retval .= "#$readings[$i]->[0]"; - $retval .= ":"; - $retval .= "$readings[$i]->[1]" if($readings[$i]->[1]); - $retval .= ":"; - $retval .= "$readings[$i]->[2]" if($readings[$i]->[2]); - $retval .= ":"; - $retval .= "$readings[$i]->[3]" if($readings[$i]->[3]); - $retval .= ":"; - $retval .= "$readings[$i]->[4]" if($readings[$i]->[4]); - $retval .= "\n"; + $retval .= "Timestamp: Device, Type, Event, Reading, Value, Unit\n"; + $retval .= "=====================================================\n"; + } + while( ($sql_timestamp,$sql_dev,$sql_reading,$sql_value, $type, $event, $unit)= $sth->fetchrow_array) { + $writeout = 0; + $out_value = ""; + $out_tstamp = ""; + + ############ Auswerten des 5. Parameters: Regexp ################### + if($readings[$i]->[4] && $readings[$i]->[4]) { + #evaluate + my $val = $sql_value; + eval("$readings[$i]->[4]"); + $sql_value = $val; + if($@) {Log 3, "DbLog: Error in inline function: <".$readings[$i]->[4].">, Fehler: $@";} + $out_tstamp = $sql_timestamp; + $writeout=1; + } + + ############ Auswerten des 4. Parameters: function ################### + if($readings[$i]->[3] && $readings[$i]->[3] eq "int") { + #nur den integerwert uebernehmen falls zb value=15°C + $out_value = $1 if($sql_value =~ m/^(\d+).*/o); + $out_tstamp = $sql_timestamp; + $writeout=1; + + } elsif ($readings[$i]->[3] && $readings[$i]->[3] =~ m/^int(\d+).*/o) { + #Übernehme den Dezimalwert mit den angegebenen Stellen an Nachkommastellen + $out_value = $1 if($sql_value =~ m/^([-\.\d]+).*/o); + $out_tstamp = $sql_timestamp; + $writeout=1; + + } elsif ($readings[$i]->[3] && $readings[$i]->[3] eq "delta-h") { + #Berechnung eines Stundenwertes + %tstamp = DbLog_explode_datetime($sql_timestamp, ()); + if($lastd[$i] eq "undef") { + %lasttstamp = DbLog_explode_datetime($sql_timestamp, ()); + } else { + %lasttstamp = DbLog_explode_datetime($lastd[$i], ()); + } + if("$tstamp{hour}" ne "$lasttstamp{hour}") { + # Aenderung der stunde, Berechne Delta + $out_value = sprintf("%0.1f", $maxval - $minval); + $out_tstamp = DbLog_implode_datetime($lasttstamp{year}, $lasttstamp{month}, $lasttstamp{day}, $lasttstamp{hour}, "30", "00"); + $minval = 999999; + $maxval = -999999; + $writeout=1; + } + } elsif ($readings[$i]->[3] && $readings[$i]->[3] eq "delta-d") { + #Berechnung eines Tageswertes + %tstamp = DbLog_explode_datetime($sql_timestamp, ()); + if($lastd[$i] eq "undef") { + %lasttstamp = DbLog_explode_datetime($sql_timestamp, ()); + } else { + %lasttstamp = DbLog_explode_datetime($lastd[$i], ()); + } + if("$tstamp{day}" ne "$lasttstamp{day}") { + # Aenderung des Tages, Berechne Delta + $out_value = sprintf("%0.1f", $maxval - $minval); + $out_tstamp = DbLog_implode_datetime($lasttstamp{year}, $lasttstamp{month}, $lasttstamp{day}, "00", "00", "00"); + $minval = 999999; + $maxval = -999999; + $writeout=1; + } + } else { + $out_value = $sql_value; + $out_tstamp = $sql_timestamp; + $writeout=1; + } + + ###################### Ausgabe ########################### + if($writeout) { + if(uc($outf) eq "ALL") { + $retval .= sprintf("%s: %s, %s, %s, %s, %s, %s\n", $out_tstamp, $sql_dev, $type, $event, $sql_reading, $out_value, $unit); + } else { + $out_tstamp =~ s/\ /_/g; #needed by generating plots + $retval .= "$out_tstamp $out_value\n"; + } + } + + if(defined($sql_value) || $sql_value =~ m/^[-\.\d]+$/o){ + #nur setzen wenn nummerisch + $min[$i] = $sql_value if($sql_value < $min[$i]); + $max[$i] = $sql_value if($sql_value > $max[$i]);; + $sum[$i] += $sql_value; + $minval = $sql_value if($sql_value < $minval); + $maxval = $sql_value if($sql_value > $maxval); + } else { + $min[$i] = 0; + $max[$i] = 0; + $sum[$i] = 0; + $minval = 0; + $maxval = 0; + } + $cnt[$i]++; + $lastv[$i] = $sql_value; + $lastd[$i] = $sql_timestamp; + + } #while fetchrow + + ######## den letzten Abschlusssatz rausschreiben ########## + if($readings[$i]->[3] && ($readings[$i]->[3] eq "delta-h" || $readings[$i]->[3] eq "delta-d")) { + $out_value = sprintf("%0.1f", $maxval - $minval); + $out_tstamp = DbLog_implode_datetime($lasttstamp{year}, $lasttstamp{month}, $lasttstamp{day}, $lasttstamp{hour}, "30", "00") if($readings[$i]->[3] eq "delta-h"); + $out_tstamp = DbLog_implode_datetime($lasttstamp{year}, $lasttstamp{month}, $lasttstamp{day}, "00", "00", "00") if($readings[$i]->[3] eq "delta-d"); + if(uc($outf) eq "ALL") { + $retval .= sprintf("%s: %s %s %s %s %s %s\n", $out_tstamp, $sql_dev, $type, $event, $sql_reading, $out_value, $unit); + } else { + $out_tstamp =~ s/\ /_/g; #needed by generating plots + $retval .= "$out_tstamp $out_value\n"; + } + } + # DatenTrenner setzen + $retval .= "#$readings[$i]->[0]"; + $retval .= ":"; + $retval .= "$readings[$i]->[1]" if($readings[$i]->[1]); + $retval .= ":"; + $retval .= "$readings[$i]->[2]" if($readings[$i]->[2]); + $retval .= ":"; + $retval .= "$readings[$i]->[3]" if($readings[$i]->[3]); + $retval .= ":"; + $retval .= "$readings[$i]->[4]" if($readings[$i]->[4]); + $retval .= "\n"; } #for @readings #Ueberfuehren der gesammelten Werte in die globale Variable %data for(my $j=0; $j Attributes
-=end html +=end html =begin html_DE @@ -1032,6 +1034,7 @@ DbLog_Get($@) Attributes
+ =end html_DE =cut diff --git a/fhem/contrib/dblog/db_create_mysql.sql b/fhem/contrib/dblog/db_create_mysql.sql index 3d758310b..4d7ba4a00 100644 --- a/fhem/contrib/dblog/db_create_mysql.sql +++ b/fhem/contrib/dblog/db_create_mysql.sql @@ -3,5 +3,5 @@ CREATE USER 'fhemuser'@'%' IDENTIFIED BY 'fhempassword'; CREATE TABLE history (TIMESTAMP TIMESTAMP, DEVICE varchar(32), TYPE varchar(32), EVENT varchar(64), READING varchar(32), VALUE varchar(32), UNIT varchar(32)); CREATE TABLE current (TIMESTAMP TIMESTAMP, DEVICE varchar(32), TYPE varchar(32), EVENT varchar(64), READING varchar(32), VALUE varchar(32), UNIT varchar(32)); GRANT SELECT, INSERT, DELETE ON `fhem` .* TO 'fhemuser'@'%'; - +CREATE INDEX Search_Idx ON history (DEVICE, READING, TIMESTAMP); diff --git a/fhem/contrib/dblog/db_create_postgresql.sql b/fhem/contrib/dblog/db_create_postgresql.sql index 0163f766d..bb47a9d1e 100644 --- a/fhem/contrib/dblog/db_create_postgresql.sql +++ b/fhem/contrib/dblog/db_create_postgresql.sql @@ -3,7 +3,7 @@ -- SET statement_timeout = 0; -SET client_encoding = 'SQL_ASCII'; +SET client_encoding = 'UTF8'; SET standard_conforming_strings = off; SET check_function_bodies = false; SET client_min_messages = warning; @@ -69,7 +69,7 @@ ALTER TABLE fhem.history OWNER TO fhem; -- Name: reading; Type: INDEX; Schema: fhem; Owner: fhem; Tablespace: -- -CREATE INDEX reading ON history USING btree (((((device)::text || '|'::text) || (reading)::text)), "timestamp"); +CREATE INDEX search_Idx ON history USING btree (((((device)::text || '|'::text) || (reading)::text)), "timestamp"); --