# Yii Database Change Log

## 2.0.1 February 09, 2026

- Enh #1145, #1148: Explicitly import classes, functions, and constants in "use" section (@mspirkov)
- Enh #1148: Add `declare(strict_types=1)` to `Yiisoft\Db\Constant\ColumnInfoSource` (@mspirkov)
- Enh #1156: Remove unnecessary files from Composer package (@mspirkov)
- Enh #1158: Explicitly mark readonly properties (@vjik)
- Enh #1159: Improve performance of `AbstractSqlParser` class methods (@Tigrov)
- Bug #1127: Fix `AbstractSchema::hasTable()` and `AbstractSchema::hasView()` methods to support names quoted with curly
  brackets `{{%table}}` (@batyrmastyr)

## 2.0.0 December 05, 2025

- New #1013: Add `StringableStream` class to cast binary column values to `string` using `(string) $value` (@Tigrov)
- New #1015: Add mode parameter to `Like` condition (@vjik)
- New #1020: Support column's collation (@Tigrov)
- New #1024: Add `ColumnName` and `Value` expressions (@vjik)
- New #1029, #1048, #1069: Add functions as expressions (@Tigrov)
- New #1033: Add `All` and `None` conditions (@vjik)
- New #1034: Add `ConnectionInterface::getColumnBuilderClass()` method (@Tigrov)
- New #1040, #1043: Add `DateTimeValue` class (@vjik, @Tigrov)
- New #1057: Add `CompositeExpression` class (@vjik)
- New #1062: `Stringable` value support in `Like` and `NotLike` conditions (@vjik)
- New #1063: Add `indexBy()` method to `BatchQueryResultInterface` and `BatchQueryResult` class (@vjik)
- New #1074: Add `ConnectionProvider` class (@Tigrov)
- New #1076: Allow to use expressions as table name or condition in "join" query methods (@vjik)
- New #1082: Add `WithQuery` class that holds the information for a single "WITH" query clause (@vjik)
- New #1082: Add `QueryPartsInterface::addWithQuery()` method (@vjik)
- New #1107: Add abstract enumeration column type (@vjik)
- New #1121: Add `yiisoft/db.schema-cache.enabled` parameter to disable schema caching via configuration (@samdark)
- New #1124: Add source of column information (@Tigrov)
- New #752, #974, #1013: Implement `ColumnInterface` classes according to the data type of database table columns
  for type casting performance (@Tigrov)
- New #773: Add parameters `$ifExists` and `$cascade` to `CommandInterface::dropTable()` and
 `DDLQueryBuilderInterface::dropTable()` methods (@vjik)
