feat: add support for indexes (#7756)
This commit is contained in:
@@ -479,6 +479,91 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("Entity builder | indexes", () => {
|
||||||
|
test("define index on a field", () => {
|
||||||
|
const model = new EntityBuilder()
|
||||||
|
const user = model.define("user", {
|
||||||
|
id: model.number().index(),
|
||||||
|
username: model.text(),
|
||||||
|
email: model.text().unique(),
|
||||||
|
})
|
||||||
|
|
||||||
|
const entityBuilder = createMikrORMEntity()
|
||||||
|
const User = entityBuilder(user)
|
||||||
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
|
id: number
|
||||||
|
username: string
|
||||||
|
email: string
|
||||||
|
deleted_at: Date | null
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const metaData = MetadataStorage.getMetadataFromDecorator(User)
|
||||||
|
expect(metaData.className).toEqual("User")
|
||||||
|
expect(metaData.path).toEqual("User")
|
||||||
|
|
||||||
|
expect(metaData.indexes).toEqual([
|
||||||
|
{
|
||||||
|
name: "IDX_users_id",
|
||||||
|
expression:
|
||||||
|
'CREATE INDEX IF NOT EXISTS "IDX_users_id" ON "users" (id) WHERE deleted_at IS NULL',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "IDX_users_email",
|
||||||
|
expression:
|
||||||
|
'CREATE UNIQUE INDEX IF NOT EXISTS "IDX_users_email" ON "users" (email) WHERE deleted_at IS NULL',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
expect(metaData.filters).toEqual({
|
||||||
|
softDeletable: {
|
||||||
|
name: "softDeletable",
|
||||||
|
cond: expect.any(Function),
|
||||||
|
default: true,
|
||||||
|
args: false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(metaData.properties).toEqual({
|
||||||
|
id: {
|
||||||
|
reference: "scalar",
|
||||||
|
type: "number",
|
||||||
|
columnType: "integer",
|
||||||
|
name: "id",
|
||||||
|
nullable: false,
|
||||||
|
getter: false,
|
||||||
|
setter: false,
|
||||||
|
},
|
||||||
|
username: {
|
||||||
|
reference: "scalar",
|
||||||
|
type: "string",
|
||||||
|
columnType: "text",
|
||||||
|
name: "username",
|
||||||
|
nullable: false,
|
||||||
|
getter: false,
|
||||||
|
setter: false,
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
reference: "scalar",
|
||||||
|
type: "string",
|
||||||
|
columnType: "text",
|
||||||
|
name: "email",
|
||||||
|
nullable: false,
|
||||||
|
getter: false,
|
||||||
|
setter: false,
|
||||||
|
},
|
||||||
|
deleted_at: {
|
||||||
|
reference: "scalar",
|
||||||
|
type: "date",
|
||||||
|
columnType: "timestamptz",
|
||||||
|
name: "deleted_at",
|
||||||
|
nullable: true,
|
||||||
|
getter: false,
|
||||||
|
setter: false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe("Entity builder | hasOne", () => {
|
describe("Entity builder | hasOne", () => {
|
||||||
test("define hasOne relationship", () => {
|
test("define hasOne relationship", () => {
|
||||||
const model = new EntityBuilder()
|
const model = new EntityBuilder()
|
||||||
|
|||||||
@@ -9,7 +9,11 @@ import {
|
|||||||
Filter,
|
Filter,
|
||||||
} from "@mikro-orm/core"
|
} from "@mikro-orm/core"
|
||||||
import { DmlEntity } from "../entity"
|
import { DmlEntity } from "../entity"
|
||||||
import { camelToSnakeCase, pluralize } from "../../common"
|
import {
|
||||||
|
pluralize,
|
||||||
|
camelToSnakeCase,
|
||||||
|
createPsqlIndexStatementHelper,
|
||||||
|
} from "../../common"
|
||||||
import { upperCaseFirst } from "../../common/upper-case-first"
|
import { upperCaseFirst } from "../../common/upper-case-first"
|
||||||
import type {
|
import type {
|
||||||
Infer,
|
Infer,
|
||||||
@@ -114,6 +118,30 @@ export function createMikrORMEntity() {
|
|||||||
})(MikroORMEntity.prototype, field.fieldName)
|
})(MikroORMEntity.prototype, field.fieldName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares indexes for a given field
|
||||||
|
*/
|
||||||
|
function applyIndexes(
|
||||||
|
MikroORMEntity: EntityConstructor<any>,
|
||||||
|
tableName: string,
|
||||||
|
field: SchemaMetadata
|
||||||
|
) {
|
||||||
|
field.indexes.forEach((index) => {
|
||||||
|
const name =
|
||||||
|
index.name || `IDX_${tableName}_${camelToSnakeCase(field.fieldName)}`
|
||||||
|
|
||||||
|
const providerEntityIdIndexStatement = createPsqlIndexStatementHelper({
|
||||||
|
name,
|
||||||
|
tableName,
|
||||||
|
columns: [field.fieldName],
|
||||||
|
unique: index.type === "unique",
|
||||||
|
where: "deleted_at IS NULL",
|
||||||
|
})
|
||||||
|
|
||||||
|
providerEntityIdIndexStatement.MikroORMIndex()(MikroORMEntity)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines has one relationship on the Mikro ORM entity.
|
* Defines has one relationship on the Mikro ORM entity.
|
||||||
*/
|
*/
|
||||||
@@ -421,6 +449,7 @@ export function createMikrORMEntity() {
|
|||||||
const field = property.parse(name)
|
const field = property.parse(name)
|
||||||
if ("fieldName" in field) {
|
if ("fieldName" in field) {
|
||||||
defineProperty(MikroORMEntity, field)
|
defineProperty(MikroORMEntity, field)
|
||||||
|
applyIndexes(MikroORMEntity, tableName, field)
|
||||||
} else {
|
} else {
|
||||||
defineRelationship(MikroORMEntity, field, cascades)
|
defineRelationship(MikroORMEntity, field, cascades)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,22 @@ export abstract class BaseSchema<T> implements SchemaType<T> {
|
|||||||
return new NullableModifier<T, this>(this)
|
return new NullableModifier<T, this>(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define an index on the property
|
||||||
|
*/
|
||||||
|
index(name?: string) {
|
||||||
|
this.#indexes.push({ name, type: "index" })
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define a unique index on the property
|
||||||
|
*/
|
||||||
|
unique(name?: string) {
|
||||||
|
this.#indexes.push({ name, type: "unique" })
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define default value for the property
|
* Define default value for the property
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ export type SchemaMetadata = MaybeFieldMetadata & {
|
|||||||
options?: Record<string, any>
|
options?: Record<string, any>
|
||||||
}
|
}
|
||||||
indexes: {
|
indexes: {
|
||||||
name: string
|
name?: string
|
||||||
type: string
|
type: "index" | "unique"
|
||||||
}[]
|
}[]
|
||||||
relationships: RelationshipMetadata[]
|
relationships: RelationshipMetadata[]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user