I have managed to get working a solution for the ENUM datatype for MySQL. I don't yet know how to create patches etc. so I put describe here my work and I hope that if you are looking for a way to make this work you can use my work to help you, or even better, if you are able to make this fix get into core, all the better.
In your database schema add an extra item called 'enum_items' as shown in the example below:
...
$schema['vchess_games'] = array(
'description' => 'This table contains a summary of each game',
'fields' => array(
'turn' => array(
'description' => 'Whose turn it is to play, either "w" (white) or "b" (black)',
'type' => 'enum',
'enum_items' => array('w', 'b'),
'not null' => TRUE,
'default' => 'w',
),
'status' => array(
'description' => 'Status of the game',
'type' => 'enum',
'enum_items' => array('in progress','1/2-1/2','1-0','0-1'),
'not null' => TRUE,
),
...
In the MySQL version of schema.inc in /includes/database/mysql/schema.inc file add code for using these ENUM items:
protected function createFieldSql($name, $spec) {
$sql = "`" . $name . "` " . $spec['mysql_type'];
if (in_array($spec['mysql_type'], array('VARCHAR', 'CHAR', 'TINYTEXT', 'MEDIUMTEXT', 'LONGTEXT', 'TEXT')) && isset($spec['length'])) {
$sql .= '(' . $spec['length'] . ')';
}
// New ENUM code begins here:
elseif ($spec['mysql_type'] == 'ENUM') {
// Build a string of the enum items like "('a','b','c')"
$sql .= '(';
foreach ($spec['enum_items'] as $enum_item) {
$sql .= "'" . $enum_item . "',";
}
$sql = trim($sql, ","); // Remove the final trailing comma
$sql .= ')';
}
// End of new ENUM code
elseif (isset($spec['precision']) && isset($spec['scale'])) {
$sql .= '(' . $spec['precision'] . ', ' . $spec['scale'] . ')';
}
...
In the same file, add 'enum:normal' => 'ENUM', to the getFieldTypeMap() function:
public function getFieldTypeMap() {
// Put :normal last so it gets preserved by array_flip. This makes
// it much easier for modules (such as schema.module) to map
// database types back into schema types.
// $map does not use drupal_static as its value never changes.
static $map = array(
'varchar:normal' => 'VARCHAR',
'char:normal' => 'CHAR',
'text:tiny' => 'TINYTEXT',
'text:small' => 'TINYTEXT',
'text:medium' => 'MEDIUMTEXT',
'text:big' => 'LONGTEXT',
'text:normal' => 'TEXT',
'serial:tiny' => 'TINYINT',
'serial:small' => 'SMALLINT',
'serial:medium' => 'MEDIUMINT',
'serial:big' => 'BIGINT',
'serial:normal' => 'INT',
'int:tiny' => 'TINYINT',
'int:small' => 'SMALLINT',
'int:medium' => 'MEDIUMINT',
'int:big' => 'BIGINT',
'int:normal' => 'INT',
'float:tiny' => 'FLOAT',
'float:small' => 'FLOAT',
'float:medium' => 'FLOAT',
'float:big' => 'DOUBLE',
'float:normal' => 'FLOAT',
'numeric:normal' => 'DECIMAL',
'enum:normal' => 'ENUM', // This is the line to add for ENUM
'blob:big' => 'LONGBLOB',
'blob:normal' => 'BLOB',
);
return $map;
}
I'm absolutely delighted it's working for me; it's the first time I've ever tried to patch anything in core! I hope that this work can also help others to get it working.
Comment | File | Size | Author |
---|---|---|---|
#29 | 1464354-enum-solution.patch | 1.46 KB | RhiP |
#12 | core-8.x-ENUM_and_TIMESTAMP-1464354.12.patch | 1.12 KB | drupalshrek |
#9 | drupal-ENUM_and_TIMESTAMP-1464354.patch | 1.26 KB | drupalshrek |
#7 | core-7.14-ENUM_and_TIMESTAMP-1464354.patch | 1.07 KB | drupalshrek |
#4 | drupal-ENUM_and_TIMESTAMP-1464354.patch | 1.26 KB | drupalshrek |
Issue fork drupal-1464354
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #1
marcingy CreditAttribution: marcingy commentedNot a bug and also needs to be against d8.
Comment #2
drupalshrek CreditAttribution: drupalshrek commentedGreat, thanks.
Comment #3
drupalshrek CreditAttribution: drupalshrek commentedFor reference, a similar fix for TIMESTAMP is available here:
http://drupal.org/node/1466122
Comment #4
drupalshrek CreditAttribution: drupalshrek commentedHere is a patch for fixing this in Drupal 8.x-dev.
This is my first ever patch, so be gentle with it and me.
It fixes both this issue and the issue http://drupal.org/node/1466122. I hope that's OK.
Comment #5
drupalshrek CreditAttribution: drupalshrek commentedComment #6
drupalshrek CreditAttribution: drupalshrek commentedOne thing I do want to add is that I decided to use the term 'enum' rather than 'enum_items' in my introductory post on this page.
Comment #7
drupalshrek CreditAttribution: drupalshrek commentedAttached is a patch for this for 7.14
Comment #9
drupalshrek CreditAttribution: drupalshrek commentedOK, I think I understand how this system works now: one issue, one patch! So I have raised a separate issue for the 7.x patch: http://drupal.org/node/1560974
And here I am putting back the 8.x-dev patch (first posted above on March 30, 2012 at 3:33pm).
Comment #10
drupalshrek CreditAttribution: drupalshrek commentedComment #12
drupalshrek CreditAttribution: drupalshrek commentedOK, redone patch for latest 8.x
Comment #13
drupalshrek CreditAttribution: drupalshrek commentedComment #14
xbroom CreditAttribution: xbroom commented#9: drupal-ENUM_and_TIMESTAMP-1464354.patch queued for re-testing.
Comment #15
drupalshrek CreditAttribution: drupalshrek commented#12: core-8.x-ENUM_and_TIMESTAMP-1464354.12.patch queued for re-testing.
Comment #16
dalin12: core-8.x-ENUM_and_TIMESTAMP-1464354.12.patch queued for re-testing.
Comment #17
dalinI do think this is needed because there is no other way that I can see to hack around this limitation. You can *almost* do this:
But DBTNG will convert those enums to uppercase.
I think this patch is a good approach, but it needs some changes:
+ // Build a string of the enum items like "('a','b','c')"
Code comments that describe what a line of code is doing are only useful if it's a really complicated line. Otherwise it's just redundant.
This can be replaced with a simple
$sql .= '(' . implode(', ', $spec['enum']) . ')';
. Also according to Drupal coding standards comments must be on their own line.This is unrelated to this issue. It should be in a separate patch on the other issue.
+ $sql .= ')';
Comment #18
dalinComment #25
Sophie.SKI've been using the patch from #12 on a number of different sites over the last few years and find it hella useful. It allows for much better storage of dates.
It still applies on the latest 8.7, but it probably needs updating for 8.9 and beyond. Just wanted to bump this issue up and add extra info in case anyone else is wondering whether this works :)
Comment #26
daffie CreditAttribution: daffie commentedFor adding new datatypes to Drupal core they must work for all three by core supported databases. There is no enum datatype for SQLite.
I do not see how we can fix this for Drupal core. This should be fixed in a contrib module.
Comment #29
RhiP CreditAttribution: RhiP at Investis Digital commentedRerolled Patch #12 for those of us yet to remove our ENUMs https://git.drupalcode.org/issue/drupal-1464354/-/merge_requests/1.patch