private function updateDerivedValues($key = null, $value = null) {
		
		/* 
		 * TODO
		 * I darkly suspect that there is a possibility that you could create a loop
		 * of derived references that would be irresolvable and not currently detected
		 * e.g. A => '@B', B=>'@C', C=>'@A'. Perhaps the best approach would be to
		 * limit the depth of the derivation search?
		 */
		
		$derived = array();

		/* determine breadth of derived fields affected */
		$derivedPattern = '%@_%';
		if (!empty($key)) {
			$_key = $this->sql->real_escape_string($key);
			$derivedPattern = "%@$_key%";
			
			if (!empty($value) && is_string($value)) {
				$derived[$key] = $value;
			}
		}
		
		/* build a list of affected key => value pairs */
		if ($result = $this->sql->query("
			SELECT *
				FROM `{$this->table}`
				WHERE
					`value` LIKE '$derivedPattern'
					
		")) {
			while($row = $result->fetch_assoc()) {
				$value = unserialize($row['value']);
				if (is_string($value)) {
					$derived[$row['key']] = $value;
				}
			}
		}
		
		/* generate derived fields based on prior fields */
		while (count($derived) > 0) {
			$next = array();
			foreach ($derived as $key => $value) {

				/* look for @keys in the value */				
				preg_match_all('/@(\w+)/', $value, $sources, PREG_SET_ORDER);
				
				$dirty = false;
				foreach($sources as $source) {
					if ($this->offsetExists($source[1]) && is_string($this->offsetGet($source[1]))) {
						$value = preg_replace("/{$source[0]}/", $this->offsetGet($source[1]), $value);
						$dirty = true;
					}
				}
				/* ...and queue up again to check */
				if ($dirty) {
					$next[$key] = $value;
				} else {
					$this->_offsetSet($key, $value, false);
				}
			}
			
			/* use new queue */
			$derived = $next;
		}
	}