- New #855: Add array and JSON overlaps conditions (@Tigrov)
- New #860: Add `bit` abstract type (@Tigrov)
- New #864, #897, #898, #950, #1009, #1125: Realize column factory (@Tigrov, @vjik)
- New #878, #1095: Realize `ColumnBuilder` class (@Tigrov, @vjik)
- New #878, #900, #914, #922: Implement `ColumnDefinitionParser` class (@Tigrov)
- New #882: Move `ArrayColumnSchema` and `StructuredColumnSchema` classes from `db-pgsql` package (@Tigrov)
- New #883, #901, #922: Add `ColumnDefinitionBuilder` class and `QueryBuilderInterface::buildColumnDefinition()` method (@Tigrov)
- New #899: Add `ColumnSchemaInterface::hasDefaultValue()` and `ColumnSchemaInterface::null()` methods (@Tigrov)
- New #902, #982, #983, #995: Add `prepareParam()` and `prepareValue()` methods in `QueryBuilderInterface` (@Tigrov)
- New #906: Add `ServerInfoInterface` and its implementation (@Tigrov)
- New #913: Add methods `SchemaInterface::hasSchema()`, `SchemaInterface::hasTable()`, `SchemaInterface::hasView()` (@evil1)
- New #928: Add `ReferentialAction` class with constants of possible values of referential actions (@Tigrov)
- New #939: Add `caseSensitive` option to like condition (@vjik)
- New #942: Allow PHP backed enums as values (@Tigrov)
- New #945: Add option for typecasting values retrieved from DB (@Tigrov)
- New #949: Add option for typecasting when insert or update values (@Tigrov)
- New #954: Add `DbArrayHelper::arrange()` method (@Tigrov)
- New #964: Add `QueryBuilderInterface::replacePlaceholders()` method (@Tigrov)
- New #967, #1059: Add `FOR` clause to query (@vjik)
- New #968: Add `DateTimeColumn` column class (@Tigrov)
- New #973, #976, #1081: Add `CommandInterface::upsertReturningPks()` method (@Tigrov, @vjik)
- New #973, #976, #1081: Add `upsertReturning()` method to `CommandInterface` and `DMLQueryBuilderInterface` (@Tigrov, @vjik)
- New #984: Add `createQuery()` and `select()` methods to `ConnectionInterface` (@Tigrov)
- New #988, #1053, #1067: Add `CaseX` and `CaseXBuilder` to build `CASE-WHEN-THEN-ELSE` SQL expressions (@Tigrov)
- Chg #1000, #1007, #1027: Add compare conditions: `Equals`, `NotEquals`, `GreaterThan`, `GreaterThanOrEqual`,
  `LessThan` and `LessThanOrEqual`. Remove `Hash` condition in favor `Equals` and `In` usage (@vjik)
- Chg #1001: Remove `ParamInterface` (@vjik)
- Chg #1001: Add public properties `$type` and `$value` to `Param` class instead of `getType()` and `getValue()` methods that were removed (@vjik)
- Chg #1002: Remove specific condition interfaces (@vjik)
- Chg #1003, #1006: Refactor namespace of condition objects and use promoted properties instead of getters (@vjik)
- Chg #1014: Replace `getEscapingReplacements()`/`setEscapingReplacements()` methods with `escape` constructor parameter 
  in `Like` condition (@vjik)
- Chg #1017: Split `Between` condition to `Between` and `NotBetween` (@vjik)
- Chg #1018, #1024: Remove `BetweenColumns` in favor `Between` with `ColumnName` usage (@vjik)
- Chg #1019: Split `In` condition to `In` and `NotIn` (@vjik)
- Chg #1021: Move conjunction type from operator string value to `Like` condition constructor parameter (@vjik)
- Chg #1023: Split `Like` condition to `Like` and `NotLike` (@vjik)
- Chg #1025: Move expression builders to `Yiisoft\Db\Expression\Builder` namespace (@vjik)
- Chg #1026: Remove `precision()`, `getPrecision()` and `getPhpType()` methods from `ColumnInterface` (@vjik)
- Chg #1028: Split `Exists` condition to `Exists` and `NotExists` (@vjik)
- Chg #1037: Change result type of `QueryBuilderInterface::getExpressionBuilder()` and
  `DQLQueryBuilderInterface::getExpressionBuilder()` methods to `ExpressionBuilderInterface` (@vjik)
- Chg #1052: Rearrange expression namespaces (@Tigrov)
- Chg #1054: Rename `ArrayExpression` to `ArrayValue`, `JsonExpression` to `JsonValue`,
  `StructuredExpression` to `StructuredValue` (@Tigrov)
- Chg #1056: Remove unused exceptions (@Tigrov)
- Chg #1058: Refactor `Expression` class: declare `$expression` and `$params` as public readonly properties, remove 
  `getParams()` method (@vjik)
- Chg #1063: `AbstractConnection::createBatchQueryResult()` passes parameters `indexBy` and `resultCallback` to
  `BatchQueryResult` being created (@vjik)
- Chg #1070: Change "IndexBy" closure signature to `Closure(array|object):int|string` (@vjik)
- Chg #1075: Rename `Query::$join` property to `$joins` (@vjik)
- Chg #1078: Change type of `$tables` to `array` in `DQLQueryBuilderInterface::buildFrom()` (@vjik)
- Chg #1082: `QueryPartsInterface::withQuery()` method replace "WITH" clause instead of adding before (@vjik)
- Chg #1083: Add `pdoStatementExecute()` protected method to `AbstractPdoCommand` class and cleanup `internalExecute()`
  method (@vjik)
