Commit c95a539e authored by Ralf Becker's avatar Ralf Becker Committed by Ralf Becker

ZP-1002 SQL state backend fails with PostgreSQL.

Released under the Affero GNU General Public License (AGPL) version 3.
parent a93e5be5
...@@ -145,8 +145,8 @@ class SqlStateMachine implements IStateMachine { ...@@ -145,8 +145,8 @@ class SqlStateMachine implements IStateMachine {
$hash = null; $hash = null;
$record = null; $record = null;
try { try {
$sth = $this->getStateHashStatement($key);
$params = $this->getParams($devid, $type, $key, $counter); $params = $this->getParams($devid, $type, $key, $counter);
$sth = $this->getStateHashStatement($params);
$sth->execute($params); $sth->execute($params);
$record = $sth->fetch(PDO::FETCH_ASSOC); $record = $sth->fetch(PDO::FETCH_ASSOC);
...@@ -189,8 +189,8 @@ class SqlStateMachine implements IStateMachine { ...@@ -189,8 +189,8 @@ class SqlStateMachine implements IStateMachine {
if ($counter && $cleanstates) if ($counter && $cleanstates)
$this->CleanStates($devid, $type, $key, $counter); $this->CleanStates($devid, $type, $key, $counter);
$sql = "SELECT state_data FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid". $this->getSQLOp($key) .":key AND counter = :counter";
$params = $this->getParams($devid, $type, $key, $counter); $params = $this->getParams($devid, $type, $key, $counter);
$sql = "SELECT state_data FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid". $this->getSQLOp($params, ':key') ." AND counter = :counter";
$data = null; $data = null;
$sth = null; $sth = null;
...@@ -242,8 +242,8 @@ class SqlStateMachine implements IStateMachine { ...@@ -242,8 +242,8 @@ class SqlStateMachine implements IStateMachine {
$key = $this->returnNullified($key); $key = $this->returnNullified($key);
ZLog::Write(LOGLEVEL_DEBUG, sprintf("SqlStateMachine->SetState(): devid:'%s' type:'%s' key:'%s' counter:'%s'", $devid, $type, Utils::PrintAsString($key), Utils::PrintAsString($counter))); ZLog::Write(LOGLEVEL_DEBUG, sprintf("SqlStateMachine->SetState(): devid:'%s' type:'%s' key:'%s' counter:'%s'", $devid, $type, Utils::PrintAsString($key), Utils::PrintAsString($counter)));
$sql = "SELECT device_id FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid". $this->getSQLOp($key) .":key AND counter = :counter";
$params = $this->getParams($devid, $type, $key, $counter); $params = $this->getParams($devid, $type, $key, $counter);
$sql = "SELECT device_id FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid". $this->getSQLOp($params, ':key') ." AND counter = :counter";
$sth = null; $sth = null;
$record = null; $record = null;
...@@ -263,14 +263,14 @@ class SqlStateMachine implements IStateMachine { ...@@ -263,14 +263,14 @@ class SqlStateMachine implements IStateMachine {
} }
else { else {
// Existing record, we update it // Existing record, we update it
$sql = "UPDATE {$this->states_table} SET state_data = :data, updated_at = :updated_at WHERE device_id = :devid AND state_type = :type AND uuid ". $this->getSQLOp($key) .":key AND counter = :counter"; $sql = "UPDATE {$this->states_table} SET state_data = :data, updated_at = :updated_at WHERE device_id = :devid AND state_type = :type AND uuid ". $this->getSQLOp($params, ':key') ." AND counter = :counter";
$sth = $this->getDbh()->prepare($sql); $sth = $this->getDbh()->prepare($sql);
} }
$sth->bindParam(":devid", $devid, PDO::PARAM_STR); $sth->bindParam(":devid", $devid, PDO::PARAM_STR);
$sth->bindParam(":type", $type, PDO::PARAM_STR); $sth->bindParam(":type", $type, PDO::PARAM_STR);
$sth->bindParam(":key", $key, PDO::PARAM_STR); if (!$record || isset($key)) $sth->bindParam(":key", $key, PDO::PARAM_STR);
$sth->bindValue(":counter", ($counter === false ? 0 : $counter), PDO::PARAM_INT); $sth->bindValue(":counter", ($counter === false ? 0 : $counter), PDO::PARAM_INT);
$sth->bindValue(":data", serialize($state), PDO::PARAM_LOB); $sth->bindValue(":data", serialize($state), PDO::PARAM_LOB);
$sth->bindValue(":updated_at", $this->getNow(), PDO::PARAM_STR); $sth->bindValue(":updated_at", $this->getNow(), PDO::PARAM_STR);
...@@ -312,17 +312,17 @@ class SqlStateMachine implements IStateMachine { ...@@ -312,17 +312,17 @@ class SqlStateMachine implements IStateMachine {
$key = $this->returnNullified($key); $key = $this->returnNullified($key);
ZLog::Write(LOGLEVEL_DEBUG, sprintf("SqlStateMachine->CleanStates(): devid:'%s' type:'%s' key:'%s' counter:'%s' thisCounterOnly:'%s'", $devid, $type, Utils::PrintAsString($key), Utils::PrintAsString($counter), Utils::PrintAsString($thisCounterOnly))); ZLog::Write(LOGLEVEL_DEBUG, sprintf("SqlStateMachine->CleanStates(): devid:'%s' type:'%s' key:'%s' counter:'%s' thisCounterOnly:'%s'", $devid, $type, Utils::PrintAsString($key), Utils::PrintAsString($counter), Utils::PrintAsString($thisCounterOnly)));
$params = $this->getParams($devid, $type, $key, $counter);
if ($counter === false) { if ($counter === false) {
// Remove all the states. Counter are 0 or >0, then deleting >= 0 deletes all // Remove all the states. Counter are 0 or >0, then deleting >= 0 deletes all
$sql = "DELETE FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid". $this->getSQLOp($key) .":key AND counter >= :counter"; $sql = "DELETE FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid". $this->getSQLOp($params, ':key') ." AND counter >= :counter";
} }
else if ($counter !== false && $thisCounterOnly === true) { else if ($counter !== false && $thisCounterOnly === true) {
$sql = "DELETE FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid". $this->getSQLOp($key).":key AND counter = :counter"; $sql = "DELETE FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid". $this->getSQLOp($params, ':key') ." AND counter = :counter";
} }
else { else {
$sql = "DELETE FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid". $this->getSQLOp($key) .":key AND counter < :counter"; $sql = "DELETE FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid". $this->getSQLOp($params, ':key') ." AND counter < :counter";
} }
$params = $this->getParams($devid, $type, $key, $counter);
$sth = null; $sth = null;
try { try {
...@@ -651,18 +651,20 @@ class SqlStateMachine implements IStateMachine { ...@@ -651,18 +651,20 @@ class SqlStateMachine implements IStateMachine {
/** /**
* Returns the SQL operator for the parameter. * Returns the SQL operator for the parameter.
* If the parameter is null then " IS " is returned, else " = ". * If the parameter is null then " IS NULL" is returned, else " = $key".
* *
* @param mixed $param * @param array& $params $params[$key] will be unset, if is_null($params[$key])
* @param string $key eg. ":key"
* *
* @access protected * @access protected
* @return string * @return string
*/ */
protected function getSQLOp($param) { protected function getSQLOp(&$params, $key) {
if ($param == null) { if (is_null($params[$key])) {
return " IS "; unset($params[$key]);
return " IS NULL";
} }
return " = "; return " = $key";
} }
/** /**
...@@ -701,16 +703,20 @@ class SqlStateMachine implements IStateMachine { ...@@ -701,16 +703,20 @@ class SqlStateMachine implements IStateMachine {
/** /**
* Prepares PDOStatement which will be used to get the state hash. * Prepares PDOStatement which will be used to get the state hash.
* *
* @param string $key state uuid * @param array& $params $params[$key] will be unset, if is_null($params[$key])
* @param string $key =':key'
* @access protected * @access protected
* @return PDOStatement * @return PDOStatement
*/ */
protected function getStateHashStatement($key) { protected function getStateHashStatement(&$params, $key=':key') {
if (!isset($this->stateHashStatement) || $this->stateHashStatement == null) { if (!isset($this->stateHashStatement) || $this->stateHashStatement == null) {
$sql = "SELECT updated_at FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid ". (($key == null) ? " IS " : " = ") . ":key AND counter = :counter"; $sql = "SELECT updated_at FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid ". $this->getSQLOp($params, $key) ." AND counter = :counter";
$this->stateHashStatement = $this->getDbh()->prepare($sql); $this->stateHashStatement = $this->getDbh()->prepare($sql);
} }
else {
$this->getSQLOp($params, $key); // need to unset $params[':key'] for NULL
}
return $this->stateHashStatement; return $this->stateHashStatement;
} }
/** /**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment