diff --git a/app/src/Lib/Util/SchemaManager.php b/app/src/Lib/Util/SchemaManager.php index 416f4e95a..0236cf68c 100644 --- a/app/src/Lib/Util/SchemaManager.php +++ b/app/src/Lib/Util/SchemaManager.php @@ -183,12 +183,15 @@ protected function processSchema( string $tablePrefix="" ) { $schema = new Schema(); - + $mysqlIndexKeyLen = []; + // Walk through $schemaConfig and build our schema in DBAL format. foreach($schemaConfig->tables as $tName => $tCfg) { $table = $schema->createTable($tablePrefix.$tName); - + // Create the mapper for this table + $mysqlIndexKeyLen[$tablePrefix.$tName] = []; + foreach($tCfg->columns as $cName => $cCfg) { // We allow "inherited" definitions from the fieldLibrary, so merge together // the configurations (if appropriate) @@ -211,6 +214,21 @@ protected function processSchema( if($colCfg->type == "string") { $options['length'] = $colCfg->size; + + // By default, VARCHAR is limited to a maximum of 255 characters and its limit must be specified implicitly + // within a bracket right after its declaration, i.e VARCHAR(200) will limit it to 200 characters long only. + // Sometimes, even though you don’t use TEXT or BLOB related type in your table, the Error 1170 may + // also appear. It happens in a situation such as when you specify VARCHAR column as primary key, + // but wrongly set its length or characters size. VARCHAR can only accept up to 256 characters, + // so anything such as VARCHAR(512) will force MySQL to auto-convert the VARCHAR(512) to a SMALLTEXT + // datatype, which subsequently fails with error 1170 on key length if the column is used as primary key or + // unique or non-unique index + if($colCfg->size > 512 + && in_array($this->driver, array( + "Cake\Database\Driver\Mysql" + ))) { + $mysqlIndexKeyLen[$tablePrefix.$tName][$cName] = "(256)"; + } } if(isset($colCfg->notnull)) { @@ -280,8 +298,20 @@ protected function processSchema( // XXX MariadBD is not supported $tempColumns = []; foreach ($iCfg->columns as $idx => $clm_name) { + // Index with key length (only applied to MySQL) and for the use cases where + // more than one column is combined to form an index + $isExpression = true; + if(!empty($mysqlIndexKeyLen[$tablePrefix.$tName][$clm_name]) + && count($iCfg->columns) > 1 + && !str_contains($clm_name, "(")) { + $iCfg->columns[$idx] = $clm_name = $clm_name . $mysqlIndexKeyLen[$tablePrefix.$tName][$clm_name]; + $isExpression = false; + } + + // Index with expression if (! $table->hasColumn($clm_name)) { - if(in_array($this->driver, array( + if($isExpression + && in_array($this->driver, array( "Cake\Database\Driver\Mysql", "Cake\Database\Driver\Sqlite", ))) { @@ -298,9 +328,15 @@ protected function processSchema( } if(isset($iCfg->unique) && $iCfg->unique) { - $table->addUniqueConstraint($iCfg->columns, $iName, $flags, $options); + $table->addUniqueConstraint($iCfg->columns , + $iName, + $flags, + $options); } else { - $table->addIndex($iCfg->columns, $iName, $flags, $options); + $table->addIndex($iCfg->columns, + $iName, + $flags, + $options); } foreach ($tempColumns as $clm_name) {