Skip to content

Query (packages/query)

Высокоуровневый, типобезопасный клиент для YQL‑запросов и транзакций.

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

ts
import { Driver } from '@ydbjs/core'
import { query } from '@ydbjs/query'

const driver = new Driver('grpc://localhost:2136/local')
await driver.ready()

const sql = query(driver)
const rows = await sql`SELECT 1 + 1 AS sum`
console.log(rows)

Примеры

Параметры и AS_TABLE

ts
const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
]
await sql`INSERT INTO users SELECT * FROM AS_TABLE(${users})`

Именованные параметры

ts
await sql`SELECT * FROM users WHERE id = $id`.parameter('id', 42)

Получение статистики

ts
import { StatsMode } from '@ydbjs/api/query'

const q = sql`SELECT * FROM users`.withStats(StatsMode.FULL)
q.on('stats', (s) => console.log('Stats:', s))
await q

Форматы результата

ts
// Массив значений (в порядке колонок)
const vals = await sql`SELECT 1 AS a, 2 AS b`.values()
console.log(vals) // [ [1, 2] ]

// Сырые TypedValue
const raw = await sql`SELECT 1`.raw()

Изоляция одиночного вызова

ts
await sql`SELECT * FROM users`
  .isolation('snapshotReadOnly')
  .timeout(3000)

Обработка ошибок

ts
import { YDBError } from '@ydbjs/error'

try {
  await sql`SELECT * FROM non_existent`
} catch (e) {
  if (e instanceof YDBError) {
    console.error('YDB error code:', e.code)
  }
}

Динамические идентификаторы и небезопасные фрагменты

ts
// Безопасные динамические имена таблиц/колонок
const table = sql.identifier('users')
const column = sql.identifier('created_at')
const rows = await sql`SELECT ${column} FROM ${table} WHERE id = ${42}`

// Небезопасные фрагменты — только для доверенного кода (миграции, DDL)
await sql`PRAGMA TablePathPrefix(${sql.unsafe('/Root/dev')});`

События запроса и ретраи

ts
import { StatsMode } from '@ydbjs/api/query'

const q = sql`SELECT * FROM heavy_table`
  .idempotent(true)
  .withStats(StatsMode.FULL)

q.on('retry', (ctx) => console.log('retry attempt', ctx.attempt, ctx.error))
q.on('stats', (s) => console.log('cpu(us)=', s.queryPhaseStats?.cpuTimeUs))
await q

Отмена и таймауты

ts
const ac = new AbortController()
setTimeout(() => ac.abort('user cancelled'), 1000)

await sql`SELECT pg_sleep(10)`
  .timeout(5000)
  .signal(ac.signal)

Режимы изоляции

ts
// Snapshot read-only одиночная транзакция
await sql`SELECT COUNT(*) FROM users`.isolation('snapshotReadOnly')

// Online read-only с разрешением неконсистентных чтений
await sql`SELECT COUNT(*) FROM users`
  .isolation('onlineReadOnly', { allowInconsistentReads: true })

Syntax и pool

ts
import { Syntax } from '@ydbjs/api/query'

await sql`SELECT 1`.syntax(Syntax.YQL_V1)
await sql`SELECT 1`.pool('analytics')

Хуки транзакции

ts
const result = await sql.begin(async (tx, signal) => {
  tx.onCommit(() => console.log('committing tx', tx.transactionId))
  tx.onRollback((err) => console.log('rolling back tx', err))

  await tx`UPSERT INTO audit(id, ts) VALUES (${1}, CurrentUtcDatetime())`
  return await tx`SELECT * FROM audit WHERE id = ${1}`
})