Frog Proger 18 сентября 2024

😮 SQL: от Тетриса до ИИ – неожиданные возможности языка баз данных

Рекурсивные общие табличные выражения (CTE) превратили SQL в полный по Тьюрингу язык. Разберемся, как энтузиасты создают на нем сложные алгоритмы – от визуализации фракталов до полноценных игр.
😮 SQL: от Тетриса до ИИ – неожиданные возможности языка баз данных
Этот материал взят из нашей еженедельной email-рассылки, посвященной бэкенду. Подпишитесь, чтобы быть в числе первых, кто получит дайджест.

Долгое время SQL использовали лишь для запросов и изменения записей в базах данных – для полноценного программирования в привычном смысле слова он не подходил. Однако добавление рекурсивных общих табличных выражений (CTE) сделало SQL полным по Тьюрингу. Рекурсивные CTE состоят из двух частей:

  • Нерекурсивная часть (базовый случай) – создает начальные данные.
  • Рекурсивная часть – может выполняться много раз, каждый раз используя результат предыдущего шага.
Пример генерации чисел от 1 до 5 с помощью СТЕ
Пример генерации чисел от 1 до 5 с помощью СТЕ

Благодаря CTE на SQL можно при желании реализовать любой алгоритм. Энтузиасты уже сделали:

  • Визуализацию множества Мандельброта с помощью ASCII-графики.
  • 3D-движок для рисования объемных фигур.
  • GPT на 500 строках SQL-кода. Подробная статья о реализации этого проекта опубликована здесь.
  • Трассировку лучей (это метод создания реалистичных изображений).
Результат трассировки лучей на SQL
Результат трассировки лучей на SQL

На прошлой неделе коллекция крутых SQL-проектов пополнилась еще одной интересной разработкой – версией «Тетриса».

«Тетрис» на SQL
«Тетрис» на SQL

Эта реализация демонстрирует несколько нестандартных SQL-техник, о которых стоит знать, даже если вы используете SQL только по прямому назначению:

  • Игровой цикл. В основе игры – рекурсивное общее табличное выражение (CTE). Оно создает бесконечный цикл, который инициализирует состояние игры, обновляет его на основе ввода пользователя и отрисовывает игру. Цикл продолжается, пока игра не закончится.
  • Вывод игры. Поскольку SQL-запрос обычно возвращает результат только после завершения, для отображения игры в реальном времени используется команда RAISE NOTICE. Эта команда выводит информацию в стандартный вывод, позволяя отображать игровое поле и другую информацию в процессе игры.
  • Пользовательский ввод. Обработка пользовательского ввода реализована через отдельную таблицу в базе данных. Эта таблица служит коммуникационной шиной между игрой и пользователем. Пользователь добавляет команды в эту таблицу, а игра их считывает.
  • Решение проблемы изоляции данных. Чтобы игра могла видеть новые команды, добавленные в таблицу ввода во время выполнения запроса, используется расширение dblink. Оно позволяет создавать новое подключение к базе данных с новым снимком данных, что дает возможность считывать самые последние команды пользователя.
  • Предотвращение кэширования. Чтобы PostgreSQL не кэшировал результаты запроса к таблице ввода, к запросу добавляется уникальный идентификатор итерации. Это заставляет базу данных выполнять запрос заново на каждой итерации игрового цикла.
💻 Библиотека программиста
Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека программиста»

Для управления состоянием игры и обработки игровых событий используются подзапросы и агрегатные функции:

  • Подзапросы позволяют вычислить новое состояние игры после каждого хода, включая позицию фигуры, состояние поля, счет и т. д. К примеру, рекурсивный подзапрос используется для вычисления максимального количества линий, на которые может упасть текущая фигура.
  • Агрегации применяются для подсчета очищенных линий, выбора фигуры с наименьшим рангом, обновления счета и уровня игры. Например, BOOL_OR() применяется для определения, есть ли хотя бы одно столкновение между фигурой и занятыми клетками на поле.
***

Какой самый необычный проект на SQL вы встречали или реализовывали сами?

Комментарии

ВАКАНСИИ

Добавить вакансию
Разработчик C++
Москва, по итогам собеседования

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