Как стать автором
Обновить

Комментарии 8

3. Делаем простой Select-запрос

const result = await db.select().from(users);
// SELECT "id", "first_name" FROM users;

Ну-ка, ну-ка... вот точно показанный код ORM отсылает на сервер ИМЕННО ПОКАЗАННЫЙ текст запроса? То есть ORM сперва запросит с сервера БД структуру таблицы или представления, на основе полученного результата сформирует список полей в запросе, и только потом выполнит собственно затребованный запрос? Проверяли?

Или всё же ORM отправит на сервер запрос

SELECT * FROM users;

?

Вы правы в том, что пример запроса выглядит странно. Однако запрос структуры тут ни при чем. Данных должно быть достаточно, так как users уже хранит описание таблицы.

export const users = table(
  "users",
  {
    id: t.integer().primaryKey().generatedAlwaysAsIdentity(),
    firstName: t.varchar("first_name", { length: 256 }),
    lastName: t.varchar("last_name", { length: 256 }),
    email: t.varchar().notNull(),
    invitee: t.integer().references((): AnyPgColumn => users.id),
    role: rolesEnum().default("guest"),
  },
  (table) => [
    t.uniqueIndex("email_idx").on(table.email)
  ]
);

Но вот что точно смущает, так это то, что в запросе поля взяты как будто наобум. Обычно ожидается увидеть одно из трех:

  1. Запрос всех "своих" полей без ссылочных сущностей

  2. Запрос вообще всех полей со ссылками

  3. Запрос через * (хотя я такое нн встречал в выхлопе ORM, но не удивился бы такое увидеть)

А вот в актуальном примере какая-то лажа.

Однако запрос структуры тут ни при чем. Данных должно быть достаточно, так как users уже хранит описание таблицы.

Тогда вообще ничего не понял. Вот тот начальный код, где объявляется схема - это что, просто тупо хардкодится ожидаемая схема структуры хранения данных? И потом код с ней работает, вообще ничего не проверяя, авось никто структуру не поменял? И что будет, если в структуру были внесены изменения, а в код по какой-то причине ещё нет - если повезёт, то вылетим по ошибке, а если нет, то "Здравствуй, армагеддон"? Не-е-е, такой хоккей нам не нужен.

А как вам запрос структуры поможет, если эту структуру абы как поменяли, например, до запуска приложения? В любом случае на этапе запроса получим ошибку, что схема не соответствует ожидаемой.

Вы извлечённые из базы данные потом как‑то должны обработать. И если эта обработка — не просто «получи и передай куда‑то ещё как‑есть», тогда вы ожидаете, что данные будут содержать определённые поля и хранить данные определённого типа, чтобы понимать, как это обрабатывать.

Для этого у вас должны быть гарантии, что вы извлекли то, что ожидали извлечь, и ничего неожиданного (например, данные из других полей) не получили. Для получения этих гарантий требуется выбрать, что будет источником истины: приложение или база — что‑то одно.

В данном случае источник истинны — код, в котором мы сами описываем ту схему данных, с которое это приложение умеет работать. И да, вы правильно заметили, что структура базы может поменяться, и надо как‑то обеспечить поддержку этих изменений в приложении. Для этого есть свои инструменты.

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

Ещё можно использовать версионирование моделей данных, чтобы обеспечить обратную совместимость, а запросом структуры тогда уже решать, какую версию моделей брать. Но появление новой структуры всё равно требует изменений кода.

Описанные выше подходы были про Code First. Есть ещё DB first, когда мы извлекаем из базы описание структуры и, например, генерируем описание схемы и модели в коде.
Однако тут также требуется на этапе разработки после изменения схемы базы вызвать соответствующие инструменты. Так что это как будто ещё более нестабильно.

Как видим, код всё равно менять придётся. Так что я не совсем понимаю, что именно вы вкладывали в сценарий "кто-то поменял структуру"?

Понятно, вы - адепт подхода "вся логика на клиенте". Тогда мы точно не договоримся. Вопросы снимаются.

Каким образом "логика на клиенте" связана с тем, что источник информации о структуре БД - бекенд? Это не просто нормальная практика, это фактически доминирующий подход в современных ORM - когда структуру требуется поменять в реальной БД - делают миграцию, но главный источник этой структуры - всегда бекенд.

Причем здесь клиент я не понимаю.

Подразумевается, что базу создает разработчик бэкенда, а не какой-то там DBA. Т.е. схема пишется в Typescript, создаются миграции и накатываются в базу. И не дай бог кто-то там в базе что-то поправит.

Да, именно показанный текст запроса. Таблица users объявлена выше по тексту - в ней 2 колонки, id и firstName. Разные ORM поступают по разному - какие-то действительно делают `select *`, а какие-то перечисляют колонки. Drizzle - перечисляет.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации