View Issue Details

IDProjectCategoryView StatusLast Update
0007856OXID eShop (all versions)4.01. Database handlingpublic2025-11-20 12:33
Reporter[email protected] Assigned To 
PrioritynormalSeverityminorReproducibilityalways
Status newResolutionopen 
Summary0007856: ENUM not supported by DBAL
Description# OXID eShop 7.x: ENUM Type Compatibility Issue with Doctrine DBAL Migrations

## Problem Description

OXID eShop 7.x uses Doctrine DBAL for database schema management and migrations. However, when creating custom migrations that need to introspect the existing database schema, the migration system fails with the following error:

```
Unknown database type enum requested, Doctrine\DBAL\Platforms\MySQL57Platform may not support it.
```

This occurs because:
1. OXID core database tables contain MySQL ENUM columns
2. Doctrine DBAL does not natively support the ENUM type
3. When migrations use `Schema::hasTable()` or any schema introspection, Doctrine reads the entire database schema
4. Upon encountering ENUM columns, Doctrine throws an exception because it cannot map the ENUM type to a Doctrine type

## OXID Core Tables with ENUM Fields

The following OXID eShop core tables contain ENUM columns:

### oxdelivery
- `OXADDSUMTYPE` - enum('%','abs')
- `OXDELTYPE` - enum('a','s','w','p')

### oxdiscount
- `OXADDSUMTYPE` - enum('%','abs','itm')

### oxpayments
- `OXADDSUMTYPE` - enum('abs','%')

### oxratings
- `OXTYPE` - enum('oxarticle','oxrecommlist')

### oxremark
- `OXTYPE` - enum('o','r','n','c')

### oxreviews
- `OXTYPE` - enum('oxarticle','oxrecommlist')

### oxseo
- `OXTYPE` - enum('static','oxarticle','oxcategory','oxvendor','oxcontent','dynamic','oxmanufacturer')

**Note:** All corresponding OXID view tables (oxv_*) also inherit these ENUM columns.

## Impact on Module Development

This issue prevents module developers from creating migrations that:
- Check if tables exist before creating them (`$schema->hasTable()`)
- Perform any schema introspection operations
- Use standard Doctrine DBAL schema comparison features
- Create migrations in a defensive way (checking before modifying)

### Example Failing Migration

```php
public function up(Schema $schema): void
{
    // This will fail if ANY table in the database has ENUM columns
    if (!$schema->hasTable('my_custom_table')) {
        $table = $schema->createTable('my_custom_table');
        // ... table definition
    }
}
```

The error occurs even though the migration doesn't touch any ENUM columns - simply reading the schema to check table existence triggers the exception.

## Current Workarounds

Developers currently must use one of these suboptimal workarounds:

### 1. Register ENUM mapping in each migration
```php
private function registerEnumMapping(): void
{
    $platform = $this->connection->getDatabasePlatform();
    if (!$platform->hasDoctrineTypeMappingFor('enum')) {
        $platform->registerDoctrineTypeMapping('enum', 'string');
    }
}

public function preUp(Schema $schema): void
{
    parent::preUp($schema);
    $this->registerEnumMapping();
}
```

### 2. Create custom base migration class
Extend `AbstractMigration` with ENUM handling for all module migrations.

### 3. Avoid schema introspection
Don't use `$schema->hasTable()` or similar methods - use raw SQL queries instead.

## Proposed Solution

The OXID eShop migration infrastructure should automatically register the ENUM type mapping before executing any migrations.

### Implementation Location

File: `vendor/oxid-esales/oxideshop-doctrine-migration-wrapper/src/migrations-db.php`

This file provides the database connection configuration to Doctrine Migrations. It should also register custom type mappings.

### Suggested Fix

Modify `migrations-db.php` to register ENUM mapping after connection is established:

```php
<?php

declare(strict_types=1);

namespace OxidEsales\DoctrineMigrationWrapper;

use Doctrine\DBAL\DriverManager;
use OxidEsales\Facts\Facts;

$facts = new Facts();

$connectionParams = [
    'dbname' => $facts->getDatabaseName(),
    'user' => $facts->getDatabaseUserName(),
    'password' => $facts->getDatabasePassword(),
    'host' => $facts->getDatabaseHost(),
    'port' => $facts->getDatabasePort(),
    'driver' => $facts->getDatabaseDriver(),
    'charset' => 'utf8',
    'driverOptions' => [
        \PDO::MYSQL_ATTR_INIT_COMMAND => 'SET @@SESSION.sql_mode=\'\''
    ]
];

// Create connection and register ENUM type mapping
$connection = DriverManager::getConnection($connectionParams);
$platform = $connection->getDatabasePlatform();

// Register ENUM as string type for MySQL compatibility
if (method_exists($platform, 'registerDoctrineTypeMapping')) {
    if (!$platform->hasDoctrineTypeMappingFor('enum')) {
        $platform->registerDoctrineTypeMapping('enum', 'string');
    }
}

return $connection;
```

Alternatively, add a bootstrap mechanism that allows projects to register custom type mappings.

## Alternative: Long-term Solution

Consider migrating OXID core tables away from ENUM types to VARCHAR columns with appropriate constraints or validation. ENUMs are:
- Not supported by Doctrine DBAL
- Less flexible (adding values requires ALTER TABLE)
- Database-specific (not portable)
- Cannot be easily extended by modules

Converting to VARCHAR would:
- Eliminate the Doctrine DBAL compatibility issue
- Follow Doctrine best practices
- Allow easier schema migrations
- Be more compatible with modern ORM patterns

## Environment

- OXID eShop: 7.3.x Enterprise Edition
- PHP: 8.2+
- Doctrine DBAL: 3.x (via oxideshop-doctrine-migration-wrapper)
- MySQL: 5.7/8.0/MariaDB

## References

- Doctrine DBAL Type System: https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/types.html
- Custom Mapping Types: https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/types.html#custom-mapping-types
Steps To ReproduceCreate migration:
<?php

declare(strict_types=1);

namespace Opal\OpalPDFDocuments\Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
 * Minimal migration to reproduce ENUM type compatibility issue.
 *
 * This migration will FAIL with:
 * "Unknown database type enum requested, Doctrine\DBAL\Platforms\MySQL57Platform may not support it."
 *
 * The error occurs when Doctrine reads the existing database schema
 * and encounters ENUM columns in OXID core tables (oxdelivery, oxpayments, etc.).
 */
final class Version20251120000001 extends AbstractMigration
{
    public function getDescription(): string
    {
        return 'Test migration to reproduce ENUM type error - simply checks if a table exists';
    }

    public function up(Schema $schema): void
    {
        // This simple check will fail because Doctrine reads ALL tables in the schema
        // and chokes on ENUM columns in oxdelivery, oxpayments, oxdiscount, etc.
        if (!$schema->hasTable('test_enum_issue')) {
            $table = $schema->createTable('test_enum_issue');
            $table->addColumn('id', 'integer', ['autoincrement' => true]);
            $table->addColumn('test', 'string', ['length' => 255]);
            $table->setPrimaryKey(['id']);
        }
    }

    public function down(Schema $schema): void
    {
        if ($schema->hasTable('test_enum_issue')) {
            $schema->dropTable('test_enum_issue');
        }
    }
}


run migration
TagsNo tags attached.
ThemeNot defined
BrowserNot defined
PHP Version8.1
Database VersionMySQL 5.7

Activities

There are no notes attached to this issue.