From e9dd2204c698a01c3aa2020f398a279af0d2b0d5 Mon Sep 17 00:00:00 2001 From: Iwona Just Date: Thu, 11 Apr 2024 14:34:05 +0100 Subject: [PATCH 1/4] fix error when altering column to boolean in pgsql --- src/services/Fields.php | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/services/Fields.php b/src/services/Fields.php index 4844c01d587..120c0eedeaf 100644 --- a/src/services/Fields.php +++ b/src/services/Fields.php @@ -1726,9 +1726,20 @@ protected function updateColumn( if ($existingColumn) { // Alter it first, in case that results in an error due to incompatible column data try { - $db->createCommand() - ->alterColumn($table, $oldName, $type) - ->execute(); + if ($db->getIsPgsql() && $type === Schema::TYPE_BOOLEAN) { + $alterColumnSql = $db->createCommand() + ->alterColumn($table, $oldName, $type) + ->getRawSql(); + + $replacement = " TYPE boolean USING CASE WHEN \"$oldName\" IS NULL THEN NULL WHEN length(\"$oldName\") = 0 THEN FALSE ELSE TRUE END"; + + $sql = preg_replace('/\s+TYPE\s+boolean/i', $replacement, $alterColumnSql); + $db->createCommand($sql)->execute(); + } else { + $db->createCommand() + ->alterColumn($table, $oldName, $type) + ->execute(); + } } catch (DbException $e) { // Restart the transaction $transaction->rollBack(); From f1a828fcf87f8398f89247a2619800f358d5a5b5 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Fri, 12 Apr 2024 12:01:57 -0700 Subject: [PATCH 2/4] Cleanup --- src/services/Fields.php | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/services/Fields.php b/src/services/Fields.php index 120c0eedeaf..7d2f2294f01 100644 --- a/src/services/Fields.php +++ b/src/services/Fields.php @@ -1726,20 +1726,15 @@ protected function updateColumn( if ($existingColumn) { // Alter it first, in case that results in an error due to incompatible column data try { - if ($db->getIsPgsql() && $type === Schema::TYPE_BOOLEAN) { - $alterColumnSql = $db->createCommand() - ->alterColumn($table, $oldName, $type) - ->getRawSql(); - - $replacement = " TYPE boolean USING CASE WHEN \"$oldName\" IS NULL THEN NULL WHEN length(\"$oldName\") = 0 THEN FALSE ELSE TRUE END"; + $command = $db->createCommand()->alterColumn($table, $oldName, $type); - $sql = preg_replace('/\s+TYPE\s+boolean/i', $replacement, $alterColumnSql); - $db->createCommand($sql)->execute(); - } else { - $db->createCommand() - ->alterColumn($table, $oldName, $type) - ->execute(); + if ($db->getIsPgsql() && $type === Schema::TYPE_BOOLEAN) { + $replacement = sprintf(' TYPE boolean USING CASE WHEN "%s" IS NULL THEN NULL WHEN length("%s") = 0 THEN FALSE ELSE TRUE END"', $oldName, $oldName); + $sql = preg_replace('/\s+TYPE\s+boolean/i', $replacement, $command->getRawSql()); + $command->setSql($sql); } + + $command->execute(); } catch (DbException $e) { // Restart the transaction $transaction->rollBack(); From 2e6c1101960064dd5b603467c25ff67946d3b382 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Fri, 12 Apr 2024 12:02:55 -0700 Subject: [PATCH 3/4] Release note [ci skip] --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 93559449b30..a1f98aece3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Release Notes for Craft CMS 4 +## Unreleased + +- Fixed a SQL error that could occur when converting a field to a Lightswitch field on PostgreSQL. ([#14792](https://github.com/craftcms/cms/issues/14792)) + ## 4.8.9 - 2024-04-10 - Fixed a bug where element queries with the `relatedTo` param set to a list of element IDs were overly complex. From ba2aafeb45174e01598013bc1dca194306485a79 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Fri, 12 Apr 2024 14:14:02 -0700 Subject: [PATCH 4/4] Fixed bugs --- src/services/Fields.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/services/Fields.php b/src/services/Fields.php index 7d2f2294f01..0725f564021 100644 --- a/src/services/Fields.php +++ b/src/services/Fields.php @@ -1728,8 +1728,12 @@ protected function updateColumn( try { $command = $db->createCommand()->alterColumn($table, $oldName, $type); - if ($db->getIsPgsql() && $type === Schema::TYPE_BOOLEAN) { - $replacement = sprintf(' TYPE boolean USING CASE WHEN "%s" IS NULL THEN NULL WHEN length("%s") = 0 THEN FALSE ELSE TRUE END"', $oldName, $oldName); + if ( + $db->getIsPgsql() && + $type === Schema::TYPE_BOOLEAN && + Db::isTextualColumnType($db->getTableSchema($table)->getColumn($oldName)->dbType) + ) { + $replacement = sprintf(' TYPE boolean USING CASE WHEN "%s" IS NULL THEN NULL WHEN length("%s") = 0 THEN FALSE ELSE TRUE END', $oldName, $oldName); $sql = preg_replace('/\s+TYPE\s+boolean/i', $replacement, $command->getRawSql()); $command->setSql($sql); }