Search by

cloud-castle / query-builder

alex-4-17

Immutable, type-safe, cross-dialect SQL query builder for PHP 8.1+: 69 SQL dialects and 9 non-SQL languages, DDL/DML/DQL/DCL/TCL, safe parameterized generation.

v1.0.0 2026-09-03 19:57 UTC

README

🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano

CloudCastle QueryBuilder

CloudCastle QueryBuilder

Иммутабельный, типобезопасный, кросс-диалектный конструктор SQL-запросов для PHP 8.1+. Строит запросы любой сложности и вложенности для максимально широкого спектра СУБД, генерируя безопасный SQL с плейсхолдерами. Библиотека не исполняет запросы — она их корректно порождает под 69 SQL-диалектов и 9 не-SQL языков из единого дерева выражений (AST).

Packagist Version Downloads PHP Version License

GitVerse

PHPStan Psalm PHPMD PHPCS Coverage Infection MSI

Ключевые особенности

  • 69 SQL-диалектов и 9 не-SQL языков — реляционные, NewSQL, колоночные/OLAP, встраиваемые, time-series, wide-column, search, streaming, federated, vector, multi-model, а также графовые и документные языки. Один AST компилируется под любой из них.
  • Иммутабельность — каждый вызов возвращает новый строитель; базовый запрос безопасно переиспользуется и ветвится.
  • Типобезопасность — строгая типизация, полные PHPDoc-типы, проверка PHPStan (max) и Psalm (level 1).
  • Только параметризованные запросы — значения никогда не попадают в текст SQL; идентификаторы квотируются и экранируются по правилам диалекта (включая обратный слэш в ClickHouse/BigQuery/Spanner). Защита от инъекций на уровне архитектуры.
  • Fail-safe контракт — при отсутствии нативной конструкции библиотека либо генерирует семантически эквивалентную эмуляцию, либо явно и безопасно отказывает; никогда не порождает молча запрос, возвращающий другой результат.
  • Один AST — любой диалект — смена целевой СУБД без пересборки запроса.

Установка

composer require cloud-castle/query-builder

Требуется PHP 8.1+ (тестируется на 8.1–8.5).

Быстрый старт

<?php

use CloudCastle\QueryBuilder\Query;
use CloudCastle\QueryBuilder\Expr;
use CloudCastle\QueryBuilder\Enum\OrderDirection;
use CloudCastle\QueryBuilder\Grammar\PostgresDialect;
use CloudCastle\QueryBuilder\Grammar\MySqlDialect;

$query = Query::select('u.id', 'u.email', Expr::alias(Expr::count('orders.id'), 'orders_count'))
    ->from('users', 'u')
    ->leftJoin('orders', 'orders.user_id', 'u.id')
    ->where('u.status', '=', 'active')
    ->groupBy('u.id', 'u.email')
    ->having('orders_count', '>', 5)
    ->orderBy('orders_count', OrderDirection::Desc)
    ->limit(50);

$compiled = $query->toCompiled(new PostgresDialect());

// SELECT "u"."id", "u"."email", COUNT("orders"."id") AS "orders_count" FROM "users" AS "u"
//   LEFT JOIN "orders" ON "orders"."user_id" = "u"."id" WHERE "u"."status" = $1
//   GROUP BY "u"."id", "u"."email" HAVING "orders_count" > $2 ORDER BY "orders_count" DESC LIMIT 50
$compiled->sql();
$compiled->bindings(); // ['active', 5]

Тот же AST компилируется под другой диалект без пересборки:

$query->toCompiled(new MySqlDialect())->sql();  // тот же запрос в лексике MySQL

Возможности

