diff --git a/fhem/CHANGED b/fhem/CHANGED index 8783b2dff..15e078291 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: support of primary key (set in table history/current) - update: 88_HMCCU: Optimized reading update performance - feature: 00_SONOS: New lists for groupinformations - bugfix: 88_HMCCU: Fixed toggle function for HMCCUCHN devices diff --git a/fhem/FHEM/93_DbRep.pm b/fhem/FHEM/93_DbRep.pm index 845f1adf8..5c10913a6 100644 --- a/fhem/FHEM/93_DbRep.pm +++ b/fhem/FHEM/93_DbRep.pm @@ -40,6 +40,7 @@ ########################################################################################################### # Versions History: # +# 4.12.0 31.03.2017 support of primary key (set in table history/current) for insert functions # 4.11.4 29.03.2017 bugfix timestamp in minValue, maxValue if VALUE contains more than one # numeric value (like in sysmon) # 4.11.3 26.03.2017 usage of daylight saving time changed to avoid wrong selection when wintertime @@ -180,7 +181,7 @@ use Blocking; use Time::Local; # no if $] >= 5.017011, warnings => 'experimental'; -my $DbRepVersion = "4.11.4"; +my $DbRepVersion = "4.12.0"; my %dbrep_col = ("DEVICE" => 64, "TYPE" => 64, @@ -2570,7 +2571,7 @@ sub insert_Push($) { my $dbuser = $dbloghash->{dbuser}; my $dblogname = $dbloghash->{NAME}; my $dbpassword = $attr{"sec$dblogname"}{secret}; - my $err; + my ($err,$sth); # Background-Startzeit my $bst = [gettimeofday]; @@ -2599,21 +2600,37 @@ sub insert_Push($) { my $i_unit = $hash->{HELPER}{I_UNIT} ? $hash->{HELPER}{I_UNIT} : " "; # SQL zusammenstellen für DB-Operation - Log3 ($name, 5, "DbRep $name -> data to insert Timestamp: $i_timestamp, Device: $i_device, Type: $i_type, Event: $i_event, Reading: $i_reading, Value: $i_value, Unit: $i_unit"); # SQL-Startzeit my $st = [gettimeofday]; - $dbh->begin_work(); - my $sth = $dbh->prepare_cached("INSERT INTO history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"); + # insert history mit/ohne primary key + if ($usepkh && $dbloghash->{DBMODEL} eq 'MYSQL') { + eval { $sth = $dbh->prepare("INSERT IGNORE INTO history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"); }; + } elsif ($usepkh && $dbloghash->{DBMODEL} eq 'SQLITE') { + eval { $sth = $dbh->prepare("INSERT OR IGNORE INTO history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"); }; + } elsif ($usepkh && $dbloghash->{DBMODEL} eq 'POSTGRESQL') { + eval { $sth = $dbh->prepare("INSERT INTO history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?) ON CONFLICT DO NOTHING"); }; + } else { + eval { $sth = $dbh->prepare("INSERT INTO history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"); }; + } + if ($@) { + $err = encode_base64($@,""); + Log3 ($name, 2, "DbRep $name - $@"); + Log3 ($name, 4, "DbRep $name -> BlockingCall insert_Push finished"); + $dbh->disconnect(); + return "$name|''|''|$err"; + } + $dbh->begin_work(); + eval {$sth->execute($i_timestamp, $i_device, $i_type, $i_event, $i_reading, $i_value, $i_unit);}; my $irow; if ($@) { $err = encode_base64($@,""); - Log3 ($name, 2, "DbRep $name - Failed to insert new dataset into database: $@"); + Log3 ($name, 2, "DbRep $name - Insert new dataset into database failed".($usepkh?" (possible PK violation) ":": ")."$@"); $dbh->rollback(); $dbh->disconnect(); Log3 ($name, 4, "DbRep $name -> BlockingCall insert_Push finished"); @@ -3142,6 +3159,7 @@ sub impfile_Push($) { my $dbmodel = $hash->{dbloghash}{DBMODEL}; my $dbpassword = $attr{"sec$dblogname"}{secret}; my $err=0; + my $sth; # Background-Startzeit my $bst = [gettimeofday]; @@ -3158,6 +3176,9 @@ sub impfile_Push($) { return "$name|''|''|$err"; } + # check ob PK verwendet wird, @usepkx?Anzahl der Felder im PK:0 wenn kein PK, $pkx?Namen der Felder:none wenn kein PK + my ($usepkh,$usepkc,$pkh,$pkc) = DbRep_checkUsePK($hash,$dbh); + my $infile = AttrVal($name, "expimpfile", undef); if (open(FH, "$infile")) { binmode (FH); @@ -3178,8 +3199,26 @@ sub impfile_Push($) { # Beispiel Inline: # "2016-09-25 08:53:56","STP_5000","SMAUTILS","etotal: 11859.573","etotal","11859.573","" + # insert history mit/ohne primary key + if ($usepkh && $dbloghash->{DBMODEL} eq 'MYSQL') { + eval { $sth = $dbh->prepare_cached("INSERT IGNORE INTO history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"); }; + } elsif ($usepkh && $dbloghash->{DBMODEL} eq 'SQLITE') { + eval { $sth = $dbh->prepare_cached("INSERT OR IGNORE INTO history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"); }; + } elsif ($usepkh && $dbloghash->{DBMODEL} eq 'POSTGRESQL') { + eval { $sth = $dbh->prepare_cached("INSERT INTO history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?) ON CONFLICT DO NOTHING"); }; + } else { + eval { $sth = $dbh->prepare_cached("INSERT INTO history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"); }; + } + if ($@) { + $err = encode_base64($@,""); + Log3 ($name, 2, "DbRep $name - $@"); + Log3 ($name, 4, "DbRep $name -> BlockingCall impfile_Push finished"); + $dbh->disconnect(); + return "$name|''|''|$err"; + } + $dbh->begin_work(); - my $sth = $dbh->prepare_cached("INSERT INTO history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"); + my $irowdone = 0; my $irowcount = 0; my $warn = 0; @@ -3995,7 +4034,7 @@ return; # If "Value=0" has to be inserted, use "Value = 0.0" to do it.

example: 2016-08-01,23:00:09,TestValue,TestUnit
- # field length is maximum 32 (MYSQL) / 64 (POSTGRESQL) characters long, Spaces are NOT allowed in fieldvalues !
+ # Spaces are NOT allowed in fieldvalues !

Note:
@@ -4495,7 +4534,7 @@ return; # Soll "Value=0" eingefügt werden, ist "Value = 0.0" zu verwenden.

Beispiel: 2016-08-01,23:00:09,TestValue,TestUnit
- # die Feldlänge ist maximal 64 Zeichen lang , es sind KEINE Leerzeichen im Feldwert erlaubt !
+ # Es sind KEINE Leerzeichen im Feldwert erlaubt !

Hinweis: