PostgreSQL | Как привести bigint к boolean?

PostgreSQL | Как привести bigint к boolean?

В чём проблема?

Столкнулся с такой проблемой, что PostgreSQL не умеет приводить тип данных «большого целого числа» к «логическому типу«.

SELECT CAST (9223372036854775807 AS boolean);

Скриншот из pgAdmin4:

ERROR ОШИБКА - привести тип bigint к boolean нельзя - PostgreSQL
ERROR ОШИБКА — привести тип bigint к boolean нельзя — PostgreSQL

ОШИБКА — привести тип bigint к boolean нельзя.

 

Это весьма неожиданно, особенно когда приходишь в SQL с какого-нибудь языка программирования, где подобных проблем просто не возникает. Например в JavaScript можно без проблем привести любое по размеру число к логическому типу.

Приведение большого целого числа к логическому типу в JavaScript
Приведение большого целого числа к логическому типу в JavaScript

Но PostgreSQL обделён такой функциональностью. И это смешно. Знаете почему? Потому что PostgreSQL может привести к логическому типу integer или smallint.

Приведение integer к boolean в PostgreSQL прошло успешно
Приведение integer к boolean в PostgreSQL прошло успешно
Приведение smallint к boolean в PostgreSQL прошло успешно
Приведение smallint к boolean в PostgreSQL прошло успешно

Есть некое чувство, что нам обманули и что-то просто не работает как нужно. Половина функционала работает, а половина нет.

 

Как я столкнулся с этой проблемой?

Забавно то, что при использовании функции count() для подсчёта записей в таблице, нам возвращается результат в табличном виде, где тип данных у единственной ячейки — это bigint.

А почему не integer или smallint? Что не так то?

Функция count возвращает тип bigint в PostgreSQL
Функция count возвращает тип bigint в PostgreSQL

Я хотел привязаться к этому значению и использовать его для отлова пустых таблиц из базы данных. Это временные таблицы, которые создаются динамически другим алгоритмом. В этих таблицах происходят подсчёты и преобразования, а потом они просто не нужны и их можно удалять. Но удалить только когда они полностью пустые.

Что делать в таком случае?

 

Решение

Для приведения типа bigint к типу boolean было принято решение сначала приводить тип bigint к типу text и только потом сравнивать его со строкой ‘0‘.

Смысл в том, что любое количество последовательных нулей приводится в PostgreSQL к одному символу ‘0‘.

SELECT CAST (000000000000000000000000000000000000000000000 AS text);
Любое последовательное количество нулей приводится к типу text в виде одного символа ноль в PostgreSQL
Любое последовательное количество нулей приводится к типу text в виде одного символа ноль в PostgreSQL

Только один символ «ноль» должен приводить для нас значение false. Во всех остальных случаях мы ожидаем получить true.

Если брать за основу возможные результаты count(), то даже отрицательных целых чисел мы никогда не получим. Только больше или равные нулю.

 

Выглядит это так:

SELECT (SELECT CAST (9223372036854775807 AS text)) != '0';

SELECT (SELECT CAST (0000000000000000000 AS text)) != '0';

Скриншоты:

Привели большое целое больше нуля к логическому типу в PostgreSQL
Привели большое целое больше нуля к логическому типу в PostgreSQL
Привели большую последовательность нулей к логическому типу в PostgreSQL
Привели большую последовательность нулей к логическому типу в PostgreSQL

По этой системе можно скармливать в CAST любой из трёх:

  • bigint
  • int
  • smallint

Сочетание «НЕ РАВНО НУЛЮ» (!= ‘0’) означает для нас получение нужного отрицания, для смены истинности.

 

Информационные ссылки

Официальный сайт WEB-оболочки pgAdminhttps://www.pgadmin.org

Официальный сайт СУБД PostgreSQLhttps://www.postgresql.org

Оператор CREATE CASThttps://postgrespro.ru/docs/postgresql/14/sql-createcast