Перейти к основному содержанию

Обработка значений null и undefined в условиях WHERE

Неофициальный Бета-перевод

Эта страница переведена PageTurner AI (бета). Не одобрена официально проектом. Нашли ошибку? Сообщить о проблеме →

В условиях 'WHERE' значения null и undefined не являются строго допустимыми в TypeORM.

Передача явного null запрещена TypeScript (при включённом strictNullChecks в tsconfig.json) на этапе компиляции. Однако поведение по умолчанию для значений null, обнаруженных во время выполнения, — их игнорирование. Аналогично значения undefined разрешены TypeScript и игнорируются при выполнении.

Такая обработка null и undefined иногда приводит к неожиданным результатам и требует осторожности. Особенно это критично при передаче значений из пользовательского ввода без должной валидации.

Например, вызов Repository.findOneBy({ id: undefined }) вернёт первую строку таблицы, а Repository.findBy({ userId: null }) не применит фильтрацию и вернёт все строки.

Поведение при обработке null и undefined можно настроить через опцию invalidWhereValuesBehavior в конфигурации источника данных. Это применяется ко всем операциям с условиями 'WHERE', включая методы поиска, построители запросов и репозитории.

примечание

Текущее поведение изменится в будущих версиях TypeORM. Рекомендуем установить поведение для null и undefined в 'throw' для подготовки к этим изменениям.

Поведение по умолчанию

По умолчанию TypeORM пропускает значения null и undefined в условиях WHERE. Это означает, что если свойство в условии содержит null или undefined, оно будет проигнорировано:

// Both queries will return all posts, ignoring the text property
const posts1 = await repository.find({
where: {
text: null,
},
})

const posts2 = await repository.find({
where: {
text: undefined,
},
})

Корректный способ поиска значений null в условиях WHERE — использование оператора IsNull (подробнее см. Опции поиска):

const posts = await repository.find({
where: {
text: IsNull(),
},
})

Настройка

Поведение для null и undefined можно настроить через опцию invalidWhereValuesBehavior в конфигурации соединения:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
null: "ignore" | "sql-null" | "throw",
undefined: "ignore" | "throw",
},
})

Опции поведения для null

Поведение null может принимать одно из трёх значений:

'ignore' (по умолчанию)

Значения JavaScript null в условиях WHERE игнорируются, и свойство пропускается:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
null: "ignore",
},
})

// This will return all posts, ignoring the text property
const posts = await repository.find({
where: {
text: null,
},
})

'sql-null'

Значения JavaScript null преобразуются в условия SQL NULL:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
null: "sql-null",
},
})

// This will only return posts where the text column is NULL in the database
const posts = await repository.find({
where: {
text: null,
},
})

'throw'

Значения JavaScript null вызывают исключение TypeORMError:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
null: "throw",
},
})

// This will throw an error
const posts = await repository.find({
where: {
text: null,
},
})
// Error: Null value encountered in property 'text' of a where condition.
// To match with SQL NULL, the IsNull() operator must be used.
// Set 'invalidWhereValuesBehavior.null' to 'ignore' or 'sql-null' in connection options to skip or handle null values.

Опции поведения для undefined

Поведение undefined может принимать одно из двух значений:

'ignore' (по умолчанию)

Значения JavaScript undefined в условиях WHERE игнорируются, и свойство пропускается:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
undefined: "ignore",
},
})

// This will return all posts, ignoring the text property
const posts = await repository.find({
where: {
text: undefined,
},
})

'throw'

Значения JavaScript undefined вызывают исключение TypeORMError:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
undefined: "throw",
},
})

// This will throw an error
const posts = await repository.find({
where: {
text: undefined,
},
})
// Error: Undefined value encountered in property 'text' of a where condition.
// Set 'invalidWhereValuesBehavior.undefined' to 'ignore' in connection options to skip properties with undefined values.

Это относится только к явно установленным значениям undefined, а не к отсутствующим свойствам.

Совместное использование опций

Оба поведения можно настроить независимо для полного контроля:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
null: "sql-null",
undefined: "throw",
},
})

Такая конфигурация:

  1. Преобразует JavaScript null в SQL NULL в условиях WHERE

  2. Выбросит исключение при обнаружении значений undefined

  3. Будет игнорировать свойства, отсутствующие в условии WHERE

Этот подход полезен, когда требуется:

  • Явно указывать поиск значений NULL в базе данных

  • Отлавливать потенциальные ошибки программирования, при которых значения undefined могут попасть в запросы

Применимость для всех операций

Конфигурация invalidWhereValuesBehavior действует для всех операций TypeORM с условиями WHERE, а не только для методов поиска в репозиториях:

Построители запросов

// UpdateQueryBuilder
await dataSource
.createQueryBuilder()
.update(Post)
.set({ title: "Updated" })
.where({ text: null }) // Respects invalidWhereValuesBehavior
.execute()

// DeleteQueryBuilder
await dataSource
.createQueryBuilder()
.delete()
.from(Post)
.where({ text: null }) // Respects invalidWhereValuesBehavior
.execute()

// SoftDeleteQueryBuilder
await dataSource
.createQueryBuilder()
.softDelete()
.from(Post)
.where({ text: null }) // Respects invalidWhereValuesBehavior
.execute()

Методы репозитория

// Repository.update()
await repository.update({ text: null }, { title: "Updated" }) // Respects invalidWhereValuesBehavior

// Repository.delete()
await repository.delete({ text: null }) // Respects invalidWhereValuesBehavior

// EntityManager.update()
await manager.update(Post, { text: null }, { title: "Updated" }) // Respects invalidWhereValuesBehavior

// EntityManager.delete()
await manager.delete(Post, { text: null }) // Respects invalidWhereValuesBehavior

// EntityManager.softDelete()
await manager.softDelete(Post, { text: null }) // Respects invalidWhereValuesBehavior

Все эти операции будут последовательно применять ваши настройки invalidWhereValuesBehavior.