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", () => {
|
||||
test("define hasOne relationship", () => {
|
||||
const model = new EntityBuilder()
|
||||
|
||||
@@ -9,7 +9,11 @@ import {
|
||||
Filter,
|
||||
} from "@mikro-orm/core"
|
||||
import { DmlEntity } from "../entity"
|
||||
import { camelToSnakeCase, pluralize } from "../../common"
|
||||
import {
|
||||
pluralize,
|
||||
camelToSnakeCase,
|
||||
createPsqlIndexStatementHelper,
|
||||
} from "../../common"
|
||||
import { upperCaseFirst } from "../../common/upper-case-first"
|
||||
import type {
|
||||
Infer,
|
||||
@@ -114,6 +118,30 @@ export function createMikrORMEntity() {
|
||||
})(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.
|
||||
*/
|
||||
@@ -421,6 +449,7 @@ export function createMikrORMEntity() {
|
||||
const field = property.parse(name)
|
||||
if ("fieldName" in field) {
|
||||
defineProperty(MikroORMEntity, field)
|
||||
applyIndexes(MikroORMEntity, tableName, field)
|
||||
} else {
|
||||
defineRelationship(MikroORMEntity, field, cascades)
|
||||
}
|
||||
|
||||
@@ -29,6 +29,22 @@ export abstract class BaseSchema<T> implements SchemaType<T> {
|
||||
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
|
||||
*/
|
||||
|
||||
@@ -42,8 +42,8 @@ export type SchemaMetadata = MaybeFieldMetadata & {
|
||||
options?: Record<string, any>
|
||||
}
|
||||
indexes: {
|
||||
name: string
|
||||
type: string
|
||||
name?: string
|
||||
type: "index" | "unique"
|
||||
}[]
|
||||
relationships: RelationshipMetadata[]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user