Skip to content

Commit 7e9e8ec

Browse files
author
Dale Sikkema
committed
MAGETWO-37848: Generate data fails when table prefix exceeds length of 5
- use existing mysql identifier compression to shorten long trigger names
1 parent ea7b254 commit 7e9e8ec

File tree

6 files changed

+167
-74
lines changed

6 files changed

+167
-74
lines changed

lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php

Lines changed: 8 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -3117,23 +3117,6 @@ public function getDateExtractSql($date, $unit)
31173117
return new \Zend_Db_Expr($expr);
31183118
}
31193119

3120-
/**
3121-
* Minus superfluous characters from hash.
3122-
*
3123-
* @param string $hash
3124-
* @param string $prefix
3125-
* @param int $maxCharacters
3126-
* @return string
3127-
*/
3128-
protected function _minusSuperfluous($hash, $prefix, $maxCharacters)
3129-
{
3130-
$diff = strlen($hash) + strlen($prefix) - $maxCharacters;
3131-
$superfluous = $diff / 2;
3132-
$odd = $diff % 2;
3133-
$hash = substr($hash, $superfluous, - ($superfluous + $odd));
3134-
return $hash;
3135-
}
3136-
31373120
/**
31383121
* Retrieve valid table name
31393122
* Check table name length and allowed symbols
@@ -3143,22 +3126,12 @@ protected function _minusSuperfluous($hash, $prefix, $maxCharacters)
31433126
*/
31443127
public function getTableName($tableName)
31453128
{
3146-
$prefix = 't_';
3147-
if (strlen($tableName) > self::LENGTH_TABLE_NAME) {
3148-
$shortName = ExpressionConverter::shortName($tableName);
3149-
if (strlen($shortName) > self::LENGTH_TABLE_NAME) {
3150-
$hash = md5($tableName);
3151-
if (strlen($prefix . $hash) > self::LENGTH_TABLE_NAME) {
3152-
$tableName = $this->_minusSuperfluous($hash, $prefix, self::LENGTH_TABLE_NAME);
3153-
} else {
3154-
$tableName = $prefix . $hash;
3155-
}
3156-
} else {
3157-
$tableName = $shortName;
3158-
}
3159-
}
3129+
return ExpressionConverter::shortenEntityName($tableName, 't_');
3130+
}
31603131

3161-
return $tableName;
3132+
public function getTriggerName($triggerName)
3133+
{
3134+
return ExpressionConverter::shortenEntityName($triggerName, 'trg_');
31623135
}
31633136

31643137
/**
@@ -3179,35 +3152,15 @@ public function getIndexName($tableName, $fields, $indexType = '')
31793152
switch (strtolower($indexType)) {
31803153
case AdapterInterface::INDEX_TYPE_UNIQUE:
31813154
$prefix = 'unq_';
3182-
$shortPrefix = 'u_';
31833155
break;
31843156
case AdapterInterface::INDEX_TYPE_FULLTEXT:
31853157
$prefix = 'fti_';
3186-
$shortPrefix = 'f_';
31873158
break;
31883159
case AdapterInterface::INDEX_TYPE_INDEX:
31893160
default:
31903161
$prefix = 'idx_';
3191-
$shortPrefix = 'i_';
31923162
}
3193-
3194-
$hash = $tableName . '_' . $fields;
3195-
3196-
if (strlen($hash) + strlen($prefix) > self::LENGTH_INDEX_NAME) {
3197-
$short = ExpressionConverter::shortName($prefix . $hash);
3198-
if (strlen($short) > self::LENGTH_INDEX_NAME) {
3199-
$hash = md5($hash);
3200-
if (strlen($hash) + strlen($shortPrefix) > self::LENGTH_INDEX_NAME) {
3201-
$hash = $this->_minusSuperfluous($hash, $shortPrefix, self::LENGTH_INDEX_NAME);
3202-
}
3203-
} else {
3204-
$hash = $short;
3205-
}
3206-
} else {
3207-
$hash = $prefix . $hash;
3208-
}
3209-
3210-
return strtoupper($hash);
3163+
return strtoupper(ExpressionConverter::shortenEntityName($tableName . '_' . $fields, $prefix));
32113164
}
32123165

32133166
/**
@@ -3222,25 +3175,8 @@ public function getIndexName($tableName, $fields, $indexType = '')
32223175
*/
32233176
public function getForeignKeyName($priTableName, $priColumnName, $refTableName, $refColumnName)
32243177
{
3225-
$prefix = 'fk_';
3226-
$hash = sprintf('%s_%s_%s_%s', $priTableName, $priColumnName, $refTableName, $refColumnName);
3227-
if (strlen($prefix . $hash) > self::LENGTH_FOREIGN_NAME) {
3228-
$short = ExpressionConverter::shortName($prefix . $hash);
3229-
if (strlen($short) > self::LENGTH_FOREIGN_NAME) {
3230-
$hash = md5($hash);
3231-
if (strlen($prefix . $hash) > self::LENGTH_FOREIGN_NAME) {
3232-
$hash = $this->_minusSuperfluous($hash, $prefix, self::LENGTH_FOREIGN_NAME);
3233-
} else {
3234-
$hash = $prefix . $hash;
3235-
}
3236-
} else {
3237-
$hash = $short;
3238-
}
3239-
} else {
3240-
$hash = $prefix . $hash;
3241-
}
3242-
3243-
return strtoupper($hash);
3178+
$fkName = sprintf('%s_%s_%s_%s', $priTableName, $priColumnName, $refTableName, $refColumnName);
3179+
return strtoupper(ExpressionConverter::shortenEntityName($fkName, 'fk_'));
32443180
}
32453181