- Chg #1091: Remove `SchemaInterface::findUniqueIndexes()` method (@vjik)
- Chg #1091: Remove `SchemaInterface::INDEX_*` and `SchemaInterface::TYPE_*` constants (@vjik)
- Chg #1103: Remove `AbstractCommand::refreshTableSchema()` method (@vjik)
- Chg #1106: Remove parameters from `PdoConnectionInterface::getActivePdo()` method (@vjik)
- Chg #836: Remove `AbstractDMLQueryBuilder::getTypecastValue()` method (@Tigrov)
- Chg #837: Remove `$table` parameter from `normalizeColumnNames()` and `getNormalizeColumnNames()` methods 
  of `AbstractDMLQueryBuilder` class (@Tigrov)
- Chg #838: Remove `SchemaInterface::TYPE_JSONB` constant (@Tigrov)
- Chg #839: Remove `TableSchemaInterface::compositeForeignKey()` method (@Tigrov)
- Chg #840: Remove parameter `$withColumn` from `QuoterInterface::getTableNameParts()` method (@Tigrov)
- Chg #841: Remove `$rawSql` parameter from `AbstractCommand::internalExecute()` method
  and `AbstractPdoCommand::internalExecute()` method (@Tigrov)
- Chg #845: Remove `AbstractSchema::normalizeRowKeyCase()` method (@Tigrov)
- Chg #846: Remove `SchemaInterface::isReadQuery()` and `AbstractSchema::isReadQuery()` methods (@Tigrov)
- Chg #847: Remove `SchemaInterface::getRawTableName()` and `AbstractSchema::getRawTableName()` methods (@Tigrov)
- Chg #889: Update `AbstractDMLQueryBuilder::insertBatch()` method (@Tigrov)
- Chg #911, #1113: Change supported PHP versions to `8.1 - 8.5` (@Tigrov, @vjik)
- Chg #936: Remove `hasLimit()` and `hasOffset()` methods from `AbstractDQLQueryBuilder` class (@Tigrov)
- Chg #937: Remove `baseName()` and `pascalCaseToId()` methods from `DbStringHelper` (@Tigrov)
- Chg #938, #936, #937: Remove `ext-json`, `ext-ctype`, `ext-mbstring` from `require` section of `composer.json` (@Tigrov)
- Chg #956: Remove nullable from `PdoConnectionInterface::getActivePdo()` result (@vjik)
- Chg #972: Change in query "distinct" flag type from `bool|null` to `bool` (@vjik)
- Chg #980: Add constructor with DB connection to `AbstractCommand` (@vjik)
- Chg #985: Rename `insertWithReturningPks()` to `insertReturningPks()` in `CommandInterface` and `DMLQueryBuilderInterface` (@Tigrov)
- Chg #990: Delete `Yiisoft\Db\Exception\InvalidArgumentException` and `Yiisoft\Db\Exception\InvalidParamException` and
  use `\InvalidArgumentException` instead (@DikoIbragimov)
- Chg #998: Add `yiisoft/db-implementation` virtual package as dependency (@vjik)
- Chg #999: Remove `requireTransaction()` method and `$isolationLevel` property from `AbstractCommand` (@vjik)
- Enh #1010: Improve `Quoter::getTableNameParts()` method (@Tigrov)
- Enh #1011: Refactor `TableSchemaInterface` and `AbstractSchema` (@Tigrov)
- Enh #1011: Remove `AbstractTableSchema` and add `TableSchema` instead (@Tigrov)
- Enh #1016: Refactor `AbstractDMLQueryBuilder::getTableUniqueColumnNames()` method (@Tigrov)
- Enh #1031: Optimize SQL generation for `Not` condition (@vjik)
- Enh #1038: Add ability to pass `FROM` clause to `CommandInterface::update()` and `DMLQueryBuilderInterface::update()` methods (@rustamwin)
- Enh #1038: Allow passing `ExpressionInterface` as condition in `CommandInterface::update()` and `DMLQueryBuilderInterface::update()` methods (@rustamwin)
- Enh #1042, #1084: Refactor `AbstractDMLQueryBuilder` class to `upsert()` method (@Tigrov)
- Enh #1045: Support multi-operand functions in `CommandInterface::upsert()` and `DMLQueryBuilderInterface::upsert()` 
  methods (@Tigrov)
