@mikro-orm/mariadb 7.0.3-dev.9 → 7.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MariaDbDriver.d.ts +22 -6
- package/MariaDbDriver.js +19 -19
- package/MariaDbMikroORM.d.ts +50 -12
- package/MariaDbMikroORM.js +14 -14
- package/MariaDbPlatform.d.ts +3 -3
- package/MariaDbPlatform.js +9 -9
- package/MariaDbQueryBuilder.d.ts +7 -2
- package/MariaDbQueryBuilder.js +73 -76
- package/MariaDbSchemaHelper.d.ts +20 -8
- package/MariaDbSchemaHelper.js +142 -139
- package/README.md +2 -2
- package/index.d.ts +5 -1
- package/index.js +1 -1
- package/package.json +4 -4
package/MariaDbDriver.d.ts
CHANGED
|
@@ -1,13 +1,29 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type AnyEntity,
|
|
3
|
+
type Configuration,
|
|
4
|
+
type ConnectionType,
|
|
5
|
+
type LoggingOptions,
|
|
6
|
+
type Transaction,
|
|
7
|
+
type Constructor,
|
|
8
|
+
type EntityName,
|
|
9
|
+
} from '@mikro-orm/core';
|
|
2
10
|
import { MySqlDriver, type SqlEntityManager } from '@mikro-orm/mysql';
|
|
3
11
|
import { MariaDbPlatform } from './MariaDbPlatform.js';
|
|
4
12
|
import { MariaDbQueryBuilder } from './MariaDbQueryBuilder.js';
|
|
5
13
|
import { MariaDbMikroORM } from './MariaDbMikroORM.js';
|
|
6
14
|
/** Database driver for MariaDB, extending the MySQL driver with MariaDB-specific behavior. */
|
|
7
15
|
export declare class MariaDbDriver extends MySqlDriver {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
16
|
+
readonly platform: MariaDbPlatform;
|
|
17
|
+
constructor(config: Configuration);
|
|
18
|
+
createQueryBuilder<T extends AnyEntity<T>>(
|
|
19
|
+
entityName: EntityName<T>,
|
|
20
|
+
ctx?: Transaction,
|
|
21
|
+
preferredConnectionType?: ConnectionType,
|
|
22
|
+
convertCustomTypes?: boolean,
|
|
23
|
+
loggerContext?: LoggingOptions,
|
|
24
|
+
alias?: string,
|
|
25
|
+
em?: SqlEntityManager,
|
|
26
|
+
): MariaDbQueryBuilder<T, any, any, any>;
|
|
27
|
+
/** @inheritDoc */
|
|
28
|
+
getORMClass(): Constructor<MariaDbMikroORM>;
|
|
13
29
|
}
|
package/MariaDbDriver.js
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import { QueryFlag
|
|
1
|
+
import { QueryFlag } from '@mikro-orm/core';
|
|
2
2
|
import { MySqlDriver } from '@mikro-orm/mysql';
|
|
3
3
|
import { MariaDbPlatform } from './MariaDbPlatform.js';
|
|
4
4
|
import { MariaDbQueryBuilder } from './MariaDbQueryBuilder.js';
|
|
5
5
|
import { MariaDbMikroORM } from './MariaDbMikroORM.js';
|
|
6
6
|
/** Database driver for MariaDB, extending the MySQL driver with MariaDB-specific behavior. */
|
|
7
7
|
export class MariaDbDriver extends MySqlDriver {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
return qb;
|
|
22
|
-
}
|
|
23
|
-
/** @inheritDoc */
|
|
24
|
-
getORMClass() {
|
|
25
|
-
return MariaDbMikroORM;
|
|
8
|
+
constructor(config) {
|
|
9
|
+
super(config);
|
|
10
|
+
this.platform = new MariaDbPlatform();
|
|
11
|
+
}
|
|
12
|
+
createQueryBuilder(entityName, ctx, preferredConnectionType, convertCustomTypes, loggerContext, alias, em) {
|
|
13
|
+
// do not compute the connectionType if EM is provided as it will be computed from it in the QB later on
|
|
14
|
+
const connectionType = em
|
|
15
|
+
? preferredConnectionType
|
|
16
|
+
: this.resolveConnectionType({ ctx, connectionType: preferredConnectionType });
|
|
17
|
+
const qb = new MariaDbQueryBuilder(entityName, this.metadata, this, ctx, alias, connectionType, em, loggerContext);
|
|
18
|
+
if (!convertCustomTypes) {
|
|
19
|
+
qb.unsetFlag(QueryFlag.CONVERT_CUSTOM_TYPES);
|
|
26
20
|
}
|
|
21
|
+
return qb;
|
|
22
|
+
}
|
|
23
|
+
/** @inheritDoc */
|
|
24
|
+
getORMClass() {
|
|
25
|
+
return MariaDbMikroORM;
|
|
26
|
+
}
|
|
27
27
|
}
|
package/MariaDbMikroORM.d.ts
CHANGED
|
@@ -1,20 +1,58 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type AnyEntity,
|
|
3
|
+
type EntityClass,
|
|
4
|
+
type EntitySchema,
|
|
5
|
+
MikroORM,
|
|
6
|
+
type Options,
|
|
7
|
+
type IDatabaseDriver,
|
|
8
|
+
type EntityManager,
|
|
9
|
+
type EntityManagerType,
|
|
10
|
+
} from '@mikro-orm/core';
|
|
2
11
|
import type { SqlEntityManager } from '@mikro-orm/mysql';
|
|
3
12
|
import { MariaDbDriver } from './MariaDbDriver.js';
|
|
4
13
|
/** Configuration options for the MariaDB driver. */
|
|
5
|
-
export type MariaDbOptions<
|
|
14
|
+
export type MariaDbOptions<
|
|
15
|
+
EM extends SqlEntityManager<MariaDbDriver> = SqlEntityManager<MariaDbDriver>,
|
|
16
|
+
Entities extends (string | EntityClass<AnyEntity> | EntitySchema)[] = (
|
|
17
|
+
| string
|
|
18
|
+
| EntityClass<AnyEntity>
|
|
19
|
+
| EntitySchema
|
|
20
|
+
)[],
|
|
21
|
+
> = Partial<Options<MariaDbDriver, EM, Entities>>;
|
|
6
22
|
/** Creates a type-safe configuration object for the MariaDB driver. */
|
|
7
|
-
export declare function defineMariaDbConfig<
|
|
23
|
+
export declare function defineMariaDbConfig<
|
|
24
|
+
EM extends SqlEntityManager<MariaDbDriver> = SqlEntityManager<MariaDbDriver>,
|
|
25
|
+
Entities extends (string | EntityClass<AnyEntity> | EntitySchema)[] = (
|
|
26
|
+
| string
|
|
27
|
+
| EntityClass<AnyEntity>
|
|
28
|
+
| EntitySchema
|
|
29
|
+
)[],
|
|
30
|
+
>(options: Partial<Options<MariaDbDriver, EM, Entities>>): Partial<Options<MariaDbDriver, EM, Entities>>;
|
|
8
31
|
/**
|
|
9
32
|
* @inheritDoc
|
|
10
33
|
*/
|
|
11
|
-
export declare class MariaDbMikroORM<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
34
|
+
export declare class MariaDbMikroORM<
|
|
35
|
+
EM extends SqlEntityManager<MariaDbDriver> = SqlEntityManager<MariaDbDriver>,
|
|
36
|
+
Entities extends (string | EntityClass<AnyEntity> | EntitySchema)[] = (
|
|
37
|
+
| string
|
|
38
|
+
| EntityClass<AnyEntity>
|
|
39
|
+
| EntitySchema
|
|
40
|
+
)[],
|
|
41
|
+
> extends MikroORM<MariaDbDriver, EM, Entities> {
|
|
42
|
+
/**
|
|
43
|
+
* @inheritDoc
|
|
44
|
+
*/
|
|
45
|
+
static init<
|
|
46
|
+
D extends IDatabaseDriver = MariaDbDriver,
|
|
47
|
+
EM extends EntityManager<D> = D[typeof EntityManagerType] & EntityManager<D>,
|
|
48
|
+
Entities extends (string | EntityClass<AnyEntity> | EntitySchema)[] = (
|
|
49
|
+
| string
|
|
50
|
+
| EntityClass<AnyEntity>
|
|
51
|
+
| EntitySchema
|
|
52
|
+
)[],
|
|
53
|
+
>(options: Partial<Options<D, EM, Entities>>): Promise<MikroORM<D, EM, Entities>>;
|
|
54
|
+
/**
|
|
55
|
+
* @inheritDoc
|
|
56
|
+
*/
|
|
57
|
+
constructor(options: Partial<Options<MariaDbDriver, EM, Entities>>);
|
|
20
58
|
}
|
package/MariaDbMikroORM.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import { defineConfig, MikroORM
|
|
1
|
+
import { defineConfig, MikroORM } from '@mikro-orm/core';
|
|
2
2
|
import { MariaDbDriver } from './MariaDbDriver.js';
|
|
3
3
|
/** Creates a type-safe configuration object for the MariaDB driver. */
|
|
4
4
|
export function defineMariaDbConfig(options) {
|
|
5
|
-
|
|
5
|
+
return defineConfig({ driver: MariaDbDriver, ...options });
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
8
|
* @inheritDoc
|
|
9
9
|
*/
|
|
10
10
|
export class MariaDbMikroORM extends MikroORM {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
11
|
+
/**
|
|
12
|
+
* @inheritDoc
|
|
13
|
+
*/
|
|
14
|
+
static async init(options) {
|
|
15
|
+
return super.init(defineMariaDbConfig(options));
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* @inheritDoc
|
|
19
|
+
*/
|
|
20
|
+
constructor(options) {
|
|
21
|
+
super(defineMariaDbConfig(options));
|
|
22
|
+
}
|
|
23
23
|
}
|
package/MariaDbPlatform.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { MySqlPlatform, type TransformContext } from '@mikro-orm/mysql';
|
|
|
2
2
|
import { MariaDbSchemaHelper } from './MariaDbSchemaHelper.js';
|
|
3
3
|
/** Platform implementation for MariaDB. */
|
|
4
4
|
export declare class MariaDbPlatform extends MySqlPlatform {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
protected readonly schemaHelper: MariaDbSchemaHelper;
|
|
6
|
+
convertJsonToDatabaseValue(value: unknown, context?: TransformContext): unknown;
|
|
7
|
+
convertsJsonAutomatically(): boolean;
|
|
8
8
|
}
|
package/MariaDbPlatform.js
CHANGED
|
@@ -2,14 +2,14 @@ import { MySqlPlatform } from '@mikro-orm/mysql';
|
|
|
2
2
|
import { MariaDbSchemaHelper } from './MariaDbSchemaHelper.js';
|
|
3
3
|
/** Platform implementation for MariaDB. */
|
|
4
4
|
export class MariaDbPlatform extends MySqlPlatform {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
return JSON.stringify(value);
|
|
11
|
-
}
|
|
12
|
-
convertsJsonAutomatically() {
|
|
13
|
-
return false;
|
|
5
|
+
schemaHelper = new MariaDbSchemaHelper(this);
|
|
6
|
+
convertJsonToDatabaseValue(value, context) {
|
|
7
|
+
if (context?.mode === 'hydration') {
|
|
8
|
+
return value;
|
|
14
9
|
}
|
|
10
|
+
return JSON.stringify(value);
|
|
11
|
+
}
|
|
12
|
+
convertsJsonAutomatically() {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
15
|
}
|
package/MariaDbQueryBuilder.d.ts
CHANGED
|
@@ -3,6 +3,11 @@ import { QueryBuilder } from '@mikro-orm/mysql';
|
|
|
3
3
|
/**
|
|
4
4
|
* @inheritDoc
|
|
5
5
|
*/
|
|
6
|
-
export declare class MariaDbQueryBuilder<
|
|
7
|
-
|
|
6
|
+
export declare class MariaDbQueryBuilder<
|
|
7
|
+
Entity extends object = AnyEntity,
|
|
8
|
+
RootAlias extends string = never,
|
|
9
|
+
Hint extends string = never,
|
|
10
|
+
Context extends object = never,
|
|
11
|
+
> extends QueryBuilder<Entity, RootAlias, Hint, Context> {
|
|
12
|
+
protected wrapPaginateSubQuery(meta: EntityMetadata): void;
|
|
8
13
|
}
|
package/MariaDbQueryBuilder.js
CHANGED
|
@@ -4,83 +4,80 @@ import { QueryBuilder } from '@mikro-orm/mysql';
|
|
|
4
4
|
* @inheritDoc
|
|
5
5
|
*/
|
|
6
6
|
export class MariaDbQueryBuilder extends QueryBuilder {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
const key = raw(`min(${this.platform.quoteIdentifier(fieldName)}${type})`);
|
|
37
|
-
orderBy.push({ [key]: direction });
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
subQuery.orderBy(orderBy);
|
|
7
|
+
wrapPaginateSubQuery(meta) {
|
|
8
|
+
const pks = this.prepareFields(meta.primaryKeys, 'sub-query');
|
|
9
|
+
const quotedPKs = pks.map(pk => this.platform.quoteIdentifier(pk));
|
|
10
|
+
const subQuery = this.clone(['orderBy', 'fields']).select(pks).groupBy(pks).limit(this.state.limit);
|
|
11
|
+
// revert the on conditions added via populateWhere, we want to apply those only once
|
|
12
|
+
Object.values(subQuery.state.joins).forEach(join => (join.cond = join.cond_ ?? {}));
|
|
13
|
+
if (this.state.offset) {
|
|
14
|
+
subQuery.offset(this.state.offset);
|
|
15
|
+
}
|
|
16
|
+
const addToSelect = [];
|
|
17
|
+
if (this.state.orderBy.length > 0) {
|
|
18
|
+
const orderBy = [];
|
|
19
|
+
for (const orderMap of this.state.orderBy) {
|
|
20
|
+
for (const field of Utils.getObjectQueryKeys(orderMap)) {
|
|
21
|
+
const direction = orderMap[field];
|
|
22
|
+
if (RawQueryFragment.isKnownFragmentSymbol(field)) {
|
|
23
|
+
orderBy.push({ [field]: direction });
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const [a, f] = this.helper.splitField(field);
|
|
27
|
+
const prop = this.helper.getProperty(f, a);
|
|
28
|
+
const type = this.platform.castColumn(prop);
|
|
29
|
+
const fieldName = this.helper.mapper(field, this.type, undefined, null);
|
|
30
|
+
if (!prop?.persist && !prop?.formula && !pks.includes(fieldName)) {
|
|
31
|
+
addToSelect.push(fieldName);
|
|
32
|
+
}
|
|
33
|
+
const key = raw(`min(${this.platform.quoteIdentifier(fieldName)}${type})`);
|
|
34
|
+
orderBy.push({ [key]: direction });
|
|
41
35
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
36
|
+
}
|
|
37
|
+
subQuery.orderBy(orderBy);
|
|
38
|
+
}
|
|
39
|
+
subQuery.state.finalized = true;
|
|
40
|
+
const innerQuery = subQuery.as(this.mainAlias.aliasName).clear('select').select(pks);
|
|
41
|
+
/* v8 ignore next */
|
|
42
|
+
if (addToSelect.length > 0) {
|
|
43
|
+
addToSelect.forEach(prop => {
|
|
44
|
+
const field = this.state.fields.find(field => {
|
|
45
|
+
if (typeof field === 'object' && field && '__as' in field) {
|
|
46
|
+
return field.__as === prop;
|
|
47
|
+
}
|
|
48
|
+
if (field instanceof RawQueryFragment) {
|
|
49
|
+
// not perfect, but should work most of the time, ideally we should check only the alias (`... as alias`)
|
|
50
|
+
return field.sql.includes(prop);
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
53
|
+
});
|
|
54
|
+
if (field instanceof RawQueryFragment) {
|
|
55
|
+
innerQuery.select(this.platform.formatQuery(field.sql, field.params));
|
|
56
|
+
} else if (field) {
|
|
57
|
+
innerQuery.select(field);
|
|
64
58
|
}
|
|
65
|
-
|
|
66
|
-
// https://stackoverflow.com/questions/17892762/mysql-this-version-of-mysql-doesnt-yet-support-limit-in-all-any-some-subqu
|
|
67
|
-
const subSubQuery = this.platform.createNativeQueryBuilder();
|
|
68
|
-
subSubQuery.select(raw(`json_arrayagg(${quotedPKs.join(', ')})`)).from(innerQuery);
|
|
69
|
-
this.state.limit = undefined;
|
|
70
|
-
this.state.offset = undefined;
|
|
71
|
-
// Save the original WHERE conditions before pruning joins
|
|
72
|
-
const originalCond = this.state.cond;
|
|
73
|
-
const populatePaths = this.getPopulatePaths();
|
|
74
|
-
// Remove joins that are not used for population or ordering
|
|
75
|
-
this.pruneJoinsForPagination(meta, populatePaths);
|
|
76
|
-
// Transfer WHERE conditions to ORDER BY joins (GH #6160)
|
|
77
|
-
this.transferConditionsForOrderByJoins(meta, originalCond, populatePaths);
|
|
78
|
-
const subquerySql = subSubQuery.toString();
|
|
79
|
-
const key = meta.getPrimaryProps()[0].runtimeType === 'string'
|
|
80
|
-
? `concat('"', ${quotedPKs.join(', ')}, '"')`
|
|
81
|
-
: quotedPKs.join(', ');
|
|
82
|
-
const sql = `json_contains((${subquerySql}), ${key})`;
|
|
83
|
-
this.state.cond = {};
|
|
84
|
-
this.select(this.state.fields).where(sql);
|
|
59
|
+
});
|
|
85
60
|
}
|
|
61
|
+
// multiple sub-queries are needed to get around mysql limitations with order by + limit + where in + group by (o.O)
|
|
62
|
+
// https://stackoverflow.com/questions/17892762/mysql-this-version-of-mysql-doesnt-yet-support-limit-in-all-any-some-subqu
|
|
63
|
+
const subSubQuery = this.platform.createNativeQueryBuilder();
|
|
64
|
+
subSubQuery.select(raw(`json_arrayagg(${quotedPKs.join(', ')})`)).from(innerQuery);
|
|
65
|
+
this.state.limit = undefined;
|
|
66
|
+
this.state.offset = undefined;
|
|
67
|
+
// Save the original WHERE conditions before pruning joins
|
|
68
|
+
const originalCond = this.state.cond;
|
|
69
|
+
const populatePaths = this.getPopulatePaths();
|
|
70
|
+
// Remove joins that are not used for population or ordering
|
|
71
|
+
this.pruneJoinsForPagination(meta, populatePaths);
|
|
72
|
+
// Transfer WHERE conditions to ORDER BY joins (GH #6160)
|
|
73
|
+
this.transferConditionsForOrderByJoins(meta, originalCond, populatePaths);
|
|
74
|
+
const subquerySql = subSubQuery.toString();
|
|
75
|
+
const key =
|
|
76
|
+
meta.getPrimaryProps()[0].runtimeType === 'string'
|
|
77
|
+
? `concat('"', ${quotedPKs.join(', ')}, '"')`
|
|
78
|
+
: quotedPKs.join(', ');
|
|
79
|
+
const sql = `json_contains((${subquerySql}), ${key})`;
|
|
80
|
+
this.state.cond = {};
|
|
81
|
+
this.select(this.state.fields).where(sql);
|
|
82
|
+
}
|
|
86
83
|
}
|
package/MariaDbSchemaHelper.d.ts
CHANGED
|
@@ -1,12 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type AbstractSqlConnection,
|
|
3
|
+
type CheckDef,
|
|
4
|
+
type Column,
|
|
5
|
+
type IndexDef,
|
|
6
|
+
type DatabaseSchema,
|
|
7
|
+
type Table,
|
|
8
|
+
MySqlSchemaHelper,
|
|
9
|
+
} from '@mikro-orm/mysql';
|
|
2
10
|
import { type Dictionary, type Type } from '@mikro-orm/core';
|
|
3
11
|
/** Schema introspection helper for MariaDB. */
|
|
4
12
|
export declare class MariaDbSchemaHelper extends MySqlSchemaHelper {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
13
|
+
protected appendMySqlIndexSuffix(sql: string, index: IndexDef): string;
|
|
14
|
+
loadInformationSchema(schema: DatabaseSchema, connection: AbstractSqlConnection, tables: Table[]): Promise<void>;
|
|
15
|
+
getAllIndexes(connection: AbstractSqlConnection, tables: Table[]): Promise<Dictionary<IndexDef[]>>;
|
|
16
|
+
getAllColumns(connection: AbstractSqlConnection, tables: Table[]): Promise<Dictionary<Column[]>>;
|
|
17
|
+
getAllChecks(
|
|
18
|
+
connection: AbstractSqlConnection,
|
|
19
|
+
tables: Table[],
|
|
20
|
+
columns?: Dictionary<Column[]>,
|
|
21
|
+
): Promise<Dictionary<CheckDef[]>>;
|
|
22
|
+
protected getChecksSQL(tables: Table[]): string;
|
|
23
|
+
protected wrap(val: string | undefined | null, type: Type<unknown>): string | undefined | null;
|
|
12
24
|
}
|
package/MariaDbSchemaHelper.js
CHANGED
|
@@ -1,85 +1,84 @@
|
|
|
1
|
-
import { MySqlSchemaHelper
|
|
1
|
+
import { MySqlSchemaHelper } from '@mikro-orm/mysql';
|
|
2
2
|
/** Schema introspection helper for MariaDB. */
|
|
3
3
|
export class MariaDbSchemaHelper extends MySqlSchemaHelper {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
// MariaDB supports CLUSTERING=YES only with the Aria storage engine.
|
|
10
|
-
// Using this option with InnoDB tables will have no effect (silently ignored).
|
|
11
|
-
// See: https://mariadb.com/kb/en/create-index/#clustering-yes
|
|
12
|
-
if (index.clustered) {
|
|
13
|
-
sql += ' clustering=yes';
|
|
14
|
-
}
|
|
15
|
-
return sql;
|
|
4
|
+
appendMySqlIndexSuffix(sql, index) {
|
|
5
|
+
// MariaDB uses IGNORED instead of MySQL's INVISIBLE keyword
|
|
6
|
+
if (index.invisible) {
|
|
7
|
+
sql += ' ignored';
|
|
16
8
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const table = schema.addTable(t.table_name, t.schema_name, t.table_comment);
|
|
30
|
-
const pks = await this.getPrimaryKeys(connection, indexes[key], table.name, table.schema);
|
|
31
|
-
table.init(columns[key], indexes[key], checks[key], pks, fks[key], enums[key]);
|
|
32
|
-
}
|
|
9
|
+
// MariaDB supports CLUSTERING=YES only with the Aria storage engine.
|
|
10
|
+
// Using this option with InnoDB tables will have no effect (silently ignored).
|
|
11
|
+
// See: https://mariadb.com/kb/en/create-index/#clustering-yes
|
|
12
|
+
if (index.clustered) {
|
|
13
|
+
sql += ' clustering=yes';
|
|
14
|
+
}
|
|
15
|
+
return sql;
|
|
16
|
+
}
|
|
17
|
+
async loadInformationSchema(schema, connection, tables) {
|
|
18
|
+
/* v8 ignore next */
|
|
19
|
+
if (tables.length === 0) {
|
|
20
|
+
return;
|
|
33
21
|
}
|
|
34
|
-
|
|
35
|
-
|
|
22
|
+
const columns = await this.getAllColumns(connection, tables);
|
|
23
|
+
const indexes = await this.getAllIndexes(connection, tables);
|
|
24
|
+
const checks = await this.getAllChecks(connection, tables, columns);
|
|
25
|
+
const fks = await this.getAllForeignKeys(connection, tables);
|
|
26
|
+
const enums = await this.getAllEnumDefinitions(connection, tables);
|
|
27
|
+
for (const t of tables) {
|
|
28
|
+
const key = this.getTableKey(t);
|
|
29
|
+
const table = schema.addTable(t.table_name, t.schema_name, t.table_comment);
|
|
30
|
+
const pks = await this.getPrimaryKeys(connection, indexes[key], table.name, table.schema);
|
|
31
|
+
table.init(columns[key], indexes[key], checks[key], pks, fks[key], enums[key]);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async getAllIndexes(connection, tables) {
|
|
35
|
+
const sql = `select table_name as table_name, nullif(table_schema, schema()) as schema_name, index_name as index_name, non_unique as non_unique, column_name as column_name, index_type as index_type, sub_part as sub_part, collation as sort_order /*M!100600 , ignored as ignored */
|
|
36
36
|
from information_schema.statistics where table_schema = database()
|
|
37
37
|
and table_name in (${tables.map(t => this.platform.quoteValue(t.table_name)).join(', ')})
|
|
38
38
|
order by schema_name, table_name, index_name, seq_in_index`;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
ret[key].push(indexDef);
|
|
75
|
-
}
|
|
76
|
-
for (const key of Object.keys(ret)) {
|
|
77
|
-
ret[key] = await this.mapIndexes(ret[key]);
|
|
78
|
-
}
|
|
79
|
-
return ret;
|
|
39
|
+
const allIndexes = await connection.execute(sql);
|
|
40
|
+
const ret = {};
|
|
41
|
+
for (const index of allIndexes) {
|
|
42
|
+
const key = this.getTableKey(index);
|
|
43
|
+
const indexDef = {
|
|
44
|
+
columnNames: [index.column_name],
|
|
45
|
+
keyName: index.index_name,
|
|
46
|
+
unique: !index.non_unique,
|
|
47
|
+
primary: index.index_name === 'PRIMARY',
|
|
48
|
+
constraint: !index.non_unique,
|
|
49
|
+
};
|
|
50
|
+
// Capture column options (prefix length, sort order)
|
|
51
|
+
if (index.sub_part != null || index.sort_order === 'D') {
|
|
52
|
+
indexDef.columns = [
|
|
53
|
+
{
|
|
54
|
+
name: index.column_name,
|
|
55
|
+
...(index.sub_part != null && { length: index.sub_part }),
|
|
56
|
+
...(index.sort_order === 'D' && { sort: 'DESC' }),
|
|
57
|
+
},
|
|
58
|
+
];
|
|
59
|
+
}
|
|
60
|
+
// Capture index type for fulltext and spatial indexes
|
|
61
|
+
if (index.index_type === 'FULLTEXT') {
|
|
62
|
+
indexDef.type = 'fulltext';
|
|
63
|
+
} else if (index.index_type === 'SPATIAL') {
|
|
64
|
+
/* v8 ignore next */
|
|
65
|
+
indexDef.type = 'spatial';
|
|
66
|
+
}
|
|
67
|
+
// Capture ignored flag (MariaDB 10.6+, equivalent to MySQL's INVISIBLE)
|
|
68
|
+
/* v8 ignore next */
|
|
69
|
+
if (index.ignored === 'YES') {
|
|
70
|
+
indexDef.invisible = true;
|
|
71
|
+
}
|
|
72
|
+
ret[key] ??= [];
|
|
73
|
+
ret[key].push(indexDef);
|
|
80
74
|
}
|
|
81
|
-
|
|
82
|
-
|
|
75
|
+
for (const key of Object.keys(ret)) {
|
|
76
|
+
ret[key] = await this.mapIndexes(ret[key]);
|
|
77
|
+
}
|
|
78
|
+
return ret;
|
|
79
|
+
}
|
|
80
|
+
async getAllColumns(connection, tables) {
|
|
81
|
+
const sql = `select table_name as table_name,
|
|
83
82
|
nullif(table_schema, schema()) as schema_name,
|
|
84
83
|
column_name as column_name,
|
|
85
84
|
column_default as column_default,
|
|
@@ -95,69 +94,73 @@ export class MariaDbSchemaHelper extends MySqlSchemaHelper {
|
|
|
95
94
|
ifnull(datetime_precision, character_maximum_length) length
|
|
96
95
|
from information_schema.columns where table_schema = database() and table_name in (${tables.map(t => this.platform.quoteValue(t.table_name)).join(', ')})
|
|
97
96
|
order by ordinal_position`;
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
97
|
+
const allColumns = await connection.execute(sql);
|
|
98
|
+
const str = val => (val != null ? '' + val : val);
|
|
99
|
+
const extra = val =>
|
|
100
|
+
val.replace(/auto_increment|default_generated|(stored|virtual) generated/i, '').trim() || undefined;
|
|
101
|
+
const ret = {};
|
|
102
|
+
for (const col of allColumns) {
|
|
103
|
+
const mappedType = this.platform.getMappedType(col.column_type);
|
|
104
|
+
const tmp = this.normalizeDefaultValue(
|
|
105
|
+
mappedType.compareAsType() === 'boolean' && ['0', '1'].includes(col.column_default)
|
|
106
|
+
? ['false', 'true'][+col.column_default]
|
|
107
|
+
: col.column_default,
|
|
108
|
+
col.length,
|
|
109
|
+
);
|
|
110
|
+
const defaultValue = str(tmp === 'NULL' && col.is_nullable === 'YES' ? null : tmp);
|
|
111
|
+
const key = this.getTableKey(col);
|
|
112
|
+
const generated = col.generation_expression
|
|
113
|
+
? `${col.generation_expression.replaceAll(`\\'`, `'`)} ${col.extra.match(/stored generated/i) ? 'stored' : 'virtual'}`
|
|
114
|
+
: undefined;
|
|
115
|
+
ret[key] ??= [];
|
|
116
|
+
ret[key].push({
|
|
117
|
+
name: col.column_name,
|
|
118
|
+
type: this.platform.isNumericColumn(mappedType)
|
|
119
|
+
? col.column_type.replace(/ unsigned$/, '').replace(/\(\d+\)$/, '')
|
|
120
|
+
: col.column_type,
|
|
121
|
+
mappedType,
|
|
122
|
+
unsigned: col.column_type.endsWith(' unsigned'),
|
|
123
|
+
length: col.length,
|
|
124
|
+
default: this.wrap(defaultValue, mappedType),
|
|
125
|
+
nullable: col.is_nullable === 'YES',
|
|
126
|
+
primary: col.column_key === 'PRI',
|
|
127
|
+
unique: col.column_key === 'UNI',
|
|
128
|
+
autoincrement: col.extra === 'auto_increment',
|
|
129
|
+
precision: col.numeric_precision,
|
|
130
|
+
scale: col.numeric_scale,
|
|
131
|
+
comment: col.column_comment,
|
|
132
|
+
extra: extra(col.extra),
|
|
133
|
+
generated,
|
|
134
|
+
});
|
|
134
135
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
136
|
+
return ret;
|
|
137
|
+
}
|
|
138
|
+
async getAllChecks(connection, tables, columns) {
|
|
139
|
+
const sql = this.getChecksSQL(tables);
|
|
140
|
+
const allChecks = await connection.execute(sql);
|
|
141
|
+
const ret = {};
|
|
142
|
+
for (const check of allChecks) {
|
|
143
|
+
const key = this.getTableKey(check);
|
|
144
|
+
const match = /^json_valid\(`(.*)`\)$/i.exec(check.expression);
|
|
145
|
+
const col = columns?.[key]?.find(col => col.name === match?.[1]);
|
|
146
|
+
if (col && match) {
|
|
147
|
+
col.type = 'json';
|
|
148
|
+
col.mappedType = this.platform.getMappedType('json');
|
|
149
|
+
delete col.length;
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
ret[key] ??= [];
|
|
153
|
+
ret[key].push({
|
|
154
|
+
name: check.name,
|
|
155
|
+
columnName: check.column_name,
|
|
156
|
+
definition: `check ${check.expression}`,
|
|
157
|
+
expression: check.expression.replace(/^\((.*)\)$/, '$1'),
|
|
158
|
+
});
|
|
158
159
|
}
|
|
159
|
-
|
|
160
|
-
|
|
160
|
+
return ret;
|
|
161
|
+
}
|
|
162
|
+
getChecksSQL(tables) {
|
|
163
|
+
return `select
|
|
161
164
|
tc.constraint_schema as table_schema,
|
|
162
165
|
tc.table_name as table_name,
|
|
163
166
|
tc.constraint_name as name,
|
|
@@ -166,8 +169,8 @@ export class MariaDbSchemaHelper extends MySqlSchemaHelper {
|
|
|
166
169
|
from information_schema.check_constraints tc
|
|
167
170
|
where tc.table_name in (${tables.map(t => this.platform.quoteValue(t.table_name)).join(', ')}) and tc.constraint_schema = database()
|
|
168
171
|
order by tc.constraint_name`;
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
172
|
+
}
|
|
173
|
+
wrap(val, type) {
|
|
174
|
+
return val;
|
|
175
|
+
}
|
|
173
176
|
}
|
package/README.md
CHANGED
|
@@ -64,7 +64,7 @@ export class Book extends BookSchema.class {}
|
|
|
64
64
|
BookSchema.setClass(Book);
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
-
You can also define entities using [decorators](https://mikro-orm.io/docs/
|
|
67
|
+
You can also define entities using [decorators](https://mikro-orm.io/docs/using-decorators) or [`EntitySchema`](https://mikro-orm.io/docs/define-entity#entityschema-low-level-api). See the [defining entities guide](https://mikro-orm.io/docs/defining-entities) for all options.
|
|
68
68
|
|
|
69
69
|
### Initialize and Use
|
|
70
70
|
|
|
@@ -133,7 +133,7 @@ const author = await em.findOneOrFail(Author, 1, {
|
|
|
133
133
|
populate: ['books'],
|
|
134
134
|
});
|
|
135
135
|
author.name = 'Jon Snow II';
|
|
136
|
-
author.books.getItems().forEach(book => book.title += ' (2nd ed.)');
|
|
136
|
+
author.books.getItems().forEach(book => (book.title += ' (2nd ed.)'));
|
|
137
137
|
author.books.add(orm.em.create(Book, { title: 'New Book', author }));
|
|
138
138
|
|
|
139
139
|
// Flush computes change sets and executes them in a single transaction
|
package/index.d.ts
CHANGED
|
@@ -2,4 +2,8 @@ export * from '@mikro-orm/mysql';
|
|
|
2
2
|
export * from './MariaDbSchemaHelper.js';
|
|
3
3
|
export * from './MariaDbPlatform.js';
|
|
4
4
|
export * from './MariaDbDriver.js';
|
|
5
|
-
export {
|
|
5
|
+
export {
|
|
6
|
+
MariaDbMikroORM as MikroORM,
|
|
7
|
+
type MariaDbOptions as Options,
|
|
8
|
+
defineMariaDbConfig as defineConfig,
|
|
9
|
+
} from './MariaDbMikroORM.js';
|
package/index.js
CHANGED
|
@@ -2,4 +2,4 @@ export * from '@mikro-orm/mysql';
|
|
|
2
2
|
export * from './MariaDbSchemaHelper.js';
|
|
3
3
|
export * from './MariaDbPlatform.js';
|
|
4
4
|
export * from './MariaDbDriver.js';
|
|
5
|
-
export { MariaDbMikroORM as MikroORM, defineMariaDbConfig as defineConfig
|
|
5
|
+
export { MariaDbMikroORM as MikroORM, defineMariaDbConfig as defineConfig } from './MariaDbMikroORM.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/mariadb",
|
|
3
|
-
"version": "7.0.3
|
|
3
|
+
"version": "7.0.3",
|
|
4
4
|
"description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"data-mapper",
|
|
@@ -47,14 +47,14 @@
|
|
|
47
47
|
"copy": "node ../../scripts/copy.mjs"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@mikro-orm/mysql": "7.0.3
|
|
50
|
+
"@mikro-orm/mysql": "7.0.3",
|
|
51
51
|
"kysely": "0.28.12"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@mikro-orm/core": "^7.0.
|
|
54
|
+
"@mikro-orm/core": "^7.0.3"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
|
-
"@mikro-orm/core": "7.0.3
|
|
57
|
+
"@mikro-orm/core": "7.0.3"
|
|
58
58
|
},
|
|
59
59
|
"engines": {
|
|
60
60
|
"node": ">= 22.17.0"
|