/** * Calculate hash for this row * * The hashing strategy is suggested to be thus. Ordinary columns are concatenated * in their table order, and the hashing function applied to the result. However * for selected columns (usually lazy-loaded ones) their value is replaced with * a cached copy of the function applied to that column only. This ensures that * a hash can be re-calculated without having to load lazy-loaded columns, which * may be slow and memory-hungry. * * So it might look like this: hash(a + b + c + hash(blob_d) + ...) */ public function calcHash(MeshingBaseObject $object, $hashFunction) { /* @var $vsnTableMap TableMap */ /* @var $hashTableMap TableMap */ $thisMap = $object->getRowMap(); $vsnTableMap = $object->getVersionableMap(); /* @var $columnMap ColumnMap */ $values = array(); foreach ($this->getHashableColumns($object, $thisMap) as $columnMap) { $columnName = $columnMap->getName(); // See if a cached hash exists for this column in the version table $hashColumnName = $columnName . self::CACHE_COLUMN_SUFFIX; $isCached = $vsnTableMap->containsColumn($hashColumnName); if ($isCached) { // Get hash; bomb out if it doesn't exist (even nulls are hashed) $hash = $object->getByName($hashColumnName, BasePeer::TYPE_RAW_COLNAME); if (!$hash) { throw new Exception("No hash found for column '{$columnName}'"); } $value = $hashFunction($hash); } else { // Trivial case - just concatenate the column value $value = $this->getRowValue($object, $columnMap); } $values[] = $value . $this->getValueTerminator($value); } // Last chance for child classes to modify before it gets hashed $values = $this->preHash($object, $values); return $hashFunction(implode('', $values)); }