From cc56e9e0c7e23b16cb542ca0b6e68c59d757471d Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Mon, 23 Jan 2017 01:12:12 +0300 Subject: [PATCH] Explicitly cast varbinary to work around MSSQL PDO bug https://github.com/Microsoft/msphpsql/issues/140 --- framework/db/mssql/QueryBuilder.php | 38 +++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/framework/db/mssql/QueryBuilder.php b/framework/db/mssql/QueryBuilder.php index 11e4fe45e79..b86bba165c5 100644 --- a/framework/db/mssql/QueryBuilder.php +++ b/framework/db/mssql/QueryBuilder.php @@ -9,6 +9,7 @@ use yii\base\InvalidParamException; use yii\base\NotSupportedException; +use yii\db\Expression; /** * QueryBuilder is the query builder for MS SQL Server databases (version 2008 and above). @@ -312,4 +313,41 @@ public function selectExists($rawSql) { return 'SELECT CASE WHEN EXISTS(' . $rawSql . ') THEN 1 ELSE 0 END'; } + + /** + * Normalizes data to be saved into the table, performing extra preparations and type converting, if necessary. + * @param string $table the table that data will be saved into. + * @param array $columns the column data (name => value) to be saved into the table. + * @return array normalized columns + */ + private function normalizeTableRowData($table, $columns, &$params) + { + if (($tableSchema = $this->db->getSchema()->getTableSchema($table)) !== null) { + $columnSchemas = $tableSchema->columns; + foreach ($columns as $name => $value) { + // @see https://github.com/yiisoft/yii2/issues/12599 + if (isset($columnSchemas[$name]) && $columnSchemas[$name]->type === Schema::TYPE_BINARY && $columnSchemas[$name]->dbType === 'varbinary' && is_string($value)) { + $phName = self::PARAM_PREFIX . count($params); + $columns[$name] = new Expression("CONVERT(VARBINARY, $phName)", [$phName => $value]); + } + } + } + return $columns; + } + + /** + * @inheritdoc + */ + public function insert($table, $columns, &$params) + { + return parent::insert($table, $this->normalizeTableRowData($table, $columns, $params), $params); + } + + /** + * @inheritdoc + */ + public function update($table, $columns, $condition, &$params) + { + return parent::update($table, $this->normalizeTableRowData($table, $columns, $params), $condition, $params); + } }