КатегорияЧто поддерживается
DQLSELECT (подзапросы любой вложенности, CTE + рекурсивные + MATERIALIZED, оконные функции + рамки + именованные WINDOW, QUALIFY, GROUPING SETS/ROLLUP/CUBE, DISTINCT ON, LATERAL/APPLY/ASOF JOIN, FILTER, блокировки FOR UPDATE/SKIP LOCKED, keyset-пагинация), UNION/INTERSECT/EXCEPT (+ ALL), VALUES-источник, PIVOT/UNPIVOT, TABLESAMPLE
DMLINSERT (multi-row, DEFAULT VALUES, upsert/ON CONFLICT, INSERT ... SELECT, INSERT ALL), UPDATE (+FROM), DELETE (+USING), MERGE, RETURNING
DDLCREATE/ALTER/DROP TABLE, ремап типов, PRIMARY KEY/FOREIGN KEY/UNIQUE/CHECK, GENERATED, ENUM, партиционирование; индексы (методы доступа, частичные, функциональные, покрывающие); VIEW/материализованные; SEQUENCE; SCHEMA; домены и типы; триггеры; события; CREATE TABLE AS SELECT; TRUNCATE
DCLGRANT/REVOKE, CREATE/DROP ROLE/USER, RLS-политики, COMMENT ON
TCLBEGIN/COMMIT/ROLLBACK, SAVEPOINT, уровни изоляции, двухфазный коммит (2PC)
ВыраженияФасад Expr + 15 категорий Fn\* (152 функции): строковые, математические, дата/время, агрегатные, JSON, условные, оконные, приведения, массивы, гео (PostGIS), regexp, кодирование, сеть, побитовые, системные. Любая функция — через Expr::func()
FederationATTACH DATABASE, FDW (сервер / внешняя таблица / маппинг), DBLINK (Oracle), OPENQUERY (SQL Server), табличные функции ClickHouse, 3/4-частные имена
Не-SQLCypher (Neo4j), SQL/PGQ (PGQL), GSQL, Gremlin, SPARQL, CQL (Cassandra), PartiQL, AQL (ArangoDB), Cosmos
ИнтроспекцияCatalog: таблицы, колонки, представления, ограничения, схемы, подпрограммы, триггеры через INFORMATION_SCHEMA
ПрочееCALL процедур, CREATE PROCEDURE/FUNCTION, EXPLAIN [ANALYZE], векторный поиск

Сравнение с аналогами

Ниже — честное сопоставление с популярными PHP-конструкторами SQL. Оценки по функционалу даны на основе публичной документации проектов; сильная сторона CloudCastle QueryBuilder — беспрецедентная широта диалектов и кросс-диалектный fail-safe контракт, слабая — молодость и меньшая распространённость.

Функционал и охват

КритерийCloudCastle QueryBuilderDoctrine DBALLaravel Query BuilderCycle / SpiralLatitudeAura.SqlQuery🏆 Победитель
SQL-диалектов69~10~5~5агностик¹4QueryBuilder
Не-SQL языков (Cypher/SPARQL/…)9QueryBuilder
DDL (CREATE/ALTER/DROP …)✅ полн.✅ базовыйсхемы миграцийсхемыQueryBuilder
DML (INSERT/UPDATE/DELETE/MERGE)✅ + MERGEQueryBuilder
DQL (CTE/окна/QUALIFY/PIVOT)✅ полн.частичночастичночастичнобазовыйбазовыйQueryBuilder
DCL (GRANT/ROLE/RLS)QueryBuilder
TCL (изоляция/SAVEPOINT/2PC)✅ через API✅ базовыйQueryBuilder
Federation (FDW/DBLINK/ATTACH)QueryBuilder
Fail-safe (native→emulated→отказ)QueryBuilder
Иммутабельный ASTчастичноQueryBuilder

¹ Latitude генерирует стандартный SQL и почти не различает диалекты.

Позиционирование

КритерийCloudCastle QueryBuilderDoctrine DBALLaravel Query Builder
Исполняет запросы❌ (только генерация)
Зависимость от драйверов PDO❌ нет
Привязка к фреймворку❌ нет✅ Laravel
Зрелость / экосистемамолодая (v1.0)🏆 высокая🏆 высокая
Широта СУБД / переносимость🏆 максимальнаясредняянизкая

Безопасность и качество

