feat: new array find operators (#8766)

* added new array find operators; delegating how json and jsonb are stored directly to underlying driver (breaking)

* array: true must be explicitly defined for array json/jsonb values; strings being JSON-stringified must be manually escpaed
This commit is contained in:
Umed Khudoiberdiev 2022-03-21 17:48:32 +05:00 committed by GitHub
parent d61f857ce9
commit 9f1b8e3425
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 938 additions and 27 deletions

View File

@ -426,6 +426,13 @@ This change was required to simplify ORM internals and introduce new features.
* issue with non-reliable `new Date(ISOString)` parsing ([#7796](https://github.com/typeorm/typeorm/pull/7796))
* true JSON / JSONB support - manual `JSON.stringify` was removed,
instead object handled by underlying driver. This opens ability to properly work with json/jsonb structures,
but brings few breaking changes:
* `array: true` must be explicitly defined for array json/jsonb values
* strings being JSON-stringified must be manually escaped
### DEPRECATIONS
* all CLI commands do not support `ormconfig` anymore. You must specify a file with data source instance instead.

View File

@ -488,6 +488,54 @@ will execute following query:
SELECT * FROM "post" WHERE "title" IS NULL
```
- `ArrayContains`
```ts
import { ArrayContains } from "typeorm"
const loadedPosts = await dataSource.getRepository(Post).findBy({
categories: ArrayContains(["TypeScript"]),
})
```
will execute following query:
```sql
SELECT * FROM "post" WHERE "categories" @> '{TypeScript}'
```
- `ArrayContainedBy`
```ts
import { ArrayContainedBy } from "typeorm"
const loadedPosts = await dataSource.getRepository(Post).findBy({
categories: ArrayContainedBy(["TypeScript"]),
})
```
will execute following query:
```sql
SELECT * FROM "post" WHERE "categories" <@ '{TypeScript}'
```
- `ArrayOverlap`
```ts
import { ArrayOverlap } from "typeorm"
const loadedPosts = await dataSource.getRepository(Post).findBy({
categories: ArrayOverlap(["TypeScript"]),
})
```
will execute following query:
```sql
SELECT * FROM "post" WHERE "categories" && '{TypeScript}'
```
- `Raw`
```ts

View File

@ -622,7 +622,7 @@ export class PostgresDriver implements Driver {
columnMetadata.type,
) >= 0
) {
return JSON.stringify(value)
return value // JSON.stringify()
} else if (columnMetadata.type === "hstore") {
if (typeof value === "string") {
return value

View File

@ -15,3 +15,6 @@ export type FindOperatorType =
| "ilike"
| "like"
| "raw"
| "arrayContains"
| "arrayContainedBy"
| "arrayOverlap"

View File

@ -0,0 +1,11 @@
import { FindOperator } from "../FindOperator"
/**
* FindOptions Operator.
* Example: { someField: ArrayContainedBy([...]) }
*/
export function ArrayContainedBy<T>(
value: T[] | FindOperator<T>,
): FindOperator<any> {
return new FindOperator("arrayContainedBy", value as any)
}

View File

@ -0,0 +1,11 @@
import { FindOperator } from "../FindOperator"
/**
* FindOptions Operator.
* Example: { someField: ArrayContains([...]) }
*/
export function ArrayContains<T>(
value: T[] | FindOperator<T>,
): FindOperator<any> {
return new FindOperator("arrayContains", value as any)
}

View File

@ -0,0 +1,11 @@
import { FindOperator } from "../FindOperator"
/**
* FindOptions Operator.
* Example: { someField: ArrayOverlap([...]) }
*/
export function ArrayOverlap<T>(
value: T[] | FindOperator<T>,
): FindOperator<any> {
return new FindOperator("arrayOverlap", value as any)
}

View File

@ -993,6 +993,12 @@ export abstract class QueryBuilder<Entity> {
return `${condition.parameters[0]} < ${condition.parameters[1]}`
case "lessThanOrEqual":
return `${condition.parameters[0]} <= ${condition.parameters[1]}`
case "arrayContains":
return `${condition.parameters[0]} @> ${condition.parameters[1]}`
case "arrayContainedBy":
return `${condition.parameters[0]} <@ ${condition.parameters[1]}`
case "arrayOverlap":
return `${condition.parameters[0]} && ${condition.parameters[1]}`
case "moreThan":
return `${condition.parameters[0]} > ${condition.parameters[1]}`
case "moreThanOrEqual":

View File

@ -13,6 +13,9 @@ type PredicateOperator =
| "in"
| "any"
| "isNull"
| "arrayContains"
| "arrayContainedBy"
| "arrayOverlap"
export interface WherePredicateOperator {
operator: PredicateOperator

View File

@ -16,7 +16,7 @@ export class Document {
@Column("text")
context: string
@Column({ type: "jsonb" })
@Column({ type: "jsonb", array: true })
distributions: Distribution[]
@Column({ type: "timestamp with time zone" })

View File

@ -0,0 +1,253 @@
import "../../../utils/test-setup"
import { DataSource, EntityManager } from "../../../../src"
import {
closeTestingConnections,
createTestingConnections,
reloadTestingDatabases,
} from "../../../utils/test-utils"
import { Post, PostStatus } from "./entity/Post"
import { ArrayContainedBy } from "../../../../src/find-options/operator/ArrayContainedBy"
describe("find options > find operators > ArrayContainedBy", () => {
let connections: DataSource[]
before(
async () =>
(connections = await createTestingConnections({
__dirname,
enabledDrivers: ["postgres"],
// logging: true,
})),
)
beforeEach(() => reloadTestingDatabases(connections))
after(() => closeTestingConnections(connections))
async function prepareData(manager: EntityManager) {
const post1 = new Post()
post1.title = "Post #1"
post1.authors = ["dmitry", "olimjon"]
post1.categories = [{ name: "typescript" }, { name: "programming" }]
post1.statuses = [PostStatus.draft, PostStatus.published]
await manager.save(post1)
const post2 = new Post()
post2.title = "Post #2"
post2.authors = ["olimjon"]
post2.categories = [{ name: "programming" }]
post2.statuses = [PostStatus.published]
await manager.save(post2)
const post3 = new Post()
post3.title = "Post #3"
post3.authors = []
post3.categories = []
post3.statuses = []
await manager.save(post3)
}
it("should find entries in regular arrays", () =>
Promise.all(
connections.map(async (connection) => {
await prepareData(connection.manager)
const loadedPost1 = await connection.manager.find(Post, {
where: {
authors: ArrayContainedBy(["dmitry", "olimjon"]),
},
order: {
id: "asc",
},
})
loadedPost1.should.be.eql([
{
id: 1,
title: "Post #1",
authors: ["dmitry", "olimjon"],
categories: [
{ name: "typescript" },
{ name: "programming" },
],
statuses: [PostStatus.draft, PostStatus.published],
},
{
id: 2,
title: "Post #2",
authors: ["olimjon"],
categories: [{ name: "programming" }],
statuses: [PostStatus.published],
},
{
id: 3,
title: "Post #3",
authors: [],
categories: [],
statuses: [],
},
])
const loadedPost2 = await connection.manager.find(Post, {
where: {
authors: ArrayContainedBy(["olimjon"]),
},
order: {
id: "asc",
},
})
loadedPost2.should.be.eql([
{
id: 2,
title: "Post #2",
authors: ["olimjon"],
categories: [{ name: "programming" }],
statuses: [PostStatus.published],
},
{
id: 3,
title: "Post #3",
authors: [],
categories: [],
statuses: [],
},
])
}),
))
it("should find entries in jsonb", () =>
Promise.all(
connections.map(async (connection) => {
await prepareData(connection.manager)
const loadedPost1 = await connection.manager.find(Post, {
where: {
categories: ArrayContainedBy([
{ name: "typescript" },
{ name: "programming" },
]),
},
order: {
id: "asc",
},
})
loadedPost1.should.be.eql([
{
id: 1,
title: "Post #1",
authors: ["dmitry", "olimjon"],
categories: [
{ name: "typescript" },
{ name: "programming" },
],
statuses: [PostStatus.draft, PostStatus.published],
},
{
id: 2,
title: "Post #2",
authors: ["olimjon"],
categories: [{ name: "programming" }],
statuses: [PostStatus.published],
},
{
id: 3,
title: "Post #3",
authors: [],
categories: [],
statuses: [],
},
])
const loadedPost2 = await connection.manager.find(Post, {
where: {
categories: ArrayContainedBy([{ name: "programming" }]),
},
order: {
id: "asc",
},
})
loadedPost2.should.be.eql([
{
id: 2,
title: "Post #2",
authors: ["olimjon"],
categories: [{ name: "programming" }],
statuses: [PostStatus.published],
},
{
id: 3,
title: "Post #3",
authors: [],
categories: [],
statuses: [],
},
])
}),
))
it("should find entries in enum arrays", () =>
Promise.all(
connections.map(async (connection) => {
await prepareData(connection.manager)
const loadedPost1 = await connection.manager.find(Post, {
where: {
statuses: ArrayContainedBy([
PostStatus.draft,
PostStatus.published,
]),
},
order: {
id: "asc",
},
})
loadedPost1.should.be.eql([
{
id: 1,
title: "Post #1",
authors: ["dmitry", "olimjon"],
categories: [
{ name: "typescript" },
{ name: "programming" },
],
statuses: [PostStatus.draft, PostStatus.published],
},
{
id: 2,
title: "Post #2",
authors: ["olimjon"],
categories: [{ name: "programming" }],
statuses: [PostStatus.published],
},
{
id: 3,
title: "Post #3",
authors: [],
categories: [],
statuses: [],
},
])
const loadedPost2 = await connection.manager.find(Post, {
where: {
statuses: ArrayContainedBy([PostStatus.published]),
},
order: {
id: "asc",
},
})
loadedPost2.should.be.eql([
{
id: 2,
title: "Post #2",
authors: ["olimjon"],
categories: [{ name: "programming" }],
statuses: [PostStatus.published],
},
{
id: 3,
title: "Post #3",
authors: [],
categories: [],
statuses: [],
},
])
}),
))
})

View File

@ -0,0 +1,39 @@
import { Column, Entity, PrimaryGeneratedColumn } from "../../../../../src"
export type PostCategory = {
name: string
}
export enum PostStatus {
draft = "draft",
published = "published",
unknown = "unknown",
}
@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number
@Column()
title: string
@Column({
type: "varchar",
array: true,
})
authors: string[]
@Column({
type: "jsonb",
array: true,
})
categories: PostCategory[]
@Column({
type: "enum",
enum: PostStatus,
array: true,
})
statuses: PostStatus[]
}

View File

@ -0,0 +1,214 @@
import "../../../utils/test-setup"
import { DataSource, EntityManager } from "../../../../src"
import {
closeTestingConnections,
createTestingConnections,
reloadTestingDatabases,
} from "../../../utils/test-utils"
import { Post, PostStatus } from "./entity/Post"
import { ArrayContains } from "../../../../src/find-options/operator/ArrayContains"
describe("find options > find operators > ArrayContains", () => {
let connections: DataSource[]
before(
async () =>
(connections = await createTestingConnections({
__dirname,
enabledDrivers: ["postgres"],
logging: true,
})),
)
beforeEach(() => reloadTestingDatabases(connections))
after(() => closeTestingConnections(connections))
async function prepareData(manager: EntityManager) {
const post1 = new Post()
post1.title = "Post #1"
post1.authors = ["dmitry", "olimjon"]
post1.categories = [{ name: "typescript" }, { name: "programming" }]
post1.statuses = [PostStatus.draft, PostStatus.published]
await manager.save(post1)
const post2 = new Post()
post2.title = "Post #2"
post2.authors = ["olimjon"]
post2.categories = [{ name: "programming" }]
post2.statuses = [PostStatus.published]
await manager.save(post2)
const post3 = new Post()
post3.title = "Post #3"
post3.authors = []
post3.categories = []
post3.statuses = []
await manager.save(post3)
}
it("should find entries in regular arrays", () =>
Promise.all(
connections.map(async (connection) => {
await prepareData(connection.manager)
const loadedPost1 = await connection.manager.find(Post, {
where: {
authors: ArrayContains(["dmitry"]),
},
order: {
id: "asc",
},
})
loadedPost1.should.be.eql([
{
id: 1,
title: "Post #1",
authors: ["dmitry", "olimjon"],
categories: [
{ name: "typescript" },
{ name: "programming" },
],
statuses: [PostStatus.draft, PostStatus.published],
},
])
const loadedPost2 = await connection.manager.find(Post, {
where: {
authors: ArrayContains(["olimjon"]),
},
order: {
id: "asc",
},
})
loadedPost2.should.be.eql([
{
id: 1,
title: "Post #1",
authors: ["dmitry", "olimjon"],
categories: [
{ name: "typescript" },
{ name: "programming" },
],
statuses: [PostStatus.draft, PostStatus.published],
},
{
id: 2,
title: "Post #2",
authors: ["olimjon"],
categories: [{ name: "programming" }],
statuses: [PostStatus.published],
},
])
}),
))
it("should find entries in jsonb", () =>
Promise.all(
connections.map(async (connection) => {
await prepareData(connection.manager)
const loadedPost1 = await connection.manager.find(Post, {
where: {
categories: ArrayContains([{ name: "typescript" }]),
},
order: {
id: "asc",
},
})
loadedPost1.should.be.eql([
{
id: 1,
title: "Post #1",
authors: ["dmitry", "olimjon"],
categories: [
{ name: "typescript" },
{ name: "programming" },
],
statuses: [PostStatus.draft, PostStatus.published],
},
])
const loadedPost2 = await connection.manager.find(Post, {
where: {
categories: ArrayContains([{ name: "programming" }]),
},
order: {
id: "asc",
},
})
loadedPost2.should.be.eql([
{
id: 1,
title: "Post #1",
authors: ["dmitry", "olimjon"],
categories: [
{ name: "typescript" },
{ name: "programming" },
],
statuses: [PostStatus.draft, PostStatus.published],
},
{
id: 2,
title: "Post #2",
authors: ["olimjon"],
categories: [{ name: "programming" }],
statuses: [PostStatus.published],
},
])
}),
))
it("should find entries in enum arrays", () =>
Promise.all(
connections.map(async (connection) => {
await prepareData(connection.manager)
const loadedPost1 = await connection.manager.find(Post, {
where: {
statuses: ArrayContains([PostStatus.draft]),
},
order: {
id: "asc",
},
})
loadedPost1.should.be.eql([
{
id: 1,
title: "Post #1",
authors: ["dmitry", "olimjon"],
categories: [
{ name: "typescript" },
{ name: "programming" },
],
statuses: [PostStatus.draft, PostStatus.published],
},
])
const loadedPost2 = await connection.manager.find(Post, {
where: {
statuses: ArrayContains([PostStatus.published]),
},
order: {
id: "asc",
},
})
loadedPost2.should.be.eql([
{
id: 1,
title: "Post #1",
authors: ["dmitry", "olimjon"],
categories: [
{ name: "typescript" },
{ name: "programming" },
],
statuses: [PostStatus.draft, PostStatus.published],
},
{
id: 2,
title: "Post #2",
authors: ["olimjon"],
categories: [{ name: "programming" }],
statuses: [PostStatus.published],
},
])
}),
))
})

View File

@ -0,0 +1,39 @@
import { Column, Entity, PrimaryGeneratedColumn } from "../../../../../src"
export type PostCategory = {
name: string
}
export enum PostStatus {
draft = "draft",
published = "published",
unknown = "unknown",
}
@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number
@Column()
title: string
@Column({
type: "varchar",
array: true,
})
authors: string[]
@Column({
type: "jsonb",
array: true,
})
categories: PostCategory[]
@Column({
type: "enum",
enum: PostStatus,
array: true,
})
statuses: PostStatus[]
}

View File

@ -0,0 +1,226 @@
import "../../../utils/test-setup"
import { DataSource, EntityManager } from "../../../../src"
import {
closeTestingConnections,
createTestingConnections,
reloadTestingDatabases,
} from "../../../utils/test-utils"
import { Post, PostStatus } from "./entity/Post"
import { ArrayOverlap } from "../../../../src/find-options/operator/ArrayOverlap"
describe("find options > find operators > ArrayOverlap", () => {
let connections: DataSource[]
before(
async () =>
(connections = await createTestingConnections({
__dirname,
enabledDrivers: ["postgres"],
// logging: true,
})),
)
beforeEach(() => reloadTestingDatabases(connections))
after(() => closeTestingConnections(connections))
async function prepareData(manager: EntityManager) {
const post1 = new Post()
post1.title = "Post #1"
post1.authors = ["dmitry", "olimjon"]
post1.categories = [{ name: "typescript" }, { name: "programming" }]
post1.statuses = [PostStatus.draft, PostStatus.published]
await manager.save(post1)
const post2 = new Post()
post2.title = "Post #2"
post2.authors = ["olimjon"]
post2.categories = [{ name: "programming" }]
post2.statuses = [PostStatus.published]
await manager.save(post2)
const post3 = new Post()
post3.title = "Post #3"
post3.authors = []
post3.categories = []
post3.statuses = []
await manager.save(post3)
}
it("should find entries in regular arrays", () =>
Promise.all(
connections.map(async (connection) => {
await prepareData(connection.manager)
const loadedPost1 = await connection.manager.find(Post, {
where: {
authors: ArrayOverlap(["dmitry", "umed"]),
},
order: {
id: "asc",
},
})
loadedPost1.should.be.eql([
{
id: 1,
title: "Post #1",
authors: ["dmitry", "olimjon"],
categories: [
{ name: "typescript" },
{ name: "programming" },
],
statuses: [PostStatus.draft, PostStatus.published],
},
])
const loadedPost2 = await connection.manager.find(Post, {
where: {
authors: ArrayOverlap(["olimjon", "umed"]),
},
order: {
id: "asc",
},
})
loadedPost2.should.be.eql([
{
id: 1,
title: "Post #1",
authors: ["dmitry", "olimjon"],
categories: [
{ name: "typescript" },
{ name: "programming" },
],
statuses: [PostStatus.draft, PostStatus.published],
},
{
id: 2,
title: "Post #2",
authors: ["olimjon"],
categories: [{ name: "programming" }],
statuses: [PostStatus.published],
},
])
}),
))
it("should find entries in jsonb", () =>
Promise.all(
connections.map(async (connection) => {
await prepareData(connection.manager)
const loadedPost1 = await connection.manager.find(Post, {
where: {
categories: ArrayOverlap([
{ name: "typescript" },
{ name: "python" },
]),
},
order: {
id: "asc",
},
})
loadedPost1.should.be.eql([
{
id: 1,
title: "Post #1",
authors: ["dmitry", "olimjon"],
categories: [
{ name: "typescript" },
{ name: "programming" },
],
statuses: [PostStatus.draft, PostStatus.published],
},
])
const loadedPost2 = await connection.manager.find(Post, {
where: {
categories: ArrayOverlap([
{ name: "programming" },
{ name: "python" },
]),
},
order: {
id: "asc",
},
})
loadedPost2.should.be.eql([
{
id: 1,
title: "Post #1",
authors: ["dmitry", "olimjon"],
categories: [
{ name: "typescript" },
{ name: "programming" },
],
statuses: [PostStatus.draft, PostStatus.published],
},
{
id: 2,
title: "Post #2",
authors: ["olimjon"],
categories: [{ name: "programming" }],
statuses: [PostStatus.published],
},
])
}),
))
it("should find entries in enum arrays", () =>
Promise.all(
connections.map(async (connection) => {
await prepareData(connection.manager)
const loadedPost1 = await connection.manager.find(Post, {
where: {
statuses: ArrayOverlap([
PostStatus.draft,
PostStatus.unknown,
]),
},
order: {
id: "asc",
},
})
loadedPost1.should.be.eql([
{
id: 1,
title: "Post #1",
authors: ["dmitry", "olimjon"],
categories: [
{ name: "typescript" },
{ name: "programming" },
],
statuses: [PostStatus.draft, PostStatus.published],
},
])
const loadedPost2 = await connection.manager.find(Post, {
where: {
statuses: ArrayOverlap([
PostStatus.published,
PostStatus.unknown,
]),
},
order: {
id: "asc",
},
})
loadedPost2.should.be.eql([
{
id: 1,
title: "Post #1",
authors: ["dmitry", "olimjon"],
categories: [
{ name: "typescript" },
{ name: "programming" },
],
statuses: [PostStatus.draft, PostStatus.published],
},
{
id: 2,
title: "Post #2",
authors: ["olimjon"],
categories: [{ name: "programming" }],
statuses: [PostStatus.published],
},
])
}),
))
})

View File

@ -0,0 +1,39 @@
import { Column, Entity, PrimaryGeneratedColumn } from "../../../../../src"
export type PostCategory = {
name: string
}
export enum PostStatus {
draft = "draft",
published = "published",
unknown = "unknown",
}
@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number
@Column()
title: string
@Column({
type: "varchar",
array: true,
})
authors: string[]
@Column({
type: "jsonb",
array: true,
})
categories: PostCategory[]
@Column({
type: "enum",
enum: PostStatus,
array: true,
})
statuses: PostStatus[]
}

View File

@ -1,6 +1,4 @@
import { Entity } from "../../../../src/decorator/entity/Entity"
import { PrimaryGeneratedColumn } from "../../../../src/decorator/columns/PrimaryGeneratedColumn"
import { Column } from "../../../../src/decorator/columns/Column"
import { Column, Entity, PrimaryGeneratedColumn } from "../../../../src"
/**
* For testing Postgres jsonb
@ -16,6 +14,9 @@ export class Record {
@Column({ type: "jsonb", nullable: true })
data: any
@Column({ type: "jsonb", nullable: true, array: true })
data2: any
@Column({
type: "jsonb",
nullable: true,

View File

@ -1,10 +1,11 @@
import "reflect-metadata"
import "../../utils/test-setup"
import { expect } from "chai"
import { Record } from "./entity/Record"
import { DataSource } from "../../../src/data-source/DataSource"
import { DataSource } from "../../../src"
import {
closeTestingConnections,
createTestingConnections,
reloadTestingDatabases,
} from "../../utils/test-utils"
describe("jsonb type", () => {
@ -14,9 +15,10 @@ describe("jsonb type", () => {
(connections = await createTestingConnections({
entities: [Record],
enabledDrivers: ["postgres"], // because only postgres supports jsonb type
logging: true,
})),
)
// beforeEach(() => reloadTestingDatabases(connections));
beforeEach(() => reloadTestingDatabases(connections))
after(() => closeTestingConnections(connections))
it("should make correct schema with Postgres' jsonb type", () =>
@ -84,7 +86,7 @@ describe("jsonb type", () => {
connections.map(async (connection) => {
let recordRepo = connection.getRepository(Record)
let record = new Record()
record.data = "foo"
record.data = `"foo"`
let persistedRecord = await recordRepo.save(record)
let foundRecord = await recordRepo.findOneBy({
id: persistedRecord.id,
@ -100,13 +102,13 @@ describe("jsonb type", () => {
connections.map(async (connection) => {
let recordRepo = connection.getRepository(Record)
let record = new Record()
record.data = [1, "2", { a: 3 }]
record.data2 = [1, `"2"`, { a: 3 }]
let persistedRecord = await recordRepo.save(record)
let foundRecord = await recordRepo.findOneBy({
id: persistedRecord.id,
})
expect(foundRecord).to.be.not.undefined
expect(foundRecord!.data).to.deep.include.members([
expect(foundRecord!.data2).to.deep.include.members([
1,
"2",
{ a: 3 },

View File

@ -1,10 +1,10 @@
import "reflect-metadata"
import "../../utils/test-setup"
import {
createTestingConnections,
closeTestingConnections,
reloadTestingDatabases,
} from "../../utils/test-utils"
import { DataSource } from "../../../src/data-source/DataSource"
import { DataSource } from "../../../src"
import { expect } from "chai"
import { Record } from "./entity/Record"

View File

@ -1,6 +1,4 @@
import { Entity } from "../../../../src/decorator/entity/Entity"
import { PrimaryGeneratedColumn } from "../../../../src/decorator/columns/PrimaryGeneratedColumn"
import { Column } from "../../../../src/decorator/columns/Column"
import { Column, Entity, PrimaryGeneratedColumn } from "../../../../src"
import { RecordData } from "./RecordData"
import { RecordConfig } from "./RecordConfig"
@ -9,9 +7,9 @@ export class Record {
@PrimaryGeneratedColumn()
id: number
@Column({ type: "json" })
@Column({ type: "json", array: true })
configs: RecordConfig[]
@Column({ type: "jsonb" })
@Column({ type: "jsonb", array: true })
datas: RecordData[]
}

View File

@ -1,7 +1,7 @@
import "reflect-metadata"
import "../../utils/test-setup"
import { expect } from "chai"
import { Record } from "./entity/Record"
import { DataSource } from "../../../src/data-source/DataSource"
import { DataSource } from "../../../src"
import {
closeTestingConnections,
createTestingConnections,

View File

@ -10,6 +10,6 @@ export class Post {
@VersionColumn()
version: number
@Column({ type: "jsonb" })
@Column({ type: "jsonb", array: true })
problems: object
}

View File

@ -1,4 +1,4 @@
import "reflect-metadata"
import "../../utils/test-setup"
import { DataSource } from "../../../src"
import {
closeTestingConnections,

View File

@ -1,10 +1,10 @@
import "reflect-metadata"
import "../../utils/test-setup"
import {
closeTestingConnections,
createTestingConnections,
reloadTestingDatabases,
} from "../../utils/test-utils"
import { DataSource } from "../../../src/data-source/DataSource"
import { DataSource } from "../../../src"
import { Post } from "./entity/Post"
import { expect } from "chai"

View File

@ -1,4 +1,4 @@
import "reflect-metadata"
import "../../utils/test-setup"
import { expect } from "chai"
import { DataSource } from "../../../src"
import {

View File

@ -1,10 +1,10 @@
import "reflect-metadata"
import "../../utils/test-setup"
import {
createTestingConnections,
closeTestingConnections,
reloadTestingDatabases,
} from "../../utils/test-utils"
import { DataSource } from "../../../src/data-source/DataSource"
import { DataSource } from "../../../src"
import { expect } from "chai"
import { DummyJSONEntity } from "./entity/json-entity"
import { DummyJSONBEntity } from "./entity/jsonb-entity"