- Enh #1049: Refactor `AbstractDQLQueryBuilder::buildSelect()` to fix possible bugs (@Tigrov)
- Enh #1051: Refactor `Quoter` class (@Tigrov)
- Enh #1064: Remove duplicate code in favor of the `DbArrayHelper::normalizeExpressions()` method (@rustamwin)
- Enh #1065: Allow to use table name as a column prefix in update queries (@Tigrov)
- Enh #1068: Quote string values as column names when join condition is an associative array (@Tigrov)
- Enh #1072, #1077, #1078, #1079, #1080, #1085, #1087, #1096: Improve psalm types (@vjik)
- Enh #1092: Change the exceptions thrown to be more appropriate (@Tigrov)
- Enh #730: Add `ExpressionBuilderInterface::build()` (@samdark)
- Enh #766: Allow `ColumnInterface` as column type. (@Tigrov)
- Enh #798: Allow `QueryInterface::one()` and `QueryInterface::all()` to return objects (@darkdef, @Tigrov)
- Enh #806, #964: Build `Expression` instances inside `Expression::$params` when build a query using `QueryBuilder` (@Tigrov)
- Enh #806: Non-unique placeholder names inside `Expression::$params` will be replaced with unique names (@Tigrov)
- Enh #815: Refactor `Query::column()` method (@Tigrov)
- Enh #816: Allow scalar values for `$columns` parameter of `Query::select()` and `Query::addSelect()` methods (@Tigrov)
- Enh #820: Support `Traversable` values for `AbstractDMLQueryBuilder::batchInsert()` method with empty columns (@Tigrov)
- Enh #822: Refactor data readers (@Tigrov)
- Enh #829: Rename `batchInsert()` to `insertBatch()` in `DMLQueryBuilderInterface` and `CommandInterface`
  and change parameters from `$table, $columns, $rows` to `$table, $rows, $columns = []` (@Tigrov)
