YQL — это SQL‑диалект, специфичный для базы данных YDB. YQL требует заранее объявлять имена и типы параметров запроса. Это обеспечивает высокую производительность и корректное поведение. В синтаксисе YQL параметры необходимо перечислять явно с помощью инструкции DECLARE. И этот нюанс YDB может быть неожиданным для пользователей традиционных баз данных.

Кроме того, поскольку таблицы YDB находятся в структуре, подобной виртуальной файловой системе, их имена могут быть довольно длинными. Существует PRAGMA TablePathPrefix, которая может охватить остальную часть запроса внутри заданного префикса, упрощая имена таблиц. Например, запрос к таблице «/local/path/to/tables/seasons» может выглядеть следующим образом:
DECLARE $title AS Text; DECLARE $views AS Uint64; SELECT season_id FROM `/local/path/to/tables/seasons` WHERE title LIKE $title AND views > $views;
Используя инструкцию PRAGMA, вы можете упростить префиксную часть в названии всех таблиц, участвующих в YQL-запросе:
PRAGMA TablePathPrefix(“/local/path/to/tables/”); DECLARE $title AS Text; DECLARE $views AS Uint64; SELECT season_id FROM seasons WHERE title LIKE $title AND views > $views;
Также YQL поддерживает только именованные параметры запроса. Это означает, что вы не можете использовать привычные нумерованные (с использованием плейсхолдеров типа «$1», «$2», «$3» и т. п.) или позиционные (с использованием плейсхолдеров «?») параметры запроса. Это может стать неожиданностью для пользователей, привыкших к синтаксису PostgreSQL или MySQL (или другой СУБД).
Как YDB Go SDK может помочь вам упростить такие запросы?
database/sql драйвер для YDB (часть YDB Go SDK) поддерживает биндинги (обогащение) запросов для:
указания PRAGMA TablePathPrefix
авто‑выведения DECLARE для типов параметров
нумерованных или позиционных параметров запросов
Биндинги запросов могут быть явно включены на этапе инициализации драйвера с помощью опций коннектора или параметра строки подключения. По умолчанию database/sql драйвер для YDB не изменяет запросы.
Следующий пример (без включения биндингов запросов) демонстрирует работу с типами YDB явным образом:
package main import ( "context" "database/sql" "github.com/ydb-platform/ydb-go-sdk/v3" "github.com/ydb-platform/ydb-go-sdk/v3/table" "github.com/ydb-platform/ydb-go-sdk/v3/table/types" ) func main() { db := sql.Open("ydb", "grpc://localhost:2136/local") defer db.Close() row := db.QueryRowContext(context.TODO(), ` PRAGMA TablePathPrefix("/local/path/to/my/folder"); DECLARE $p0 AS Int32; DECLARE $p1 AS Utf8; SELECT $p0, $p1`, sql.Named("$p0", 42), table.ValueParam("$p1", types.TextValue("my string")), ) ... }
Как вы можете видеть, в этом примере также требовался импорт пакетов ydb‑go‑sdk и непосредственная работа с ними.
С включенными биндингами тот же результат может быть достигнут намного проще:
через параметры строку подключения:
package main import ( "context" "database/sql" // anonymous import for registering driver _ "github.com/ydb-platform/ydb-go-sdk/v3" ) func main() { var ( ctx = context.TODO() db = sql.Open("ydb", "grpc://localhost:2136/local?"+ "go_auto_bind="+ "table_path_prefix(/local/path/to/my/folder),"+ "declare,"+ "positional" ) ) // cleanup resources on exit from func defer db.Close() // query with positional args row := db.QueryRowContext(ctx, `SELECT ?, ?`, 42, "my string") ... }
через опции коннектора:
package main import ( "context" "database/sql" "github.com/ydb-platform/ydb-go-sdk/v3" ) func main() { var ( ctx = context.TODO() nativeDriver = ydb.MustOpen(ctx, "grpc://localhost:2136/local") db = sql.OpenDB(ydb.MustConnector(nativeDriver, // bind pragma TablePathPrefix ydb.WithTablePathPrefix("/local/path/to/my/folder"), // bind parameters declare ydb.WithAutoDeclare(), // bind positional args ydb.WithPositionalArgs(), )) ) // cleanup resources on exit from func defer nativeDriver.Close(ctx) defer db.Close() // query with positional args row := db.QueryRowContext(ctx, `SELECT ?, ?`, 42, "my string") ... }
В обоих случаях исходный простой запрос
SELECT ?, ?
на стороне драйвера будет обогащен до следующего:
-- bind TablePathPrefix PRAGMA TablePathPrefix("/local/path/to/my/folder"); -- bind declares DECLARE $p0 AS Int32; DECLARE $p1 AS Utf8; -- origin query with positional args replacement SELECT $p0, $p1
Этот обогащенный запрос будет отправлен в YDB вместо исходного.
Порядок объявления привязок (через параметры строки подключения или через опции коннектора) определяет порядок, в котором биндинги отрабатывают на стороне драйвера.
Дополнительные примеры включения биндингов запросов смотрите в документации ydb-go-sdk:
1) обогащение запроса прагмой TablePathPrefix:
через опции коннектора
2) авто-выведение типов параметров (DECLARE):
через опции коннектора
3) биндинг позиционных параметров:
через опции коннектора
4) биндинг нумерованных параметров:
через опции коннектора
Для глубокого понимания биндингов запросов смотрите также unit-тесты в ydb-go-sdk
Вы можете написать свои собственные unit-тесты для проверки корректности работы биндингов над вашими запросами следующим образом:
import ( "testing" "github.com/stretchr/testify/require" "github.com/ydb-platform/ydb-go-sdk/v3" "github.com/ydb-platform/ydb-go-sdk/v3/table" "github.com/ydb-platform/ydb-go-sdk/v3/testutil" ) func TestBinding(t *testing.T) { binder := testutil.QueryBind( // bind pragma TablePathPrefix ydb.WithTablePathPrefix("/local/path/to/my/folder"), // bind parameters declare ydb.WithAutoDeclare(), // auto-replace positional args ydb.WithPositionalArgs(), ) query, params, err := binder.RewriteQuery( "SELECT ?, ?, ?", 1, uint64(2), "3", ) require.NoError(t, err) require.Equal(t, `-- bind TablePathPrefix PRAGMA TablePathPrefix(“/local/path/to/my/folder”); -- bind declares DECLARE $p0 AS Int32; DECLARE $p1 AS Uint64; DECLARE $p2 AS Utf8; -- origin query with positional args replacement SELECT $p0, $p1, $p2`, query, ) require.Equal(t, table.NewQueryParameters( table.ValueParam("$p0", types.Int32Value(1)), table.ValueParam("$p1", types.Uint64Value(2)), table.ValueParam("$p2", types.TextValue("3")), ), params, ) }
Биндинги запросов в database/sql драйвере для YDB доступны ��ачиная с версии v3.44.0 ydb-go-sdk. Пробуйте и возвращайтесь с обратной связью!
Если у вас возникнут какие-либо трудности или вопросы, пожалуйста, не стесняйтесь обращаться к нам через:
