Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Propel/Generator/Platform/MysqlPlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -464,9 +464,9 @@ public function getColumnDDL(Column $col): string
if ($def && $def->isExpression()) {
throw new EngineException('DATE columns cannot have default *expressions* in MySQL.');
}
} elseif ($sqlType === 'TEXT' || $sqlType === 'BLOB') {
} elseif ($sqlType === 'BLOB') {
if ($domain->getDefaultValue()) {
throw new EngineException('BLOB and TEXT columns cannot have DEFAULT values. in MySQL.');
throw new EngineException('BLOB columns cannot have DEFAULT values in MySQL.');
}
}

Expand Down
10 changes: 9 additions & 1 deletion src/Propel/Generator/Reverse/MysqlSchemaParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,15 @@ public function getColumnFromRow(array $row, Table $table): Column
}

// BLOBs can't have any default values in MySQL
$default = preg_match('~blob|text~', $nativeType) ? null : $row['Default'];
if (preg_match('~blob~', $nativeType)) {
$default = null;
} elseif ($row['Default'] !== null && $row['Default'] !== '' && preg_match('~text~', $nativeType)) {
// MySQL 8.0+ wraps TEXT defaults with a charset prefix like _utf8mb3'value'
// MariaDB wraps TEXT type default values in extra single quotes like 'value'
$default = preg_replace('~^(?:_\w+)?\'(.*)\'$~', '$1', $row['Default']);
} else {
$default = $row['Default'];
}

$propelType = $this->getMappedPropelType($nativeType);
if (!$propelType) {
Expand Down
27 changes: 27 additions & 0 deletions tests/Propel/Tests/Generator/Platform/MysqlPlatformTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

use Propel\Generator\Builder\Util\SchemaReader;
use Propel\Generator\Config\GeneratorConfig;
use Propel\Generator\Exception\EngineException;
use Propel\Generator\Model\Column;
use Propel\Generator\Model\ColumnDefaultValue;
use Propel\Generator\Model\IdMethod;
Expand Down Expand Up @@ -481,6 +482,32 @@ public function testGetColumnDDL()
$this->assertEquals($expected, $this->getPlatform()->getColumnDDL($column));
}

/**
* @return void
*/
public function testGetColumnDDLTextDefaultValue(): void
{
$column = new Column('foo');
$column->getDomain()->copy($this->getPlatform()->getDomainForType(PropelTypes::LONGVARCHAR));
$column->getDomain()->setDefaultValue(new ColumnDefaultValue('hello', ColumnDefaultValue::TYPE_VALUE));
$expected = '`foo` TEXT DEFAULT \'hello\'';
$this->assertEquals($expected, $this->getPlatform()->getColumnDDL($column));
}

/**
* @return void
*/
public function testGetColumnDDLBlobDefaultValueThrowsException(): void
{
$this->expectException(EngineException::class);
$this->expectExceptionMessage('BLOB columns cannot have DEFAULT values in MySQL.');

$column = new Column('bar');
$column->getDomain()->copy($this->getPlatform()->getDomainForType(PropelTypes::BLOB));
$column->getDomain()->setDefaultValue(new ColumnDefaultValue('data', ColumnDefaultValue::TYPE_VALUE));
$this->getPlatform()->getColumnDDL($column);
}

/**
* @return void
*/
Expand Down
69 changes: 69 additions & 0 deletions tests/Propel/Tests/Generator/Reverse/MysqlSchemaParserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
namespace Propel\Tests\Generator\Reverse;

use PDO;
use Propel\Generator\Config\QuickGeneratorConfig;
use Propel\Generator\Model\ColumnDefaultValue;
use Propel\Generator\Model\Database;
use Propel\Generator\Platform\DefaultPlatform;
use Propel\Generator\Reverse\MysqlSchemaParser;
use Propel\Tests\Bookstore\Map\BookTableMap;

Expand Down Expand Up @@ -93,4 +96,70 @@ public function testOnUpdateIsImported(): void
$this->assertEquals(ColumnDefaultValue::TYPE_EXPR, $updatedAtColumn->getDefaultValue()->getType());
$this->assertEquals('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP', $updatedAtColumn->getDefaultValue()->getValue());
}

/**
* @return void
*/
public function testTextDefaultValues(): void
{
$serverVersion = $this->con->getAttribute(PDO::ATTR_SERVER_VERSION);
$isMariaDb = stripos($serverVersion, 'mariadb') !== false;

if ($isMariaDb) {
if (version_compare(preg_replace('/^.*?(\d+\.\d+\.\d+).*$/', '$1', $serverVersion), '10.2.1', '<')) {
$this->markTestSkipped('TEXT columns with DEFAULT values require MariaDB 10.2.1+');
}
} else {
if (version_compare($serverVersion, '8.0.13', '<')) {
$this->markTestSkipped('TEXT columns with DEFAULT values require MySQL 8.0.13+');
}
}

$this->con->exec('DROP TABLE IF EXISTS test_text_defaults');
$this->con->exec("CREATE TABLE test_text_defaults (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
content_text TEXT DEFAULT ('hello text'),
content_text_empty TEXT DEFAULT (''),
content_text_not_null TEXT NOT NULL,
content_text_none TEXT
)");

try {
$parser = new MysqlSchemaParser($this->con);
$parser->setGeneratorConfig(new QuickGeneratorConfig());

$database = new Database();
$database->setPlatform(new DefaultPlatform());
$parser->parse($database);

$table = $database->getTable('test_text_defaults');
$this->assertNotNull($table, 'Table test_text_defaults should be parsed');

// TEXT with default value
$contentText = $table->getColumn('content_text');
$this->assertNotNull($contentText, 'Column content_text should exist');
$this->assertNotNull($contentText->getDefaultValue(), 'TEXT column default value should be preserved');
$this->assertEquals(ColumnDefaultValue::TYPE_VALUE, $contentText->getDefaultValue()->getType());
$this->assertEquals('hello text', $contentText->getDefaultValue()->getValue());

// TEXT with empty string default
$contentTextEmpty = $table->getColumn('content_text_empty');
$this->assertNotNull($contentTextEmpty, 'Column content_text_empty should exist');
$this->assertNotNull($contentTextEmpty->getDefaultValue(), 'TEXT column with empty default should be preserved');
$this->assertEquals(ColumnDefaultValue::TYPE_VALUE, $contentTextEmpty->getDefaultValue()->getType());
$this->assertEquals('', $contentTextEmpty->getDefaultValue()->getValue());

// TEXT NOT NULL without default
$contentTextNotNull = $table->getColumn('content_text_not_null');
$this->assertNotNull($contentTextNotNull, 'Column content_text_not_null should exist');
$this->assertNull($contentTextNotNull->getDefaultValue(), 'TEXT NOT NULL column without default should have no default');

// TEXT without default (nullable, implicit DEFAULT NULL)
$contentTextNone = $table->getColumn('content_text_none');
$this->assertNotNull($contentTextNone, 'Column content_text_none should exist');
$this->assertNull($contentTextNone->getDefaultValue(), 'TEXT column without explicit default should have no default');
} finally {
$this->con->exec('DROP TABLE IF EXISTS test_text_defaults');
}
}
}
Loading