Smart A. S. blog

Alexei Shuga, the web developer

Archive for the ‘cakePHP’ tag

CakePHP schema TIMESTAMP field create error solution

without comments

What a dissapointment! CakePHP schema generation feature does not handle DB TIMESTAMP fields default values correctly. While we wait for the official fix, we can use a quickfix for the issue.

The code responsible for column creation is in the cake/libs/model/datasources/dbo_source.php file. Scan for the “function buildColumn()”. The particular place where default DB fields values are handled is this:

if (($column['type'] == 'integer' || $column['type'] == 'float' ) && isset($column['default'])
&& $column['default'] === '') {
$column['default'] = null;
}

if (isset($column['key']) && $column['key'] == 'primary' && $type == 'integer') {
$out .= ' ' . $this->columns['primary_key']['name'];
} elseif (isset($column['key']) && $column['key'] == 'primary') {
$out .= ' NOT NULL';
} elseif (isset($column['default']) && isset($column['null']) && $column['null'] == false) {
$out .= ' DEFAULT ' . $this->value($column['default'], $type) . ' NOT NULL';
} elseif (isset($column['default'])) {
$out .= ' DEFAULT ' . $this->value($column['default'], $type);
} elseif (isset($column['null']) && $column['null'] == true) {
$out .= ' DEFAULT NULL';
} elseif (isset($column['null']) && $column['null'] == false) {
$out .= ' NOT NULL';
}
return $out;
Our fix will be as simple as it can be yet it will serve the purpose of correct column generation. Let's see what we can do:
if (($column['type'] == 'integer' || $column['type'] == 'float' ) && isset($column['default'])
&& $column['default'] === '') {
$column['default'] = null;
} elseif ($column['type'] =='timestamp' && $column['default'] != 'CURRENT_TIMESTAMP') {
                        $column['default'] = '2000-01-01 00:00:00';
                }

if (isset($column['key']) && $column['key'] == 'primary' && $type == 'integer') {
$out .= ' ' . $this->columns['primary_key']['name'];
} elseif (isset($column['key']) && $column['key'] == 'primary') {
$out .= ' NOT NULL';
} elseif (isset($column['default']) && isset($column['null']) && $column['null'] == false) {
            if ($column['type'] == 'timestamp' && $column['default']=='CURRENT_TIMESTAMP'){
               $out .= ' DEFAULT CURRENT_TIMESTAMP NOT NULL';
            } else {
               $out .= ' DEFAULT ' . $this->value($column['default'], $type) . ' NOT NULL';
            }
} elseif (isset($column['default'])) {
$out .= ' DEFAULT ' . $this->value($column['default'], $type);
} elseif (isset($column['null']) && $column['null'] == true) {
$out .= ' DEFAULT NULL';
} elseif (isset($column['null']) && $column['null'] == false) {
$out .= ' NOT NULL';
}
return $out;
}
 

Actually, we added a trick for all the next timestamp fields (except the one with CURRENT_TIMESTAMP default value) to have arbitrary not NULL default values.

Another trick is to have CURRENT_TIMESTAMP default value unquoted by CakePHP schema code (which actually prevents the schema script from running).

Tricks above are pretty dumb, but I’d not bother with the perfect solution as we’re going to have one from “the clean IP” really soon (I hope).

Written by Alexei Shulga

August 17th, 2009 at 2:50 am

You're encouraged to check out my developer resume.