- Enh #834: Refactor `AbstractCommand::insertBatch()`, add `Quoter::getRawTableName()` to `QuoterInterface` (@Tigrov)
- Enh #840: Remove `Quoter::unquoteParts()` method (@Tigrov)
- Enh #842: Allow `ExpressionInterface` for `$alias` parameter of `QueryPartsInterface::withQuery()` method (@Tigrov)
- Enh #843: Remove `AbstractPdoCommand::logQuery()` method (@Tigrov)
- Enh #852: Add method chaining for column classes (@Tigrov)
- Enh #862: Refactor PHP type of `ColumnSchemaInterface` instances (@Tigrov)
- Enh #865: Raise minimum PHP version to `^8.1` with minor refactoring (@Tigrov, @vjik)
- Enh #872: Use `#[\SensitiveParameter]` attribute to mark sensitive parameters (@heap-s)
- Enh #875: Ignore "Packets out of order..." warnings in `AbstractPdoCommand::internalExecute()` method (@Tigrov)
- Enh #877: Separate column type constants (@Tigrov)
- Enh #879: Rename `getLastInsertID()` method in `ConnectionInterface` to `getLastInsertId()` (@vjik)
- Enh #881: Refactor `ColumnSchemaInterface` and `AbstractColumnSchema` (@Tigrov)
- Enh #885, #1005: Refactor DSN classes (@Tigrov)
- Enh #890: Add properties of `AbstractColumnSchema` class to constructor (@Tigrov)
- Enh #902: Refactor `Quoter::quoteValue()` method (@Tigrov)
- Enh #905: Use `AbstractColumnDefinitionBuilder` to generate table column SQL representation (@Tigrov)
- Enh #911, #940, #1116: Minor refactoring (@Tigrov)
- Enh #915: Remove `ColumnInterface` (@Tigrov)
- Enh #917: Rename `ColumnSchemaInterface` to `ColumnInterface` (@Tigrov)
- Enh #919: Replace `name()` with immutable `withName()` method in `ColumnInterface` interface (@Tigrov)
- Enh #920: Move index constants to the appropriate DBMS driver's `IndexType` and `IndexMethod` classes (@Tigrov)
- Enh #921: Move `DataType` class to `Yiisoft\Db\Constant` namespace (@Tigrov)
- Enh #925, #951: Add callback to `Query::all()` and `Query::one()` methods (@Tigrov, @vjik)
- Enh #926, #954: Refactor `DbArrayHelper` (@Tigrov)
- Enh #929: Refactor array, structured and JSON column type expressions and expression builders (@Tigrov)
- Enh #929: Implement lazy arrays for array, structured and JSON column types (@Tigrov)
- Enh #940: Rename `quoter()` method to `getQuoter()` in `QueryBuilderInterface` and `AbstractQueryBuilder` class (@Tigrov)
- Enh #940: Change constructor parameters in `AbstractQueryBuilder` class (@Tigrov)
- Enh #941: Add the ability for user-defined type casting (@Tigrov)
- Enh #943: Add `getCacheKey()` and `getCacheTag()` methods to `AbstractPdoSchema` class (@Tigrov)
- Enh #944: Added `setWhere()` as a forced method to overwrite `where()` (@lav45)
- Enh #961: Added `setHaving()` as a forced method to overwrite `having()` (@lav45)
- Enh #963: Make `Query::andHaving()` similar to `Query::andWhere()` (@Tigrov)
- Enh #979: Allow `ExpressionInterface` for column definitions when create table (@Tigrov)
- Enh #981, #1004: Refactor constraints (@Tigrov)
- Enh #982, #995, #1044: Reduce binding parameters, add `QueryBuilderInterface::buildValue()` method (@Tigrov, @vjik)
- Enh #991: Improve types in `ConnectionInterface::transaction()` (@kikara)
- Enh #992: Add optional type casting to `DataReaderInterface` using columns (@Tigrov)
- Enh #996: Adapt summary data in debug collector (@rustamwin)
- Bug #1099: Fix an issue where `AbstractSchema::refresh()` didn't completely clear cache (@vjik)
- Bug #1103: Fix view names' cache refreshing after "drop table" command execution (@vjik)
- Bug #1109: Fix column definition parsing in cases with brackets and escaped quotes (@vjik)
- Bug #1115: Do not reset `$retryHandler` property on `AbstractCommand::reset()` method call (@Tigrov)
- Bug #828: Fix `float` type when use `AbstractCommand::getRawSql()` method (@Tigrov)
- Bug #933: Explicitly mark nullable parameters (@vjik)
- Bug #978: Fix memory leaking in `Command::exists()` method (@Tigrov)

## 1.3.0 March 21, 2024

- Enh #778: Deprecate unnecessary argument `$rawSql` of `AbstractCommand::internalExecute()` (@Tigrov)
- Enh #779: Specify result type of `QueryInterface::all()`, `CommandInterface::queryAll()` and
  `DbArrayHelper::populate()` methods to `array[]` (@vjik)