32463182
/**

lib/internal/Magento/Framework/DB/ExpressionConverter.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99

1010
class ExpressionConverter
1111
{
12+
/**
13+
* Maximum length for many MySql identifiers, including database, table, trigger, and column names
14+
*/
15+
const MYSQL_IDENTIFIER_LEN = 64;
16+
1217
/**
1318
* Dictionary for generate short name
1419
*
@@ -83,4 +88,44 @@ public static function addTranslate($from, $to)
8388
{
8489
self::$_translateMap[$from] = $to;
8590
}
91+
92+
/**
93+
* @param string $tableName
94+
* @param string $prefix
95+
* @return string
96+
*/
97+
public static function shortenEntityName($tableName, $prefix)
98+
{
99+
if (strlen($tableName) > self::MYSQL_IDENTIFIER_LEN) {
100+
$shortName = ExpressionConverter::shortName($tableName);
101+
if (strlen($shortName) > self::MYSQL_IDENTIFIER_LEN) {
102+
$hash = md5($tableName);
103+
if (strlen($prefix . $hash) > self::MYSQL_IDENTIFIER_LEN) {
104+
$tableName = self::_minusSuperfluous($hash, $prefix, self::MYSQL_IDENTIFIER_LEN);
105+
} else {
106+
$tableName = $prefix . $hash;
107+
}
108+
} else {
109+
$tableName = $shortName;
110+
}
111+
}
112+
return $tableName;
113+
}
114+
115+
/**
116+
* Minus superfluous characters from hash.
117+
*
118+
* @param string $hash
119+
* @param string $prefix
120+
* @param int $maxCharacters
121+
* @return string
122+
*/
123+
protected static function _minusSuperfluous($hash, $prefix, $maxCharacters)
124+
{
125+
$diff = strlen($hash) + strlen($prefix) - $maxCharacters;
126+
$superfluous = $diff / 2;
127+
$odd = $diff % 2;
128+
$hash = substr($hash, $superfluous, - ($superfluous + $odd));
129+
return $hash;
130+
}
86131
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
/***
3+
* Copyright © 2015 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Framework\DB\Test\Unit;
8+
9+
10+
use Magento\Framework\DB\ExpressionConverter;
11+
12+
class ExpressionConverterTest extends \PHPUnit_Framework_TestCase
13+
{
14+
/**
15+
* @dataProvider shortenEntityNameDataProvider
16+
*/
17+
public function testShortenEntityName($in, $prefix, $expectedOut)
18+
{
19+
$this->assertSame($expectedOut, ExpressionConverter::shortenEntityName($in, $prefix));
20+
}
21+
22+
public function shortenEntityNameDataProvider()
23+
{
24+
/** Length of 64 characters, to go over max MySql identifier length */
25+
$length64 = '________________________________________________________________';
26+
$length40 = '________________________________________';
27+
$length20 = '____________________';
28+
echo $length20;
29+
return [
30+
'Short identifier' => [
31+
'already_short',
32+
'pre_',
33+
'already_short'
34+
],
35+
'Hashed identifer' => [
36+
$length64 . '_cannotBeAbbreviated',
37+
'pre_',
38+
'pre_be55448d703c761bf8a322a9993c9ed3'
39+
],
40+
'Abbreviated identifier' => [
41+
$length40 . '_enterprise_notification_index',
42+
'pre_',
43+
'_________________________________________ent_ntfc_idx'
44+
],
45+
'Reduced hash' => [
46+
$length64 . '_cannotBeAbbreviated',
47+
$length40,
48+
'448d703c761bf8a322a9993c'
49+
],
50+
];
51+
}
52+
}

