---
title: "Feature: #104493 - Add castText() expression support to ExpressionBuilder"
manual: "TYPO3 Core Changelog"
version: "main"
permalink: "https://docs.typo3.org/permalink/changelog:feature-104493-1722127314"
source: "Changelog/13.3/Feature-104493-AddCastTextExpressionSupportToExpressionBuilder.rst"
typo3-version: "13.3"
typo3-major: 13
type: "feature"
issue: 104493
forge: "https://forge.typo3.org/issues/104493"
tags: ["Database", "PHP-API", "ext:core"]
rendered: "2026-10-03T08:19:36+00:00"
---

# Feature: #104493 - Add `castText()` expression support to `ExpressionBuilder` {#feature-104493-1722127314}

See [forge#104493](https://forge.typo3.org/issues/104493)

## Description {#description}

The TYPO3 `\TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder`
provides a new method to cast expression results to text like datatypes. This
is done to large `VARCHAR/CHAR` types using the `CAST/CONVERT` or similar
methods based on the used database engine.

> [!NOTE]
> This should not be mixed with `TEXT`, `CHAR` or `VARCHAR`
> data types for column (fields) definition used to describe the structure
> of a table.

### `ExpressionBuilder::castText()` {#expressionbuilder-casttext}

Creates a `CAST` expression.

**Method signature**

```php
/**
 * Creates a cast for the `$expression` result to a text datatype depending on the database management system.
 *
 * Note that for MySQL/MariaDB the corresponding CHAR/VARCHAR types are used with a length of `16383` reflecting
 * 65554 bytes with `utf8mb4` and working with default `max_packet_size=16KB`. For SQLite and PostgreSQL the text
 * type conversion is used.
 *
 * Main purpose of this expression is to use it in a expression chain to convert non-text values to text in chain
 * with other expressions, for example to {@see self::concat()} multiple values or to ensure the type,  within
 * `UNION/UNION ALL` query parts for example in recursive `Common Table Expressions` parts.
 *
 * This is a replacement for {@see QueryBuilder::castFieldToTextType()} with minor adjustments like enforcing and
 * limiting the size to a fixed variant to be more usable in sensible areas like `Common Table Expressions`.
 *
 * Alternatively the {@see self::castVarchar()} can be used which allows for dynamic length setting per expression
 * call.
 *
 * **Example:**
 * ```
 * $queryBuilder->expr()->castText(
 *    '(' . '1 * 10' . ')',
 *    'virtual_field'
 * );
 * ```
 *
 * **Result with MySQL:**
 * ```
 * CAST((1 * 10) AS CHAR(16383) AS `virtual_field`
 * ```
 *
 * @throws \RuntimeException when used with a unsupported platform.
 */
public function castText(CompositeExpression|\Stringable|string $expression, string $asIdentifier = ''): string
{
    $platform = $this->connection->getDatabasePlatform();
    if ($platform instanceof DoctrinePostgreSQLPlatform) {
        return $this->as(sprintf('((%s)::%s)', $expression, 'text'), $asIdentifier);
    }
    if ($platform instanceof DoctrineSQLitePlatform) {
        return $this->as(sprintf('(CAST((%s) AS %s))', $expression, 'TEXT'), $asIdentifier);
    }
    if ($platform instanceof DoctrineMariaDBPlatform) {
        // 16383 is the maximum for a VARCHAR field with `utf8mb4`
        return $this->as(sprintf('(CAST((%s) AS %s(%s)))', $expression, 'VARCHAR', '16383'), $asIdentifier);
    }
    if ($platform instanceof DoctrineMySQLPlatform) {
        // 16383 is the maximum for a VARCHAR field with `utf8mb4`
        return $this->as(sprintf('(CAST((%s) AS %s(%s)))', $expression, 'CHAR', '16383'), $asIdentifier);
    }
    throw new \RuntimeException(
        sprintf(
            '%s is not implemented for the used database platform "%s", yet!',
            __METHOD__,
            get_class($this->connection->getDatabasePlatform())
        ),
        1722105672
    );
}
```

## Impact {#impact}

Extension authors can use the new expression method to build more advanced
queries without the requirement to deal with the correct implementation
for all supported database vendors - at least to some grade.