- Enh #779: Specify populate closure type in `BatchQueryResultInterface` (@vjik)
- Enh #781: Skip calling `CommandInterface::getRawSql()` if no `logger` or `profiler` is set (@Tigrov)
- Enh #784: Specify result type of `ConstraintSchemaInterface::getTableIndexes()` method to `IndexConstraint[]` (@vjik)
- Enh #784: Remove unused code in `AbstractSchema::getTableIndexes()` (@vjik)
- Enh #785: Refactor `AbstractCommand::getRawSql()` (@Tigrov)
- Enh #786: Refactor `AbstractSchema::getDataType()` (@Tigrov)
- Enh #789: Remove unnecessary type casting to array in `AbstractDMLQueryBuilder::getTableUniqueColumnNames()` (@Tigrov)
- Enh #794: Add message type to log context (@darkdef)
- Enh #795: Allow to use `DMLQueryBuilderInterface::batchInsert()` method with empty columns (@Tigrov)
- Enh #801: Deprecate `AbstractSchema::normalizeRowKeyCase()` method (@Tigrov)
- Enh #801: Deprecate `SchemaInterface::getRawTableName()` and add `Quoter::getRawTableName()` method (@Tigrov)
- Enh #801: Deprecate `SchemaInterface::isReadQuery()` and add `DbStringHelper::isReadQuery()` method (@Tigrov)
- Enh #801: Remove unnecessary symbol `\\` from `rtrim()` function inside `DbStringHelper::baseName()` method (@Tigrov)
- Enh #802: Minor refactoring of `SchemaCache`, `AbstractPdoCommand` and `AbstractDDLQueryBuilder` (@Tigrov)
- Enh #809: Add psalm type for parameters to bind to the SQL statement (@vjik)
- Enh #810: Add more specific psalm type for `QueryFunctionsInterface::count()` result (@vjik)
- Bug #777: Fix `Query::count()` when it returns an incorrect value if the result is greater
  than `PHP_INT_MAX` (@Tigrov)
- Bug #785: Fix bug of `AbstractCommand::getRawSql()` when a param value is `Stringable` object (@Tigrov)
- Bug #788: Fix casting integer to string in `AbstractCommand::getRawSql()` (@Tigrov)
- Bug #801: Fix bug with `Quoter::$tablePrefix` when change `AbstractConnection::$tablePrefix` property (@Tigrov)

## 1.2.0 November 12, 2023

- Chg #755: Deprecate `TableSchemaInterface::compositeForeignKey()` (@Tigrov)
- Chg #765: Deprecate `SchemaInterface::TYPE_JSONB` (@Tigrov)
- Enh #746: Enhanced documentation of `batchInsert()` and `update()` methods of `DMLQueryBuilderInterface` interface (@Tigrov)
- Enh #756: Refactor `Quoter` (@Tigrov)
- Enh #770: Move methods from concrete `Command` class to `AbstractPdoCommand` class (@Tigrov)
- Bug #746: Typecast values in `AbstractDMLQueryBuilder::batchInsert()` if column names with table name and brackets (@Tigrov)
- Bug #746, #61: Typecast values in `AbstractDMLQueryBuilder::batchInsert()` if values with string keys (@Tigrov)
- Bug #751: Fix collected debug actions (@xepozz)
- Bug #756: Fix `Quoter::quoteTableName()` for sub-query with alias (@Tigrov)
- Bug #761: Quote aliases of CTE in `WITH` queries (@Tigrov)
- Bug #769, #61: Fix `AbstractDMLQueryBuilder::batchInsert()` for values as associative arrays (@Tigrov)

## 1.1.1 August 16, 2023

- New #617: Add debug collector for `yiisoft/yii-debug` (@xepozz)
- Enh #617, #733: Add specific psalm annotation of `$closure` parameter in `ConnectionInterface::transaction()` 
  method (@xepozz, @vjik)
- Bug #741: Fix `alterColumn()` method to accept `ColumnInterface::class` in argument `$type` (@terabytesoftw)

## 1.1.0 July 24, 2023

- Chg #722: Remove legacy array syntax for typecast. Use `Param` instead (@terabytesoftw)
- Chg #724: Typecast refactoring (@Tigrov)
- Chg #728: Refactor `AbstractSchema::getColumnPhpType()` (@Tigrov)

## 1.0.0 April 12, 2023

- Initial release.
