Integration with Doctrine

This guide covers integration with Doctrine DBAL 3.x/4.x and ORM 2.14+/3.x. For older versions, please refer to previous documentation versions.

Register DBAL Types

Register the DBAL types you plan to use. The full set of available types can be found in AVAILABLE-TYPES.md.

<?php

use Doctrine\DBAL\Types\Type as DoctrineType;

// Binary types
DoctrineType::addType('bytea', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Bytea");
DoctrineType::addType('bytea[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\ByteaArray");

// Bit types
DoctrineType::addType('bit', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Bit");
DoctrineType::addType('bit[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\BitArray");
DoctrineType::addType('bit varying', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\BitVarying");
DoctrineType::addType('bit varying[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\BitVaryingArray");

// Array types
DoctrineType::addType('bool[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\BooleanArray");
DoctrineType::addType('smallint[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\SmallIntArray");
DoctrineType::addType('integer[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\IntegerArray");
DoctrineType::addType('bigint[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\BigIntArray");
DoctrineType::addType('double precision[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\DoublePrecisionArray");
DoctrineType::addType('numeric[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\NumericArray");
DoctrineType::addType('real[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\RealArray");
DoctrineType::addType('text[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\TextArray");
DoctrineType::addType('uuid[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\UuidArray");
DoctrineType::addType('varchar[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\VarcharArray");

// Case-insensitive text types
DoctrineType::addType('citext', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Citext");
DoctrineType::addType('citext[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\CitextArray");

// ULID types
DoctrineType::addType('ulid', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Ulid");
DoctrineType::addType('ulid[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\UlidArray");

// Date and time types
DoctrineType::addType('date[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\DateArray");
DoctrineType::addType('interval', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Interval");
DoctrineType::addType('interval[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\IntervalArray");
DoctrineType::addType('time[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\TimeArray");
DoctrineType::addType('timestamp[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\TimestampArray");
DoctrineType::addType('timestamptz[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\TimestampTzArray");
DoctrineType::addType('timetz', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Timetz");
DoctrineType::addType('timetz[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\TimetzArray");

// JSON types
DoctrineType::addType('json[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\JsonArray");
DoctrineType::addType('jsonb', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Jsonb");
DoctrineType::addType('jsonb[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\JsonbArray");

// Network types
DoctrineType::addType('cidr', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Cidr");
DoctrineType::addType('cidr[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\CidrArray");
DoctrineType::addType('inet', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Inet");
DoctrineType::addType('inet[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\InetArray");
DoctrineType::addType('macaddr', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Macaddr");
DoctrineType::addType('macaddr[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\MacaddrArray");
DoctrineType::addType('macaddr8', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Macaddr8");
DoctrineType::addType('macaddr8[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Macaddr8Array");

// Geometric types
DoctrineType::addType('box', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Box");
DoctrineType::addType('box[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\BoxArray");
DoctrineType::addType('circle', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Circle");
DoctrineType::addType('circle[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\CircleArray");
DoctrineType::addType('line', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Line");
DoctrineType::addType('line[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\LineArray");
DoctrineType::addType('lseg', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Lseg");
DoctrineType::addType('lseg[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\LsegArray");
DoctrineType::addType('path', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Path");
DoctrineType::addType('path[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\PathArray");
DoctrineType::addType('point', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Point");
DoctrineType::addType('point[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\PointArray");
DoctrineType::addType('polygon', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Polygon");
DoctrineType::addType('polygon[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\PolygonArray");

// Cube types
DoctrineType::addType('cube', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Cube");
DoctrineType::addType('cube[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\CubeArray");

// PostGIS spatial types
DoctrineType::addType('geometry', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Geometry");
DoctrineType::addType('geometry[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\GeometryArray");
DoctrineType::addType('geography', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Geography");
DoctrineType::addType('geography[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\GeographyArray");

// Range types
DoctrineType::addType('daterange', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\DateRange");
DoctrineType::addType('daterange[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\DateRangeArray");
DoctrineType::addType('int4range', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Int4Range");
DoctrineType::addType('int4range[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Int4RangeArray");
DoctrineType::addType('int8range', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Int8Range");
DoctrineType::addType('int8range[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Int8RangeArray");
DoctrineType::addType('numrange', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\NumRange");
DoctrineType::addType('numrange[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\NumRangeArray");
DoctrineType::addType('tsrange', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\TsRange");
DoctrineType::addType('tsrange[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\TsRangeArray");
DoctrineType::addType('tstzrange', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\TstzRange");
DoctrineType::addType('tstzrange[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\TstzRangeArray");

// Multirange types
DoctrineType::addType('datemultirange', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\DateMultirange");
DoctrineType::addType('datemultirange[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\DateMultirangeArray");
DoctrineType::addType('int4multirange', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Int4Multirange");
DoctrineType::addType('int4multirange[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Int4MultirangeArray");
DoctrineType::addType('int8multirange', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Int8Multirange");
DoctrineType::addType('int8multirange[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Int8MultirangeArray");
DoctrineType::addType('nummultirange', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\NumMultirange");
DoctrineType::addType('nummultirange[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\NumMultirangeArray");
DoctrineType::addType('tsmultirange', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\TsMultirange");
DoctrineType::addType('tsmultirange[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\TsMultirangeArray");
DoctrineType::addType('tstzmultirange', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\TstzMultirange");
DoctrineType::addType('tstzmultirange[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\TstzMultirangeArray");

// Text search types
DoctrineType::addType('tsquery', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Tsquery");
DoctrineType::addType('tsquery[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\TsqueryArray");
DoctrineType::addType('tsvector', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Tsvector");
DoctrineType::addType('tsvector[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\TsvectorArray");

// Monetary types
DoctrineType::addType('money', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Money");
DoctrineType::addType('money[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\MoneyArray");

// Key-value types
DoctrineType::addType('hstore', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Hstore");
DoctrineType::addType('hstore[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\HstoreArray");

// Hierarchical types
DoctrineType::addType('lquery', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Lquery");
DoctrineType::addType('lquery[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\LqueryArray");
DoctrineType::addType('ltree', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Ltree");
DoctrineType::addType('ltree[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\LtreeArray");
DoctrineType::addType('ltxtquery', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Ltxtquery");
DoctrineType::addType('ltxtquery[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\LtxtqueryArray");

// XML types
DoctrineType::addType('xml', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Xml");
DoctrineType::addType('xml[]', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\XmlArray");

// Vector types
DoctrineType::addType('halfvec', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Halfvec");
DoctrineType::addType('sparsevec', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Sparsevec");
DoctrineType::addType('vector', "MartinGeorgiev\\Doctrine\\DBAL\\Types\\Vector");

Register DQL Functions

Register the functions you’ll use in your DQL queries. The full set of available functions and operators can be found in the Available Functions and Operators documentation and its specialized sub-pages:

<?php

use Doctrine\DBAL\DriverManager;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\ORMSetup;

$configuration = ORMSetup::createAttributeMetadataConfiguration(
    paths: [__DIR__ . '/src'],
    isDevMode: true,
);

# alternative implementation of ALL() and ANY() where subquery is not required, useful for arrays
$configuration->addCustomStringFunction('ALL_OF', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\All::class);
$configuration->addCustomStringFunction('ANY_OF', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Any::class);

# operators for working with array and json(b) data
$configuration->addCustomStringFunction('GREATEST', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Greatest::class);
$configuration->addCustomStringFunction('LEAST', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Least::class);
$configuration->addCustomStringFunction('CONTAINS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Contains::class); # @>
$configuration->addCustomStringFunction('IS_CONTAINED_BY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\IsContainedBy::class); # <@
$configuration->addCustomStringFunction('OVERLAPS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Overlaps::class); # &&
$configuration->addCustomStringFunction('RIGHT_EXISTS_ON_LEFT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TheRightExistsOnTheLeft::class); # ?
$configuration->addCustomStringFunction('ALL_ON_RIGHT_EXIST_ON_LEFT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\AllOnTheRightExistOnTheLeft::class); # ?&
$configuration->addCustomStringFunction('ANY_ON_RIGHT_EXISTS_ON_LEFT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\AnyOnTheRightExistsOnTheLeft::class); # ?|
$configuration->addCustomStringFunction('RETURNS_VALUE_FOR_JSON_VALUE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ReturnsValueForJsonValue::class); # @?
$configuration->addCustomStringFunction('DELETE_AT_PATH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DeleteAtPath::class); # #-

# array and string specific functions
$configuration->addCustomStringFunction('IN_ARRAY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\InArray::class);
$configuration->addCustomStringFunction('ANY_VALUE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\AnyValue::class);
$configuration->addCustomStringFunction('ARRAY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Arr::class);
$configuration->addCustomStringFunction('ARRAY_APPEND', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayAppend::class);
$configuration->addCustomStringFunction('ARRAY_CARDINALITY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayCardinality::class);
$configuration->addCustomStringFunction('ARRAY_CAT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayCat::class);
$configuration->addCustomStringFunction('ARRAY_DIMENSIONS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayDimensions::class);
$configuration->addCustomStringFunction('ARRAY_FILL', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayFill::class);
$configuration->addCustomStringFunction('ARRAY_LENGTH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayLength::class);
$configuration->addCustomStringFunction('ARRAY_LOWER', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayLower::class);
$configuration->addCustomStringFunction('ARRAY_NUMBER_OF_DIMENSIONS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayNumberOfDimensions::class);
$configuration->addCustomStringFunction('ARRAY_POSITION', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayPosition::class);
$configuration->addCustomStringFunction('ARRAY_POSITIONS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayPositions::class);
$configuration->addCustomStringFunction('ARRAY_PREPEND', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayPrepend::class);
$configuration->addCustomStringFunction('ARRAY_REMOVE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayRemove::class);
$configuration->addCustomStringFunction('ARRAY_REPLACE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayReplace::class);
$configuration->addCustomStringFunction('ARRAY_REVERSE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayReverse::class);
$configuration->addCustomStringFunction('ARRAY_SAMPLE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArraySample::class);
$configuration->addCustomStringFunction('ARRAY_SHUFFLE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayShuffle::class);
$configuration->addCustomStringFunction('ARRAY_SORT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArraySort::class);
$configuration->addCustomStringFunction('ARRAY_TO_JSON', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayToJson::class);
$configuration->addCustomStringFunction('ARRAY_TO_STRING', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayToString::class);
$configuration->addCustomStringFunction('ARRAY_UPPER', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayUpper::class);
$configuration->addCustomStringFunction('ASCII', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ascii::class);
$configuration->addCustomStringFunction('BTRIM', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Btrim::class);
$configuration->addCustomStringFunction('CASEFOLD', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Casefold::class);
$configuration->addCustomStringFunction('CHAR_LENGTH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\CharLength::class);
$configuration->addCustomStringFunction('CHR', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Chr::class);
$configuration->addCustomStringFunction('CONCAT_WS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ConcatWs::class);
$configuration->addCustomStringFunction('DECODE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Decode::class);
$configuration->addCustomStringFunction('ENCODE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Encode::class);
$configuration->addCustomStringFunction('FORMAT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Format::class);
$configuration->addCustomStringFunction('INITCAP', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Initcap::class);
$configuration->addCustomStringFunction('LEFT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Left::class);
$configuration->addCustomStringFunction('LPAD', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Lpad::class);
$configuration->addCustomStringFunction('LTRIM', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ltrim::class);
$configuration->addCustomStringFunction('OCTET_LENGTH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\OctetLength::class);
$configuration->addCustomStringFunction('QUOTE_IDENT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\QuoteIdent::class);
$configuration->addCustomStringFunction('QUOTE_LITERAL', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\QuoteLiteral::class);
$configuration->addCustomStringFunction('QUOTE_NULLABLE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\QuoteNullable::class);
$configuration->addCustomStringFunction('REPEAT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Repeat::class);
$configuration->addCustomStringFunction('REVERSE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Reverse::class);
$configuration->addCustomStringFunction('RIGHT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Right::class);
$configuration->addCustomStringFunction('RPAD', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Rpad::class);
$configuration->addCustomStringFunction('RTRIM', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Rtrim::class);
$configuration->addCustomStringFunction('SPLIT_PART', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\SplitPart::class);
$configuration->addCustomStringFunction('STARTS_WITH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\StartsWith::class);
$configuration->addCustomStringFunction('STRPOS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Strpos::class);
$configuration->addCustomStringFunction('STRING_TO_ARRAY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\StringToArray::class);
$configuration->addCustomStringFunction('ROW', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Row::class);
$configuration->addCustomStringFunction('TRANSLATE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Translate::class);
$configuration->addCustomStringFunction('UNNEST', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Unnest::class);

# json specific functions
$configuration->addCustomStringFunction('JSON_ARRAY_LENGTH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonArrayLength::class);
$configuration->addCustomStringFunction('JSON_BUILD_ARRAY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonBuildArray::class);
$configuration->addCustomStringFunction('JSON_BUILD_OBJECT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonBuildObject::class);
$configuration->addCustomStringFunction('JSON_EACH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonEach::class);
$configuration->addCustomStringFunction('JSON_EACH_TEXT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonEachText::class);
$configuration->addCustomStringFunction('JSON_EXISTS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonExists::class);
$configuration->addCustomStringFunction('JSON_EXTRACT_PATH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonExtractPath::class);
$configuration->addCustomStringFunction('JSON_EXTRACT_PATH_TEXT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonExtractPathText::class);
$configuration->addCustomStringFunction('JSON_GET_FIELD', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonGetField::class);
$configuration->addCustomStringFunction('JSON_GET_FIELD_AS_INTEGER', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonGetFieldAsInteger::class);
$configuration->addCustomStringFunction('JSON_GET_FIELD_AS_TEXT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonGetFieldAsText::class);
$configuration->addCustomStringFunction('JSON_GET_OBJECT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonGetObject::class);
$configuration->addCustomStringFunction('JSON_GET_OBJECT_AS_TEXT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonGetObjectAsText::class);
$configuration->addCustomStringFunction('JSON_OBJECT_KEYS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonObjectKeys::class);
$configuration->addCustomStringFunction('JSON_QUERY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonQuery::class);
$configuration->addCustomStringFunction('JSON_SCALAR', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonScalar::class);
$configuration->addCustomStringFunction('JSON_SERIALIZE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonSerialize::class);
$configuration->addCustomStringFunction('JSON_STRIP_NULLS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonStripNulls::class);
$configuration->addCustomStringFunction('JSON_TYPEOF', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonTypeof::class);
$configuration->addCustomStringFunction('JSON_VALUE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonValue::class);
$configuration->addCustomStringFunction('TO_JSON', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToJson::class);
$configuration->addCustomStringFunction('ROW_TO_JSON', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RowToJson::class);

# jsonb specific functions
$configuration->addCustomStringFunction('JSONB_ARRAY_ELEMENTS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbArrayElements::class);
$configuration->addCustomStringFunction('JSONB_ARRAY_ELEMENTS_TEXT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbArrayElementsText::class);
$configuration->addCustomStringFunction('JSONB_ARRAY_LENGTH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbArrayLength::class);
$configuration->addCustomStringFunction('JSONB_BUILD_ARRAY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbBuildArray::class);
$configuration->addCustomStringFunction('JSONB_BUILD_OBJECT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbBuildObject::class);
$configuration->addCustomStringFunction('JSONB_EACH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbEach::class);
$configuration->addCustomStringFunction('JSONB_EACH_TEXT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbEachText::class);
$configuration->addCustomStringFunction('JSONB_EXISTS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbExists::class);
$configuration->addCustomStringFunction('JSONB_EXTRACT_PATH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbExtractPath::class);
$configuration->addCustomStringFunction('JSONB_EXTRACT_PATH_TEXT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbExtractPathText::class);
$configuration->addCustomStringFunction('JSONB_INSERT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbInsert::class);
$configuration->addCustomStringFunction('JSONB_OBJECT_KEYS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbObjectKeys::class);
$configuration->addCustomStringFunction('JSONB_PATH_EXISTS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbPathExists::class);
$configuration->addCustomStringFunction('JSONB_PATH_MATCH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbPathMatch::class);
$configuration->addCustomStringFunction('JSONB_PATH_QUERY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbPathQuery::class);
$configuration->addCustomStringFunction('JSONB_PATH_QUERY_ARRAY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbPathQueryArray::class);
$configuration->addCustomStringFunction('JSONB_PATH_QUERY_FIRST', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbPathQueryFirst::class);
$configuration->addCustomStringFunction('JSONB_PRETTY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbPretty::class);
$configuration->addCustomStringFunction('JSONB_SET', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbSet::class);
$configuration->addCustomStringFunction('JSONB_SET_LAX', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbSetLax::class);
$configuration->addCustomStringFunction('JSONB_STRIP_NULLS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbStripNulls::class);
$configuration->addCustomStringFunction('JSONB_TYPEOF', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbTypeof::class);
$configuration->addCustomStringFunction('TO_JSONB', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToJsonb::class);

# text search specific
$configuration->addCustomStringFunction('ARRAY_TO_TSVECTOR', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayToTsvector::class);
$configuration->addCustomStringFunction('JSON_TO_TSVECTOR', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonToTsvector::class);
$configuration->addCustomStringFunction('JSONB_TO_TSVECTOR', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbToTsvector::class);
$configuration->addCustomStringFunction('PHRASETO_TSQUERY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PhrasetoTsquery::class);
$configuration->addCustomStringFunction('PLAINTO_TSQUERY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PlaintoTsquery::class);
$configuration->addCustomStringFunction('SETWEIGHT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Setweight::class);
$configuration->addCustomStringFunction('STRIP', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Strip::class);
$configuration->addCustomStringFunction('TO_TSQUERY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToTsquery::class);
$configuration->addCustomStringFunction('TO_TSVECTOR', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToTsvector::class);
$configuration->addCustomStringFunction('TS_HEADLINE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TsHeadline::class);
$configuration->addCustomStringFunction('TS_RANK', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TsRank::class);
$configuration->addCustomStringFunction('TS_RANK_CD', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TsRankCd::class);
$configuration->addCustomStringFunction('TSMATCH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Tsmatch::class);
$configuration->addCustomStringFunction('TSQUERY_PHRASE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TsqueryPhrase::class);
$configuration->addCustomStringFunction('TSVECTOR_TO_ARRAY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TsvectorToArray::class);
$configuration->addCustomStringFunction('WEBSEARCH_TO_TSQUERY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\WebsearchToTsquery::class);

# date specific functions
$configuration->addCustomStringFunction('AGE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Age::class);
$configuration->addCustomStringFunction('AT_TIME_ZONE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\AtTimeZone::class);
$configuration->addCustomStringFunction('CLOCK_TIMESTAMP', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ClockTimestamp::class);
$configuration->addCustomStringFunction('DATE_ADD', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DateAdd::class);
$configuration->addCustomStringFunction('DATE_BIN', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DateBin::class);
$configuration->addCustomStringFunction('DATE_EXTRACT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DateExtract::class);
$configuration->addCustomStringFunction('DATE_OVERLAPS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DateOverlaps::class);
$configuration->addCustomStringFunction('DATE_PART', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DatePart::class);
$configuration->addCustomStringFunction('DATE_SUBTRACT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DateSubtract::class);
$configuration->addCustomStringFunction('DATE_TRUNC', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DateTrunc::class);
$configuration->addCustomStringFunction('GENERATE_TIME_SERIES', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\GenerateTimeSeries::class);
$configuration->addCustomStringFunction('ISFINITE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Isfinite::class);
$configuration->addCustomStringFunction('JUSTIFY_DAYS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JustifyDays::class);
$configuration->addCustomStringFunction('JUSTIFY_HOURS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JustifyHours::class);
$configuration->addCustomStringFunction('JUSTIFY_INTERVAL', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JustifyInterval::class);
$configuration->addCustomStringFunction('MAKE_DATE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\MakeDate::class);
$configuration->addCustomStringFunction('MAKE_TIME', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\MakeTime::class);
$configuration->addCustomStringFunction('MAKE_TIMESTAMP', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\MakeTimestamp::class);
$configuration->addCustomStringFunction('MAKE_TIMESTAMPTZ', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\MakeTimestamptz::class);
$configuration->addCustomStringFunction('STATEMENT_TIMESTAMP', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\StatementTimestamp::class);
$configuration->addCustomStringFunction('TRANSACTION_TIMESTAMP', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TransactionTimestamp::class);

# range functions
$configuration->addCustomStringFunction('DATERANGE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Daterange::class);
$configuration->addCustomStringFunction('INT4RANGE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Int4range::class);
$configuration->addCustomStringFunction('INT8RANGE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Int8range::class);
$configuration->addCustomStringFunction('NUMRANGE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Numrange::class);
$configuration->addCustomStringFunction('TSRANGE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Tsrange::class);
$configuration->addCustomStringFunction('TSTZRANGE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Tstzrange::class);

# Arithmetic functions
$configuration->addCustomStringFunction('CBRT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Cbrt::class);
$configuration->addCustomStringFunction('CEIL', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ceil::class);
$configuration->addCustomStringFunction('DEGREES', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Degrees::class);
$configuration->addCustomStringFunction('DIV', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Div::class);
$configuration->addCustomStringFunction('ERF', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Erf::class);
$configuration->addCustomStringFunction('ERFC', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Erfc::class);
$configuration->addCustomStringFunction('EXP', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exp::class);
$configuration->addCustomStringFunction('FACTORIAL', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Factorial::class);
$configuration->addCustomStringFunction('FLOOR', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Floor::class);
$configuration->addCustomStringFunction('GAMMA', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Gamma::class);
$configuration->addCustomStringFunction('GCD', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Gcd::class);
$configuration->addCustomStringFunction('GENERATE_NUMERIC_SERIES', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\GenerateNumericSeries::class);
$configuration->addCustomStringFunction('LCM', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Lcm::class);
$configuration->addCustomStringFunction('LGAMMA', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Lgamma::class);
$configuration->addCustomStringFunction('LN', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ln::class);
$configuration->addCustomStringFunction('LOG', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Log::class);
$configuration->addCustomStringFunction('MIN_SCALE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\MinScale::class);
$configuration->addCustomStringFunction('PI', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Pi::class);
$configuration->addCustomStringFunction('POWER', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Power::class);
$configuration->addCustomStringFunction('RADIANS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Radians::class);
$configuration->addCustomStringFunction('RANDOM', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Random::class);
$configuration->addCustomStringFunction('RANDOM_NORMAL', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RandomNormal::class);
$configuration->addCustomStringFunction('ROUND', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Round::class);
$configuration->addCustomStringFunction('SCALE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Scale::class);
$configuration->addCustomStringFunction('SIGN', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Sign::class);
$configuration->addCustomStringFunction('TRIM_SCALE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TrimScale::class);
$configuration->addCustomStringFunction('TRUNC', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trunc::class);
$configuration->addCustomStringFunction('WIDTH_BUCKET', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\WidthBucket::class);

# Trigonometric functions
$configuration->addCustomStringFunction('ACOS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Acos::class);
$configuration->addCustomStringFunction('ACOSD', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Acosd::class);
$configuration->addCustomStringFunction('ACOSH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Acosh::class);
$configuration->addCustomStringFunction('ASIN', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Asin::class);
$configuration->addCustomStringFunction('ASIND', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Asind::class);
$configuration->addCustomStringFunction('ASINH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Asinh::class);
$configuration->addCustomStringFunction('ATAN', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Atan::class);
$configuration->addCustomStringFunction('ATAN2', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Atan2::class);
$configuration->addCustomStringFunction('ATAN2D', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Atan2d::class);
$configuration->addCustomStringFunction('ATAND', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Atand::class);
$configuration->addCustomStringFunction('ATANH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Atanh::class);
$configuration->addCustomStringFunction('COS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Cos::class);
$configuration->addCustomStringFunction('COSD', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Cosd::class);
$configuration->addCustomStringFunction('COSH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Cosh::class);
$configuration->addCustomStringFunction('COT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Cot::class);
$configuration->addCustomStringFunction('COTD', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Cotd::class);
$configuration->addCustomStringFunction('SIN', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Sin::class);
$configuration->addCustomStringFunction('SIND', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Sind::class);
$configuration->addCustomStringFunction('SINH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Sinh::class);
$configuration->addCustomStringFunction('TAN', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Tan::class);
$configuration->addCustomStringFunction('TAND', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Tand::class);
$configuration->addCustomStringFunction('TANH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Tanh::class);

# other operators
$configuration->addCustomStringFunction('COMPOSITE_FIELD', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\CompositeField::class);
$configuration->addCustomStringFunction('ILIKE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ilike::class);
$configuration->addCustomStringFunction('SIMILAR_TO', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\SimilarTo::class);
$configuration->addCustomStringFunction('NOT_SIMILAR_TO', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\NotSimilarTo::class);
$configuration->addCustomStringFunction('UNACCENT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Unaccent::class);
$configuration->addCustomStringFunction('REGEXP', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Regexp::class);
$configuration->addCustomStringFunction('IREGEXP', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\IRegexp::class);
$configuration->addCustomStringFunction('NOT_REGEXP', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\NotRegexp::class);
$configuration->addCustomStringFunction('NOT_IREGEXP', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\NotIRegexp::class);
$configuration->addCustomStringFunction('REGEXP_LIKE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpLike::class);
$configuration->addCustomStringFunction('REGEXP_COUNT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpCount::class);
$configuration->addCustomStringFunction('REGEXP_INSTR', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpInstr::class);
$configuration->addCustomStringFunction('REGEXP_SUBSTR', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpSubstr::class);
$configuration->addCustomStringFunction('REGEXP_MATCH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpMatch::class);
$configuration->addCustomStringFunction('STRCONCAT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\StrConcat::class);
$configuration->addCustomStringFunction('REGEXP_REPLACE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpReplace::class);
$configuration->addCustomStringFunction('DISTANCE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Distance::class);

# vector distance functions
$configuration->addCustomStringFunction('COSINE_DISTANCE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Vector\CosineDistance::class);
$configuration->addCustomStringFunction('INNER_PRODUCT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Vector\InnerProduct::class);
$configuration->addCustomStringFunction('L2_DISTANCE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Vector\L2Distance::class);

# ltree functions
$configuration->addCustomStringFunction('INDEX', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ltree\Index::class);
$configuration->addCustomStringFunction('LCA', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ltree\Lca::class);
$configuration->addCustomStringFunction('LTREE2TEXT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ltree\Ltree2text::class);
$configuration->addCustomStringFunction('NLEVEL', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ltree\Nlevel::class);
$configuration->addCustomStringFunction('SUBLTREE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ltree\Subltree::class);
$configuration->addCustomStringFunction('SUBPATH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ltree\Subpath::class);
$configuration->addCustomStringFunction('TEXT2LTREE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ltree\Text2ltree::class);

# ltree match operators
$configuration->addCustomStringFunction('MATCHES_LQUERY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ltree\MatchesLquery::class); # ~
$configuration->addCustomStringFunction('MATCHES_LTXTQUERY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ltree\MatchesLtxtquery::class); # @
$configuration->addCustomStringFunction('MATCHES_ANY_LQUERY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ltree\MatchesAnyLquery::class); # ?

# hstore functions
$configuration->addCustomStringFunction('HSTORE_AKEYS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Hstore\Akeys::class);
$configuration->addCustomStringFunction('HSTORE_AVALS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Hstore\Avals::class);
$configuration->addCustomStringFunction('HSTORE_DEFINED', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Hstore\Defined::class);
$configuration->addCustomStringFunction('HSTORE_DELETE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Hstore\Delete::class);
$configuration->addCustomStringFunction('HSTORE_SKEYS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Hstore\Skeys::class);
$configuration->addCustomStringFunction('HSTORE_SVALS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Hstore\Svals::class);
$configuration->addCustomStringFunction('HSTORE_TO_JSON', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Hstore\HstoreToJson::class);
$configuration->addCustomStringFunction('HSTORE_TO_JSON_LOOSE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Hstore\HstoreToJsonLoose::class);

# PostGIS functions
$configuration->addCustomStringFunction('ST_3DDFULLYWITHIN', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_3DDFullyWithin::class);
$configuration->addCustomStringFunction('ST_3DDISTANCE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_3DDistance::class);
$configuration->addCustomStringFunction('ST_3DDWITHIN', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_3DDWithin::class);
$configuration->addCustomStringFunction('ST_3DINTERSECTS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_3DIntersects::class);
$configuration->addCustomStringFunction('ST_3DLENGTH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_3DLength::class);
$configuration->addCustomStringFunction('ST_3DPERIMETER', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_3DPerimeter::class);
$configuration->addCustomStringFunction('ST_AREA', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Area::class);
$configuration->addCustomStringFunction('ST_ASEWKT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_AsEWKT::class);
$configuration->addCustomStringFunction('ST_ASGEOJSON', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_AsGeoJSON::class);
$configuration->addCustomStringFunction('ST_ASTEXT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_AsText::class);
$configuration->addCustomStringFunction('ST_AZIMUTH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Azimuth::class);
$configuration->addCustomStringFunction('ST_BOUNDARY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Boundary::class);
$configuration->addCustomStringFunction('ST_BUFFER', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Buffer::class);
$configuration->addCustomStringFunction('ST_CENTROID', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Centroid::class);
$configuration->addCustomStringFunction('ST_CLIPBYBOX2D', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_ClipByBox2D::class);
$configuration->addCustomStringFunction('ST_CLOSESTPOINT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_ClosestPoint::class);
$configuration->addCustomStringFunction('ST_COLLECT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Collect::class);
$configuration->addCustomStringFunction('ST_COLLECTIONEXTRACT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_CollectionExtract::class);
$configuration->addCustomStringFunction('ST_COLLECTIONHOMOGENIZE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_CollectionHomogenize::class);
$configuration->addCustomStringFunction('ST_CONCAVEHULL', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_ConcaveHull::class);
$configuration->addCustomStringFunction('ST_CONTAINS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Contains::class);
$configuration->addCustomStringFunction('ST_CONTAINSPROPERLY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_ContainsProperly::class);
$configuration->addCustomStringFunction('ST_CONVEXHULL', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_ConvexHull::class);
$configuration->addCustomStringFunction('ST_COORDDIM', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_CoordDim::class);
$configuration->addCustomStringFunction('ST_COVERAGEUNION', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_CoverageUnion::class);
$configuration->addCustomStringFunction('ST_COVEREDBY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_CoveredBy::class);
$configuration->addCustomStringFunction('ST_COVERS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Covers::class);
$configuration->addCustomStringFunction('ST_CROSSES', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Crosses::class);
$configuration->addCustomStringFunction('ST_CURVEN', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_CurveN::class);
$configuration->addCustomStringFunction('ST_CURVETOLINE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_CurveToLine::class);
$configuration->addCustomStringFunction('ST_DFULLYWITHIN', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_DFullyWithin::class);
$configuration->addCustomStringFunction('ST_DIFFERENCE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Difference::class);
$configuration->addCustomStringFunction('ST_DISJOINT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Disjoint::class);
$configuration->addCustomStringFunction('ST_DISTANCE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Distance::class);
$configuration->addCustomStringFunction('ST_DWITHIN', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_DWithin::class);
$configuration->addCustomStringFunction('ST_ENDPOINT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_EndPoint::class);
$configuration->addCustomStringFunction('ST_ENVELOPE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Envelope::class);
$configuration->addCustomStringFunction('ST_EQUALS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Equals::class);
$configuration->addCustomStringFunction('ST_EXTERIORRING', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_ExteriorRing::class);
$configuration->addCustomStringFunction('ST_FLIPCOORDINATES', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_FlipCoordinates::class);
$configuration->addCustomStringFunction('ST_FORCE2D', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Force2D::class);
$configuration->addCustomStringFunction('ST_FORCE3D', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Force3D::class);
$configuration->addCustomStringFunction('ST_FORCE4D', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Force4D::class);
$configuration->addCustomStringFunction('ST_FRECHETDISTANCE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_FrechetDistance::class);
$configuration->addCustomStringFunction('ST_GENERATEPOINTS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_GeneratePoints::class);
$configuration->addCustomStringFunction('ST_GEOMETRYN', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_GeometryN::class);
$configuration->addCustomStringFunction('ST_GEOMETRYTYPE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_GeometryType::class);
$configuration->addCustomStringFunction('ST_GEOMFROMEWKT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_GeomFromEWKT::class);
$configuration->addCustomStringFunction('ST_GEOMFROMGEOJSON', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_GeomFromGeoJSON::class);
$configuration->addCustomStringFunction('ST_GEOMFROMTEXT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_GeomFromText::class);
$configuration->addCustomStringFunction('ST_HASM', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_HasM::class);
$configuration->addCustomStringFunction('ST_HASZ', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_HasZ::class);
$configuration->addCustomStringFunction('ST_HAUSDORFFDISTANCE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_HausdorffDistance::class);
$configuration->addCustomStringFunction('ST_INTERIORRINGN', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_InteriorRingN::class);
$configuration->addCustomStringFunction('ST_INTERSECTION', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Intersection::class);
$configuration->addCustomStringFunction('ST_INTERSECTS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Intersects::class);
$configuration->addCustomStringFunction('ST_ISCLOSED', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_IsClosed::class);
$configuration->addCustomStringFunction('ST_ISEMPTY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_IsEmpty::class);
$configuration->addCustomStringFunction('ST_ISVALID', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_IsValid::class);
$configuration->addCustomStringFunction('ST_ISVALIDREASON', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_IsValidReason::class);
$configuration->addCustomStringFunction('ST_LENGTH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Length::class);
$configuration->addCustomStringFunction('ST_LENGTH2D', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Length2D::class);
$configuration->addCustomStringFunction('ST_LETTERS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Letters::class);
$configuration->addCustomStringFunction('ST_LINECROSSINGDIRECTION', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_LineCrossingDirection::class);
$configuration->addCustomStringFunction('ST_LINEEXTEND', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_LineExtend::class);
$configuration->addCustomStringFunction('ST_LINEINTERPOLATEPOINT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_LineInterpolatePoint::class);
$configuration->addCustomStringFunction('ST_LINELOCATEPOINT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_LineLocatePoint::class);
$configuration->addCustomStringFunction('ST_LINESUBSTRING', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_LineSubstring::class);
$configuration->addCustomStringFunction('ST_LINETOCURVE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_LineToCurve::class);
$configuration->addCustomStringFunction('ST_MAKEENVELOPE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_MakeEnvelope::class);
$configuration->addCustomStringFunction('ST_MAKELINE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_MakeLine::class);
$configuration->addCustomStringFunction('ST_MAKEPOINT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_MakePoint::class);
$configuration->addCustomStringFunction('ST_MAKEVALID', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_MakeValid::class);
$configuration->addCustomStringFunction('ST_MAXDISTANCE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_MaxDistance::class);
$configuration->addCustomStringFunction('ST_MINIMUMBOUNDINGCIRCLE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_MinimumBoundingCircle::class);
$configuration->addCustomStringFunction('ST_NPOINTS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_NPoints::class);
$configuration->addCustomStringFunction('ST_NUMCURVES', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_NumCurves::class);
$configuration->addCustomStringFunction('ST_NUMGEOMETRIES', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_NumGeometries::class);
$configuration->addCustomStringFunction('ST_NUMINTERIORRINGS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_NumInteriorRings::class);
$configuration->addCustomStringFunction('ST_NUMPOINTS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_NumPoints::class);
$configuration->addCustomStringFunction('ST_OFFSETCURVE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_OffsetCurve::class);
$configuration->addCustomStringFunction('ST_ORDERINGEQUALS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_OrderingEquals::class);
$configuration->addCustomStringFunction('ST_OVERLAPS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Overlaps::class);
$configuration->addCustomStringFunction('ST_PERIMETER', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Perimeter::class);
$configuration->addCustomStringFunction('ST_POINT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Point::class);
$configuration->addCustomStringFunction('ST_POINTINSIDECIRCLE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_PointInsideCircle::class);
$configuration->addCustomStringFunction('ST_POINTN', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_PointN::class);
$configuration->addCustomStringFunction('ST_POINTONSURFACE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_PointOnSurface::class);
$configuration->addCustomStringFunction('ST_PROJECT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Project::class);
$configuration->addCustomStringFunction('ST_RELATE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Relate::class);
$configuration->addCustomStringFunction('ST_RELATEMATCH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_RelateMatch::class);
$configuration->addCustomStringFunction('ST_REMOVEIRRELEVANTPOINTSFORVIEW', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_RemoveIrrelevantPointsForView::class);
$configuration->addCustomStringFunction('ST_REMOVESMALLPARTS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_RemoveSmallParts::class);
$configuration->addCustomStringFunction('ST_REVERSE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Reverse::class);
$configuration->addCustomStringFunction('ST_ROTATE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Rotate::class);
$configuration->addCustomStringFunction('ST_SCALE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Scale::class);
$configuration->addCustomStringFunction('ST_SEGMENTIZE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Segmentize::class);
$configuration->addCustomStringFunction('ST_SETSRID', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_SetSRID::class);
$configuration->addCustomStringFunction('ST_SHORTESTLINE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_ShortestLine::class);
$configuration->addCustomStringFunction('ST_SIMPLIFY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Simplify::class);
$configuration->addCustomStringFunction('ST_SIMPLIFYPOLYGONHULL', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_SimplifyPolygonHull::class);
$configuration->addCustomStringFunction('ST_SIMPLIFYPRESERVETOPOLOGY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_SimplifyPreserveTopology::class);
$configuration->addCustomStringFunction('ST_SIMPLIFYVW', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_SimplifyVW::class);
$configuration->addCustomStringFunction('ST_SNAP', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Snap::class);
$configuration->addCustomStringFunction('ST_SPLIT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Split::class);
$configuration->addCustomStringFunction('ST_SRID', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_SRID::class);
$configuration->addCustomStringFunction('ST_STARTPOINT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_StartPoint::class);
$configuration->addCustomStringFunction('ST_SUBDIVIDE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Subdivide::class);
$configuration->addCustomStringFunction('ST_SYMDIFFERENCE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_SymDifference::class);
$configuration->addCustomStringFunction('ST_TILEENVELOPE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_TileEnvelope::class);
$configuration->addCustomStringFunction('ST_TOUCHES', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Touches::class);
$configuration->addCustomStringFunction('ST_TRANSFORM', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Transform::class);
$configuration->addCustomStringFunction('ST_TRANSLATE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Translate::class);
$configuration->addCustomStringFunction('ST_TRIANGULATEPOLYGON', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_TriangulatePolygon::class);
$configuration->addCustomStringFunction('ST_UNARYUNION', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_UnaryUnion::class);
$configuration->addCustomStringFunction('ST_UNION', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Union::class);
$configuration->addCustomStringFunction('ST_VORONOIPOLYGONS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_VoronoiPolygons::class);
$configuration->addCustomStringFunction('ST_WITHIN', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Within::class);
$configuration->addCustomStringFunction('ST_X', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_X::class);
$configuration->addCustomStringFunction('ST_Y', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Y::class);
$configuration->addCustomStringFunction('ST_Z', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\ST_Z::class);

# PostGIS operators
$configuration->addCustomStringFunction('BOUNDING_BOX_DISTANCE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\BoundingBoxDistance::class); # <#>
$configuration->addCustomStringFunction('GEOMETRY_DISTANCE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\GeometryDistance::class); # <->
$configuration->addCustomStringFunction('ND_CENTROID_DISTANCE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\NDimensionalCentroidDistance::class); # <<->>
$configuration->addCustomStringFunction('ND_OVERLAPS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\NDimensionalOverlaps::class); # &&&
$configuration->addCustomStringFunction('OVERLAPS_ABOVE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\OverlapsAbove::class); # |&>
$configuration->addCustomStringFunction('OVERLAPS_BELOW', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\OverlapsBelow::class); # &<|
$configuration->addCustomStringFunction('OVERLAPS_LEFT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\OverlapsLeft::class); # &<
$configuration->addCustomStringFunction('OVERLAPS_RIGHT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\OverlapsRight::class); # &>
$configuration->addCustomStringFunction('SPATIAL_CONTAINED_BY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\SpatialContainedBy::class); # @
$configuration->addCustomStringFunction('SPATIAL_CONTAINS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\SpatialContains::class); # ~
$configuration->addCustomStringFunction('SPATIAL_SAME', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\SpatialSame::class); # ~=
$configuration->addCustomStringFunction('STRICTLY_ABOVE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\StrictlyAbove::class); # |>>
$configuration->addCustomStringFunction('STRICTLY_BELOW', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\StrictlyBelow::class); # <<|
$configuration->addCustomStringFunction('STRICTLY_LEFT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\StrictlyLeft::class); # <<
$configuration->addCustomStringFunction('STRICTLY_RIGHT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\StrictlyRight::class); # >>
$configuration->addCustomStringFunction('TRAJECTORY_DISTANCE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS\TrajectoryDistance::class); # |=|

# pg_trgm functions
$configuration->addCustomStringFunction('SIMILARITY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\Similarity::class);
$configuration->addCustomStringFunction('STRICT_WORD_SIMILARITY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\StrictWordSimilarity::class);
$configuration->addCustomStringFunction('WORD_SIMILARITY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\WordSimilarity::class);

# pg_trgm operators
$configuration->addCustomStringFunction('ARE_SIMILAR', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\AreSimilar::class); # %
$configuration->addCustomStringFunction('CONTAINS_STRICT_WORD_SIMILAR_TO', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\ContainsStrictWordSimilarTo::class); # %>>
$configuration->addCustomStringFunction('CONTAINS_WORD_SIMILAR_TO', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\ContainsWordSimilarTo::class); # %>
$configuration->addCustomStringFunction('IS_STRICT_WORD_SIMILAR_TO', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\IsStrictWordSimilarTo::class); # <<%
$configuration->addCustomStringFunction('IS_WORD_SIMILAR_TO', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\IsWordSimilarTo::class); # <%
$configuration->addCustomStringFunction('REVERSE_STRICT_WORD_SIMILARITY_DISTANCE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\ReverseStrictWordSimilarityDistance::class); # <->>>
$configuration->addCustomStringFunction('REVERSE_WORD_SIMILARITY_DISTANCE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\ReverseWordSimilarityDistance::class); # <->>
$configuration->addCustomStringFunction('SIMILARITY_DISTANCE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\SimilarityDistance::class); # <->
$configuration->addCustomStringFunction('STRICT_WORD_SIMILARITY_DISTANCE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\StrictWordSimilarityDistance::class); # <<<->
$configuration->addCustomStringFunction('WORD_SIMILARITY_DISTANCE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\WordSimilarityDistance::class); # <<->

# fuzzystrmatch functions
$configuration->addCustomStringFunction('DAITCH_MOKOTOFF', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Fuzzystrmatch\DaitchMokotoff::class);
$configuration->addCustomStringFunction('DIFFERENCE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Fuzzystrmatch\Difference::class);
$configuration->addCustomStringFunction('DMETAPHONE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Fuzzystrmatch\Dmetaphone::class);
$configuration->addCustomStringFunction('DMETAPHONE_ALT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Fuzzystrmatch\DmetaphoneAlt::class);
$configuration->addCustomStringFunction('LEVENSHTEIN', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Fuzzystrmatch\Levenshtein::class);
$configuration->addCustomStringFunction('LEVENSHTEIN_LESS_EQUAL', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Fuzzystrmatch\LevenshteinLessEqual::class);
$configuration->addCustomStringFunction('METAPHONE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Fuzzystrmatch\Metaphone::class);
$configuration->addCustomStringFunction('SOUNDEX', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Fuzzystrmatch\Soundex::class);

# network address functions
$configuration->addCustomStringFunction('ABBREV', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Network\Abbrev::class);
$configuration->addCustomStringFunction('BROADCAST', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Network\Broadcast::class);
$configuration->addCustomStringFunction('FAMILY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Network\Family::class);
$configuration->addCustomStringFunction('HOST', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Network\Host::class);
$configuration->addCustomStringFunction('HOSTMASK', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Network\Hostmask::class);
$configuration->addCustomStringFunction('INET_MERGE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Network\InetMerge::class);
$configuration->addCustomStringFunction('INET_SAME_FAMILY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Network\InetSameFamily::class);
$configuration->addCustomStringFunction('MASKLEN', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Network\Masklen::class);
$configuration->addCustomStringFunction('NETMASK', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Network\Netmask::class);
$configuration->addCustomStringFunction('NETWORK', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Network\Network::class);
$configuration->addCustomStringFunction('SET_MASKLEN', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Network\SetMasklen::class);

# aggregation functions
$configuration->addCustomStringFunction('ARRAY_AGG', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayAgg::class);
$configuration->addCustomStringFunction('BIT_AND', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BitAnd::class);
$configuration->addCustomStringFunction('BIT_OR', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BitOr::class);
$configuration->addCustomStringFunction('BIT_XOR', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BitXor::class);
$configuration->addCustomStringFunction('BOOL_AND', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BoolAnd::class);
$configuration->addCustomStringFunction('BOOL_OR', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BoolOr::class);
$configuration->addCustomStringFunction('CORR', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Corr::class);
$configuration->addCustomStringFunction('COVAR_POP', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\CovarPop::class);
$configuration->addCustomStringFunction('COVAR_SAMP', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\CovarSamp::class);
$configuration->addCustomStringFunction('EVERY', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Every::class);
$configuration->addCustomStringFunction('FILTER', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Filter::class);
$configuration->addCustomStringFunction('JSON_AGG', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonAgg::class);
$configuration->addCustomStringFunction('JSON_OBJECT_AGG', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonObjectAgg::class);
$configuration->addCustomStringFunction('JSONB_AGG', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbAgg::class);
$configuration->addCustomStringFunction('JSONB_OBJECT_AGG', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbObjectAgg::class);
$configuration->addCustomStringFunction('MODE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Mode::class);
$configuration->addCustomStringFunction('PERCENTILE_CONT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PercentileCont::class);
$configuration->addCustomStringFunction('PERCENTILE_DISC', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PercentileDisc::class);
$configuration->addCustomStringFunction('RANGE_AGG', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RangeAgg::class);
$configuration->addCustomStringFunction('RANGE_INTERSECT_AGG', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RangeIntersectAgg::class);
$configuration->addCustomStringFunction('STDDEV', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Stddev::class);
$configuration->addCustomStringFunction('STDDEV_POP', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\StddevPop::class);
$configuration->addCustomStringFunction('STRING_AGG', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\StringAgg::class);
$configuration->addCustomStringFunction('VAR_POP', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\VarPop::class);
$configuration->addCustomStringFunction('VARIANCE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Variance::class);

# Window functions
$configuration->addCustomStringFunction('CUME_DIST', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\CumeDist::class);
$configuration->addCustomStringFunction('DENSE_RANK', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DenseRank::class);
$configuration->addCustomStringFunction('FIRST_VALUE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\FirstValue::class);
$configuration->addCustomStringFunction('LAG', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Lag::class);
$configuration->addCustomStringFunction('LAST_VALUE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\LastValue::class);
$configuration->addCustomStringFunction('LEAD', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Lead::class);
$configuration->addCustomStringFunction('NTH_VALUE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\NthValue::class);
$configuration->addCustomStringFunction('NTILE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ntile::class);
$configuration->addCustomStringFunction('OVER', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Over::class);
$configuration->addCustomStringFunction('PERCENT_RANK', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PercentRank::class);
$configuration->addCustomStringFunction('RANK', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Rank::class);
$configuration->addCustomStringFunction('ROW_NUMBER', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RowNumber::class);

# XML functions
$configuration->addCustomStringFunction('XML_IS_WELL_FORMED', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\XmlIsWellFormed::class);
$configuration->addCustomStringFunction('XML_IS_WELL_FORMED_CONTENT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\XmlIsWellFormedContent::class);
$configuration->addCustomStringFunction('XML_IS_WELL_FORMED_DOCUMENT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\XmlIsWellFormedDocument::class);
$configuration->addCustomStringFunction('XMLAGG', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\XmlAgg::class);
$configuration->addCustomStringFunction('XMLCOMMENT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\XmlComment::class);
$configuration->addCustomStringFunction('XMLCONCAT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\XmlConcat::class);
$configuration->addCustomStringFunction('XMLEXISTS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\XmlExists::class);
$configuration->addCustomStringFunction('XMLPI', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\XmlPi::class);
$configuration->addCustomStringFunction('XMLTEXT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\XmlText::class);
$configuration->addCustomStringFunction('XPATH', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Xpath::class);
$configuration->addCustomStringFunction('XPATH_EXISTS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\XpathExists::class);

# hashing and checksum functions
$configuration->addCustomStringFunction('CRC32', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Crc32::class);
$configuration->addCustomStringFunction('CRC32C', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Crc32c::class);
$configuration->addCustomStringFunction('MD5', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Md5::class);
$configuration->addCustomStringFunction('REVERSE_BYTES', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ReverseBytes::class);
$configuration->addCustomStringFunction('SHA224', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Sha224::class);
$configuration->addCustomStringFunction('SHA256', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Sha256::class);
$configuration->addCustomStringFunction('SHA384', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Sha384::class);
$configuration->addCustomStringFunction('SHA512', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Sha512::class);

# uuid functions
$configuration->addCustomStringFunction('GEN_RANDOM_UUID', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\GenRandomUuid::class);
$configuration->addCustomStringFunction('UUID_EXTRACT_TIMESTAMP', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\UuidExtractTimestamp::class);
$configuration->addCustomStringFunction('UUID_EXTRACT_VERSION', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\UuidExtractVersion::class);
$configuration->addCustomStringFunction('UUIDV4', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Uuidv4::class);
$configuration->addCustomStringFunction('UUIDV7', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Uuidv7::class);

# type conversion and formatting functions
$configuration->addCustomStringFunction('CAST', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Cast::class);
$configuration->addCustomStringFunction('TO_CHAR', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToChar::class);
$configuration->addCustomStringFunction('TO_DATE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToDate::class);
$configuration->addCustomStringFunction('TO_NUMBER', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToNumber::class);
$configuration->addCustomStringFunction('TO_TIMESTAMP', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToTimestamp::class);

$connection = DriverManager::getConnection([
    'driver' => 'pdo_pgsql',
    // ... your connection parameters
], $configuration);

$em = new EntityManager($connection, $configuration);

Register Platform Type Mappings

Register type mappings between PostgreSQL and Doctrine types. This is required for schema introspection and migrations. Based on the Doctrine documentation.

<?php

$platform = $em->getConnection()->getDatabasePlatform();

// Bit type mappings
$platform->registerDoctrineTypeMapping('bit', 'bit');
$platform->registerDoctrineTypeMapping('bit[]', 'bit[]');
$platform->registerDoctrineTypeMapping('_bit', 'bit[]');
$platform->registerDoctrineTypeMapping('bit varying', 'bit varying');
$platform->registerDoctrineTypeMapping('varbit', 'bit varying');
$platform->registerDoctrineTypeMapping('bit varying[]', 'bit varying[]');
$platform->registerDoctrineTypeMapping('_varbit', 'bit varying[]');

// Array type mappings
$platform->registerDoctrineTypeMapping('bool[]', 'bool[]');
$platform->registerDoctrineTypeMapping('_bool', 'bool[]');
$platform->registerDoctrineTypeMapping('smallint[]', 'smallint[]');
$platform->registerDoctrineTypeMapping('_int2', 'smallint[]');
$platform->registerDoctrineTypeMapping('integer[]', 'integer[]');
$platform->registerDoctrineTypeMapping('_int4', 'integer[]');
$platform->registerDoctrineTypeMapping('bigint[]', 'bigint[]');
$platform->registerDoctrineTypeMapping('_int8', 'bigint[]');
$platform->registerDoctrineTypeMapping('double precision[]', 'double precision[]');
$platform->registerDoctrineTypeMapping('_float8', 'double precision[]');
$platform->registerDoctrineTypeMapping('numeric[]', 'numeric[]');
$platform->registerDoctrineTypeMapping('_numeric', 'numeric[]');
$platform->registerDoctrineTypeMapping('real[]', 'real[]');
$platform->registerDoctrineTypeMapping('_float4', 'real[]');
$platform->registerDoctrineTypeMapping('text[]', 'text[]');
$platform->registerDoctrineTypeMapping('_text', 'text[]');
$platform->registerDoctrineTypeMapping('uuid[]', 'uuid[]');
$platform->registerDoctrineTypeMapping('_uuid', 'uuid[]');
$platform->registerDoctrineTypeMapping('varchar[]', 'varchar[]');
$platform->registerDoctrineTypeMapping('_varchar', 'varchar[]');

// Case-insensitive text type mappings
$platform->registerDoctrineTypeMapping('citext', 'citext');
$platform->registerDoctrineTypeMapping('citext[]', 'citext[]');
$platform->registerDoctrineTypeMapping('_citext', 'citext[]');

// ULID type mappings
$platform->registerDoctrineTypeMapping('ulid', 'ulid');
$platform->registerDoctrineTypeMapping('ulid[]', 'ulid[]');
$platform->registerDoctrineTypeMapping('_ulid', 'ulid[]');

// Datetime array type mappings
$platform->registerDoctrineTypeMapping('date[]', 'date[]');
$platform->registerDoctrineTypeMapping('_date', 'date[]');
$platform->registerDoctrineTypeMapping('interval', 'interval');
$platform->registerDoctrineTypeMapping('interval[]', 'interval[]');
$platform->registerDoctrineTypeMapping('_interval', 'interval[]');
$platform->registerDoctrineTypeMapping('time[]', 'time[]');
$platform->registerDoctrineTypeMapping('_time', 'time[]');
$platform->registerDoctrineTypeMapping('timestamp[]', 'timestamp[]');
$platform->registerDoctrineTypeMapping('_timestamp', 'timestamp[]');
$platform->registerDoctrineTypeMapping('timestamptz[]', 'timestamptz[]');
$platform->registerDoctrineTypeMapping('_timestamptz', 'timestamptz[]');
$platform->registerDoctrineTypeMapping('timetz', 'timetz');
$platform->registerDoctrineTypeMapping('timetz[]', 'timetz[]');
$platform->registerDoctrineTypeMapping('_timetz', 'timetz[]');

// JSON type mappings
$platform->registerDoctrineTypeMapping('json[]', 'json[]');
$platform->registerDoctrineTypeMapping('_json', 'json[]');
$platform->registerDoctrineTypeMapping('jsonb', 'jsonb');
$platform->registerDoctrineTypeMapping('jsonb[]', 'jsonb[]');
$platform->registerDoctrineTypeMapping('_jsonb', 'jsonb[]');

// Network type mappings
$platform->registerDoctrineTypeMapping('cidr', 'cidr');
$platform->registerDoctrineTypeMapping('cidr[]', 'cidr[]');
$platform->registerDoctrineTypeMapping('_cidr', 'cidr[]');
$platform->registerDoctrineTypeMapping('inet', 'inet');
$platform->registerDoctrineTypeMapping('inet[]', 'inet[]');
$platform->registerDoctrineTypeMapping('_inet', 'inet[]');
$platform->registerDoctrineTypeMapping('macaddr', 'macaddr');
$platform->registerDoctrineTypeMapping('macaddr[]', 'macaddr[]');
$platform->registerDoctrineTypeMapping('_macaddr', 'macaddr[]');
$platform->registerDoctrineTypeMapping('macaddr8', 'macaddr8');
$platform->registerDoctrineTypeMapping('macaddr8[]', 'macaddr8[]');
$platform->registerDoctrineTypeMapping('_macaddr8', 'macaddr8[]');

// Geometric type mappings
$platform->registerDoctrineTypeMapping('box', 'box');
$platform->registerDoctrineTypeMapping('box[]', 'box[]');
$platform->registerDoctrineTypeMapping('_box', 'box[]');
$platform->registerDoctrineTypeMapping('circle', 'circle');
$platform->registerDoctrineTypeMapping('circle[]', 'circle[]');
$platform->registerDoctrineTypeMapping('_circle', 'circle[]');
$platform->registerDoctrineTypeMapping('line', 'line');
$platform->registerDoctrineTypeMapping('line[]', 'line[]');
$platform->registerDoctrineTypeMapping('_line', 'line[]');
$platform->registerDoctrineTypeMapping('lseg', 'lseg');
$platform->registerDoctrineTypeMapping('lseg[]', 'lseg[]');
$platform->registerDoctrineTypeMapping('_lseg', 'lseg[]');
$platform->registerDoctrineTypeMapping('path', 'path');
$platform->registerDoctrineTypeMapping('path[]', 'path[]');
$platform->registerDoctrineTypeMapping('_path', 'path[]');
$platform->registerDoctrineTypeMapping('point', 'point');
$platform->registerDoctrineTypeMapping('point[]', 'point[]');
$platform->registerDoctrineTypeMapping('_point', 'point[]');
$platform->registerDoctrineTypeMapping('polygon', 'polygon');
$platform->registerDoctrineTypeMapping('polygon[]', 'polygon[]');
$platform->registerDoctrineTypeMapping('_polygon', 'polygon[]');

// Cube type mappings
$platform->registerDoctrineTypeMapping('cube', 'cube');
$platform->registerDoctrineTypeMapping('cube[]', 'cube[]');
$platform->registerDoctrineTypeMapping('_cube', 'cube[]');

// PostGIS spatial type mappings
$platform->registerDoctrineTypeMapping('geometry', 'geometry');
$platform->registerDoctrineTypeMapping('geometry[]', 'geometry[]');
$platform->registerDoctrineTypeMapping('_geometry', 'geometry[]');
$platform->registerDoctrineTypeMapping('geography', 'geography');
$platform->registerDoctrineTypeMapping('geography[]', 'geography[]');
$platform->registerDoctrineTypeMapping('_geography', 'geography[]');

// Range type mappings
$platform->registerDoctrineTypeMapping('daterange', 'daterange');
$platform->registerDoctrineTypeMapping('daterange[]', 'daterange[]');
$platform->registerDoctrineTypeMapping('_daterange', 'daterange[]');
$platform->registerDoctrineTypeMapping('int4range', 'int4range');
$platform->registerDoctrineTypeMapping('int4range[]', 'int4range[]');
$platform->registerDoctrineTypeMapping('_int4range', 'int4range[]');
$platform->registerDoctrineTypeMapping('int8range', 'int8range');
$platform->registerDoctrineTypeMapping('int8range[]', 'int8range[]');
$platform->registerDoctrineTypeMapping('_int8range', 'int8range[]');
$platform->registerDoctrineTypeMapping('numrange', 'numrange');
$platform->registerDoctrineTypeMapping('numrange[]', 'numrange[]');
$platform->registerDoctrineTypeMapping('_numrange', 'numrange[]');
$platform->registerDoctrineTypeMapping('tsrange', 'tsrange');
$platform->registerDoctrineTypeMapping('tsrange[]', 'tsrange[]');
$platform->registerDoctrineTypeMapping('_tsrange', 'tsrange[]');
$platform->registerDoctrineTypeMapping('tstzrange', 'tstzrange');
$platform->registerDoctrineTypeMapping('tstzrange[]', 'tstzrange[]');
$platform->registerDoctrineTypeMapping('_tstzrange', 'tstzrange[]');

// Multirange type mappings
$platform->registerDoctrineTypeMapping('datemultirange', 'datemultirange');
$platform->registerDoctrineTypeMapping('_datemultirange', 'datemultirange[]');
$platform->registerDoctrineTypeMapping('datemultirange[]', 'datemultirange[]');
$platform->registerDoctrineTypeMapping('int4multirange', 'int4multirange');
$platform->registerDoctrineTypeMapping('int4multirange[]', 'int4multirange[]');
$platform->registerDoctrineTypeMapping('_int4multirange', 'int4multirange[]');
$platform->registerDoctrineTypeMapping('int8multirange', 'int8multirange');
$platform->registerDoctrineTypeMapping('int8multirange[]', 'int8multirange[]');
$platform->registerDoctrineTypeMapping('_int8multirange', 'int8multirange[]');
$platform->registerDoctrineTypeMapping('nummultirange', 'nummultirange');
$platform->registerDoctrineTypeMapping('nummultirange[]', 'nummultirange[]');
$platform->registerDoctrineTypeMapping('_nummultirange', 'nummultirange[]');
$platform->registerDoctrineTypeMapping('tsmultirange', 'tsmultirange');
$platform->registerDoctrineTypeMapping('tsmultirange[]', 'tsmultirange[]');
$platform->registerDoctrineTypeMapping('_tsmultirange', 'tsmultirange[]');
$platform->registerDoctrineTypeMapping('tstzmultirange', 'tstzmultirange');
$platform->registerDoctrineTypeMapping('tstzmultirange[]', 'tstzmultirange[]');
$platform->registerDoctrineTypeMapping('_tstzmultirange', 'tstzmultirange[]');

// Text search type mappings
$platform->registerDoctrineTypeMapping('tsquery', 'tsquery');
$platform->registerDoctrineTypeMapping('tsquery[]', 'tsquery[]');
$platform->registerDoctrineTypeMapping('_tsquery', 'tsquery[]');
$platform->registerDoctrineTypeMapping('tsvector', 'tsvector');
$platform->registerDoctrineTypeMapping('tsvector[]', 'tsvector[]');
$platform->registerDoctrineTypeMapping('_tsvector', 'tsvector[]');

// Monetary type mappings
$platform->registerDoctrineTypeMapping('money', 'money');
$platform->registerDoctrineTypeMapping('money[]', 'money[]');
$platform->registerDoctrineTypeMapping('_money', 'money[]');

// Key-value type mappings
$platform->registerDoctrineTypeMapping('hstore', 'hstore');
$platform->registerDoctrineTypeMapping('hstore[]', 'hstore[]');
$platform->registerDoctrineTypeMapping('_hstore', 'hstore[]');

// Hierarchical mappings
$platform->registerDoctrineTypeMapping('lquery', 'lquery');
$platform->registerDoctrineTypeMapping('lquery[]', 'lquery[]');
$platform->registerDoctrineTypeMapping('_lquery', 'lquery[]');
$platform->registerDoctrineTypeMapping('ltree','ltree');
$platform->registerDoctrineTypeMapping('ltree[]', 'ltree[]');
$platform->registerDoctrineTypeMapping('_ltree', 'ltree[]');
$platform->registerDoctrineTypeMapping('ltxtquery', 'ltxtquery');
$platform->registerDoctrineTypeMapping('ltxtquery[]', 'ltxtquery[]');
$platform->registerDoctrineTypeMapping('_ltxtquery', 'ltxtquery[]');

// XML mappings
$platform->registerDoctrineTypeMapping('xml', 'xml');
$platform->registerDoctrineTypeMapping('xml[]', 'xml[]');
$platform->registerDoctrineTypeMapping('_xml', 'xml[]');

// Vector mappings
$platform->registerDoctrineTypeMapping('halfvec', 'halfvec');
$platform->registerDoctrineTypeMapping('sparsevec', 'sparsevec');
$platform->registerDoctrineTypeMapping('vector', 'vector');

Mapping User-Defined PostgreSQL Enum Types

For each PostgreSQL native ENUM type, create a concrete class extending MartinGeorgiev\Doctrine\DBAL\Types\Enum and register it like the examples above. Columns holding an array of that enum get a second concrete class extending MartinGeorgiev\Doctrine\DBAL\Types\EnumArray. See ENUM-TYPE.md for a full example.

<?php

use Doctrine\DBAL\Types\Type as DoctrineType;
use MartinGeorgiev\Doctrine\DBAL\Types\Enum;
use MartinGeorgiev\Doctrine\DBAL\Types\EnumArray;

enum Status: string
{
    case ACTIVE = 'active';
    case INACTIVE = 'inactive';
}

final class StatusType extends Enum
{
    protected const TYPE_NAME = 'status'; // must match PostgreSQL enum type name exactly

    protected function getEnumClass(): string
    {
        return Status::class;
    }
}

final class StatusArrayType extends EnumArray
{
    protected const TYPE_NAME = 'status[]'; // the PostgreSQL enum type name followed by []

    protected function getEnumClass(): string
    {
        return Status::class;
    }
}

// Register like any other type
DoctrineType::addType('status', StatusType::class);
DoctrineType::addType('status[]', StatusArrayType::class);
$platform->registerDoctrineTypeMapping('status', 'status');
$platform->registerDoctrineTypeMapping('status[]', 'status[]');
$platform->registerDoctrineTypeMapping('_status', 'status[]');

Mapping User-Defined PostgreSQL Composite Types

For each PostgreSQL composite (row) type, create a concrete class extending MartinGeorgiev\Doctrine\DBAL\Types\Composite and register it like the examples above. See COMPOSITE-TYPE.md for a full example.

<?php

use Doctrine\DBAL\Types\Type as DoctrineType;
use Doctrine\DBAL\Types\Types;
use MartinGeorgiev\Doctrine\DBAL\Types\Composite;

// CREATE TYPE inventory_item AS (name text, supplier_id integer, price numeric);

final class InventoryItemType extends Composite
{
    protected const TYPE_NAME = 'inventory_item'; // must match PostgreSQL composite type name exactly

    protected function getFieldTypes(): array
    {
        // Field order must match the CREATE TYPE declaration - record literals are positional
        return [
            'name' => Types::TEXT,
            'supplier_id' => Types::INTEGER,
            'price' => Types::DECIMAL,
        ];
    }
}

// Register like any other type
DoctrineType::addType('inventory_item', InventoryItemType::class);
$platform->registerDoctrineTypeMapping('inventory_item', 'inventory_item');

For a composite[] column, extend CompositeArray and point it at the scalar type’s class:

use MartinGeorgiev\Doctrine\DBAL\Types\CompositeArray;

final class InventoryItemArrayType extends CompositeArray
{
    protected const TYPE_NAME = 'inventory_item[]';

    protected function getCompositeClass(): string
    {
        return InventoryItemType::class;
    }
}

DoctrineType::addType('inventory_item[]', InventoryItemArrayType::class);
$platform->registerDoctrineTypeMapping('inventory_item[]', 'inventory_item[]');
$platform->registerDoctrineTypeMapping('_inventory_item', 'inventory_item[]');

Usage in Entities

Once types are registered, you can use them in your Doctrine entities:

<?php

use Doctrine\ORM\Mapping as ORM;
use MartinGeorgiev\Doctrine\DBAL\Types\ValueObject\DateRange;
use MartinGeorgiev\Doctrine\DBAL\Types\ValueObject\Interval;
use MartinGeorgiev\Doctrine\DBAL\Types\ValueObject\Ltree;
use MartinGeorgiev\Doctrine\DBAL\Types\ValueObject\NumericRange;
use MartinGeorgiev\Doctrine\DBAL\Types\ValueObject\Point;
use MartinGeorgiev\Doctrine\DBAL\Types\ValueObject\WktSpatialData;

#[ORM\Entity]
class MyEntity
{
    #[ORM\Column(type: 'jsonb')]
    private array $metadata = [];

    #[ORM\Column(type: 'text[]')]
    private array $tags = [];

    #[ORM\Column(type: 'point')]
    private Point $location;

    #[ORM\Column(type: 'geometry')]
    private WktSpatialData $shape;

    #[ORM\Column(type: 'numrange')]
    private NumericRange $priceRange;

    #[ORM\Column(type: 'daterange')]
    private DateRange $validPeriod;

    #[ORM\Column(type: 'inet')]
    private string $ipAddress;

    #[ORM\Column(type: 'interval')]
    private Interval $duration;

    #[ORM\Column(type: 'money')]
    private string $price;

    #[ORM\Column(type: 'ltree')]
    private Ltree $pathFromRoot;

    #[ORM\Column(type: 'xml')]
    private string $configXml;
}