КритерийCloudCastle QueryBuilderТипичный аналог🏆
Только параметризованные значения✅ на уровне архитектуры➖ паритет
Экранирование идентификаторов (вкл. backslash CH/BQ/Spanner)частичноQueryBuilder
Белый список имён функций/типов⚠️ редкоQueryBuilder
Покрытие строк тестами100%варьируетсяQueryBuilder
Mutation Score Indicator100%редко замеряетсяQueryBuilder
Статанализ (PHPStan max + Psalm)варьируетсяQueryBuilder

Преимущества и ограничения

Честная выжимка — без маркетинга.

Преимущества

  • Беспрецедентная широта СУБД — 69 SQL-диалектов и 9 не-SQL языков из единого AST; ни один известный PHP-конструктор SQL не покрывает столько.
  • Кросс-диалектность без пересборки — один и тот же запрос компилируется под любую целевую СУБД; смена базы не требует переписывания кода.
  • Fail-safe контракт — либо нативная конструкция, либо семантически эквивалентная эмуляция, либо явный типизированный отказ; библиотека никогда не порождает молча SQL с другим результатом. Критично для финтеха и обработки данных.
  • Безопасность на уровне архитектуры — только параметризованные значения, экранирование идентификаторов (включая обратный слэш в ClickHouse/BigQuery/Spanner), белый список имён функций и типов.
  • Независимость — не привязан к фреймворку, не требует PDO/драйверов, встраивается в любой слой исполнения.
  • Иммутабельность и типобезопасность — безопасное переиспользование и ветвление запросов; PHPStan (max) + Psalm (level 1).
  • Полнота операций — DDL/DML/DQL/DCL/TCL, а также процедуры, оконные функции, триггеры, события, разные типы индексов и federation.
  • Проверенное качество — 2724 теста, покрытие строк 100 %, MSI 100 %.

Ограничения

  • Только генерация, не исполнение — библиотека порождает SQL и плейсхолдеры, но не выполняет запросы; слой исполнения (PDO/драйвер) остаётся за вами. Это осознанный дизайн (легковесность, совместимость с любым драйвером), а не «ORM из коробки».
  • Не ORM — маппинг сущностей, миграции, lazy-loading, репозитории — вне области пакета по замыслу; это конструктор SQL, а не ORM.
  • Молодость и меньшая распространённость — версия 1.0; экосистема, число интеграций и примеров пока меньше, чем у Doctrine/Laravel. Это единственный честный недостаток относительно зрелых аналогов — он уходит со временем.
  • Экзотические диалекты выверены по документации — для нишевых СУБД синтаксис приведён по официальным докам; для редких edge-кейсов рекомендуется проверка на живом движке.

Где и когда применять

Подходит лучше всего

  • Мультибазовые продукты и SaaS — одно приложение обслуживает клиентов на разных СУБД (PostgreSQL у одного, Oracle или SQL Server у другого) без ветвления кода.
  • Аналитика и OLAP — генерация SQL под ClickHouse, BigQuery, Snowflake, Trino, Redshift, DuckDB, Spark из общего кода.
  • Data-инжиниринг и ETL — целевые time-series (QuestDB, InfluxDB, Timestream), streaming (Flink, ksqlDB), распределённые OLAP (Doris, StarRocks, Druid, Pinot).
  • Собственные ORM, DBAL и фреймворки — как безопасный кросс-диалектный генератор SQL внутри своего слоя исполнения.
  • Финтех и обработка чувствительных данных — где молчаливо-неверный SQL недопустим: fail-safe контракт даёт либо корректный SQL, либо явный отказ.
  • Графовые и документные базы — генерация Cypher, Gremlin, SPARQL, CQL, PartiQL, AQL из единого API.
  • Миграция между СУБД — перенос запросов с одной базы на другую без ручного переписывания.

