Skip to content

Commit

Permalink
fix(types): allow Op.contains on a jsonb column (#16167)
Browse files Browse the repository at this point in the history
  • Loading branch information
jwatzman committed Jul 21, 2023
1 parent 0012466 commit 70c2bf5
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 1 deletion.
5 changes: 4 additions & 1 deletion packages/core/src/model.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,10 @@ export interface WhereOperators<AttributeType = any> {
// https://www.postgresql.org/docs/14/functions-array.html array @> array
[Op.contains]?:
// RANGE @> ELEMENT
| AttributeType extends Range<infer RangeType> ? OperatorValues<OperatorValues<NonNullable<RangeType>>> : never
| AttributeType extends Range<infer RangeType> ? OperatorValues<OperatorValues<NonNullable<RangeType>>>
// jsonb @> ELEMENT
: AttributeType extends object ? OperatorValues<Partial<AttributeType>>
: never
// ARRAY @> ARRAY ; RANGE @> RANGE
| WhereOperators<AttributeType>[typeof Op.overlap];

Expand Down
35 changes: 35 additions & 0 deletions packages/core/test/unit/sql/where.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ const dialectSupportsJsonOperations = () => sequelize.dialect.supports.jsonOpera
const dialectSupportsJsonQuotedExtraction = () => sequelize.dialect.supports.jsonExtraction.quoted;
const dialectSupportsJsonUnquotedExtraction = () => sequelize.dialect.supports.jsonExtraction.unquoted;

interface SomeInterface {
foo: string;
}

class TestModel extends Model<InferAttributes<TestModel>> {
declare intAttr1: number;
declare intAttr2: number;
Expand All @@ -64,6 +68,9 @@ class TestModel extends Model<InferAttributes<TestModel>> {
declare aliasedJsonAttr: object;
declare aliasedJsonbAttr: object;

declare jsonbTypeLiteralAttr: { foo: string };
declare jsonbInterfaceAttr: SomeInterface;

declare uuidAttr: string;
}

Expand Down Expand Up @@ -96,6 +103,8 @@ TestModel.init({
...(dialectSupportsJsonB() && {
jsonbAttr: { type: DataTypes.JSONB },
aliasedJsonbAttr: { type: DataTypes.JSONB, field: 'aliased_jsonb' },
jsonbTypeLiteralAttr: { type: DataTypes.JSONB },
jsonbInterfaceAttr: { type: DataTypes.JSONB },
}),

uuidAttr: DataTypes.UUID,
Expand Down Expand Up @@ -2431,6 +2440,32 @@ Caused by: "undefined" cannot be escaped`),
default: `[jsonbAttr] @> '{"company":"Magnafone"}'`,
});

testSql({
jsonbTypeLiteralAttr: { [Op.contains]: { foo: 'bar' } },
}, {
postgres: '"jsonbTypeLiteralAttr" @> \'{"foo":"bar"}\'',
});

testSql({
// @ts-expect-error -- key `bad` isn't known
jsonbTypeLiteralAttr: { [Op.contains]: { bad: 'bad' } },
}, {
postgres: '"jsonbTypeLiteralAttr" @> \'{"bad":"bad"}\'',
});

testSql({
jsonbInterfaceAttr: { [Op.contains]: { foo: 'bar' } },
}, {
postgres: '"jsonbInterfaceAttr" @> \'{"foo":"bar"}\'',
});

testSql({
// @ts-expect-error -- key `bad` isn't known
jsonbInterfaceAttr: { [Op.contains]: { bad: 'bad' } },
}, {
postgres: '"jsonbInterfaceAttr" @> \'{"bad":"bad"}\'',
});

// aliases correctly

testSql({ aliasedJsonbAttr: { key: 'value' } }, {
Expand Down

0 comments on commit 70c2bf5

Please sign in to comment.