I found a workaround! It is very clean and does not require application code changes. This works for the Doctrine and can be applied to another ORM.
Basically, save the timestamp as a string.
Comparison and sorting works if the date string is formatted correctly. MySQL temporary functions will truncate the microsecond part when transmitting a date string. This is normal if for date_diff etc. No microsecond precision is required.
SELECT DATEDIFF('2010-04-04 17:24:42.000000','2010-04-04 17:24:42.999999'); > 0 SELECT microsecond('2010-04-04 17:24:42.021343'); > 21343
I ended up writing a MicroTimestampable class that will implement this. I just comment my fields as actAs:MicroTimestampable and actAs:MicroTimestampable , precision micros in MySQL and Doctrine.
Doctrine_Template_MicroTimestampable
class Doctrine_Template_MicroTimestampable extends Doctrine_Template_Timestampable { protected $_options = array('created' => array('name' => 'created_at', 'alias' => null, 'type' => 'string(30)', 'format' => 'Ymd H:i:s', 'disabled' => false, 'expression' => false, 'options' => array('notnull' => true)), 'updated' => array('name' => 'updated_at', 'alias' => null, 'type' => 'string(30)', 'format' => 'Ymd H:i:s', 'disabled' => false, 'expression' => false, 'onInsert' => true, 'options' => array('notnull' => true))); public function setTableDefinition() { if ( ! $this->_options['created']['disabled']) { $name = $this->_options['created']['name']; if ($this->_options['created']['alias']) { $name .= ' as ' . $this->_options['created']['alias']; } $this->hasColumn($name, $this->_options['created']['type'], null, $this->_options['created']['options']); } if ( ! $this->_options['updated']['disabled']) { $name = $this->_options['updated']['name']; if ($this->_options['updated']['alias']) { $name .= ' as ' . $this->_options['updated']['alias']; } $this->hasColumn($name, $this->_options['updated']['type'], null, $this->_options['updated']['options']); } $this->addListener(new Doctrine_Template_Listener_MicroTimestampable($this->_options)); } }
Doctrine_Template_Listener_MicroTimestampable
class Doctrine_Template_Listener_MicroTimestampable extends Doctrine_Template_Listener_Timestampable { protected $_options = array(); public function __construct(array $options) { $this->_options = $options; } public function getTimestamp($type, $conn = null) { $options = $this->_options[$type]; if ($options['expression'] !== false && is_string($options['expression'])) { return new Doctrine_Expression($options['expression'], $conn); } else { if ($options['type'] == 'date') { return date($options['format'], time().".".microtime()); } else if ($options['type'] == 'timestamp') { return date($options['format'], time().".".microtime()); } else { return time().".".microtime(); } } } }