Стоит выбрать альтернативу

  • Нужен готовый ORM с исполнением под 1–2 популярные СУБД — Doctrine ORM, Laravel Eloquent, Cycle (маппинг сущностей, миграции, репозитории «из коробки»).
  • Проект жёстко в экосистеме Laravel/Symfony — нативные конструкторы фреймворка дадут более тесную интеграцию.
  • Нужен простейший SQL под одну СУБД — лёгкого Latitude или нативного PDO может быть достаточно.
  • Требуются исполнение, пул соединений и транзакции «из коробки» — DBAL с драйверами.

Fail-safe контракт

Для каждой возможности стратегия выбирается по порядку:

  1. native — нативная конструкция диалекта.
  2. emulated — семантически эквивалентная эмуляция, дающая тот же результат (например, NULLS FIRST/LAST через CASE там, где это валидно).
  3. degraded — приблизительная эмуляция; разрешена только в режиме lenient с регистрацией предупреждения.
  4. unsupported — типизированное исключение UnsupportedCapabilityException с указанием возможности, диалекта и альтернативы.
use CloudCastle\QueryBuilder\Enum\CompilationMode;

// strict (по умолчанию): отказ при приблизительной эмуляции и отсутствии поддержки
$query->toCompiled($dialect);

// lenient: приблизительная эмуляция разрешена, предупреждения — в CompiledQuery::warnings()
$query->toCompiled($dialect, CompilationMode::Lenient);

Безопасность

  • Только параметризованные запросы — значения передаются отдельно от текста SQL.
  • Идентификаторы, алиасы и направления сортировки экранируются/квотируются по правилам диалекта, включая обратный слэш в квотированных идентификаторах ClickHouse/BigQuery/Spanner (защита от выхода из идентификатора через недоверенное имя).
  • Имена функций, типов и полей проходят белый список символов; строковые литералы в DDL (DEFAULT/CHECK/COMMENT/ENUM) экранируются, включая обратный слэш на MySQL-семействе, ClickHouse, BigQuery, Hive/Impala/Spark.
  • Библиотека не логирует значения привязок по умолчанию (потенциальные ПД/финданные).

Диалекты

69 SQL-диалектов, среди них PostgreSQL, MySQL, MariaDB, Oracle, SQL Server, SQLite, DB2, H2, HSQLDB, Firebird, Derby, SAP HANA, Teradata, Exasol, SAP ASE, Informix, MonetDB, NuoDB, VoltDB, DuckDB, ClickHouse, Snowflake, BigQuery, Redshift, Trino, Spark SQL, Vertica, Impala, Hive, Firebolt, Druid, Pinot, Kylin, Dremio, Drill, Spanner, CockroachDB, YugabyteDB, TiDB, SingleStore, StarRocks, Doris, Greenplum, Materialize, RisingWave, CrateDB, TimescaleDB, QuestDB, InfluxDB, TDengine, Timestream, Cassandra, ScyllaDB, Elasticsearch SQL, OpenSearch SQL, Solr SQL, Rockset, Couchbase, DynamoDB PartiQL, Cosmos DB, OrientDB, LanceDB, ksqlDB, Flink SQL, Beam SQL, Aurora (MySQL/PostgreSQL), HeatWave, pgvector и другие.

Плюс 9 не-SQL языков: Cypher (Neo4j), SQL/PGQ (PGQL), GSQL, Gremlin, SPARQL, CQL (Cassandra), PartiQL, AQL (ArangoDB), Cosmos.

Полный перечень с машинными именами и категориями — на странице Dialects в Wiki.

Качество

  • 2724 теста, покрытие строк 100%, Mutation Score Indicator (MSI) 100%.
  • Прогон анализаторов: phplint → Psalm (level 1) → PHPStan (max) → PHPMD → PHPCS (PSR-12) → Rector → Deptrac → Infection.
  • PHP 8.1–8.5.

Разработка

composer install
composer check    # линтеры + статический анализ + тесты
composer fix      # автоисправления (Rector, PHP CS Fixer, PHPCBF)
composer ci       # полный CI-пайплайн локально

Документация

Лицензия

MIT © CloudCastle (alex-4-17@yandex.ru)

🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano