/**
  * @param NodeRef $nodeRef
  * @param $metaID
  * @param int $value
  *
  * @throws NodeException
  * @throws SQLException
  * @throws Exception
  */
 public function decrementMeta(NodeRef $nodeRef, $metaID, $value = 1)
 {
     $metaID = ltrim($metaID, '#');
     $this->NodeEvents->fireNodeEvents(__FUNCTION__, '', $nodeRef, $metaID);
     $db = $this->getConnectionForWrite($nodeRef);
     $id = $this->getRecordIDFromNodeRef($nodeRef);
     // determine the meta storage
     $metaDef = $nodeRef->getElement()->getSchema()->getMetaDef($metaID);
     $datatype = $metaDef->getDatatype();
     $table = $db->quoteIdentifier($this->NodeDBMeta->getMetaTable($nodeRef, $datatype));
     $tableid = $this->NodeDBMeta->getPrimaryKey($nodeRef);
     $datatypeCol = $this->NodeDBMeta->getMetaDatatypeColumn($datatype);
     $value = intval($value);
     $newValue = false;
     $oldValue = false;
     $originalMeta = null;
     $maxValue = $this->getMaxIntForDatatype($datatype);
     $minValue = $this->getMinIntForDatatype($datatype);
     try {
         $affectedRows = $db->write("UPDATE {$table} SET {$datatypeCol}Value = LAST_INSERT_ID({$datatypeCol}Value-{$value}) WHERE {$tableid} = {$db->quote($id)} AND Name = {$db->quote($metaID)}", DatabaseInterface::AFFECTED_ROWS);
         if ($affectedRows == 1) {
             $newValue = intval($db->readField("SELECT LAST_INSERT_ID()"));
             $oldValue = $newValue + $value;
         }
     } catch (SQLException $e) {
         if ($e->getCode() != 22003 || strpos($e->getMessage(), 'Numeric value out of range') === false) {
             throw $e;
         }
         // must ask the DB for its current value
         $oldValue = intval($db->readField("SELECT {$datatypeCol}Value FROM {$table} WHERE {$tableid} = {$db->quote($id)} AND Name = {$db->quote($metaID)}"));
         $newValue = $oldValue - $value;
         // ensure the new values don't overflow (note that $value can be positive or negative and isn't necessarily 1)
         if ($newValue > $maxValue) {
             $newValue = $maxValue;
         } elseif ($newValue < $minValue) {
             $newValue = $minValue;
         }
         if ($newValue === $oldValue) {
             $affectedRows = 1;
         } else {
             $affectedRows = $db->write("UPDATE {$table} SET {$datatypeCol}Value = {$newValue} WHERE {$tableid} = {$db->quote($id)} AND Name = {$db->quote($metaID)}", DatabaseInterface::AFFECTED_ROWS);
         }
     } catch (Exception $e) {
         throw $e;
     }
     // new value didn't get set because the meta record hasn't been created yet.
     if ($newValue === false) {
         $newValue = $value * -1;
         // ensure the new values don't overflow (note that $value can be positive or negative and isn't necessarily 1)
         if ($newValue > $maxValue) {
             $newValue = $maxValue;
         } elseif ($newValue < $minValue) {
             $newValue = $minValue;
         }
     }
     if ($affectedRows == 0) {
         $affectedRows = $db->write("INSERT INTO {$table} ({$tableid}, Name, {$datatypeCol}Value) Values ({$db->quote($id)}, {$db->quote($metaID)}, {$newValue}) ON DUPLICATE KEY UPDATE {$datatypeCol}Value = LAST_INSERT_ID({$datatypeCol}Value-{$value})", DatabaseInterface::AFFECTED_ROWS);
         // new record inserted
         if ($affectedRows == 1) {
             $metaEvent = 'add';
             $newMeta = new Meta($metaID, $newValue);
             $newMeta->setMetaStorageDatatype($metaDef->Datatype);
             $originalMeta = null;
             // duplicate key update encountered
         } else {
             if ($affectedRows == 2) {
                 $metaEvent = 'update';
                 $newValue = intval($db->readField("SELECT LAST_INSERT_ID()"));
                 $oldValue = $newValue + $value;
                 $newMeta = new Meta($metaID, $newValue);
                 $newMeta->setMetaStorageDatatype($metaDef->Datatype);
                 $originalMeta = new Meta($metaID, $oldValue);
                 $originalMeta->setMetaStorageDatatype($metaDef->Datatype);
             } else {
                 throw new NodeException('Unable to decrement meta ID [' . $metaID . '] on record [' . $nodeRef . ']');
             }
         }
     } else {
         $metaEvent = 'update';
         $newMeta = new Meta($metaID, $newValue);
         $newMeta->setMetaStorageDatatype($metaDef->Datatype);
         $originalMeta = new Meta($metaID, $oldValue);
         $originalMeta->setMetaStorageDatatype($metaDef->Datatype);
     }
     $this->NodeEvents->fireMetaEvents('meta', $metaEvent, $nodeRef, $newMeta, $originalMeta);
 }