lib/internal/Magento/Framework/Mview/Test/Unit/View/SubscriptionTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,4 +276,8 @@ protected function mockGetTableName()
276276
->method('getTableName')
277277
->will($this->returnArgument(0));
278278
}
279+
280+
public function testGetTriggerName()
281+
{
282+
}
279283
}

lib/internal/Magento/Framework/Mview/View/Subscription.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@
88

99
namespace Magento\Framework\Mview\View;
1010

11+
use Magento\Framework\DB\ExpressionConverter;
12+
1113
class Subscription implements SubscriptionInterface
1214
{
1315
/**
1416
* Trigger name qualifier
1517
*/
16-
const TRIGGER_NAME_QUALIFIER = 'trg';
18+
const TRIGGER_NAME_QUALIFIER = 'trg_';
1719

1820
/**
1921
* Database write connection
@@ -239,7 +241,8 @@ protected function buildStatement($event, $changelog)
239241
*/
240242
protected function getTriggerName($tableName, $time, $event)
241243
{
242-
return self::TRIGGER_NAME_QUALIFIER . '_' . $tableName . '_' . $time . '_' . $event;
244+
$triggerName = $tableName . '_' . $time . '_' . $event;
245+
return ExpressionConverter::shortenEntityName($triggerName, self::TRIGGER_NAME_QUALIFIER);
243246
}
244247

245248
/**

reinstall-pre.sh

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#!/bin/bash
2+
3+
DATABASE_NAME=magento2
4+
DATABASE_USERNAME=root
5+
ADMIN_EMAIL=admin@example.com
6+
ADMIN_USERNAME=admin
7+
ADMIN_PASSWORD=password1
8+
BASE_URL=http://m2.com/
9+
10+
mysql -u $DATABASE_USERNAME -e "drop database $DATABASE_NAME;"
11+
mysql -u $DATABASE_USERNAME -e "create database $DATABASE_NAME;"
12+
13+
rm app/etc/env.php app/etc/config.php
14+
rm -rf var/*
15+
rm -rf pub/media/*
16+
rm app/etc/config.php
17+
rm -rf pub/static/*
18+
rm -rf pub/opt/*
19+
rm -rf pub/errors/*
20+
21+
git checkout -- pub
22+
23+
# Should really do a chown to the right user
24+
chmod -R a+wX var
25+
chmod -R a+wX app/etc
26+
chmod -R a+wX pub
27+
28+
composer install
29+
30+
php bin/magento setup:install \
31+
--db-host=127.0.0.1 \
32+
--db-name=$DATABASE_NAME \
33+
--db-user=$DATABASE_USERNAME \
34+
--base-url=$BASE_URL \
35+
--language=en_US \
36+
--timezone=America/Chicago \
37+
--currency=USD \
38+
--admin-user=$ADMIN_USERNAME \
39+
--admin-password=$ADMIN_PASSWORD \
40+
--admin-email=$ADMIN_EMAIL \
41+
--admin-firstname=John \
42+
--admin-lastname=Doe \
43+
--cleanup-database \
44+
--backend-frontname=admin \
45+
--use-rewrites=1 \
46+
--db-prefix=zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
47+
# --use-sample-data=1
48+
49+
# Should really do a chown to the right user
50+
chmod -R a+wX var
51+
chmod -R a+wX app/etc
52+
chmod -R a+wX pub
53+

0 commit comments

Comments
 (0)