@mikro-orm/sql 7.1.0-dev.9 → 7.1.0
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/AbstractSqlConnection.d.ts +1 -1
- package/AbstractSqlConnection.js +27 -6
- package/AbstractSqlDriver.d.ts +15 -1
- package/AbstractSqlDriver.js +143 -26
- package/AbstractSqlPlatform.d.ts +15 -3
- package/AbstractSqlPlatform.js +25 -7
- package/PivotCollectionPersister.d.ts +2 -2
- package/PivotCollectionPersister.js +6 -1
- package/README.md +2 -1
- package/SqlEntityManager.d.ts +44 -5
- package/SqlEntityManager.js +41 -6
- package/SqlMikroORM.d.ts +23 -0
- package/SqlMikroORM.js +23 -0
- package/dialects/mysql/BaseMySqlPlatform.d.ts +3 -5
- package/dialects/mysql/BaseMySqlPlatform.js +6 -10
- package/dialects/mysql/MySqlSchemaHelper.d.ts +16 -3
- package/dialects/mysql/MySqlSchemaHelper.js +197 -49
- package/dialects/oracledb/OracleDialect.d.ts +1 -1
- package/dialects/oracledb/OracleDialect.js +2 -1
- package/dialects/postgresql/BasePostgreSqlEntityManager.d.ts +19 -0
- package/dialects/postgresql/BasePostgreSqlEntityManager.js +24 -0
- package/dialects/postgresql/BasePostgreSqlPlatform.d.ts +11 -5
- package/dialects/postgresql/BasePostgreSqlPlatform.js +75 -17
- package/dialects/postgresql/PostgreSqlSchemaHelper.d.ts +31 -1
- package/dialects/postgresql/PostgreSqlSchemaHelper.js +269 -28
- package/dialects/postgresql/index.d.ts +2 -0
- package/dialects/postgresql/index.js +2 -0
- package/dialects/postgresql/typeOverrides.d.ts +14 -0
- package/dialects/postgresql/typeOverrides.js +12 -0
- package/dialects/sqlite/SqlitePlatform.d.ts +2 -1
- package/dialects/sqlite/SqlitePlatform.js +4 -0
- package/dialects/sqlite/SqliteSchemaHelper.d.ts +4 -1
- package/dialects/sqlite/SqliteSchemaHelper.js +49 -19
- package/index.d.ts +2 -0
- package/index.js +2 -0
- package/package.json +4 -4
- package/plugin/transformer.d.ts +11 -3
- package/plugin/transformer.js +138 -29
- package/query/CriteriaNode.d.ts +1 -1
- package/query/CriteriaNode.js +2 -2
- package/query/ObjectCriteriaNode.js +1 -1
- package/query/QueryBuilder.d.ts +42 -1
- package/query/QueryBuilder.js +78 -7
- package/schema/DatabaseSchema.d.ts +29 -2
- package/schema/DatabaseSchema.js +131 -4
- package/schema/DatabaseTable.d.ts +14 -1
- package/schema/DatabaseTable.js +165 -32
- package/schema/SchemaComparator.d.ts +18 -0
- package/schema/SchemaComparator.js +196 -1
- package/schema/SchemaHelper.d.ts +67 -1
- package/schema/SchemaHelper.js +255 -25
- package/schema/SqlSchemaGenerator.d.ts +2 -2
- package/schema/SqlSchemaGenerator.js +40 -10
- package/schema/partitioning.d.ts +13 -0
- package/schema/partitioning.js +326 -0
- package/typings.d.ts +59 -5
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<a href="https://mikro-orm.io"><img src="https://raw.githubusercontent.com/mikro-orm/mikro-orm/master/docs/static/img/logo-readme.svg?sanitize=true" alt="MikroORM" /></a>
|
|
3
3
|
</h1>
|
|
4
4
|
|
|
5
|
-
TypeScript ORM for Node.js based on Data Mapper, [Unit of Work](https://mikro-orm.io/docs/unit-of-work/) and [Identity Map](https://mikro-orm.io/docs/identity-map/) patterns. Supports MongoDB, MySQL, MariaDB, PostgreSQL, SQLite (including libSQL), MSSQL and Oracle databases.
|
|
5
|
+
TypeScript ORM for Node.js based on Data Mapper, [Unit of Work](https://mikro-orm.io/docs/unit-of-work/) and [Identity Map](https://mikro-orm.io/docs/identity-map/) patterns. Supports MongoDB, MySQL, MariaDB, PostgreSQL (including CockroachDB and PGlite), SQLite (including libSQL), MSSQL and Oracle databases.
|
|
6
6
|
|
|
7
7
|
> Heavily inspired by [Doctrine](https://www.doctrine-project.org/) and [Hibernate](https://hibernate.org/).
|
|
8
8
|
|
|
@@ -19,6 +19,7 @@ Install a driver package for your database:
|
|
|
19
19
|
|
|
20
20
|
```sh
|
|
21
21
|
npm install @mikro-orm/postgresql # PostgreSQL
|
|
22
|
+
npm install @mikro-orm/pglite # PGlite (embedded PostgreSQL in WASM)
|
|
22
23
|
npm install @mikro-orm/mysql # MySQL
|
|
23
24
|
npm install @mikro-orm/mariadb # MariaDB
|
|
24
25
|
npm install @mikro-orm/sqlite # SQLite
|
package/SqlEntityManager.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type EntitySchemaWithMeta, EntityManager, type AnyEntity, type ConnectionType, type CountByOptions, type Dictionary, type EntityData, type EntityKey, type EntityName, type EntityRepository, type FilterQuery, type GetRepository, type LoggingOptions, type QueryResult, type RawQueryFragment } from '@mikro-orm/core';
|
|
1
|
+
import { type AbortQueryOptions, type EntitySchemaWithMeta, EntityManager, type AnyEntity, type ConnectionType, type CountByOptions, type Dictionary, type EntityData, type EntityKey, type EntityName, type EntityRepository, type FilterQuery, type GetRepository, type LoggingOptions, type QueryResult, type RawQueryFragment } from '@mikro-orm/core';
|
|
2
2
|
import type { AbstractSqlDriver } from './AbstractSqlDriver.js';
|
|
3
3
|
import type { NativeQueryBuilder } from './query/NativeQueryBuilder.js';
|
|
4
4
|
import type { QueryBuilder } from './query/QueryBuilder.js';
|
|
@@ -6,6 +6,13 @@ import type { SqlEntityRepository } from './SqlEntityRepository.js';
|
|
|
6
6
|
import type { Kysely } from 'kysely';
|
|
7
7
|
import type { InferClassEntityDB, InferKyselyDB } from './typings.js';
|
|
8
8
|
import { type MikroKyselyPluginOptions } from './plugin/index.js';
|
|
9
|
+
/** Options for the modern signature of `SqlEntityManager.execute()`. */
|
|
10
|
+
export interface EmExecuteOptions extends AbortQueryOptions {
|
|
11
|
+
/** Result shape — `'all'` for rows, `'get'` for a single row, `'run'` for affected count. Defaults to `'all'`. */
|
|
12
|
+
method?: 'all' | 'get' | 'run';
|
|
13
|
+
/** Logger context payload forwarded to `Logger.logQuery`. */
|
|
14
|
+
loggerContext?: LoggingOptions;
|
|
15
|
+
}
|
|
9
16
|
/** Options for `SqlEntityManager.getKysely()`. */
|
|
10
17
|
export interface GetKyselyOptions extends MikroKyselyPluginOptions {
|
|
11
18
|
/** Connection type to use (`'read'` or `'write'`). */
|
|
@@ -24,11 +31,43 @@ export declare class SqlEntityManager<Driver extends AbstractSqlDriver = Abstrac
|
|
|
24
31
|
*/
|
|
25
32
|
qb<Entity extends object, RootAlias extends string = never>(entityName: EntityName<Entity>, alias?: RootAlias, type?: ConnectionType, loggerContext?: LoggingOptions): QueryBuilder<Entity, RootAlias>;
|
|
26
33
|
/**
|
|
27
|
-
* Returns configured Kysely instance.
|
|
34
|
+
* Returns a configured Kysely instance bound to this EntityManager.
|
|
35
|
+
*
|
|
36
|
+
* When the EntityManager is inside a transaction (e.g. within `em.transactional(...)`, or after
|
|
37
|
+
* `em.begin()`), the returned Kysely instance automatically uses the transaction context, so any
|
|
38
|
+
* queries executed via Kysely's own `.execute()` / `.executeTakeFirst*()` participate in the
|
|
39
|
+
* current transaction.
|
|
40
|
+
*
|
|
41
|
+
* If you need a Kysely instance that is **not** bound to the current transaction (e.g. to perform
|
|
42
|
+
* a side query against the pool while inside a transactional block), fork the EntityManager first:
|
|
43
|
+
*
|
|
44
|
+
* ```ts
|
|
45
|
+
* await em.transactional(async em => {
|
|
46
|
+
* // bound to the current transaction
|
|
47
|
+
* await em.getKysely().selectFrom('user').selectAll().execute();
|
|
48
|
+
*
|
|
49
|
+
* // bound to the pool, runs outside the transaction
|
|
50
|
+
* await em.fork().getKysely().selectFrom('audit_log').selectAll().execute();
|
|
51
|
+
* });
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* The `options.type` (`'read'` / `'write'`) is only honored outside a transaction — inside a
|
|
55
|
+
* transaction the connection is already pinned.
|
|
28
56
|
*/
|
|
29
57
|
getKysely<TDB = undefined, TOptions extends GetKyselyOptions = GetKyselyOptions>(options?: TOptions): Kysely<TDB extends undefined ? InferKyselyDB<EntitiesFromManager<this>, TOptions> & InferClassEntityDB<AllEntitiesFromManager<this>, TOptions> : TDB>;
|
|
30
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Executes a raw SQL query, using the current transaction context if available. The fork-level
|
|
60
|
+
* `signal` / `inflightQueryAbortStrategy` (set via `em.fork({ signal })`) is applied automatically.
|
|
61
|
+
* For per-call cancellation use the options-bag overload below.
|
|
62
|
+
*/
|
|
31
63
|
execute<T extends QueryResult | EntityData<AnyEntity> | EntityData<AnyEntity>[] = EntityData<AnyEntity>[]>(query: string | NativeQueryBuilder | RawQueryFragment, params?: any[], method?: 'all' | 'get' | 'run', loggerContext?: LoggingOptions): Promise<T>;
|
|
64
|
+
/**
|
|
65
|
+
* Executes a raw SQL query with an options bag carrying `method`, `loggerContext`, `signal`
|
|
66
|
+
* and `inflightQueryAbortStrategy`. Per-call `signal` / `inflightQueryAbortStrategy` override
|
|
67
|
+
* the fork-level defaults set via `em.fork({ signal })`. The current transaction context is
|
|
68
|
+
* applied automatically.
|
|
69
|
+
*/
|
|
70
|
+
execute<T extends QueryResult | EntityData<AnyEntity> | EntityData<AnyEntity>[] = EntityData<AnyEntity>[]>(query: string | NativeQueryBuilder | RawQueryFragment, params: any[], options: EmExecuteOptions): Promise<T>;
|
|
32
71
|
/**
|
|
33
72
|
* @inheritDoc
|
|
34
73
|
*/
|
|
@@ -36,6 +75,6 @@ export declare class SqlEntityManager<Driver extends AbstractSqlDriver = Abstrac
|
|
|
36
75
|
getRepository<T extends object, U extends EntityRepository<T> = SqlEntityRepository<T>>(entityName: EntityName<T>): GetRepository<T, U>;
|
|
37
76
|
protected applyDiscriminatorCondition<Entity extends object>(entityName: EntityName<Entity>, where: FilterQuery<Entity>): FilterQuery<Entity>;
|
|
38
77
|
}
|
|
39
|
-
type EntitiesFromManager<TEntityManager extends EntityManager<any>> = NonNullable<TEntityManager['~entities']> extends any[] ? Extract<NonNullable<TEntityManager['~entities']>[number], EntitySchemaWithMeta> : never;
|
|
40
|
-
type AllEntitiesFromManager<TEntityManager extends EntityManager<any>> = NonNullable<TEntityManager['~entities']> extends any[] ? NonNullable<TEntityManager['~entities']>[number] : never;
|
|
78
|
+
type EntitiesFromManager<TEntityManager extends EntityManager<any>> = NonNullable<TEntityManager['~entities']> extends readonly any[] ? Extract<NonNullable<TEntityManager['~entities']>[number], EntitySchemaWithMeta> : never;
|
|
79
|
+
type AllEntitiesFromManager<TEntityManager extends EntityManager<any>> = NonNullable<TEntityManager['~entities']> extends readonly any[] ? NonNullable<TEntityManager['~entities']>[number] : never;
|
|
41
80
|
export {};
|
package/SqlEntityManager.js
CHANGED
|
@@ -9,7 +9,9 @@ export class SqlEntityManager extends EntityManager {
|
|
|
9
9
|
*/
|
|
10
10
|
createQueryBuilder(entityName, alias, type, loggerContext) {
|
|
11
11
|
const context = this.getContext(false);
|
|
12
|
-
|
|
12
|
+
const qb = this.driver.createQueryBuilder(entityName, context.getTransactionContext(), type, true, loggerContext ?? context.loggerContext, alias, this);
|
|
13
|
+
qb.setAbortOptions(context.getAbortOptions());
|
|
14
|
+
return qb;
|
|
13
15
|
}
|
|
14
16
|
/**
|
|
15
17
|
* Shortcut for `createQueryBuilder()`
|
|
@@ -18,10 +20,33 @@ export class SqlEntityManager extends EntityManager {
|
|
|
18
20
|
return this.createQueryBuilder(entityName, alias, type, loggerContext);
|
|
19
21
|
}
|
|
20
22
|
/**
|
|
21
|
-
* Returns configured Kysely instance.
|
|
23
|
+
* Returns a configured Kysely instance bound to this EntityManager.
|
|
24
|
+
*
|
|
25
|
+
* When the EntityManager is inside a transaction (e.g. within `em.transactional(...)`, or after
|
|
26
|
+
* `em.begin()`), the returned Kysely instance automatically uses the transaction context, so any
|
|
27
|
+
* queries executed via Kysely's own `.execute()` / `.executeTakeFirst*()` participate in the
|
|
28
|
+
* current transaction.
|
|
29
|
+
*
|
|
30
|
+
* If you need a Kysely instance that is **not** bound to the current transaction (e.g. to perform
|
|
31
|
+
* a side query against the pool while inside a transactional block), fork the EntityManager first:
|
|
32
|
+
*
|
|
33
|
+
* ```ts
|
|
34
|
+
* await em.transactional(async em => {
|
|
35
|
+
* // bound to the current transaction
|
|
36
|
+
* await em.getKysely().selectFrom('user').selectAll().execute();
|
|
37
|
+
*
|
|
38
|
+
* // bound to the pool, runs outside the transaction
|
|
39
|
+
* await em.fork().getKysely().selectFrom('audit_log').selectAll().execute();
|
|
40
|
+
* });
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* The `options.type` (`'read'` / `'write'`) is only honored outside a transaction — inside a
|
|
44
|
+
* transaction the connection is already pinned.
|
|
22
45
|
*/
|
|
23
46
|
getKysely(options = {}) {
|
|
24
|
-
|
|
47
|
+
const context = this.getContext(false);
|
|
48
|
+
const ctx = context.getTransactionContext();
|
|
49
|
+
let kysely = ctx ?? this.getConnection(options.type).getClient();
|
|
25
50
|
if (options.columnNamingStrategy != null ||
|
|
26
51
|
options.tableNamingStrategy != null ||
|
|
27
52
|
options.processOnCreateHooks != null ||
|
|
@@ -31,9 +56,19 @@ export class SqlEntityManager extends EntityManager {
|
|
|
31
56
|
}
|
|
32
57
|
return kysely;
|
|
33
58
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
59
|
+
async execute(query, params = [], methodOrOptions = 'all', loggerContext) {
|
|
60
|
+
const opts = typeof methodOrOptions === 'string' ? { method: methodOrOptions, loggerContext } : methodOrOptions;
|
|
61
|
+
const context = this.getContext(false);
|
|
62
|
+
// Per-field fallback to fork-level abort, matching `EntityManager.prepareOptions` semantics.
|
|
63
|
+
const fork = context.getAbortOptions();
|
|
64
|
+
const hasAbort = opts.signal != null || opts.inflightQueryAbortStrategy != null || fork != null;
|
|
65
|
+
// Connection layer carries abort piggy-backed on `loggerContext`; merge only when needed.
|
|
66
|
+
const merged = hasAbort || opts.loggerContext ? { ...opts.loggerContext } : undefined;
|
|
67
|
+
if (merged && hasAbort) {
|
|
68
|
+
merged.signal = opts.signal ?? fork?.signal;
|
|
69
|
+
merged.inflightQueryAbortStrategy = opts.inflightQueryAbortStrategy ?? fork?.inflightQueryAbortStrategy;
|
|
70
|
+
}
|
|
71
|
+
return this.getDriver().execute(query, params, opts.method ?? 'all', context.getTransactionContext(), merged);
|
|
37
72
|
}
|
|
38
73
|
/**
|
|
39
74
|
* @inheritDoc
|
package/SqlMikroORM.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type AnyEntity, type EntityClass, type EntityManager, type EntityManagerType, type EntitySchema, type IDatabaseDriver, MikroORM, type Options } from '@mikro-orm/core';
|
|
2
|
+
import type { AbstractSqlDriver } from './AbstractSqlDriver.js';
|
|
3
|
+
import type { SqlEntityManager } from './SqlEntityManager.js';
|
|
4
|
+
/** Configuration options shared by all SQL drivers. */
|
|
5
|
+
export type SqlOptions<D extends AbstractSqlDriver = AbstractSqlDriver, EM extends SqlEntityManager<D> = SqlEntityManager<D>, Entities extends readonly (string | EntityClass<AnyEntity> | EntitySchema)[] = (string | EntityClass<AnyEntity> | EntitySchema)[]> = Partial<Options<D, EM, Entities>>;
|
|
6
|
+
/**
|
|
7
|
+
* Creates a type-safe configuration object for any SQL driver. The driver class
|
|
8
|
+
* must be passed via `options.driver` (e.g. `SqliteDriver`, `MySqlDriver`, …).
|
|
9
|
+
*/
|
|
10
|
+
export declare function defineSqlConfig<D extends AbstractSqlDriver = AbstractSqlDriver, EM extends SqlEntityManager<D> = SqlEntityManager<D>, Entities extends readonly (string | EntityClass<AnyEntity> | EntitySchema)[] = (string | EntityClass<AnyEntity> | EntitySchema)[]>(options: Partial<Options<D, EM, Entities>>): Partial<Options<D, EM, Entities>>;
|
|
11
|
+
/**
|
|
12
|
+
* Generic entry point for SQL drivers. Use this when consuming `@mikro-orm/sql`
|
|
13
|
+
* directly with a Kysely dialect; for the bundled driver packages prefer
|
|
14
|
+
* `@mikro-orm/sqlite`, `@mikro-orm/postgresql`, etc.
|
|
15
|
+
*
|
|
16
|
+
* @inheritDoc
|
|
17
|
+
*/
|
|
18
|
+
export declare class SqlMikroORM<D extends AbstractSqlDriver = AbstractSqlDriver, EM extends SqlEntityManager<D> = SqlEntityManager<D>, Entities extends readonly (string | EntityClass<AnyEntity> | EntitySchema)[] = (string | EntityClass<AnyEntity> | EntitySchema)[]> extends MikroORM<D, EM, Entities> {
|
|
19
|
+
/**
|
|
20
|
+
* @inheritDoc
|
|
21
|
+
*/
|
|
22
|
+
static init<D extends IDatabaseDriver = AbstractSqlDriver, EM extends EntityManager<D> = D[typeof EntityManagerType] & EntityManager<D>, Entities extends readonly (string | EntityClass<AnyEntity> | EntitySchema)[] = (string | EntityClass<AnyEntity> | EntitySchema)[]>(options: Partial<Options<D, EM, Entities>>): Promise<MikroORM<D, EM, Entities>>;
|
|
23
|
+
}
|
package/SqlMikroORM.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { defineConfig, MikroORM, } from '@mikro-orm/core';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a type-safe configuration object for any SQL driver. The driver class
|
|
4
|
+
* must be passed via `options.driver` (e.g. `SqliteDriver`, `MySqlDriver`, …).
|
|
5
|
+
*/
|
|
6
|
+
export function defineSqlConfig(options) {
|
|
7
|
+
return defineConfig(options);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Generic entry point for SQL drivers. Use this when consuming `@mikro-orm/sql`
|
|
11
|
+
* directly with a Kysely dialect; for the bundled driver packages prefer
|
|
12
|
+
* `@mikro-orm/sqlite`, `@mikro-orm/postgresql`, etc.
|
|
13
|
+
*
|
|
14
|
+
* @inheritDoc
|
|
15
|
+
*/
|
|
16
|
+
export class SqlMikroORM extends MikroORM {
|
|
17
|
+
/**
|
|
18
|
+
* @inheritDoc
|
|
19
|
+
*/
|
|
20
|
+
static async init(options) {
|
|
21
|
+
return super.init(options);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -35,11 +35,9 @@ export declare class BaseMySqlPlatform extends AbstractSqlPlatform {
|
|
|
35
35
|
getDefaultMappedType(type: string): Type<unknown>;
|
|
36
36
|
isNumericColumn(mappedType: Type<unknown>): boolean;
|
|
37
37
|
supportsUnsigned(): boolean;
|
|
38
|
-
/**
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
*/
|
|
42
|
-
getIndexName(tableName: string, columns: string[], type: 'index' | 'unique' | 'foreign' | 'primary' | 'sequence'): string;
|
|
38
|
+
/** MySQL/MariaDB identifier limit. */
|
|
39
|
+
getMaxIdentifierLength(): number;
|
|
40
|
+
getIndexName(tableName: string, columns: string[], type: 'index' | 'unique' | 'foreign' | 'primary' | 'sequence' | 'check'): string;
|
|
43
41
|
getDefaultPrimaryName(tableName: string, columns: string[]): string;
|
|
44
42
|
supportsCreatingFullTextIndex(): boolean;
|
|
45
43
|
getFullTextWhereClause(): string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { QueryOrder, DecimalType, DoubleType, } from '@mikro-orm/core';
|
|
2
2
|
import { MySqlSchemaHelper } from './MySqlSchemaHelper.js';
|
|
3
3
|
import { MySqlExceptionConverter } from './MySqlExceptionConverter.js';
|
|
4
4
|
import { AbstractSqlPlatform } from '../../AbstractSqlPlatform.js';
|
|
@@ -86,19 +86,15 @@ export class BaseMySqlPlatform extends AbstractSqlPlatform {
|
|
|
86
86
|
supportsUnsigned() {
|
|
87
87
|
return true;
|
|
88
88
|
}
|
|
89
|
-
/**
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
89
|
+
/** MySQL/MariaDB identifier limit. */
|
|
90
|
+
getMaxIdentifierLength() {
|
|
91
|
+
return 64;
|
|
92
|
+
}
|
|
93
93
|
getIndexName(tableName, columns, type) {
|
|
94
94
|
if (type === 'primary') {
|
|
95
95
|
return this.getDefaultPrimaryName(tableName, columns);
|
|
96
96
|
}
|
|
97
|
-
|
|
98
|
-
if (indexName.length > 64) {
|
|
99
|
-
return `${indexName.substring(0, 56 - type.length)}_${Utils.hash(indexName, 5)}_${type}`;
|
|
100
|
-
}
|
|
101
|
-
return indexName;
|
|
97
|
+
return super.getIndexName(tableName, columns, type);
|
|
102
98
|
}
|
|
103
99
|
getDefaultPrimaryName(tableName, columns) {
|
|
104
100
|
return 'PRIMARY'; // https://dev.mysql.com/doc/refman/8.0/en/create-table.html#create-table-indexes-keys
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Dictionary, type Transaction, type Type } from '@mikro-orm/core';
|
|
2
|
-
import type { CheckDef, Column, ForeignKey, IndexDef, Table, TableDifference, SqlTriggerDef } from '../../typings.js';
|
|
2
|
+
import type { CheckDef, Column, ForeignKey, IndexDef, Table, TableDifference, SqlTriggerDef, SqlRoutineDef } from '../../typings.js';
|
|
3
3
|
import type { AbstractSqlConnection } from '../../AbstractSqlConnection.js';
|
|
4
4
|
import { SchemaHelper } from '../../schema/SchemaHelper.js';
|
|
5
5
|
import type { DatabaseSchema } from '../../schema/DatabaseSchema.js';
|
|
@@ -11,7 +11,12 @@ export declare class MySqlSchemaHelper extends SchemaHelper {
|
|
|
11
11
|
'current_timestamp(?)': string[];
|
|
12
12
|
'0': string[];
|
|
13
13
|
};
|
|
14
|
+
private static readonly PARTIAL_INDEX_RE;
|
|
14
15
|
getSchemaBeginning(charset: string, disableForeignKeys?: boolean): string;
|
|
16
|
+
getSetSchemaSQL(schema: string): string;
|
|
17
|
+
getResetSchemaSQL(defaultSchema: string): string;
|
|
18
|
+
supportsMigrationSchema(): boolean;
|
|
19
|
+
tableExists(connection: AbstractSqlConnection, tableName: string, schemaName: string | undefined, ctx?: Transaction): Promise<boolean>;
|
|
15
20
|
disableForeignKeysSQL(): string;
|
|
16
21
|
enableForeignKeysSQL(): string;
|
|
17
22
|
finalizeTable(table: DatabaseTable, charset: string, collate?: string): string;
|
|
@@ -22,8 +27,10 @@ export declare class MySqlSchemaHelper extends SchemaHelper {
|
|
|
22
27
|
getAllIndexes(connection: AbstractSqlConnection, tables: Table[], ctx?: Transaction): Promise<Dictionary<IndexDef[]>>;
|
|
23
28
|
getCreateIndexSQL(tableName: string, index: IndexDef, partialExpression?: boolean): string;
|
|
24
29
|
/**
|
|
25
|
-
* Build the column list for a MySQL index
|
|
26
|
-
*
|
|
30
|
+
* Build the column list for a MySQL index. MySQL requires collation via an expression:
|
|
31
|
+
* `(column COLLATE collation_name)`. Partial indexes (`where`) are emulated via functional
|
|
32
|
+
* indexes — requires MySQL 8.0.13+. MariaDB does not support inline functional indexes
|
|
33
|
+
* and overrides to throw at a higher level.
|
|
27
34
|
*/
|
|
28
35
|
protected getIndexColumns(index: IndexDef): string;
|
|
29
36
|
/**
|
|
@@ -34,6 +41,12 @@ export declare class MySqlSchemaHelper extends SchemaHelper {
|
|
|
34
41
|
getAllChecks(connection: AbstractSqlConnection, tables: Table[], ctx?: Transaction): Promise<Dictionary<CheckDef[]>>;
|
|
35
42
|
/** Generates SQL to create MySQL triggers. MySQL requires one trigger per event. */
|
|
36
43
|
createTrigger(table: DatabaseTable, trigger: SqlTriggerDef): string;
|
|
44
|
+
createRoutine(routine: SqlRoutineDef): string;
|
|
45
|
+
dropRoutine(routine: SqlRoutineDef): string;
|
|
46
|
+
getAllRoutines(connection: AbstractSqlConnection): Promise<SqlRoutineDef[]>;
|
|
47
|
+
private getAllRoutineParams;
|
|
48
|
+
private formatDataAccess;
|
|
49
|
+
private parseDataAccess;
|
|
37
50
|
getAllTriggers(connection: AbstractSqlConnection, tables: Table[]): Promise<Dictionary<SqlTriggerDef[]>>;
|
|
38
51
|
getAllForeignKeys(connection: AbstractSqlConnection, tables: Table[], ctx?: Transaction): Promise<Dictionary<Dictionary<ForeignKey>>>;
|
|
39
52
|
getPreAlterTable(tableDiff: TableDifference, safe: boolean): string[];
|
|
@@ -7,12 +7,34 @@ export class MySqlSchemaHelper extends SchemaHelper {
|
|
|
7
7
|
'current_timestamp(?)': ['current_timestamp(?)'],
|
|
8
8
|
'0': ['0', 'false'],
|
|
9
9
|
};
|
|
10
|
+
// Greedy `(.+)` so nested CASE expressions inside the predicate don't trip the match on
|
|
11
|
+
// an inner `then <col> end` — the trailing `$` anchor forces the regex engine to extend
|
|
12
|
+
// the capture to the outermost case-end boundary.
|
|
13
|
+
static PARTIAL_INDEX_RE = /^\s*\(\s*case\s+when\s+(.+)\s+then\s+`([^`]+)`\s+end\s*\)\s*$/is;
|
|
10
14
|
getSchemaBeginning(charset, disableForeignKeys) {
|
|
11
15
|
if (disableForeignKeys) {
|
|
12
16
|
return `set names ${charset};\n${this.disableForeignKeysSQL()}\n\n`;
|
|
13
17
|
}
|
|
14
18
|
return `set names ${charset};\n\n`;
|
|
15
19
|
}
|
|
20
|
+
getSetSchemaSQL(schema) {
|
|
21
|
+
return `use ${this.quote(schema)}`;
|
|
22
|
+
}
|
|
23
|
+
getResetSchemaSQL(defaultSchema) {
|
|
24
|
+
return `use ${this.quote(defaultSchema)}`;
|
|
25
|
+
}
|
|
26
|
+
supportsMigrationSchema() {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
async tableExists(connection, tableName, schemaName, ctx) {
|
|
30
|
+
// MySQL "schema" = database — when none is requested, probe the connection's current DB
|
|
31
|
+
// via `schema()` rather than the base impl's `getDefaultSchemaName()` (which is undefined here).
|
|
32
|
+
const schemaClause = schemaName
|
|
33
|
+
? `table_schema = ${this.platform.quoteValue(schemaName)}`
|
|
34
|
+
: `table_schema = schema()`;
|
|
35
|
+
const rows = await connection.execute(`select 1 from information_schema.tables where ${schemaClause} and table_name = ${this.platform.quoteValue(tableName)}`, [], 'all', ctx);
|
|
36
|
+
return rows.length > 0;
|
|
37
|
+
}
|
|
16
38
|
disableForeignKeysSQL() {
|
|
17
39
|
return 'set foreign_key_checks = 0;';
|
|
18
40
|
}
|
|
@@ -31,7 +53,7 @@ export class MySqlSchemaHelper extends SchemaHelper {
|
|
|
31
53
|
return sql;
|
|
32
54
|
}
|
|
33
55
|
getListTablesSQL() {
|
|
34
|
-
return `select table_name as table_name, nullif(table_schema, schema()) as schema_name, table_comment as table_comment from information_schema.tables where table_type = 'BASE TABLE' and table_schema = schema()`;
|
|
56
|
+
return `select table_name as table_name, nullif(table_schema, schema()) as schema_name, table_comment as table_comment, table_collation as table_collation from information_schema.tables where table_type = 'BASE TABLE' and table_schema = schema()`;
|
|
35
57
|
}
|
|
36
58
|
getListViewsSQL() {
|
|
37
59
|
return `select table_name as view_name, nullif(table_schema, schema()) as schema_name, view_definition from information_schema.views where table_schema = schema()`;
|
|
@@ -68,6 +90,7 @@ export class MySqlSchemaHelper extends SchemaHelper {
|
|
|
68
90
|
for (const t of tables) {
|
|
69
91
|
const key = this.getTableKey(t);
|
|
70
92
|
const table = schema.addTable(t.table_name, t.schema_name, t.table_comment);
|
|
93
|
+
table.collation = t.table_collation ?? undefined;
|
|
71
94
|
const pks = await this.getPrimaryKeys(connection, indexes[key], table.name, table.schema);
|
|
72
95
|
table.init(columns[key], indexes[key], checks[key], pks, fks[key], enums[key]);
|
|
73
96
|
if (triggers[key]) {
|
|
@@ -84,8 +107,11 @@ export class MySqlSchemaHelper extends SchemaHelper {
|
|
|
84
107
|
const ret = {};
|
|
85
108
|
for (const index of allIndexes) {
|
|
86
109
|
const key = this.getTableKey(index);
|
|
110
|
+
const partialMatch = !index.column_name && typeof index.expression === 'string'
|
|
111
|
+
? MySqlSchemaHelper.PARTIAL_INDEX_RE.exec(index.expression)
|
|
112
|
+
: null;
|
|
87
113
|
const indexDef = {
|
|
88
|
-
columnNames: [index.column_name],
|
|
114
|
+
columnNames: [partialMatch ? partialMatch[2] : index.column_name],
|
|
89
115
|
keyName: index.index_name,
|
|
90
116
|
unique: !index.non_unique,
|
|
91
117
|
primary: index.index_name === 'PRIMARY',
|
|
@@ -113,7 +139,10 @@ export class MySqlSchemaHelper extends SchemaHelper {
|
|
|
113
139
|
if (index.is_visible === 'NO') {
|
|
114
140
|
indexDef.invisible = true;
|
|
115
141
|
}
|
|
116
|
-
if (
|
|
142
|
+
if (partialMatch) {
|
|
143
|
+
indexDef.where = partialMatch[1].trim();
|
|
144
|
+
}
|
|
145
|
+
else if (!index.column_name || index.expression?.match(/ where /i)) {
|
|
117
146
|
indexDef.expression = index.expression; // required for the `getCreateIndexSQL()` call
|
|
118
147
|
indexDef.expression = this.getCreateIndexSQL(index.table_name, indexDef, !!index.expression);
|
|
119
148
|
}
|
|
@@ -150,40 +179,43 @@ export class MySqlSchemaHelper extends SchemaHelper {
|
|
|
150
179
|
return this.appendMySqlIndexSuffix(sql, index);
|
|
151
180
|
}
|
|
152
181
|
/**
|
|
153
|
-
* Build the column list for a MySQL index
|
|
154
|
-
*
|
|
182
|
+
* Build the column list for a MySQL index. MySQL requires collation via an expression:
|
|
183
|
+
* `(column COLLATE collation_name)`. Partial indexes (`where`) are emulated via functional
|
|
184
|
+
* indexes — requires MySQL 8.0.13+. MariaDB does not support inline functional indexes
|
|
185
|
+
* and overrides to throw at a higher level.
|
|
155
186
|
*/
|
|
156
187
|
getIndexColumns(index) {
|
|
157
|
-
if (index.
|
|
158
|
-
return index
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
return expr;
|
|
171
|
-
}
|
|
172
|
-
// Standard column definition without collation
|
|
173
|
-
let colDef = quotedName;
|
|
174
|
-
// MySQL supports prefix length
|
|
175
|
-
if (col.length) {
|
|
176
|
-
colDef += `(${col.length})`;
|
|
177
|
-
}
|
|
178
|
-
// MySQL supports sort order
|
|
188
|
+
if (index.where) {
|
|
189
|
+
return this.emulatePartialIndexColumns(index);
|
|
190
|
+
}
|
|
191
|
+
return index.columnNames
|
|
192
|
+
.map(name => {
|
|
193
|
+
const col = index.columns?.find(c => c.name === name);
|
|
194
|
+
const quotedName = this.quote(name);
|
|
195
|
+
// MySQL supports collation via expression: (column_name COLLATE collation_name)
|
|
196
|
+
// When collation is specified, wrap in parentheses as an expression
|
|
197
|
+
if (col?.collation) {
|
|
198
|
+
let expr = col.length ? `${quotedName}(${col.length})` : quotedName;
|
|
199
|
+
expr = `(${expr} collate ${col.collation})`;
|
|
200
|
+
// Sort order comes after the expression
|
|
179
201
|
if (col.sort) {
|
|
180
|
-
|
|
202
|
+
expr += ` ${col.sort}`;
|
|
181
203
|
}
|
|
182
|
-
return
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
204
|
+
return expr;
|
|
205
|
+
}
|
|
206
|
+
// Standard column definition without collation
|
|
207
|
+
let colDef = quotedName;
|
|
208
|
+
// MySQL supports prefix length
|
|
209
|
+
if (col?.length) {
|
|
210
|
+
colDef += `(${col.length})`;
|
|
211
|
+
}
|
|
212
|
+
// MySQL supports sort order
|
|
213
|
+
if (col?.sort) {
|
|
214
|
+
colDef += ` ${col.sort}`;
|
|
215
|
+
}
|
|
216
|
+
return colDef;
|
|
217
|
+
})
|
|
218
|
+
.join(', ');
|
|
187
219
|
}
|
|
188
220
|
/**
|
|
189
221
|
* Append MySQL-specific index suffixes like INVISIBLE.
|
|
@@ -196,22 +228,25 @@ export class MySqlSchemaHelper extends SchemaHelper {
|
|
|
196
228
|
return sql;
|
|
197
229
|
}
|
|
198
230
|
async getAllColumns(connection, tables, ctx) {
|
|
199
|
-
const sql = `select table_name as table_name,
|
|
200
|
-
nullif(table_schema, schema()) as schema_name,
|
|
201
|
-
column_name as column_name,
|
|
202
|
-
column_default as column_default,
|
|
203
|
-
nullif(column_comment, '') as column_comment,
|
|
204
|
-
is_nullable as is_nullable,
|
|
205
|
-
data_type as data_type,
|
|
206
|
-
column_type as column_type,
|
|
207
|
-
column_key as column_key,
|
|
208
|
-
extra as extra,
|
|
209
|
-
generation_expression as generation_expression,
|
|
210
|
-
numeric_precision as numeric_precision,
|
|
211
|
-
numeric_scale as numeric_scale,
|
|
212
|
-
ifnull(datetime_precision, character_maximum_length) length
|
|
213
|
-
|
|
214
|
-
|
|
231
|
+
const sql = `select c.table_name as table_name,
|
|
232
|
+
nullif(c.table_schema, schema()) as schema_name,
|
|
233
|
+
c.column_name as column_name,
|
|
234
|
+
c.column_default as column_default,
|
|
235
|
+
nullif(c.column_comment, '') as column_comment,
|
|
236
|
+
c.is_nullable as is_nullable,
|
|
237
|
+
c.data_type as data_type,
|
|
238
|
+
c.column_type as column_type,
|
|
239
|
+
c.column_key as column_key,
|
|
240
|
+
c.extra as extra,
|
|
241
|
+
c.generation_expression as generation_expression,
|
|
242
|
+
c.numeric_precision as numeric_precision,
|
|
243
|
+
c.numeric_scale as numeric_scale,
|
|
244
|
+
ifnull(c.datetime_precision, c.character_maximum_length) length,
|
|
245
|
+
nullif(c.collation_name, t.table_collation) as collation_name
|
|
246
|
+
from information_schema.columns c
|
|
247
|
+
join information_schema.tables t on t.table_schema = c.table_schema and t.table_name = c.table_name
|
|
248
|
+
where c.table_schema = database() and c.table_name in (${tables.map(t => this.platform.quoteValue(t.table_name))})
|
|
249
|
+
order by c.ordinal_position`;
|
|
215
250
|
const allColumns = await connection.execute(sql, [], 'all', ctx);
|
|
216
251
|
const str = (val) => (val != null ? '' + val : val);
|
|
217
252
|
const extra = (val) => val.replace(/auto_increment|default_generated|(stored|virtual) generated/i, '').trim() || undefined;
|
|
@@ -242,6 +277,7 @@ export class MySqlSchemaHelper extends SchemaHelper {
|
|
|
242
277
|
precision: col.numeric_precision,
|
|
243
278
|
scale: col.numeric_scale,
|
|
244
279
|
comment: col.column_comment,
|
|
280
|
+
collation: col.collation_name ?? undefined,
|
|
245
281
|
extra: extra(col.extra),
|
|
246
282
|
generated,
|
|
247
283
|
});
|
|
@@ -289,6 +325,115 @@ export class MySqlSchemaHelper extends SchemaHelper {
|
|
|
289
325
|
}
|
|
290
326
|
return ret.join(';\n');
|
|
291
327
|
}
|
|
328
|
+
createRoutine(routine) {
|
|
329
|
+
if (routine.expression) {
|
|
330
|
+
return routine.expression;
|
|
331
|
+
}
|
|
332
|
+
const name = this.platform.quoteIdentifier(routine.name);
|
|
333
|
+
// MySQL functions reject direction prefixes (function params are always IN); procedures use them.
|
|
334
|
+
const params = routine.params
|
|
335
|
+
.map(p => {
|
|
336
|
+
const dir = routine.type === 'procedure' ? `${p.direction.toUpperCase()} ` : '';
|
|
337
|
+
return `${dir}${this.platform.quoteIdentifier(p.name)} ${p.type}`;
|
|
338
|
+
})
|
|
339
|
+
.join(', ');
|
|
340
|
+
const determinism = routine.deterministic === true ? ' deterministic' : routine.deterministic === false ? ' not deterministic' : '';
|
|
341
|
+
const dataAccess = this.formatDataAccess(routine.dataAccess);
|
|
342
|
+
const security = routine.security === 'definer'
|
|
343
|
+
? ' sql security definer'
|
|
344
|
+
: routine.security === 'invoker'
|
|
345
|
+
? ' sql security invoker'
|
|
346
|
+
: '';
|
|
347
|
+
const comment = routine.comment ? ` comment ${this.platform.quoteValue(routine.comment)}` : '';
|
|
348
|
+
const body = this.wrapRoutineBody(routine.body ?? '');
|
|
349
|
+
if (routine.type === 'procedure') {
|
|
350
|
+
return `create procedure ${name}(${params})${determinism}${dataAccess}${security}${comment} ${body}`;
|
|
351
|
+
}
|
|
352
|
+
const returnType = routine.returns?.type ?? 'text';
|
|
353
|
+
return `create function ${name}(${params}) returns ${returnType}${determinism}${dataAccess}${security}${comment} ${body}`;
|
|
354
|
+
}
|
|
355
|
+
dropRoutine(routine) {
|
|
356
|
+
const kind = routine.type === 'procedure' ? 'procedure' : 'function';
|
|
357
|
+
return `drop ${kind} if exists ${this.platform.quoteIdentifier(routine.name)}`;
|
|
358
|
+
}
|
|
359
|
+
async getAllRoutines(connection) {
|
|
360
|
+
const sql = `
|
|
361
|
+
select
|
|
362
|
+
r.routine_name as name,
|
|
363
|
+
r.routine_schema as schema_name,
|
|
364
|
+
lower(r.routine_type) as type,
|
|
365
|
+
r.routine_definition as body,
|
|
366
|
+
r.dtd_identifier as return_type,
|
|
367
|
+
r.is_deterministic as is_deterministic,
|
|
368
|
+
r.sql_data_access as sql_data_access,
|
|
369
|
+
r.security_type as security_type,
|
|
370
|
+
r.routine_comment as comment
|
|
371
|
+
from information_schema.routines r
|
|
372
|
+
where r.routine_schema = database()
|
|
373
|
+
and r.routine_type in ('PROCEDURE', 'FUNCTION')
|
|
374
|
+
`;
|
|
375
|
+
const [rows, params] = await Promise.all([
|
|
376
|
+
connection.execute(sql),
|
|
377
|
+
this.getAllRoutineParams(connection),
|
|
378
|
+
]);
|
|
379
|
+
return rows.map(row => ({
|
|
380
|
+
name: row.name,
|
|
381
|
+
type: row.type,
|
|
382
|
+
// MySQL has no schema namespace for routines — undefined matches the metadata side.
|
|
383
|
+
schema: undefined,
|
|
384
|
+
body: this.stripRoutineBody(row.body ?? ''),
|
|
385
|
+
deterministic: row.is_deterministic === 'YES',
|
|
386
|
+
dataAccess: this.parseDataAccess(row.sql_data_access),
|
|
387
|
+
security: row.security_type === 'DEFINER' ? 'definer' : 'invoker',
|
|
388
|
+
comment: row.comment || undefined,
|
|
389
|
+
params: params.get(row.name) ?? [],
|
|
390
|
+
returns: row.type === 'function' && row.return_type ? { type: row.return_type } : undefined,
|
|
391
|
+
}));
|
|
392
|
+
}
|
|
393
|
+
async getAllRoutineParams(connection) {
|
|
394
|
+
const sql = `
|
|
395
|
+
select
|
|
396
|
+
specific_name as routine_name,
|
|
397
|
+
parameter_name as name,
|
|
398
|
+
parameter_mode as direction,
|
|
399
|
+
dtd_identifier as type,
|
|
400
|
+
ordinal_position as position
|
|
401
|
+
from information_schema.parameters
|
|
402
|
+
where specific_schema = database()
|
|
403
|
+
and parameter_name is not null
|
|
404
|
+
order by specific_name, ordinal_position
|
|
405
|
+
`;
|
|
406
|
+
const rows = await connection.execute(sql);
|
|
407
|
+
const out = new Map();
|
|
408
|
+
for (const row of rows) {
|
|
409
|
+
if (!out.has(row.routine_name)) {
|
|
410
|
+
out.set(row.routine_name, []);
|
|
411
|
+
}
|
|
412
|
+
out.get(row.routine_name).push({
|
|
413
|
+
name: row.name,
|
|
414
|
+
type: row.type,
|
|
415
|
+
direction: row.direction.toLowerCase(),
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
return out;
|
|
419
|
+
}
|
|
420
|
+
formatDataAccess(access) {
|
|
421
|
+
switch (access) {
|
|
422
|
+
case 'no-sql':
|
|
423
|
+
return ' no sql';
|
|
424
|
+
case 'reads-sql-data':
|
|
425
|
+
return ' reads sql data';
|
|
426
|
+
case 'modifies-sql-data':
|
|
427
|
+
return ' modifies sql data';
|
|
428
|
+
case 'contains-sql':
|
|
429
|
+
return ' contains sql';
|
|
430
|
+
default:
|
|
431
|
+
return '';
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
parseDataAccess(access) {
|
|
435
|
+
return access.toLowerCase().replace(/\s+/g, '-');
|
|
436
|
+
}
|
|
292
437
|
async getAllTriggers(connection, tables) {
|
|
293
438
|
const names = tables.map(t => this.platform.quoteValue(t.table_name)).join(', ');
|
|
294
439
|
const sql = `select trigger_name as trigger_name, event_object_table as table_name, nullif(event_object_schema, schema()) as schema_name,
|
|
@@ -402,10 +547,13 @@ export class MySqlSchemaHelper extends SchemaHelper {
|
|
|
402
547
|
const col = this.createTableColumn(column, table, changedProperties);
|
|
403
548
|
return [`alter table ${table.getQuotedName()} modify ${col}`];
|
|
404
549
|
}
|
|
550
|
+
// MySQL MODIFY/CHANGE resets omitted column attributes to the table default, so collation must
|
|
551
|
+
// be re-emitted on rename and comment-only paths to preserve a non-default column collation.
|
|
405
552
|
getColumnDeclarationSQL(col) {
|
|
406
553
|
let ret = col.type;
|
|
407
554
|
ret += col.unsigned ? ' unsigned' : '';
|
|
408
555
|
ret += col.autoincrement ? ' auto_increment' : '';
|
|
556
|
+
ret += col.collation ? ` ${this.getCollateSQL(col.collation)}` : '';
|
|
409
557
|
ret += ' ';
|
|
410
558
|
ret += col.nullable ? 'null' : 'not null';
|
|
411
559
|
ret += col.default ? ' default ' + col.default : '';
|
|
@@ -46,7 +46,7 @@ declare class OracleConnection implements DatabaseConnection {
|
|
|
46
46
|
sql: string;
|
|
47
47
|
bindParams: unknown[];
|
|
48
48
|
};
|
|
49
|
-
streamQuery<R>(compiledQuery: CompiledQuery,
|
|
49
|
+
streamQuery<R>(compiledQuery: CompiledQuery, chunkSize?: number): AsyncIterableIterator<QueryResult<R>>;
|
|
50
50
|
get connection(): OraclePoolConnection;
|
|
51
51
|
}
|
|
52
52
|
declare class OracleDriver implements Driver {
|