mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
connection refactoring
This commit is contained in:
parent
edc6a31b57
commit
df31b4a38a
@ -4,23 +4,14 @@ import {EntitySubscriberInterface} from "../subscriber/EntitySubscriberInterface
|
||||
import {RepositoryNotFoundError} from "./error/RepositoryNotFoundError";
|
||||
import {ObjectType} from "../common/ObjectType";
|
||||
import {EntityManager} from "../entity-manager/EntityManager";
|
||||
import {importClassesFromDirectories, importJsonsFromDirectories} from "../util/DirectoryExportedClassesLoader";
|
||||
import {getFromContainer, getMetadataArgsStorage} from "../index";
|
||||
import {EntityMetadataBuilder} from "../metadata-builder/EntityMetadataBuilder";
|
||||
import {DefaultNamingStrategy} from "../naming-strategy/DefaultNamingStrategy";
|
||||
import {CannotImportAlreadyConnectedError} from "./error/CannotImportAlreadyConnectedError";
|
||||
import {CannotCloseNotConnectedError} from "./error/CannotCloseNotConnectedError";
|
||||
import {CannotConnectAlreadyConnectedError} from "./error/CannotConnectAlreadyConnectedError";
|
||||
import {TreeRepository} from "../repository/TreeRepository";
|
||||
import {NamingStrategyInterface} from "../naming-strategy/NamingStrategyInterface";
|
||||
import {RepositoryNotTreeError} from "./error/RepositoryNotTreeError";
|
||||
import {EntitySchema} from "../entity-schema/EntitySchema";
|
||||
import {CannotSyncNotConnectedError} from "./error/CannotSyncNotConnectedError";
|
||||
import {CannotUseNamingStrategyNotConnectedError} from "./error/CannotUseNamingStrategyNotConnectedError";
|
||||
import {Broadcaster} from "../subscriber/Broadcaster";
|
||||
import {LazyRelationsWrapper} from "../lazy-loading/LazyRelationsWrapper";
|
||||
import {SpecificRepository} from "../repository/SpecificRepository";
|
||||
import {RepositoryAggregator} from "../repository/RepositoryAggregator";
|
||||
import {EntityMetadata} from "../metadata/EntityMetadata";
|
||||
import {SchemaBuilder} from "../schema-builder/SchemaBuilder";
|
||||
import {Logger} from "../logger/Logger";
|
||||
@ -33,21 +24,15 @@ import {PlatformTools} from "../platform/PlatformTools";
|
||||
import {MongoRepository} from "../repository/MongoRepository";
|
||||
import {MongoDriver} from "../driver/mongodb/MongoDriver";
|
||||
import {MongoEntityManager} from "../entity-manager/MongoEntityManager";
|
||||
import {EntitySchemaTransformer} from "../entity-schema/EntitySchemaTransformer";
|
||||
import {EntityMetadataValidator} from "../metadata-builder/EntityMetadataValidator";
|
||||
import {ConnectionOptions} from "./ConnectionOptions";
|
||||
import {MysqlDriver} from "../driver/mysql/MysqlDriver";
|
||||
import {PostgresDriver} from "../driver/postgres/PostgresDriver";
|
||||
import {SqliteDriver} from "../driver/sqlite/SqliteDriver";
|
||||
import {OracleDriver} from "../driver/oracle/OracleDriver";
|
||||
import {SqlServerDriver} from "../driver/sqlserver/SqlServerDriver";
|
||||
import {WebsqlDriver} from "../driver/websql/WebsqlDriver";
|
||||
import {MissingDriverError} from "../driver/error/MissingDriverError";
|
||||
import {OrmUtils} from "../util/OrmUtils";
|
||||
import {QueryRunnerProviderAlreadyReleasedError} from "../query-runner/error/QueryRunnerProviderAlreadyReleasedError";
|
||||
import {QueryBuilder} from "../query-builder/QueryBuilder";
|
||||
import {DriverFactory} from "../driver/DriverFactory";
|
||||
import {EntityManagerFactory} from "../entity-manager/EntityManagerFactory";
|
||||
import {LoggerFactory} from "../logger/LoggerFactory";
|
||||
import {RepositoryFactory} from "../repository/RepositoryFactory";
|
||||
import {DriverFactory} from "../driver/DriverFactory";
|
||||
import {ConnectionMetadataBuilder} from "./ConnectionMetadataBuilder";
|
||||
|
||||
/**
|
||||
* Connection is a single database ORM connection to a specific DBMS database.
|
||||
@ -105,19 +90,10 @@ export class Connection {
|
||||
*/
|
||||
readonly subscribers: EntitySubscriberInterface<any>[] = [];
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Private Properties
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Stores all registered repositories.
|
||||
*/
|
||||
private repositoryAggregators: RepositoryAggregator[] = [];
|
||||
|
||||
/**
|
||||
* All entity metadatas that are registered for this connection.
|
||||
*/
|
||||
private entityMetadatas: EntityMetadata[] = [];
|
||||
readonly entityMetadatas: EntityMetadata[] = [];
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructor
|
||||
@ -126,14 +102,14 @@ export class Connection {
|
||||
constructor(options: ConnectionOptions) {
|
||||
this.name = options.name || "default";
|
||||
this.options = options;
|
||||
this.logger = new Logger(options.logging || {});
|
||||
this.logger = this.createLogger();
|
||||
this.driver = this.createDriver();
|
||||
this.manager = this.createEntityManager();
|
||||
this.namingStrategy = options.namingStrategy || new DefaultNamingStrategy();
|
||||
this.driver = new DriverFactory().create(this);
|
||||
this.manager = new EntityManagerFactory().create(this);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Accessors
|
||||
// Public Accessors
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@ -255,18 +231,6 @@ export class Connection {
|
||||
await migrationExecutor.undoLastMigration();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new entity manager with a single opened connection to the database.
|
||||
* This may be useful if you want to perform all db queries within one connection.
|
||||
* After finishing with entity manager, don't forget to release it, to release connection back to pool.
|
||||
*/
|
||||
createIsolatedManager(queryRunnerProvider?: QueryRunnerProvider): EntityManager {
|
||||
if (!queryRunnerProvider)
|
||||
queryRunnerProvider = new QueryRunnerProvider(this.driver, true);
|
||||
|
||||
return new EntityManager(this, queryRunnerProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if entity metadata exist for the given entity class.
|
||||
*/
|
||||
@ -348,40 +312,40 @@ export class Connection {
|
||||
* Gets repository for the given entity class or name.
|
||||
*/
|
||||
getRepository<Entity>(entityClassOrName: ObjectType<Entity>|string): Repository<Entity> {
|
||||
return this.findRepositoryAggregator(entityClassOrName).repository;
|
||||
return this.getMetadata(entityClassOrName).repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets tree repository for the given entity class.
|
||||
* Only tree-type entities can have a TreeRepository,
|
||||
* like ones decorated with @ClosureEntity decorator.
|
||||
* Only tree-type entities can have a TreeRepository, like ones decorated with @ClosureEntity decorator.
|
||||
*/
|
||||
getTreeRepository<Entity>(entityClass: ObjectType<Entity>): TreeRepository<Entity>;
|
||||
|
||||
/**
|
||||
* Gets tree repository for the given entity class.
|
||||
* Only tree-type entities can have a TreeRepository,
|
||||
* like ones decorated with @ClosureEntity decorator.
|
||||
* Only tree-type entities can have a TreeRepository, like ones decorated with @ClosureEntity decorator.
|
||||
*/
|
||||
getTreeRepository<Entity>(entityClassOrName: ObjectType<Entity>|string): TreeRepository<Entity>;
|
||||
|
||||
/**
|
||||
* Gets tree repository for the given entity class.
|
||||
* Only tree-type entities can have a TreeRepository,
|
||||
* like ones decorated with @ClosureEntity decorator.
|
||||
* Only tree-type entities can have a TreeRepository, like ones decorated with @ClosureEntity decorator.
|
||||
*/
|
||||
getTreeRepository<Entity>(entityName: string): TreeRepository<Entity>;
|
||||
|
||||
/**
|
||||
* Gets tree repository for the given entity class or name.
|
||||
* Only tree-type entities can have a TreeRepository,
|
||||
* like ones decorated with @ClosureEntity decorator.
|
||||
* Only tree-type entities can have a TreeRepository, like ones decorated with @ClosureEntity decorator.
|
||||
*/
|
||||
getTreeRepository<Entity>(entityClassOrName: ObjectType<Entity>|string): TreeRepository<Entity> {
|
||||
// todo: add checks if tree repository is supported by driver (not supported by mongodb at least)
|
||||
if (this.driver instanceof MongoDriver)
|
||||
throw new Error(`You cannot use getTreeRepository for MongoDB connections.`);
|
||||
|
||||
const repository = this.findRepositoryAggregator(entityClassOrName).treeRepository;
|
||||
if (!repository)
|
||||
if (!this.hasMetadata(entityClassOrName))
|
||||
throw new RepositoryNotFoundError(this.name, entityClassOrName);
|
||||
|
||||
const repository = this.getMetadata(entityClassOrName).repository;
|
||||
if (!(repository instanceof TreeRepository))
|
||||
throw new RepositoryNotTreeError(entityClassOrName);
|
||||
|
||||
return repository;
|
||||
@ -409,7 +373,10 @@ export class Connection {
|
||||
if (!(this.driver instanceof MongoDriver))
|
||||
throw new Error(`You can use getMongoRepository only for MongoDB connections.`);
|
||||
|
||||
return this.findRepositoryAggregator(entityClassOrName).repository as MongoRepository<Entity>;
|
||||
if (!this.hasMetadata(entityClassOrName))
|
||||
throw new RepositoryNotFoundError(this.name, entityClassOrName);
|
||||
|
||||
return this.getMetadata(entityClassOrName).repository as MongoRepository<Entity>;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -500,6 +467,42 @@ export class Connection {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new entity manager with a single opened connection to the database.
|
||||
* This may be useful if you want to perform all db queries within one connection.
|
||||
* After finishing with entity manager, don't forget to release it, to release connection back to pool.
|
||||
*/
|
||||
createIsolatedManager(queryRunnerProvider?: QueryRunnerProvider): EntityManager {
|
||||
if (!queryRunnerProvider)
|
||||
queryRunnerProvider = new QueryRunnerProvider(this.driver, true);
|
||||
|
||||
return new EntityManagerFactory().create(this, queryRunnerProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new repository with a single opened connection to the database.
|
||||
* This may be useful if you want to perform all db queries within one connection.
|
||||
* After finishing with entity manager, don't forget to release it, to release connection back to pool.
|
||||
*/
|
||||
createIsolatedRepository<Entity>(entityClassOrName: ObjectType<Entity>|string, queryRunnerProvider?: QueryRunnerProvider): Repository<Entity> {
|
||||
if (!queryRunnerProvider)
|
||||
queryRunnerProvider = new QueryRunnerProvider(this.driver, true);
|
||||
|
||||
return new RepositoryFactory().createRepository(this, this.getMetadata(entityClassOrName), queryRunnerProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new specific repository with a single opened connection to the database.
|
||||
* This may be useful if you want to perform all db queries within one connection.
|
||||
* After finishing with entity manager, don't forget to release it, to release connection back to pool.
|
||||
*/
|
||||
createIsolatedSpecificRepository<Entity>(entityClassOrName: ObjectType<Entity>|string, queryRunnerProvider?: QueryRunnerProvider): SpecificRepository<Entity> {
|
||||
if (!queryRunnerProvider)
|
||||
queryRunnerProvider = new QueryRunnerProvider(this.driver, true);
|
||||
|
||||
return new RepositoryFactory().createSpecificRepository(this, this.getMetadata(entityClassOrName), queryRunnerProvider);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Deprecated Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
@ -544,7 +547,10 @@ export class Connection {
|
||||
* @deprecated don't use it, it will be refactored or removed in the future versions
|
||||
*/
|
||||
getSpecificRepository<Entity>(entityClassOrName: ObjectType<Entity>|string): SpecificRepository<Entity> {
|
||||
return this.findRepositoryAggregator(entityClassOrName).specificRepository;
|
||||
if (!this.hasMetadata(entityClassOrName))
|
||||
throw new RepositoryNotFoundError(this.name, entityClassOrName);
|
||||
|
||||
return this.getMetadata(entityClassOrName).specificRepository;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -552,77 +558,63 @@ export class Connection {
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Finds repository aggregator of the given entity class or name.
|
||||
* Creates connection's Logger.
|
||||
*/
|
||||
protected findRepositoryAggregator(entityClassOrName: ObjectType<any>|string): RepositoryAggregator {
|
||||
if (!this.hasMetadata(entityClassOrName))
|
||||
throw new RepositoryNotFoundError(this.name, entityClassOrName);
|
||||
protected createLogger(): Logger {
|
||||
if (this.options.factories && this.options.factories.logger)
|
||||
return this.options.factories.logger.create(this.options.logging || {});
|
||||
|
||||
const metadata = this.getMetadata(entityClassOrName);
|
||||
const repositoryAggregator = this.repositoryAggregators.find(repositoryAggregate => repositoryAggregate.metadata === metadata);
|
||||
if (!repositoryAggregator)
|
||||
throw new RepositoryNotFoundError(this.name, entityClassOrName);
|
||||
return new LoggerFactory().create(this.options.logging || {});
|
||||
}
|
||||
|
||||
return repositoryAggregator;
|
||||
/**
|
||||
* Creates connection's Driver.
|
||||
*/
|
||||
protected createDriver(): Driver {
|
||||
if (this.options.factories && this.options.factories.driver)
|
||||
return this.options.factories.driver.create(this);
|
||||
|
||||
return new DriverFactory().create(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates EntityManager using its factory.
|
||||
*/
|
||||
protected createEntityManager(): EntityManager {
|
||||
if (this.options.factories && this.options.factories.entityManager)
|
||||
return this.options.factories.entityManager.create(this);
|
||||
|
||||
return new EntityManagerFactory().create(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds all registered metadatas.
|
||||
*/
|
||||
public buildMetadatas() {
|
||||
protected buildMetadatas(): void {
|
||||
const connectionMetadataBuilder = new ConnectionMetadataBuilder(this);
|
||||
|
||||
// import entity schemas
|
||||
const [entitySchemaDirectories, entitySchemaClasses] = OrmUtils.splitStringsAndClasses(this.options.entitySchemas || []);
|
||||
entitySchemaClasses.push(...importJsonsFromDirectories(entitySchemaDirectories));
|
||||
|
||||
const [entityDirectories, entityClasses] = OrmUtils.splitStringsAndClasses(this.options.entities || []);
|
||||
entityClasses.push(...importClassesFromDirectories(entityDirectories));
|
||||
|
||||
const [subscriberDirectories, subscriberClasses] = OrmUtils.splitStringsAndClasses(this.options.subscribers || []);
|
||||
subscriberClasses.push(...importClassesFromDirectories(subscriberDirectories));
|
||||
|
||||
const [migrationDirectories, migrationClasses] = OrmUtils.splitStringsAndClasses(this.options.migrations || []);
|
||||
migrationClasses.push(...importClassesFromDirectories(migrationDirectories));
|
||||
|
||||
// create migration instances
|
||||
const migrations = migrationClasses.map(migrationClass => {
|
||||
return getFromContainer<MigrationInterface>(migrationClass);
|
||||
});
|
||||
Object.assign(this, { migrations });
|
||||
|
||||
this.subscribers.length = 0;
|
||||
this.repositoryAggregators.length = 0;
|
||||
this.entityMetadatas.length = 0;
|
||||
|
||||
const entityMetadataValidator = new EntityMetadataValidator();
|
||||
|
||||
// take imported event subscribers
|
||||
// build subscribers if they are not disallowed from high-level (for example they can disallowed from migrations run process)
|
||||
if (!PlatformTools.getEnvVariable("SKIP_SUBSCRIBERS_LOADING")) {
|
||||
getMetadataArgsStorage()
|
||||
.filterSubscribers(subscriberClasses)
|
||||
.map(metadata => getFromContainer(metadata.target))
|
||||
.forEach(subscriber => this.subscribers.push(subscriber));
|
||||
const subscribers = connectionMetadataBuilder.buildSubscribers(this.options.subscribers || []);
|
||||
Object.assign(this, { subscribers: subscribers });
|
||||
}
|
||||
|
||||
// take imported entity listeners
|
||||
// build entity metadatas from metadata args storage (collected from decorators)
|
||||
new EntityMetadataBuilder(this, getMetadataArgsStorage())
|
||||
.build(entityClasses)
|
||||
.forEach(metadata => {
|
||||
this.entityMetadatas.push(metadata);
|
||||
this.repositoryAggregators.push(new RepositoryAggregator(this, metadata));
|
||||
});
|
||||
// build entity metadatas
|
||||
const entityMetadatas = connectionMetadataBuilder.buildEntityMetadatas(this.options.entities || [], this.options.entitySchemas || []);
|
||||
Object.assign(this, { entityMetadatas: entityMetadatas });
|
||||
|
||||
// build entity metadatas from given entity schemas
|
||||
const metadataArgsStorage = getFromContainer(EntitySchemaTransformer)
|
||||
.transform(entitySchemaClasses);
|
||||
new EntityMetadataBuilder(this, metadataArgsStorage)
|
||||
.build()
|
||||
.forEach(metadata => {
|
||||
this.entityMetadatas.push(metadata);
|
||||
this.repositoryAggregators.push(new RepositoryAggregator(this, metadata));
|
||||
});
|
||||
// create migration instances
|
||||
const migrations = connectionMetadataBuilder.buildMigrations(this.options.migrations || []);
|
||||
Object.assign(this, { migrations: migrations });
|
||||
|
||||
// initialize repositories for all entity metadatas
|
||||
this.entityMetadatas.forEach(metadata => {
|
||||
metadata.repository = new RepositoryFactory().createRepository(this, metadata);
|
||||
metadata.specificRepository = new RepositoryFactory().createSpecificRepository(this, metadata);
|
||||
});
|
||||
|
||||
// validate all created entity metadatas to make sure user created entities are valid and correct
|
||||
const entityMetadataValidator = new EntityMetadataValidator();
|
||||
entityMetadataValidator.validateMany(this.entityMetadatas);
|
||||
}
|
||||
|
||||
|
||||
53
src/connection/ConnectionMetadataBuilder.ts
Normal file
53
src/connection/ConnectionMetadataBuilder.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import {importClassesFromDirectories, importJsonsFromDirectories} from "../util/DirectoryExportedClassesLoader";
|
||||
import {OrmUtils} from "../util/OrmUtils";
|
||||
import {getFromContainer} from "../container";
|
||||
import {MigrationInterface} from "../migration/MigrationInterface";
|
||||
import {getMetadataArgsStorage} from "../index";
|
||||
import {EntityMetadataBuilder} from "../metadata-builder/EntityMetadataBuilder";
|
||||
import {EntitySchemaTransformer} from "../entity-schema/EntitySchemaTransformer";
|
||||
import {Connection} from "./Connection";
|
||||
import {EntitySchema} from "../entity-schema/EntitySchema";
|
||||
import {EntityMetadata} from "../metadata/EntityMetadata";
|
||||
import {EntitySubscriberInterface} from "../subscriber/EntitySubscriberInterface";
|
||||
|
||||
export class ConnectionMetadataBuilder {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(protected connection: Connection) {
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
buildMigrations(migrations: Function[]|string[]): MigrationInterface[] {
|
||||
const [migrationClasses, migrationDirectories] = OrmUtils.splitClassesAndStrings(migrations);
|
||||
const allMigrationClasses = [...migrationClasses, ...importClassesFromDirectories(migrationDirectories)];
|
||||
return allMigrationClasses.map(migrationClass => getFromContainer<MigrationInterface>(migrationClass));
|
||||
}
|
||||
|
||||
buildSubscribers(subscribers: Function[]|string[]): EntitySubscriberInterface<any>[] {
|
||||
const [subscriberClasses, subscriberDirectories] = OrmUtils.splitClassesAndStrings(subscribers || []);
|
||||
const allSubscriberClasses = [...subscriberClasses, ...importClassesFromDirectories(subscriberDirectories)];
|
||||
return getMetadataArgsStorage()
|
||||
.filterSubscribers(allSubscriberClasses)
|
||||
.map(metadata => getFromContainer<EntitySubscriberInterface<any>>(metadata.target));
|
||||
}
|
||||
|
||||
buildEntityMetadatas(entities: Function[]|string[], schemas: EntitySchema[]|string[]): EntityMetadata[] {
|
||||
const [entityClasses, entityDirectories] = OrmUtils.splitClassesAndStrings(entities || []);
|
||||
const allEntityClasses = [...entityClasses, ...importClassesFromDirectories(entityDirectories)];
|
||||
const decoratorEntityMetadatas = new EntityMetadataBuilder(this.connection, getMetadataArgsStorage()).build(allEntityClasses);
|
||||
|
||||
const [entitySchemaClasses, entitySchemaDirectories] = OrmUtils.splitClassesAndStrings(schemas || []);
|
||||
const allEntitySchemaClasses = [...entitySchemaClasses, ...importJsonsFromDirectories(entitySchemaDirectories)];
|
||||
const metadataArgsStorageFromSchema = new EntitySchemaTransformer().transform(allEntitySchemaClasses);
|
||||
const schemaEntityMetadatas = new EntityMetadataBuilder(this.connection, metadataArgsStorageFromSchema).build();
|
||||
|
||||
return [...decoratorEntityMetadatas, ...schemaEntityMetadatas];
|
||||
}
|
||||
|
||||
}
|
||||
@ -3,6 +3,9 @@ import {EntitySchema} from "../entity-schema/EntitySchema";
|
||||
import {LoggerOptions} from "../logger/LoggerOptions";
|
||||
import {NamingStrategyInterface} from "../naming-strategy/NamingStrategyInterface";
|
||||
import {DriverType} from "../driver/DriverType";
|
||||
import {LoggerFactory} from "../logger/LoggerFactory";
|
||||
import {DriverFactory} from "../driver/DriverFactory";
|
||||
import {EntityManagerFactory} from "../entity-manager/EntityManagerFactory";
|
||||
|
||||
/**
|
||||
* ConnectionOptions is an interface with settings and options for specific connection.
|
||||
@ -192,4 +195,27 @@ export interface ConnectionOptions {
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Special factories used to override default connection objects behaviour.
|
||||
* Advanced functionality.
|
||||
*/
|
||||
readonly factories?: {
|
||||
|
||||
/**
|
||||
* Logger factory creates logger used to log events in the connection.
|
||||
*/
|
||||
readonly logger?: LoggerFactory;
|
||||
|
||||
/**
|
||||
* Driver factory creates database driver based on the connection driver type.
|
||||
*/
|
||||
readonly driver?: DriverFactory;
|
||||
|
||||
/**
|
||||
* Creates EntityManager instances used in the connection.
|
||||
*/
|
||||
readonly entityManager?: EntityManagerFactory;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@ -10,26 +10,6 @@ import {LazyRelationsWrapper} from "../lazy-loading/LazyRelationsWrapper";
|
||||
*/
|
||||
export interface Driver {
|
||||
|
||||
/**
|
||||
* Driver options contains connectivity options used to connection to the database.
|
||||
*/
|
||||
readonly options: DriverOptions;
|
||||
|
||||
/**
|
||||
* Creates repository instance of this driver.
|
||||
*/
|
||||
// createRepository(connection: Connection, metadata: EntityMetadata, queryRunnerProvider?: QueryRunnerProvider): Repository<any>;
|
||||
|
||||
/**
|
||||
* Creates tree repository instance of this driver.
|
||||
*/
|
||||
// createTreeRepository(connection: Connection, metadata: EntityMetadata, queryRunnerProvider?: QueryRunnerProvider): TreeRepository<any>;
|
||||
|
||||
/**
|
||||
* Creates specific repository instance of this driver.
|
||||
*/
|
||||
// createSpecificRepository(connection: Connection, metadata: EntityMetadata, queryRunnerProvider?: QueryRunnerProvider): SpecificRepository<any>;
|
||||
|
||||
/**
|
||||
* Performs connection to the database.
|
||||
* Based on pooling options, it can either create connection immediately,
|
||||
|
||||
@ -3,16 +3,13 @@ import {ConnectionIsNotSetError} from "../error/ConnectionIsNotSetError";
|
||||
import {DriverOptions} from "../DriverOptions";
|
||||
import {DatabaseConnection} from "../DatabaseConnection";
|
||||
import {DriverPackageNotInstalledError} from "../error/DriverPackageNotInstalledError";
|
||||
import {Logger} from "../../logger/Logger";
|
||||
import {QueryRunner} from "../../query-runner/QueryRunner";
|
||||
import {MongoQueryRunner} from "./MongoQueryRunner";
|
||||
import {ObjectLiteral} from "../../common/ObjectLiteral";
|
||||
import {ColumnMetadata} from "../../metadata/ColumnMetadata";
|
||||
import {DriverOptionNotSetError} from "../error/DriverOptionNotSetError";
|
||||
import {PlatformTools} from "../../platform/PlatformTools";
|
||||
import {NamingStrategyInterface} from "../../naming-strategy/NamingStrategyInterface";
|
||||
import {EntityMetadata} from "../../metadata/EntityMetadata";
|
||||
import {LazyRelationsWrapper} from "../../lazy-loading/LazyRelationsWrapper";
|
||||
import {Connection} from "../../connection/Connection";
|
||||
|
||||
/**
|
||||
@ -30,11 +27,6 @@ export class MongoDriver implements Driver {
|
||||
*/
|
||||
queryRunner: MongoQueryRunner;
|
||||
|
||||
/**
|
||||
* Driver connection options.
|
||||
*/
|
||||
readonly options: DriverOptions;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Protected Properties
|
||||
// -------------------------------------------------------------------------
|
||||
@ -49,23 +41,16 @@ export class MongoDriver implements Driver {
|
||||
*/
|
||||
protected pool: any;
|
||||
|
||||
/**
|
||||
* Logger used to log queries and errors.
|
||||
*/
|
||||
protected logger: Logger;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(connection: Connection) {
|
||||
constructor(protected connection: Connection) {
|
||||
|
||||
// validate options to make sure everything is correct and driver will be able to establish connection
|
||||
this.validateOptions(connection.options);
|
||||
|
||||
// load mongodb package
|
||||
this.options = connection.options;
|
||||
this.logger = connection.logger;
|
||||
this.mongodb = this.loadDependencies();
|
||||
}
|
||||
|
||||
@ -78,7 +63,7 @@ export class MongoDriver implements Driver {
|
||||
*/
|
||||
connect(): Promise<void> {
|
||||
return new Promise<void>((ok, fail) => {
|
||||
this.mongodb.MongoClient.connect(this.buildConnectionUrl(), this.options.extra, (err: any, database: any) => {
|
||||
this.mongodb.MongoClient.connect(this.buildConnectionUrl(), this.connection.options!.extra, (err: any, database: any) => {
|
||||
if (err) return fail(err);
|
||||
|
||||
this.pool = database;
|
||||
@ -87,7 +72,7 @@ export class MongoDriver implements Driver {
|
||||
connection: this.pool,
|
||||
isTransactionActive: false
|
||||
};
|
||||
this.queryRunner = new MongoQueryRunner(databaseConnection, this, this.logger);
|
||||
this.queryRunner = new MongoQueryRunner(this.connection, databaseConnection);
|
||||
ok();
|
||||
});
|
||||
});
|
||||
@ -254,10 +239,10 @@ export class MongoDriver implements Driver {
|
||||
* Builds connection url that is passed to underlying driver to perform connection to the mongodb database.
|
||||
*/
|
||||
protected buildConnectionUrl(): string {
|
||||
if (this.options.url)
|
||||
return this.options.url;
|
||||
if (this.connection.options.url)
|
||||
return this.connection.options.url;
|
||||
|
||||
return `mongodb://${this.options.host || "127.0.0.1"}:${this.options.port || "27017"}/${this.options.database}`;
|
||||
return `mongodb://${this.connection.options.host || "127.0.0.1"}:${this.connection.options.port || "27017"}/${this.connection.options.database}`;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,8 +1,6 @@
|
||||
import {QueryRunner} from "../../query-runner/QueryRunner";
|
||||
import {DatabaseConnection} from "../DatabaseConnection";
|
||||
import {ObjectLiteral} from "../../common/ObjectLiteral";
|
||||
import {Logger} from "../../logger/Logger";
|
||||
import {MongoDriver} from "./MongoDriver";
|
||||
import {ColumnSchema} from "../../schema-builder/schema/ColumnSchema";
|
||||
import {ColumnMetadata} from "../../metadata/ColumnMetadata";
|
||||
import {TableSchema} from "../../schema-builder/schema/TableSchema";
|
||||
@ -40,6 +38,7 @@ import {
|
||||
UpdateWriteOpResult,
|
||||
CollStats
|
||||
} from "./typings";
|
||||
import {Connection} from "../../connection/Connection";
|
||||
|
||||
/**
|
||||
* Runs queries on a single MongoDB connection.
|
||||
@ -50,9 +49,8 @@ export class MongoQueryRunner implements QueryRunner {
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(protected databaseConnection: DatabaseConnection,
|
||||
protected driver: MongoDriver,
|
||||
protected logger: Logger) {
|
||||
constructor(protected connection: Connection,
|
||||
protected databaseConnection: DatabaseConnection) {
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -678,7 +676,7 @@ export class MongoQueryRunner implements QueryRunner {
|
||||
* Database name shortcut.
|
||||
*/
|
||||
protected get dbName(): string {
|
||||
return this.driver.options.database as string;
|
||||
return this.connection.options.database as string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { EventEmitter } from "events";
|
||||
import { Readable, Writable } from "stream";
|
||||
import {EventEmitter} from "events";
|
||||
import {Readable, Writable} from "stream";
|
||||
|
||||
/**
|
||||
* Creates a new MongoClient instance.
|
||||
|
||||
@ -22,15 +22,6 @@ import {Connection} from "../../connection/Connection";
|
||||
*/
|
||||
export class MysqlDriver implements Driver {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Properties
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Driver connection options.
|
||||
*/
|
||||
readonly options: DriverOptions;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Protected Properties
|
||||
// -------------------------------------------------------------------------
|
||||
@ -55,26 +46,20 @@ export class MysqlDriver implements Driver {
|
||||
*/
|
||||
protected databaseConnectionPool: DatabaseConnection[] = [];
|
||||
|
||||
/**
|
||||
* Logger used to log queries and errors.
|
||||
*/
|
||||
protected logger: Logger;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(connection: Connection) {
|
||||
constructor(protected connection: Connection) {
|
||||
|
||||
this.options = DriverUtils.buildDriverOptions(connection.options);
|
||||
this.logger = connection.logger;
|
||||
Object.assign(connection.options, DriverUtils.buildDriverOptions(connection.options)); // todo: do it better way
|
||||
|
||||
// validate options to make sure everything is set
|
||||
if (!(this.options.host || (this.options.extra && this.options.extra.socketPath)))
|
||||
if (!(connection.options.host || (connection.options.extra && connection.options.extra.socketPath)))
|
||||
throw new DriverOptionNotSetError("socketPath and host");
|
||||
if (!this.options.username)
|
||||
if (!connection.options.username)
|
||||
throw new DriverOptionNotSetError("username");
|
||||
if (!this.options.database)
|
||||
if (!connection.options.database)
|
||||
throw new DriverOptionNotSetError("database");
|
||||
|
||||
// load mysql package
|
||||
@ -94,16 +79,16 @@ export class MysqlDriver implements Driver {
|
||||
|
||||
// build connection options for the driver
|
||||
const options = Object.assign({}, {
|
||||
host: this.options.host,
|
||||
user: this.options.username,
|
||||
password: this.options.password,
|
||||
database: this.options.database,
|
||||
port: this.options.port
|
||||
}, this.options.extra || {});
|
||||
host: this.connection.options.host,
|
||||
user: this.connection.options.username,
|
||||
password: this.connection.options.password,
|
||||
database: this.connection.options.database,
|
||||
port: this.connection.options.port
|
||||
}, this.connection.options.extra || {});
|
||||
|
||||
// pooling is enabled either when its set explicitly to true,
|
||||
// either when its not defined at all (e.g. enabled by default)
|
||||
if (this.options.usePool === undefined || this.options.usePool === true) {
|
||||
if (this.connection.options.usePool === undefined || this.connection.options.usePool === true) {
|
||||
this.pool = this.mysql.createPool(options);
|
||||
return Promise.resolve();
|
||||
|
||||
@ -153,7 +138,7 @@ export class MysqlDriver implements Driver {
|
||||
return Promise.reject(new ConnectionIsNotSetError("mysql"));
|
||||
|
||||
const databaseConnection = await this.retrieveDatabaseConnection();
|
||||
return new MysqlQueryRunner(databaseConnection, this, this.logger);
|
||||
return new MysqlQueryRunner(this.connection, databaseConnection);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -14,6 +14,7 @@ import {PrimaryKeySchema} from "../../schema-builder/schema/PrimaryKeySchema";
|
||||
import {IndexSchema} from "../../schema-builder/schema/IndexSchema";
|
||||
import {QueryRunnerAlreadyReleasedError} from "../../query-runner/error/QueryRunnerAlreadyReleasedError";
|
||||
import {ColumnType} from "../../metadata/types/ColumnTypes";
|
||||
import {Connection} from "../../connection/Connection";
|
||||
|
||||
/**
|
||||
* Runs queries on a single mysql database connection.
|
||||
@ -34,9 +35,8 @@ export class MysqlQueryRunner implements QueryRunner {
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(protected databaseConnection: DatabaseConnection,
|
||||
protected driver: MysqlDriver,
|
||||
protected logger: Logger) {
|
||||
constructor(protected connection: Connection,
|
||||
protected databaseConnection: DatabaseConnection) {
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -145,11 +145,11 @@ export class MysqlQueryRunner implements QueryRunner {
|
||||
throw new QueryRunnerAlreadyReleasedError();
|
||||
|
||||
return new Promise((ok, fail) => {
|
||||
this.logger.logQuery(query, parameters);
|
||||
this.connection.logger.logQuery(query, parameters);
|
||||
this.databaseConnection.connection.query(query, parameters, (err: any, result: any) => {
|
||||
if (err) {
|
||||
this.logger.logFailedQuery(query, parameters);
|
||||
this.logger.logQueryError(err);
|
||||
this.connection.logger.logFailedQuery(query, parameters);
|
||||
this.connection.logger.logQueryError(err);
|
||||
return fail(err);
|
||||
}
|
||||
|
||||
@ -166,10 +166,10 @@ export class MysqlQueryRunner implements QueryRunner {
|
||||
throw new QueryRunnerAlreadyReleasedError();
|
||||
|
||||
const keys = Object.keys(keyValues);
|
||||
const columns = keys.map(key => this.driver.escapeColumnName(key)).join(", ");
|
||||
const columns = keys.map(key => this.connection.driver.escapeColumnName(key)).join(", ");
|
||||
const values = keys.map(key => "?").join(",");
|
||||
const parameters = keys.map(key => keyValues[key]);
|
||||
const sql = `INSERT INTO ${this.driver.escapeTableName(tableName)}(${columns}) VALUES (${values})`;
|
||||
const sql = `INSERT INTO ${this.connection.driver.escapeTableName(tableName)}(${columns}) VALUES (${values})`;
|
||||
const result = await this.query(sql, parameters);
|
||||
return generatedColumn ? result.insertId : undefined;
|
||||
}
|
||||
@ -183,7 +183,7 @@ export class MysqlQueryRunner implements QueryRunner {
|
||||
|
||||
const updateValues = this.parametrize(valuesMap).join(", ");
|
||||
const conditionString = this.parametrize(conditions).join(" AND ");
|
||||
const sql = `UPDATE ${this.driver.escapeTableName(tableName)} SET ${updateValues} ${conditionString ? (" WHERE " + conditionString) : ""}`;
|
||||
const sql = `UPDATE ${this.connection.driver.escapeTableName(tableName)} SET ${updateValues} ${conditionString ? (" WHERE " + conditionString) : ""}`;
|
||||
const conditionParams = Object.keys(conditions).map(key => conditions[key]);
|
||||
const updateParams = Object.keys(valuesMap).map(key => valuesMap[key]);
|
||||
const allParameters = updateParams.concat(conditionParams);
|
||||
@ -210,7 +210,7 @@ export class MysqlQueryRunner implements QueryRunner {
|
||||
const conditionString = typeof conditions === "string" ? conditions : this.parametrize(conditions).join(" AND ");
|
||||
const parameters = conditions instanceof Object ? Object.keys(conditions).map(key => (conditions as ObjectLiteral)[key]) : maybeParameters;
|
||||
|
||||
const sql = `DELETE FROM ${this.driver.escapeTableName(tableName)} WHERE ${conditionString}`;
|
||||
const sql = `DELETE FROM ${this.connection.driver.escapeTableName(tableName)} WHERE ${conditionString}`;
|
||||
await this.query(sql, parameters);
|
||||
}
|
||||
|
||||
@ -223,16 +223,16 @@ export class MysqlQueryRunner implements QueryRunner {
|
||||
|
||||
let sql = "";
|
||||
if (hasLevel) {
|
||||
sql = `INSERT INTO ${this.driver.escapeTableName(tableName)}(ancestor, descendant, level) ` +
|
||||
`SELECT ancestor, ${newEntityId}, level + 1 FROM ${this.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
sql = `INSERT INTO ${this.connection.driver.escapeTableName(tableName)}(ancestor, descendant, level) ` +
|
||||
`SELECT ancestor, ${newEntityId}, level + 1 FROM ${this.connection.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
`UNION ALL SELECT ${newEntityId}, ${newEntityId}, 1`;
|
||||
} else {
|
||||
sql = `INSERT INTO ${this.driver.escapeTableName(tableName)}(ancestor, descendant) ` +
|
||||
`SELECT ancestor, ${newEntityId} FROM ${this.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
sql = `INSERT INTO ${this.connection.driver.escapeTableName(tableName)}(ancestor, descendant) ` +
|
||||
`SELECT ancestor, ${newEntityId} FROM ${this.connection.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
`UNION ALL SELECT ${newEntityId}, ${newEntityId}`;
|
||||
}
|
||||
await this.query(sql);
|
||||
const results: ObjectLiteral[] = await this.query(`SELECT MAX(level) as level FROM ${this.driver.escapeTableName(tableName)} WHERE descendant = ${parentId}`);
|
||||
const results: ObjectLiteral[] = await this.query(`SELECT MAX(level) as level FROM ${this.connection.driver.escapeTableName(tableName)} WHERE descendant = ${parentId}`);
|
||||
return results && results[0] && results[0]["level"] ? parseInt(results[0]["level"]) + 1 : 1;
|
||||
}
|
||||
|
||||
@ -765,7 +765,7 @@ export class MysqlQueryRunner implements QueryRunner {
|
||||
* Truncates table.
|
||||
*/
|
||||
async truncate(tableName: string): Promise<void> {
|
||||
await this.query(`TRUNCATE TABLE ${this.driver.escapeTableName(tableName)}`);
|
||||
await this.query(`TRUNCATE TABLE ${this.connection.driver.escapeTableName(tableName)}`);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -776,14 +776,14 @@ export class MysqlQueryRunner implements QueryRunner {
|
||||
* Database name shortcut.
|
||||
*/
|
||||
protected get dbName(): string {
|
||||
return this.driver.options.database as string;
|
||||
return this.connection.options.database as string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parametrizes given object of values. Used to create column=value queries.
|
||||
*/
|
||||
protected parametrize(objectLiteral: ObjectLiteral): string[] {
|
||||
return Object.keys(objectLiteral).map(key => this.driver.escapeColumnName(key) + "=?");
|
||||
return Object.keys(objectLiteral).map(key => this.connection.driver.escapeColumnName(key) + "=?");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -24,15 +24,6 @@ import {Connection} from "../../connection/Connection";
|
||||
*/
|
||||
export class OracleDriver implements Driver {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Properties
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Driver connection options.
|
||||
*/
|
||||
readonly options: DriverOptions;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Protected Properties
|
||||
// -------------------------------------------------------------------------
|
||||
@ -57,26 +48,20 @@ export class OracleDriver implements Driver {
|
||||
*/
|
||||
protected databaseConnectionPool: DatabaseConnection[] = [];
|
||||
|
||||
/**
|
||||
* Logger used to log queries and errors.
|
||||
*/
|
||||
protected logger: Logger;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(connection: Connection) {
|
||||
constructor(protected connection: Connection) {
|
||||
|
||||
this.options = connection.options;
|
||||
this.logger = connection.logger;
|
||||
// Object.assign(connection.options, DriverUtils.buildDriverOptions(connection.options)); // todo: do it better way
|
||||
|
||||
// validate options to make sure everything is set
|
||||
if (!this.options.host)
|
||||
if (!connection.options.host)
|
||||
throw new DriverOptionNotSetError("host");
|
||||
if (!this.options.username)
|
||||
if (!connection.options.username)
|
||||
throw new DriverOptionNotSetError("username");
|
||||
if (!this.options.sid)
|
||||
if (!connection.options.sid)
|
||||
throw new DriverOptionNotSetError("sid");
|
||||
|
||||
// load oracle package
|
||||
@ -97,14 +82,14 @@ export class OracleDriver implements Driver {
|
||||
|
||||
// build connection options for the driver
|
||||
const options = Object.assign({}, {
|
||||
user: this.options.username,
|
||||
password: this.options.password,
|
||||
connectString: this.options.host + ":" + this.options.port + "/" + this.options.sid,
|
||||
}, this.options.extra || {});
|
||||
user: this.connection.options.username,
|
||||
password: this.connection.options.password,
|
||||
connectString: this.connection.options.host + ":" + this.connection.options.port + "/" + this.connection.options.sid,
|
||||
}, this.connection.options.extra || {});
|
||||
|
||||
// pooling is enabled either when its set explicitly to true,
|
||||
// either when its not defined at all (e.g. enabled by default)
|
||||
if (this.options.usePool === undefined || this.options.usePool === true) {
|
||||
if (this.connection.options.usePool === undefined || this.connection.options.usePool === true) {
|
||||
return new Promise<void>((ok, fail) => {
|
||||
this.oracle.createPool(options, (err: any, pool: any) => {
|
||||
if (err)
|
||||
@ -165,7 +150,7 @@ export class OracleDriver implements Driver {
|
||||
return Promise.reject(new ConnectionIsNotSetError("oracle"));
|
||||
|
||||
const databaseConnection = await this.retrieveDatabaseConnection();
|
||||
return new OracleQueryRunner(databaseConnection, this, this.logger);
|
||||
return new OracleQueryRunner(this.connection, databaseConnection);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -3,8 +3,6 @@ import {DatabaseConnection} from "../DatabaseConnection";
|
||||
import {ObjectLiteral} from "../../common/ObjectLiteral";
|
||||
import {TransactionAlreadyStartedError} from "../error/TransactionAlreadyStartedError";
|
||||
import {TransactionNotStartedError} from "../error/TransactionNotStartedError";
|
||||
import {Logger} from "../../logger/Logger";
|
||||
import {OracleDriver} from "./OracleDriver";
|
||||
import {DataTypeNotSupportedByDriverError} from "../error/DataTypeNotSupportedByDriverError";
|
||||
import {ColumnSchema} from "../../schema-builder/schema/ColumnSchema";
|
||||
import {ColumnMetadata} from "../../metadata/ColumnMetadata";
|
||||
@ -14,6 +12,8 @@ import {PrimaryKeySchema} from "../../schema-builder/schema/PrimaryKeySchema";
|
||||
import {IndexSchema} from "../../schema-builder/schema/IndexSchema";
|
||||
import {QueryRunnerAlreadyReleasedError} from "../../query-runner/error/QueryRunnerAlreadyReleasedError";
|
||||
import {ColumnType} from "../../metadata/types/ColumnTypes";
|
||||
import {Connection} from "../../connection/Connection";
|
||||
import {OracleDriver} from "./OracleDriver";
|
||||
|
||||
/**
|
||||
* Runs queries on a single mysql database connection.
|
||||
@ -36,9 +36,8 @@ export class OracleQueryRunner implements QueryRunner {
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(protected databaseConnection: DatabaseConnection,
|
||||
protected driver: OracleDriver,
|
||||
protected logger: Logger) {
|
||||
constructor(protected connection: Connection,
|
||||
protected databaseConnection: DatabaseConnection) {
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -146,11 +145,11 @@ export class OracleQueryRunner implements QueryRunner {
|
||||
throw new QueryRunnerAlreadyReleasedError();
|
||||
|
||||
return new Promise((ok, fail) => {
|
||||
this.logger.logQuery(query, parameters);
|
||||
this.connection.logger.logQuery(query, parameters);
|
||||
const handler = (err: any, result: any) => {
|
||||
if (err) {
|
||||
this.logger.logFailedQuery(query, parameters);
|
||||
this.logger.logQueryError(err);
|
||||
this.connection.logger.logFailedQuery(query, parameters);
|
||||
this.connection.logger.logQueryError(err);
|
||||
return fail(err);
|
||||
}
|
||||
|
||||
@ -171,18 +170,19 @@ export class OracleQueryRunner implements QueryRunner {
|
||||
throw new QueryRunnerAlreadyReleasedError();
|
||||
|
||||
const keys = Object.keys(keyValues);
|
||||
const columns = keys.map(key => this.driver.escapeColumnName(key)).join(", ");
|
||||
const columns = keys.map(key => this.connection.driver.escapeColumnName(key)).join(", ");
|
||||
const values = keys.map(key => ":" + key).join(", ");
|
||||
const parameters = keys.map(key => keyValues[key]);
|
||||
|
||||
const insertSql = columns.length > 0
|
||||
? `INSERT INTO ${this.driver.escapeTableName(tableName)}(${columns}) VALUES (${values})`
|
||||
: `INSERT INTO ${this.driver.escapeTableName(tableName)} DEFAULT VALUES`;
|
||||
? `INSERT INTO ${this.connection.driver.escapeTableName(tableName)}(${columns}) VALUES (${values})`
|
||||
: `INSERT INTO ${this.connection.driver.escapeTableName(tableName)} DEFAULT VALUES`;
|
||||
if (generatedColumn) {
|
||||
const sql2 = `declare lastId number; begin ${insertSql} returning "id" into lastId; dbms_output.enable; dbms_output.put_line(lastId); dbms_output.get_line(:ln, :st); end;`;
|
||||
const oracle = (this.connection.driver as OracleDriver).oracle;
|
||||
const saveResult = await this.query(sql2, parameters.concat([
|
||||
{ dir: this.driver.oracle.BIND_OUT, type: this.driver.oracle.STRING, maxSize: 32767 },
|
||||
{ dir: this.driver.oracle.BIND_OUT, type: this.driver.oracle.NUMBER }
|
||||
{ dir: oracle.BIND_OUT, type: oracle.STRING, maxSize: 32767 },
|
||||
{ dir: oracle.BIND_OUT, type: oracle.NUMBER }
|
||||
]));
|
||||
return parseInt(saveResult[0]);
|
||||
} else {
|
||||
@ -199,7 +199,7 @@ export class OracleQueryRunner implements QueryRunner {
|
||||
|
||||
const updateValues = this.parametrize(valuesMap).join(", ");
|
||||
const conditionString = this.parametrize(conditions).join(" AND ");
|
||||
const sql = `UPDATE ${this.driver.escapeTableName(tableName)} SET ${updateValues} ${conditionString ? (" WHERE " + conditionString) : ""}`;
|
||||
const sql = `UPDATE ${this.connection.driver.escapeTableName(tableName)} SET ${updateValues} ${conditionString ? (" WHERE " + conditionString) : ""}`;
|
||||
const conditionParams = Object.keys(conditions).map(key => conditions[key]);
|
||||
const updateParams = Object.keys(valuesMap).map(key => valuesMap[key]);
|
||||
const allParameters = updateParams.concat(conditionParams);
|
||||
@ -226,7 +226,7 @@ export class OracleQueryRunner implements QueryRunner {
|
||||
const conditionString = typeof conditions === "string" ? conditions : this.parametrize(conditions).join(" AND ");
|
||||
const parameters = conditions instanceof Object ? Object.keys(conditions).map(key => (conditions as ObjectLiteral)[key]) : maybeParameters;
|
||||
|
||||
const sql = `DELETE FROM ${this.driver.escapeTableName(tableName)} WHERE ${conditionString}`;
|
||||
const sql = `DELETE FROM ${this.connection.driver.escapeTableName(tableName)} WHERE ${conditionString}`;
|
||||
await this.query(sql, parameters);
|
||||
}
|
||||
|
||||
@ -239,16 +239,16 @@ export class OracleQueryRunner implements QueryRunner {
|
||||
|
||||
let sql = "";
|
||||
if (hasLevel) {
|
||||
sql = `INSERT INTO ${this.driver.escapeTableName(tableName)}(ancestor, descendant, level) ` +
|
||||
`SELECT ancestor, ${newEntityId}, level + 1 FROM ${this.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
sql = `INSERT INTO ${this.connection.driver.escapeTableName(tableName)}(ancestor, descendant, level) ` +
|
||||
`SELECT ancestor, ${newEntityId}, level + 1 FROM ${this.connection.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
`UNION ALL SELECT ${newEntityId}, ${newEntityId}, 1`;
|
||||
} else {
|
||||
sql = `INSERT INTO ${this.driver.escapeTableName(tableName)}(ancestor, descendant) ` +
|
||||
`SELECT ancestor, ${newEntityId} FROM ${this.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
sql = `INSERT INTO ${this.connection.driver.escapeTableName(tableName)}(ancestor, descendant) ` +
|
||||
`SELECT ancestor, ${newEntityId} FROM ${this.connection.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
`UNION ALL SELECT ${newEntityId}, ${newEntityId}`;
|
||||
}
|
||||
await this.query(sql);
|
||||
const results: ObjectLiteral[] = await this.query(`SELECT MAX(level) as level FROM ${this.driver.escapeTableName(tableName)} WHERE descendant = ${parentId}`);
|
||||
const results: ObjectLiteral[] = await this.query(`SELECT MAX(level) as level FROM ${this.connection.driver.escapeTableName(tableName)} WHERE descendant = ${parentId}`);
|
||||
return results && results[0] && results[0]["level"] ? parseInt(results[0]["level"]) + 1 : 1;
|
||||
}
|
||||
|
||||
@ -836,7 +836,7 @@ AND cons.constraint_name = cols.constraint_name AND cons.owner = cols.owner ORDE
|
||||
* Truncates table.
|
||||
*/
|
||||
async truncate(tableName: string): Promise<void> {
|
||||
await this.query(`TRUNCATE TABLE ${this.driver.escapeTableName(tableName)}`);
|
||||
await this.query(`TRUNCATE TABLE ${this.connection.driver.escapeTableName(tableName)}`);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -847,14 +847,14 @@ AND cons.constraint_name = cols.constraint_name AND cons.owner = cols.owner ORDE
|
||||
* Database name shortcut.
|
||||
*/
|
||||
protected get dbName(): string {
|
||||
return this.driver.options.schemaName as string;
|
||||
return this.connection.options.schemaName as string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parametrizes given object of values. Used to create column=value queries.
|
||||
*/
|
||||
protected parametrize(objectLiteral: ObjectLiteral): string[] {
|
||||
return Object.keys(objectLiteral).map(key => this.driver.escapeColumnName(key) + "=:" + key);
|
||||
return Object.keys(objectLiteral).map(key => this.connection.driver.escapeColumnName(key) + "=:" + key);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -27,15 +27,6 @@ import {Connection} from "../../connection/Connection";
|
||||
*/
|
||||
export class PostgresDriver implements Driver {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Properties
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Driver connection options.
|
||||
*/
|
||||
readonly options: DriverOptions;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Protected Properties
|
||||
// -------------------------------------------------------------------------
|
||||
@ -70,24 +61,22 @@ export class PostgresDriver implements Driver {
|
||||
* default: "public"
|
||||
*/
|
||||
public schemaName?: string;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(connection: Connection) {
|
||||
constructor(protected connection: Connection) {
|
||||
|
||||
this.options = DriverUtils.buildDriverOptions(connection.options);
|
||||
this.logger = connection.logger;
|
||||
Object.assign(connection.options, DriverUtils.buildDriverOptions(connection.options)); // todo: do it better way
|
||||
this.schemaName = connection.options.schemaName || "public";
|
||||
|
||||
// validate options to make sure everything is set
|
||||
if (!this.options.host)
|
||||
if (!connection.options.host)
|
||||
throw new DriverOptionNotSetError("host");
|
||||
if (!this.options.username)
|
||||
if (!connection.options.username)
|
||||
throw new DriverOptionNotSetError("username");
|
||||
if (!this.options.database)
|
||||
if (!connection.options.database)
|
||||
throw new DriverOptionNotSetError("database");
|
||||
|
||||
// load postgres package
|
||||
@ -107,16 +96,16 @@ export class PostgresDriver implements Driver {
|
||||
|
||||
// build connection options for the driver
|
||||
const options = Object.assign({}, {
|
||||
host: this.options.host,
|
||||
user: this.options.username,
|
||||
password: this.options.password,
|
||||
database: this.options.database,
|
||||
port: this.options.port
|
||||
}, this.options.extra || {});
|
||||
host: this.connection.options.host,
|
||||
user: this.connection.options.username,
|
||||
password: this.connection.options.password,
|
||||
database: this.connection.options.database,
|
||||
port: this.connection.options.port
|
||||
}, this.connection.options.extra || {});
|
||||
|
||||
// pooling is enabled either when its set explicitly to true,
|
||||
// either when its not defined at all (e.g. enabled by default)
|
||||
if (this.options.usePool === undefined || this.options.usePool === true) {
|
||||
if (this.connection.options.usePool === undefined || this.connection.options.usePool === true) {
|
||||
this.pool = new this.postgres.Pool(options);
|
||||
return Promise.resolve();
|
||||
|
||||
@ -133,8 +122,8 @@ export class PostgresDriver implements Driver {
|
||||
} else {
|
||||
this.databaseConnection!.connection.query(`SET search_path TO '${this.schemaName}', 'public';`, (err: any, result: any) => {
|
||||
if (err) {
|
||||
this.logger.logFailedQuery(`SET search_path TO '${this.schemaName}', 'public';`);
|
||||
this.logger.logQueryError(err);
|
||||
this.connection.logger.logFailedQuery(`SET search_path TO '${this.schemaName}', 'public';`);
|
||||
this.connection.logger.logQueryError(err);
|
||||
fail(err);
|
||||
} else {
|
||||
ok();
|
||||
@ -184,7 +173,7 @@ export class PostgresDriver implements Driver {
|
||||
return Promise.reject(new ConnectionIsNotSetError("postgres"));
|
||||
|
||||
const databaseConnection = await this.retrieveDatabaseConnection();
|
||||
return new PostgresQueryRunner(databaseConnection, this, this.logger);
|
||||
return new PostgresQueryRunner(this.connection, databaseConnection);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -345,8 +334,8 @@ export class PostgresDriver implements Driver {
|
||||
};
|
||||
dbConnection.connection.query(`SET search_path TO '${this.schemaName}', 'public';`, (err: any) => {
|
||||
if (err) {
|
||||
this.logger.logFailedQuery(`SET search_path TO '${this.schemaName}', 'public';`);
|
||||
this.logger.logQueryError(err);
|
||||
this.connection.logger.logFailedQuery(`SET search_path TO '${this.schemaName}', 'public';`);
|
||||
this.connection.logger.logQueryError(err);
|
||||
fail(err);
|
||||
} else {
|
||||
ok(dbConnection);
|
||||
|
||||
@ -14,6 +14,7 @@ import {ForeignKeySchema} from "../../schema-builder/schema/ForeignKeySchema";
|
||||
import {PrimaryKeySchema} from "../../schema-builder/schema/PrimaryKeySchema";
|
||||
import {QueryRunnerAlreadyReleasedError} from "../../query-runner/error/QueryRunnerAlreadyReleasedError";
|
||||
import {ColumnType} from "../../metadata/types/ColumnTypes";
|
||||
import {Connection} from "../../connection/Connection";
|
||||
|
||||
/**
|
||||
* Runs queries on a single postgres database connection.
|
||||
@ -36,10 +37,9 @@ export class PostgresQueryRunner implements QueryRunner {
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(protected databaseConnection: DatabaseConnection,
|
||||
protected driver: PostgresDriver,
|
||||
protected logger: Logger) {
|
||||
this.schemaName = driver.schemaName || "public";
|
||||
constructor(protected connection: Connection,
|
||||
protected databaseConnection: DatabaseConnection) {
|
||||
this.schemaName = connection.options.schemaName || "public";
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -139,11 +139,11 @@ export class PostgresQueryRunner implements QueryRunner {
|
||||
// console.log("query: ", query);
|
||||
// console.log("parameters: ", parameters);
|
||||
return new Promise<any[]>((ok, fail) => {
|
||||
this.logger.logQuery(query, parameters);
|
||||
this.connection.logger.logQuery(query, parameters);
|
||||
this.databaseConnection.connection.query(query, parameters, (err: any, result: any) => {
|
||||
if (err) {
|
||||
this.logger.logFailedQuery(query, parameters);
|
||||
this.logger.logQueryError(err);
|
||||
this.connection.logger.logFailedQuery(query, parameters);
|
||||
this.connection.logger.logQueryError(err);
|
||||
fail(err);
|
||||
} else {
|
||||
ok(result.rows);
|
||||
@ -160,11 +160,11 @@ export class PostgresQueryRunner implements QueryRunner {
|
||||
throw new QueryRunnerAlreadyReleasedError();
|
||||
|
||||
const keys = Object.keys(keyValues);
|
||||
const columns = keys.map(key => this.driver.escapeColumnName(key)).join(", ");
|
||||
const columns = keys.map(key => this.connection.driver.escapeColumnName(key)).join(", ");
|
||||
const values = keys.map((key, index) => "$" + (index + 1)).join(",");
|
||||
const sql = columns.length > 0
|
||||
? `INSERT INTO ${this.driver.escapeTableName(tableName)}(${columns}) VALUES (${values}) ${ generatedColumn ? " RETURNING " + this.driver.escapeColumnName(generatedColumn.databaseName) : "" }`
|
||||
: `INSERT INTO ${this.driver.escapeTableName(tableName)} DEFAULT VALUES ${ generatedColumn ? " RETURNING " + this.driver.escapeColumnName(generatedColumn.databaseName) : "" }`;
|
||||
? `INSERT INTO ${this.connection.driver.escapeTableName(tableName)}(${columns}) VALUES (${values}) ${ generatedColumn ? " RETURNING " + this.connection.driver.escapeColumnName(generatedColumn.databaseName) : "" }`
|
||||
: `INSERT INTO ${this.connection.driver.escapeTableName(tableName)} DEFAULT VALUES ${ generatedColumn ? " RETURNING " + this.connection.driver.escapeColumnName(generatedColumn.databaseName) : "" }`;
|
||||
const parameters = keys.map(key => keyValues[key]);
|
||||
const result: ObjectLiteral[] = await this.query(sql, parameters);
|
||||
if (generatedColumn)
|
||||
@ -182,7 +182,7 @@ export class PostgresQueryRunner implements QueryRunner {
|
||||
|
||||
const updateValues = this.parametrize(valuesMap).join(", ");
|
||||
const conditionString = this.parametrize(conditions, Object.keys(valuesMap).length).join(" AND ");
|
||||
const query = `UPDATE ${this.driver.escapeTableName(tableName)} SET ${updateValues} ${conditionString ? (" WHERE " + conditionString) : ""}`;
|
||||
const query = `UPDATE ${this.connection.driver.escapeTableName(tableName)} SET ${updateValues} ${conditionString ? (" WHERE " + conditionString) : ""}`;
|
||||
const updateParams = Object.keys(valuesMap).map(key => valuesMap[key]);
|
||||
const conditionParams = Object.keys(conditions).map(key => conditions[key]);
|
||||
const allParameters = updateParams.concat(conditionParams);
|
||||
@ -209,7 +209,7 @@ export class PostgresQueryRunner implements QueryRunner {
|
||||
const conditionString = typeof conditions === "string" ? conditions : this.parametrize(conditions).join(" AND ");
|
||||
const parameters = conditions instanceof Object ? Object.keys(conditions).map(key => (conditions as ObjectLiteral)[key]) : maybeParameters;
|
||||
|
||||
const sql = `DELETE FROM ${this.driver.escapeTableName(tableName)} WHERE ${conditionString}`;
|
||||
const sql = `DELETE FROM ${this.connection.driver.escapeTableName(tableName)} WHERE ${conditionString}`;
|
||||
await this.query(sql, parameters);
|
||||
}
|
||||
|
||||
@ -222,12 +222,12 @@ export class PostgresQueryRunner implements QueryRunner {
|
||||
|
||||
let sql = "";
|
||||
if (hasLevel) {
|
||||
sql = `INSERT INTO ${this.driver.escapeTableName(tableName)}(ancestor, descendant, level) ` +
|
||||
`SELECT ancestor, ${newEntityId}, level + 1 FROM ${this.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
sql = `INSERT INTO ${this.connection.driver.escapeTableName(tableName)}(ancestor, descendant, level) ` +
|
||||
`SELECT ancestor, ${newEntityId}, level + 1 FROM ${this.connection.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
`UNION ALL SELECT ${newEntityId}, ${newEntityId}, 1`;
|
||||
} else {
|
||||
sql = `INSERT INTO ${this.driver.escapeTableName(tableName)}(ancestor, descendant) ` +
|
||||
`SELECT ancestor, ${newEntityId} FROM ${this.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
sql = `INSERT INTO ${this.connection.driver.escapeTableName(tableName)}(ancestor, descendant) ` +
|
||||
`SELECT ancestor, ${newEntityId} FROM ${this.connection.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
`UNION ALL SELECT ${newEntityId}, ${newEntityId}`;
|
||||
}
|
||||
await this.query(sql);
|
||||
@ -837,7 +837,7 @@ where constraint_type = 'PRIMARY KEY' AND c.table_schema = '${this.schemaName}'
|
||||
* Truncates table.
|
||||
*/
|
||||
async truncate(tableName: string): Promise<void> {
|
||||
await this.query(`TRUNCATE TABLE ${this.driver.escapeTableName(tableName)}`);
|
||||
await this.query(`TRUNCATE TABLE ${this.connection.driver.escapeTableName(tableName)}`);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -848,14 +848,14 @@ where constraint_type = 'PRIMARY KEY' AND c.table_schema = '${this.schemaName}'
|
||||
* Database name shortcut.
|
||||
*/
|
||||
protected get dbName(): string {
|
||||
return this.driver.options.database as string;
|
||||
return this.connection.options.database as string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parametrizes given object of values. Used to create column=value queries.
|
||||
*/
|
||||
protected parametrize(objectLiteral: ObjectLiteral, startIndex: number = 0): string[] {
|
||||
return Object.keys(objectLiteral).map((key, index) => this.driver.escapeColumnName(key) + "=$" + (startIndex + index + 1));
|
||||
return Object.keys(objectLiteral).map((key, index) => this.connection.driver.escapeColumnName(key) + "=$" + (startIndex + index + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -21,15 +21,6 @@ import {Connection} from "../../connection/Connection";
|
||||
*/
|
||||
export class SqliteDriver implements Driver {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Properties
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Driver connection options.
|
||||
*/
|
||||
readonly options: DriverOptions;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Protected Properties
|
||||
// -------------------------------------------------------------------------
|
||||
@ -44,22 +35,14 @@ export class SqliteDriver implements Driver {
|
||||
*/
|
||||
protected databaseConnection: DatabaseConnection|undefined;
|
||||
|
||||
/**
|
||||
* Logger used to log queries and errors.
|
||||
*/
|
||||
protected logger: Logger;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(connection: Connection) {
|
||||
|
||||
this.options = connection.options;
|
||||
this.logger = connection.logger;
|
||||
constructor(protected connection: Connection) {
|
||||
|
||||
// validate options to make sure everything is set
|
||||
if (!this.options.storage)
|
||||
if (!connection.options.storage)
|
||||
throw new DriverOptionNotSetError("storage");
|
||||
|
||||
// load sqlite package
|
||||
@ -75,7 +58,7 @@ export class SqliteDriver implements Driver {
|
||||
*/
|
||||
connect(): Promise<void> {
|
||||
return new Promise<void>((ok, fail) => {
|
||||
const connection = new this.sqlite.Database(this.options.storage, (err: any) => {
|
||||
const connection = new this.sqlite.Database(this.connection.options.storage, (err: any) => {
|
||||
if (err)
|
||||
return fail(err);
|
||||
|
||||
@ -115,7 +98,7 @@ export class SqliteDriver implements Driver {
|
||||
return Promise.reject(new ConnectionIsNotSetError("sqlite"));
|
||||
|
||||
const databaseConnection = await this.retrieveDatabaseConnection();
|
||||
return new SqliteQueryRunner(databaseConnection, this, this.logger);
|
||||
return new SqliteQueryRunner(this.connection, databaseConnection);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -15,6 +15,7 @@ import {PrimaryKeySchema} from "../../schema-builder/schema/PrimaryKeySchema";
|
||||
import {QueryRunnerAlreadyReleasedError} from "../../query-runner/error/QueryRunnerAlreadyReleasedError";
|
||||
import {ColumnType} from "../../metadata/types/ColumnTypes";
|
||||
import {RandomGenerator} from "../../util/RandomGenerator";
|
||||
import {Connection} from "../../connection/Connection";
|
||||
|
||||
/**
|
||||
* Runs queries on a single sqlite database connection.
|
||||
@ -38,9 +39,8 @@ export class SqliteQueryRunner implements QueryRunner {
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(protected databaseConnection: DatabaseConnection,
|
||||
protected driver: SqliteDriver,
|
||||
protected logger: Logger) {
|
||||
constructor(protected connection: Connection,
|
||||
protected databaseConnection: DatabaseConnection) {
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -139,11 +139,11 @@ export class SqliteQueryRunner implements QueryRunner {
|
||||
throw new QueryRunnerAlreadyReleasedError();
|
||||
|
||||
return new Promise<any[]>((ok, fail) => {
|
||||
this.logger.logQuery(query, parameters);
|
||||
this.connection.logger.logQuery(query, parameters);
|
||||
this.databaseConnection.connection.all(query, parameters, (err: any, result: any) => {
|
||||
if (err) {
|
||||
this.logger.logFailedQuery(query, parameters);
|
||||
this.logger.logQueryError(err);
|
||||
this.connection.logger.logFailedQuery(query, parameters);
|
||||
this.connection.logger.logQueryError(err);
|
||||
fail(err);
|
||||
} else {
|
||||
ok(result);
|
||||
@ -160,18 +160,18 @@ export class SqliteQueryRunner implements QueryRunner {
|
||||
throw new QueryRunnerAlreadyReleasedError();
|
||||
|
||||
const keys = Object.keys(keyValues);
|
||||
const columns = keys.map(key => this.driver.escapeColumnName(key)).join(", ");
|
||||
const columns = keys.map(key => this.connection.driver.escapeColumnName(key)).join(", ");
|
||||
const values = keys.map((key, index) => "$" + (index + 1)).join(",");
|
||||
const sql = columns.length > 0 ? (`INSERT INTO ${this.driver.escapeTableName(tableName)}(${columns}) VALUES (${values})`) : `INSERT INTO ${this.driver.escapeTableName(tableName)} DEFAULT VALUES`;
|
||||
const sql = columns.length > 0 ? (`INSERT INTO ${this.connection.driver.escapeTableName(tableName)}(${columns}) VALUES (${values})`) : `INSERT INTO ${this.connection.driver.escapeTableName(tableName)} DEFAULT VALUES`;
|
||||
const parameters = keys.map(key => keyValues[key]);
|
||||
|
||||
return new Promise<any[]>((ok, fail) => {
|
||||
this.logger.logQuery(sql, parameters);
|
||||
this.connection.logger.logQuery(sql, parameters);
|
||||
const __this = this;
|
||||
this.databaseConnection.connection.run(sql, parameters, function (err: any): void {
|
||||
if (err) {
|
||||
__this.logger.logFailedQuery(sql, parameters);
|
||||
__this.logger.logQueryError(err);
|
||||
__this.connection.logger.logFailedQuery(sql, parameters);
|
||||
__this.connection.logger.logQueryError(err);
|
||||
fail(err);
|
||||
} else {
|
||||
if (generatedColumn)
|
||||
@ -192,7 +192,7 @@ export class SqliteQueryRunner implements QueryRunner {
|
||||
|
||||
const updateValues = this.parametrize(valuesMap).join(", ");
|
||||
const conditionString = this.parametrize(conditions, Object.keys(valuesMap).length).join(" AND ");
|
||||
const query = `UPDATE ${this.driver.escapeTableName(tableName)} SET ${updateValues} ${conditionString ? (" WHERE " + conditionString) : ""}`;
|
||||
const query = `UPDATE ${this.connection.driver.escapeTableName(tableName)} SET ${updateValues} ${conditionString ? (" WHERE " + conditionString) : ""}`;
|
||||
const updateParams = Object.keys(valuesMap).map(key => valuesMap[key]);
|
||||
const conditionParams = Object.keys(conditions).map(key => conditions[key]);
|
||||
const allParameters = updateParams.concat(conditionParams);
|
||||
@ -219,7 +219,7 @@ export class SqliteQueryRunner implements QueryRunner {
|
||||
const conditionString = typeof conditions === "string" ? conditions : this.parametrize(conditions).join(" AND ");
|
||||
const parameters = conditions instanceof Object ? Object.keys(conditions).map(key => (conditions as ObjectLiteral)[key]) : maybeParameters;
|
||||
|
||||
const sql = `DELETE FROM ${this.driver.escapeTableName(tableName)} WHERE ${conditionString}`;
|
||||
const sql = `DELETE FROM ${this.connection.driver.escapeTableName(tableName)} WHERE ${conditionString}`;
|
||||
await this.query(sql, parameters);
|
||||
}
|
||||
|
||||
@ -232,12 +232,12 @@ export class SqliteQueryRunner implements QueryRunner {
|
||||
|
||||
let sql = "";
|
||||
if (hasLevel) {
|
||||
sql = `INSERT INTO ${this.driver.escapeTableName(tableName)}(ancestor, descendant, level) ` +
|
||||
`SELECT ancestor, ${newEntityId}, level + 1 FROM ${this.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
sql = `INSERT INTO ${this.connection.driver.escapeTableName(tableName)}(ancestor, descendant, level) ` +
|
||||
`SELECT ancestor, ${newEntityId}, level + 1 FROM ${this.connection.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
`UNION ALL SELECT ${newEntityId}, ${newEntityId}, 1`;
|
||||
} else {
|
||||
sql = `INSERT INTO ${this.driver.escapeTableName(tableName)}(ancestor, descendant) ` +
|
||||
`SELECT ancestor, ${newEntityId} FROM ${this.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
sql = `INSERT INTO ${this.connection.driver.escapeTableName(tableName)}(ancestor, descendant) ` +
|
||||
`SELECT ancestor, ${newEntityId} FROM ${this.connection.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
`UNION ALL SELECT ${newEntityId}, ${newEntityId}`;
|
||||
}
|
||||
await this.query(sql);
|
||||
@ -317,7 +317,7 @@ export class SqliteQueryRunner implements QueryRunner {
|
||||
const columnForeignKeys = dbForeignKeys
|
||||
.filter(foreignKey => foreignKey["from"] === dbColumn["name"])
|
||||
.map(foreignKey => {
|
||||
// const keyName = this.driver.namingStrategy.foreignKeyName(dbTable["name"], [foreignKey["from"]], foreignKey["table"], [foreignKey["to"]]);
|
||||
// const keyName = this.connection.driver.namingStrategy.foreignKeyName(dbTable["name"], [foreignKey["from"]], foreignKey["table"], [foreignKey["to"]]);
|
||||
// todo: figure out solution here, name should be same as naming strategy generates!
|
||||
const key = `${dbTable["name"]}_${[foreignKey["from"]].join("_")}_${foreignKey["table"]}_${[foreignKey["to"]].join("_")}`;
|
||||
const keyName = "fk_" + RandomGenerator.sha1(key).substr(0, 27);
|
||||
@ -815,7 +815,7 @@ export class SqliteQueryRunner implements QueryRunner {
|
||||
* Truncates table.
|
||||
*/
|
||||
async truncate(tableName: string): Promise<void> {
|
||||
await this.query(`DELETE FROM ${this.driver.escapeTableName(tableName)}`);
|
||||
await this.query(`DELETE FROM ${this.connection.driver.escapeTableName(tableName)}`);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -826,7 +826,7 @@ export class SqliteQueryRunner implements QueryRunner {
|
||||
* Parametrizes given object of values. Used to create column=value queries.
|
||||
*/
|
||||
protected parametrize(objectLiteral: ObjectLiteral, startIndex: number = 0): string[] {
|
||||
return Object.keys(objectLiteral).map((key, index) => this.driver.escapeColumnName(key) + "=$" + (startIndex + index + 1));
|
||||
return Object.keys(objectLiteral).map((key, index) => this.connection.driver.escapeColumnName(key) + "=$" + (startIndex + index + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -26,11 +26,6 @@ export class SqlServerDriver implements Driver {
|
||||
// Public Properties
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Driver connection options.
|
||||
*/
|
||||
readonly options: DriverOptions;
|
||||
|
||||
/**
|
||||
* SQL Server library.
|
||||
*/
|
||||
@ -48,7 +43,7 @@ export class SqlServerDriver implements Driver {
|
||||
/**
|
||||
* SQL Server pool.
|
||||
*/
|
||||
protected connection: any;
|
||||
protected connectionPool: any;
|
||||
|
||||
/**
|
||||
* Pool of database connections.
|
||||
@ -64,17 +59,16 @@ export class SqlServerDriver implements Driver {
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(connection: Connection) {
|
||||
constructor(protected connection: Connection) {
|
||||
|
||||
this.options = DriverUtils.buildDriverOptions(connection.options);
|
||||
this.logger = connection.logger;
|
||||
Object.assign(connection.options, DriverUtils.buildDriverOptions(connection.options)); // todo: do it better way
|
||||
|
||||
// validate options to make sure everything is set
|
||||
if (!this.options.host)
|
||||
if (!connection.options.host)
|
||||
throw new DriverOptionNotSetError("host");
|
||||
if (!this.options.username)
|
||||
if (!connection.options.username)
|
||||
throw new DriverOptionNotSetError("username");
|
||||
if (!this.options.database)
|
||||
if (!connection.options.database)
|
||||
throw new DriverOptionNotSetError("database");
|
||||
|
||||
// load mssql package
|
||||
@ -94,12 +88,12 @@ export class SqlServerDriver implements Driver {
|
||||
|
||||
// build connection options for the driver
|
||||
const options = Object.assign({}, {
|
||||
server: this.options.host,
|
||||
user: this.options.username,
|
||||
password: this.options.password,
|
||||
database: this.options.database,
|
||||
port: this.options.port
|
||||
}, this.options.extra || {});
|
||||
server: this.connection.options.host,
|
||||
user: this.connection.options.username,
|
||||
password: this.connection.options.password,
|
||||
database: this.connection.options.database,
|
||||
port: this.connection.options.port
|
||||
}, this.connection.options.extra || {});
|
||||
|
||||
// set default useUTC option if it hasn't been set
|
||||
if (!options.options) options.options = { useUTC: false };
|
||||
@ -110,8 +104,8 @@ export class SqlServerDriver implements Driver {
|
||||
return new Promise<void>((ok, fail) => {
|
||||
const connection = new this.mssql.Connection(options).connect((err: any) => {
|
||||
if (err) return fail(err);
|
||||
this.connection = connection;
|
||||
if (this.options.usePool === false) {
|
||||
this.connectionPool = connection;
|
||||
if (this.connection.options.usePool === false) {
|
||||
this.databaseConnection = {
|
||||
id: 1,
|
||||
connection: new this.mssql.Request(connection),
|
||||
@ -127,11 +121,11 @@ export class SqlServerDriver implements Driver {
|
||||
* Closes connection with the database.
|
||||
*/
|
||||
async disconnect(): Promise<void> {
|
||||
if (!this.connection)
|
||||
if (!this.connectionPool)
|
||||
throw new ConnectionIsNotSetError("mssql");
|
||||
|
||||
this.connection.close();
|
||||
this.connection = undefined;
|
||||
this.connectionPool.close();
|
||||
this.connectionPool = undefined;
|
||||
this.databaseConnection = undefined;
|
||||
this.databaseConnectionPool = [];
|
||||
}
|
||||
@ -140,11 +134,11 @@ export class SqlServerDriver implements Driver {
|
||||
* Creates a query runner used for common queries.
|
||||
*/
|
||||
async createQueryRunner(): Promise<QueryRunner> {
|
||||
if (!this.connection)
|
||||
if (!this.connectionPool)
|
||||
return Promise.reject(new ConnectionIsNotSetError("mssql"));
|
||||
|
||||
const databaseConnection = await this.retrieveDatabaseConnection();
|
||||
return new SqlServerQueryRunner(databaseConnection, this, this.logger);
|
||||
return new SqlServerQueryRunner(this.connection, databaseConnection);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -154,7 +148,7 @@ export class SqlServerDriver implements Driver {
|
||||
return {
|
||||
driver: this.mssql,
|
||||
connection: this.databaseConnection ? this.databaseConnection.connection : undefined,
|
||||
pool: this.connection
|
||||
pool: this.connectionPool
|
||||
};
|
||||
}
|
||||
|
||||
@ -275,7 +269,7 @@ export class SqlServerDriver implements Driver {
|
||||
*/
|
||||
protected retrieveDatabaseConnection(): Promise<DatabaseConnection> {
|
||||
|
||||
if (!this.connection)
|
||||
if (!this.connectionPool)
|
||||
throw new ConnectionIsNotSetError("mssql");
|
||||
|
||||
return new Promise((ok, fail) => {
|
||||
@ -298,7 +292,7 @@ export class SqlServerDriver implements Driver {
|
||||
// if (!dbConnection) {
|
||||
let dbConnection: DatabaseConnection = {
|
||||
id: this.databaseConnectionPool.length,
|
||||
connection: this.connection,
|
||||
connection: this.connectionPool,
|
||||
isTransactionActive: false
|
||||
};
|
||||
dbConnection.releaseCallback = () => {
|
||||
|
||||
@ -14,6 +14,8 @@ import {PrimaryKeySchema} from "../../schema-builder/schema/PrimaryKeySchema";
|
||||
import {IndexSchema} from "../../schema-builder/schema/IndexSchema";
|
||||
import {QueryRunnerAlreadyReleasedError} from "../../query-runner/error/QueryRunnerAlreadyReleasedError";
|
||||
import {ColumnType} from "../../metadata/types/ColumnTypes";
|
||||
import {Connection} from "../../connection/Connection";
|
||||
import {MysqlDriver} from "../mysql/MysqlDriver";
|
||||
|
||||
/**
|
||||
* Runs queries on a single mysql database connection.
|
||||
@ -34,11 +36,9 @@ export class SqlServerQueryRunner implements QueryRunner {
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(protected databaseConnection: DatabaseConnection,
|
||||
protected driver: SqlServerDriver,
|
||||
protected logger: Logger) {
|
||||
constructor(protected connection: Connection,
|
||||
protected databaseConnection: DatabaseConnection) {
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
@ -98,12 +98,12 @@ export class SqlServerQueryRunner implements QueryRunner {
|
||||
//
|
||||
// return new Promise<void>((ok, fail) => {
|
||||
//
|
||||
// const request = new this.driver.mssql.Request(this.isTransactionActive() ? this.databaseConnection.transaction : this.databaseConnection.connection);
|
||||
// const request = new this.connection.driver.mssql.Request(this.isTransactionActive() ? this.databaseConnection.transaction : this.databaseConnection.connection);
|
||||
// request.multiple = true;
|
||||
// request.query(allQueries, (err: any, result: any) => {
|
||||
// if (err) {
|
||||
// this.logger.logFailedQuery(allQueries);
|
||||
// this.logger.logQueryError(err);
|
||||
// this.connection.logger.logFailedQuery(allQueries);
|
||||
// this.connection.logger.logQueryError(err);
|
||||
// return fail(err);
|
||||
// }
|
||||
//
|
||||
@ -195,8 +195,8 @@ export class SqlServerQueryRunner implements QueryRunner {
|
||||
|
||||
return new Promise((ok, fail) => {
|
||||
|
||||
this.logger.logQuery(query, parameters);
|
||||
const request = new this.driver.mssql.Request(this.isTransactionActive() ? this.databaseConnection.transaction : this.databaseConnection.connection);
|
||||
this.connection.logger.logQuery(query, parameters);
|
||||
const request = new (this.connection.driver as SqlServerDriver).mssql.Request(this.isTransactionActive() ? this.databaseConnection.transaction : this.databaseConnection.connection);
|
||||
if (parameters && parameters.length) {
|
||||
parameters.forEach((parameter, index) => {
|
||||
request.input(index, parameters![index]);
|
||||
@ -204,8 +204,8 @@ export class SqlServerQueryRunner implements QueryRunner {
|
||||
}
|
||||
request.query(query, (err: any, result: any) => {
|
||||
if (err) {
|
||||
this.logger.logFailedQuery(query, parameters);
|
||||
this.logger.logQueryError(err);
|
||||
this.connection.logger.logFailedQuery(query, parameters);
|
||||
this.connection.logger.logQueryError(err);
|
||||
return fail(err);
|
||||
}
|
||||
|
||||
@ -222,13 +222,13 @@ export class SqlServerQueryRunner implements QueryRunner {
|
||||
throw new QueryRunnerAlreadyReleasedError();
|
||||
|
||||
const keys = Object.keys(keyValues);
|
||||
const columns = keys.map(key => this.driver.escapeColumnName(key)).join(", ");
|
||||
const columns = keys.map(key => this.connection.driver.escapeColumnName(key)).join(", ");
|
||||
const values = keys.map((key, index) => "@" + index).join(",");
|
||||
const parameters = keys.map(key => keyValues[key]);
|
||||
|
||||
const sql = columns.length > 0
|
||||
? `INSERT INTO ${this.driver.escapeTableName(tableName)}(${columns}) ${ generatedColumn ? "OUTPUT INSERTED." + generatedColumn.databaseName + " " : "" }VALUES (${values})`
|
||||
: `INSERT INTO ${this.driver.escapeTableName(tableName)} ${ generatedColumn ? "OUTPUT INSERTED." + generatedColumn.databaseName + " " : "" }DEFAULT VALUES `;
|
||||
? `INSERT INTO ${this.connection.driver.escapeTableName(tableName)}(${columns}) ${ generatedColumn ? "OUTPUT INSERTED." + generatedColumn.databaseName + " " : "" }VALUES (${values})`
|
||||
: `INSERT INTO ${this.connection.driver.escapeTableName(tableName)} ${ generatedColumn ? "OUTPUT INSERTED." + generatedColumn.databaseName + " " : "" }DEFAULT VALUES `;
|
||||
|
||||
const result = await this.query(sql, parameters);
|
||||
return generatedColumn ? result instanceof Array ? result[0][generatedColumn.databaseName] : result[generatedColumn.databaseName] : undefined;
|
||||
@ -247,7 +247,7 @@ export class SqlServerQueryRunner implements QueryRunner {
|
||||
|
||||
const updateValues = this.parametrize(valuesMap).join(", ");
|
||||
const conditionString = this.parametrize(conditions, updateParams.length).join(" AND ");
|
||||
const sql = `UPDATE ${this.driver.escapeTableName(tableName)} SET ${updateValues} ${conditionString ? (" WHERE " + conditionString) : ""}`;
|
||||
const sql = `UPDATE ${this.connection.driver.escapeTableName(tableName)} SET ${updateValues} ${conditionString ? (" WHERE " + conditionString) : ""}`;
|
||||
|
||||
await this.query(sql, allParameters);
|
||||
}
|
||||
@ -272,7 +272,7 @@ export class SqlServerQueryRunner implements QueryRunner {
|
||||
const conditionString = typeof conditions === "string" ? conditions : this.parametrize(conditions).join(" AND ");
|
||||
const parameters = conditions instanceof Object ? Object.keys(conditions).map(key => (conditions as ObjectLiteral)[key]) : maybeParameters;
|
||||
|
||||
const sql = `DELETE FROM ${this.driver.escapeTableName(tableName)} WHERE ${conditionString}`;
|
||||
const sql = `DELETE FROM ${this.connection.driver.escapeTableName(tableName)} WHERE ${conditionString}`;
|
||||
await this.query(sql, parameters);
|
||||
}
|
||||
|
||||
@ -285,16 +285,16 @@ export class SqlServerQueryRunner implements QueryRunner {
|
||||
|
||||
let sql = "";
|
||||
if (hasLevel) {
|
||||
sql = `INSERT INTO ${this.driver.escapeTableName(tableName)}(ancestor, descendant, level) ` +
|
||||
`SELECT ancestor, ${newEntityId}, level + 1 FROM ${this.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
sql = `INSERT INTO ${this.connection.driver.escapeTableName(tableName)}(ancestor, descendant, level) ` +
|
||||
`SELECT ancestor, ${newEntityId}, level + 1 FROM ${this.connection.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
`UNION ALL SELECT ${newEntityId}, ${newEntityId}, 1`;
|
||||
} else {
|
||||
sql = `INSERT INTO ${this.driver.escapeTableName(tableName)}(ancestor, descendant) ` +
|
||||
`SELECT ancestor, ${newEntityId} FROM ${this.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
sql = `INSERT INTO ${this.connection.driver.escapeTableName(tableName)}(ancestor, descendant) ` +
|
||||
`SELECT ancestor, ${newEntityId} FROM ${this.connection.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
`UNION ALL SELECT ${newEntityId}, ${newEntityId}`;
|
||||
}
|
||||
await this.query(sql);
|
||||
const results: ObjectLiteral[] = await this.query(`SELECT MAX(level) as level FROM ${this.driver.escapeTableName(tableName)} WHERE descendant = ${parentId}`);
|
||||
const results: ObjectLiteral[] = await this.query(`SELECT MAX(level) as level FROM ${this.connection.driver.escapeTableName(tableName)} WHERE descendant = ${parentId}`);
|
||||
return results && results[0] && results[0]["level"] ? parseInt(results[0]["level"]) + 1 : 1;
|
||||
}
|
||||
|
||||
@ -870,7 +870,7 @@ WHERE columnUsages.TABLE_CATALOG = '${this.dbName}' AND tableConstraints.TABLE_C
|
||||
* Truncates table.
|
||||
*/
|
||||
async truncate(tableName: string): Promise<void> {
|
||||
await this.query(`TRUNCATE TABLE ${this.driver.escapeTableName(tableName)}`);
|
||||
await this.query(`TRUNCATE TABLE ${this.connection.driver.escapeTableName(tableName)}`);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -881,7 +881,7 @@ WHERE columnUsages.TABLE_CATALOG = '${this.dbName}' AND tableConstraints.TABLE_C
|
||||
* Database name shortcut.
|
||||
*/
|
||||
protected get dbName(): string {
|
||||
return this.driver.options.database as string;
|
||||
return this.connection.options.database as string;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -889,7 +889,7 @@ WHERE columnUsages.TABLE_CATALOG = '${this.dbName}' AND tableConstraints.TABLE_C
|
||||
*/
|
||||
protected parametrize(objectLiteral: ObjectLiteral, startFrom: number = 0): string[] {
|
||||
return Object.keys(objectLiteral).map((key, index) => {
|
||||
return this.driver.escapeColumnName(key) + "=@" + (startFrom + index);
|
||||
return this.connection.driver.escapeColumnName(key) + "=@" + (startFrom + index);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -11,8 +11,6 @@ import {ColumnMetadata} from "../../metadata/ColumnMetadata";
|
||||
import {DriverOptionNotSetError} from "../error/DriverOptionNotSetError";
|
||||
import {DataTransformationUtils} from "../../util/DataTransformationUtils";
|
||||
import {WebsqlQueryRunner} from "./WebsqlQueryRunner";
|
||||
import {NamingStrategyInterface} from "../../naming-strategy/NamingStrategyInterface";
|
||||
import {LazyRelationsWrapper} from "../../lazy-loading/LazyRelationsWrapper";
|
||||
import {Connection} from "../../connection/Connection";
|
||||
|
||||
/**
|
||||
@ -25,15 +23,6 @@ declare function openDatabase(...params: any[]): any;
|
||||
*/
|
||||
export class WebsqlDriver implements Driver {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Properties
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Driver connection options.
|
||||
*/
|
||||
readonly options: DriverOptions;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Protected Properties
|
||||
// -------------------------------------------------------------------------
|
||||
@ -43,26 +32,20 @@ export class WebsqlDriver implements Driver {
|
||||
*/
|
||||
protected databaseConnection: DatabaseConnection|undefined;
|
||||
|
||||
/**
|
||||
* Logger used to log queries and errors.
|
||||
*/
|
||||
protected logger: Logger;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(connection: Connection) {
|
||||
constructor(protected connection: Connection) {
|
||||
|
||||
this.options = DriverUtils.buildDriverOptions(connection.options);
|
||||
this.logger = connection.logger;
|
||||
Object.assign(connection.options, DriverUtils.buildDriverOptions(connection.options)); // todo: do it better way
|
||||
|
||||
// validate options to make sure everything is set
|
||||
// if (!this.options.host)
|
||||
// throw new DriverOptionNotSetError("host");
|
||||
// if (!this.options.username)
|
||||
// throw new DriverOptionNotSetError("username");
|
||||
if (!this.options.database)
|
||||
if (!connection.options.database)
|
||||
throw new DriverOptionNotSetError("database");
|
||||
// todo: what about extra options: version, description, size
|
||||
}
|
||||
@ -80,8 +63,8 @@ export class WebsqlDriver implements Driver {
|
||||
|
||||
// build connection options for the driver
|
||||
const options = Object.assign({}, {
|
||||
database: this.options.database,
|
||||
}, this.options.extra || {});
|
||||
database: this.connection.options.database,
|
||||
}, this.connection.options.extra || {});
|
||||
|
||||
return new Promise<void>((ok, fail) => {
|
||||
const connection = openDatabase(
|
||||
@ -121,7 +104,7 @@ export class WebsqlDriver implements Driver {
|
||||
return Promise.reject(new ConnectionIsNotSetError("websql"));
|
||||
|
||||
const databaseConnection = await this.retrieveDatabaseConnection();
|
||||
return new WebsqlQueryRunner(databaseConnection, this, this.logger);
|
||||
return new WebsqlQueryRunner(this.connection, databaseConnection);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -13,6 +13,7 @@ import {IndexSchema} from "../../schema-builder/schema/IndexSchema";
|
||||
import {QueryRunnerAlreadyReleasedError} from "../../query-runner/error/QueryRunnerAlreadyReleasedError";
|
||||
import {WebsqlDriver} from "./WebsqlDriver";
|
||||
import {ColumnType} from "../../metadata/types/ColumnTypes";
|
||||
import {Connection} from "../../connection/Connection";
|
||||
|
||||
/**
|
||||
* Runs queries on a single websql database connection.
|
||||
@ -33,9 +34,8 @@ export class WebsqlQueryRunner implements QueryRunner {
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(protected databaseConnection: DatabaseConnection,
|
||||
protected driver: WebsqlDriver,
|
||||
protected logger: Logger) {
|
||||
constructor(protected connection: Connection,
|
||||
protected databaseConnection: DatabaseConnection) {
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -139,7 +139,7 @@ export class WebsqlQueryRunner implements QueryRunner {
|
||||
|
||||
return new Promise((ok, fail) => {
|
||||
|
||||
this.logger.logQuery(query, parameters);
|
||||
this.connection.logger.logQuery(query, parameters);
|
||||
const db = this.databaseConnection.connection;
|
||||
// todo: check if transaction is not active
|
||||
db.transaction((tx: any) => {
|
||||
@ -151,8 +151,8 @@ export class WebsqlQueryRunner implements QueryRunner {
|
||||
ok(rows);
|
||||
|
||||
}, (tx: any, err: any) => {
|
||||
this.logger.logFailedQuery(query, parameters);
|
||||
this.logger.logQueryError(err);
|
||||
this.connection.logger.logFailedQuery(query, parameters);
|
||||
this.connection.logger.logQueryError(err);
|
||||
return fail(err);
|
||||
});
|
||||
});
|
||||
@ -167,13 +167,13 @@ export class WebsqlQueryRunner implements QueryRunner {
|
||||
throw new QueryRunnerAlreadyReleasedError();
|
||||
|
||||
const keys = Object.keys(keyValues);
|
||||
const columns = keys.map(key => this.driver.escapeColumnName(key)).join(", ");
|
||||
const columns = keys.map(key => this.connection.driver.escapeColumnName(key)).join(", ");
|
||||
const values = keys.map((key, index) => "$" + (index + 1)).join(",");
|
||||
const sql = columns.length > 0 ? (`INSERT INTO ${this.driver.escapeTableName(tableName)}(${columns}) VALUES (${values})`) : `INSERT INTO ${this.driver.escapeTableName(tableName)} DEFAULT VALUES`;
|
||||
const sql = columns.length > 0 ? (`INSERT INTO ${this.connection.driver.escapeTableName(tableName)}(${columns}) VALUES (${values})`) : `INSERT INTO ${this.connection.driver.escapeTableName(tableName)} DEFAULT VALUES`;
|
||||
const parameters = keys.map(key => keyValues[key]);
|
||||
|
||||
return new Promise<any[]>((ok, fail) => {
|
||||
this.logger.logQuery(sql, parameters);
|
||||
this.connection.logger.logQuery(sql, parameters);
|
||||
|
||||
const db = this.databaseConnection.connection;
|
||||
// todo: check if transaction is not active
|
||||
@ -184,8 +184,8 @@ export class WebsqlQueryRunner implements QueryRunner {
|
||||
ok();
|
||||
|
||||
}, (tx: any, err: any) => {
|
||||
this.logger.logFailedQuery(sql, parameters);
|
||||
this.logger.logQueryError(err);
|
||||
this.connection.logger.logFailedQuery(sql, parameters);
|
||||
this.connection.logger.logQueryError(err);
|
||||
return fail(err);
|
||||
});
|
||||
});
|
||||
@ -201,7 +201,7 @@ export class WebsqlQueryRunner implements QueryRunner {
|
||||
|
||||
const updateValues = this.parametrize(valuesMap).join(", ");
|
||||
const conditionString = this.parametrize(conditions, Object.keys(valuesMap).length).join(" AND ");
|
||||
const query = `UPDATE ${this.driver.escapeTableName(tableName)} SET ${updateValues} ${conditionString ? (" WHERE " + conditionString) : ""}`;
|
||||
const query = `UPDATE ${this.connection.driver.escapeTableName(tableName)} SET ${updateValues} ${conditionString ? (" WHERE " + conditionString) : ""}`;
|
||||
const updateParams = Object.keys(valuesMap).map(key => valuesMap[key]);
|
||||
const conditionParams = Object.keys(conditions).map(key => conditions[key]);
|
||||
const allParameters = updateParams.concat(conditionParams);
|
||||
@ -228,7 +228,7 @@ export class WebsqlQueryRunner implements QueryRunner {
|
||||
const conditionString = typeof conditions === "string" ? conditions : this.parametrize(conditions).join(" AND ");
|
||||
const parameters = conditions instanceof Object ? Object.keys(conditions).map(key => (conditions as ObjectLiteral)[key]) : maybeParameters;
|
||||
|
||||
const sql = `DELETE FROM ${this.driver.escapeTableName(tableName)} WHERE ${conditionString}`;
|
||||
const sql = `DELETE FROM ${this.connection.driver.escapeTableName(tableName)} WHERE ${conditionString}`;
|
||||
await this.query(sql, parameters);
|
||||
}
|
||||
|
||||
@ -241,12 +241,12 @@ export class WebsqlQueryRunner implements QueryRunner {
|
||||
|
||||
let sql = "";
|
||||
if (hasLevel) {
|
||||
sql = `INSERT INTO ${this.driver.escapeTableName(tableName)}(ancestor, descendant, level) ` +
|
||||
`SELECT ancestor, ${newEntityId}, level + 1 FROM ${this.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
sql = `INSERT INTO ${this.connection.driver.escapeTableName(tableName)}(ancestor, descendant, level) ` +
|
||||
`SELECT ancestor, ${newEntityId}, level + 1 FROM ${this.connection.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
`UNION ALL SELECT ${newEntityId}, ${newEntityId}, 1`;
|
||||
} else {
|
||||
sql = `INSERT INTO ${this.driver.escapeTableName(tableName)}(ancestor, descendant) ` +
|
||||
`SELECT ancestor, ${newEntityId} FROM ${this.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
sql = `INSERT INTO ${this.connection.driver.escapeTableName(tableName)}(ancestor, descendant) ` +
|
||||
`SELECT ancestor, ${newEntityId} FROM ${this.connection.driver.escapeTableName(tableName)} WHERE descendant = ${parentId} ` +
|
||||
`UNION ALL SELECT ${newEntityId}, ${newEntityId}`;
|
||||
}
|
||||
await this.query(sql);
|
||||
@ -821,7 +821,7 @@ export class WebsqlQueryRunner implements QueryRunner {
|
||||
* Truncates table.
|
||||
*/
|
||||
async truncate(tableName: string): Promise<void> {
|
||||
await this.query(`DELETE FROM ${this.driver.escapeTableName(tableName)}`);
|
||||
await this.query(`DELETE FROM ${this.connection.driver.escapeTableName(tableName)}`);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -832,7 +832,7 @@ export class WebsqlQueryRunner implements QueryRunner {
|
||||
* Parametrizes given object of values. Used to create column=value queries.
|
||||
*/
|
||||
protected parametrize(objectLiteral: ObjectLiteral, startIndex: number = 0): string[] {
|
||||
return Object.keys(objectLiteral).map((key, index) => this.driver.escapeColumnName(key) + "=$" + (startIndex + index + 1));
|
||||
return Object.keys(objectLiteral).map((key, index) => this.connection.driver.escapeColumnName(key) + "=$" + (startIndex + index + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -8,13 +8,11 @@ import {FindOneOptions} from "../find-options/FindOneOptions";
|
||||
import {DeepPartial} from "../common/DeepPartial";
|
||||
import {RemoveOptions} from "../repository/RemoveOptions";
|
||||
import {SaveOptions} from "../repository/SaveOptions";
|
||||
import {RepositoryAggregator} from "../repository/RepositoryAggregator";
|
||||
import {NoNeedToReleaseEntityManagerError} from "./error/NoNeedToReleaseEntityManagerError";
|
||||
import {SpecificRepository} from "../repository/SpecificRepository";
|
||||
import {MongoRepository} from "../repository/MongoRepository";
|
||||
import {TreeRepository} from "../repository/TreeRepository";
|
||||
import {Repository} from "../repository/Repository";
|
||||
import {RepositoryNotTreeError} from "../connection/error/RepositoryNotTreeError";
|
||||
import {QueryBuilder} from "../query-builder/QueryBuilder";
|
||||
import {FindOptionsUtils} from "../find-options/FindOptionsUtils";
|
||||
import {SubjectBuilder} from "../persistence/SubjectBuilder";
|
||||
@ -42,11 +40,6 @@ export class EntityManager {
|
||||
*/
|
||||
private data: ObjectLiteral = {};
|
||||
|
||||
/**
|
||||
* Stores all registered repositories.
|
||||
*/
|
||||
private repositoryAggregators: RepositoryAggregator[] = [];
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
@ -582,8 +575,12 @@ export class EntityManager {
|
||||
getRepository<Entity>(entityClassOrName: ObjectType<Entity>|string): Repository<Entity> {
|
||||
|
||||
// if single db connection is used then create its own repository with reused query runner
|
||||
if (this.queryRunnerProvider)
|
||||
return this.obtainRepositoryAggregator(entityClassOrName as any).repository;
|
||||
if (this.queryRunnerProvider) {
|
||||
if (this.queryRunnerProvider.isReleased)
|
||||
throw new QueryRunnerProviderAlreadyReleasedError();
|
||||
|
||||
return this.connection.createIsolatedRepository(entityClassOrName, this.queryRunnerProvider);
|
||||
}
|
||||
|
||||
return this.connection.getRepository<Entity>(entityClassOrName as any);
|
||||
}
|
||||
@ -598,11 +595,10 @@ export class EntityManager {
|
||||
|
||||
// if single db connection is used then create its own repository with reused query runner
|
||||
if (this.queryRunnerProvider) {
|
||||
const treeRepository = this.obtainRepositoryAggregator(entityClassOrName).treeRepository;
|
||||
if (!treeRepository)
|
||||
throw new RepositoryNotTreeError(entityClassOrName);
|
||||
if (this.queryRunnerProvider.isReleased)
|
||||
throw new QueryRunnerProviderAlreadyReleasedError();
|
||||
|
||||
return treeRepository;
|
||||
return this.connection.createIsolatedRepository(entityClassOrName, this.queryRunnerProvider) as TreeRepository<Entity>;
|
||||
}
|
||||
|
||||
return this.connection.getTreeRepository<Entity>(entityClassOrName as any);
|
||||
@ -624,8 +620,12 @@ export class EntityManager {
|
||||
getMongoRepository<Entity>(entityClassOrName: ObjectType<Entity>|string): MongoRepository<Entity> {
|
||||
|
||||
// if single db connection is used then create its own repository with reused query runner
|
||||
if (this.queryRunnerProvider)
|
||||
return this.obtainRepositoryAggregator(entityClassOrName as any).repository as MongoRepository<Entity>;
|
||||
if (this.queryRunnerProvider) {
|
||||
if (this.queryRunnerProvider.isReleased)
|
||||
throw new QueryRunnerProviderAlreadyReleasedError();
|
||||
|
||||
return this.connection.createIsolatedRepository(entityClassOrName, this.queryRunnerProvider) as MongoRepository<Entity>;
|
||||
}
|
||||
|
||||
return this.connection.getMongoRepository<Entity>(entityClassOrName as any);
|
||||
}
|
||||
@ -661,8 +661,12 @@ export class EntityManager {
|
||||
getSpecificRepository<Entity>(entityClassOrName: ObjectType<Entity>|string): SpecificRepository<Entity> {
|
||||
|
||||
// if single db connection is used then create its own repository with reused query runner
|
||||
if (this.queryRunnerProvider)
|
||||
return this.obtainRepositoryAggregator(entityClassOrName).specificRepository;
|
||||
if (this.queryRunnerProvider) {
|
||||
if (this.queryRunnerProvider.isReleased)
|
||||
throw new QueryRunnerProviderAlreadyReleasedError();
|
||||
|
||||
return this.connection.createIsolatedSpecificRepository(entityClassOrName, this.queryRunnerProvider);
|
||||
}
|
||||
|
||||
return this.connection.getSpecificRepository<Entity>(entityClassOrName as any);
|
||||
}
|
||||
@ -757,25 +761,4 @@ export class EntityManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets, or if does not exist yet, creates and returns a repository aggregator for a particular entity target.
|
||||
*/
|
||||
protected obtainRepositoryAggregator<Entity>(entityClassOrName: ObjectType<Entity>|string): RepositoryAggregator {
|
||||
if (this.queryRunnerProvider && this.queryRunnerProvider.isReleased)
|
||||
throw new QueryRunnerProviderAlreadyReleasedError();
|
||||
|
||||
const metadata = this.connection.getMetadata(entityClassOrName);
|
||||
let repositoryAggregator = this.repositoryAggregators.find(repositoryAggregate => repositoryAggregate.metadata === metadata);
|
||||
if (!repositoryAggregator) {
|
||||
repositoryAggregator = new RepositoryAggregator(
|
||||
this.connection,
|
||||
this.connection.getMetadata(entityClassOrName as any),
|
||||
this.queryRunnerProvider
|
||||
);
|
||||
this.repositoryAggregators.push(repositoryAggregator); // todo: check isnt memory leak here?
|
||||
}
|
||||
|
||||
return repositoryAggregator;
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,6 +2,7 @@ import {Connection} from "../connection/Connection";
|
||||
import {EntityManager} from "./EntityManager";
|
||||
import {MongoEntityManager} from "./MongoEntityManager";
|
||||
import {MongoDriver} from "../driver/mongodb/MongoDriver";
|
||||
import {QueryRunnerProvider} from "../query-runner/QueryRunnerProvider";
|
||||
|
||||
/**
|
||||
* Helps to create entity managers.
|
||||
@ -11,11 +12,11 @@ export class EntityManagerFactory {
|
||||
/**
|
||||
* Creates a new entity manager depend on a given connection's driver.
|
||||
*/
|
||||
create(connection: Connection): EntityManager {
|
||||
create(connection: Connection, queryRunnerProvider?: QueryRunnerProvider): EntityManager {
|
||||
if (connection.driver instanceof MongoDriver)
|
||||
return new MongoEntityManager(connection);
|
||||
return new MongoEntityManager(connection, queryRunnerProvider);
|
||||
|
||||
return new EntityManager(connection);
|
||||
return new EntityManager(connection, queryRunnerProvider);
|
||||
}
|
||||
|
||||
}
|
||||
16
src/logger/LoggerFactory.ts
Normal file
16
src/logger/LoggerFactory.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import {LoggerOptions} from "./LoggerOptions";
|
||||
import {Logger} from "./Logger";
|
||||
|
||||
/**
|
||||
* Helps to create logger instances.
|
||||
*/
|
||||
export class LoggerFactory {
|
||||
|
||||
/**
|
||||
* Creates a new logger depend on a given connection's driver.
|
||||
*/
|
||||
create(options: LoggerOptions): Logger {
|
||||
return new Logger(options);
|
||||
}
|
||||
|
||||
}
|
||||
@ -14,6 +14,8 @@ import {TableMetadataArgs} from "../metadata-args/TableMetadataArgs";
|
||||
import {Connection} from "../connection/Connection";
|
||||
import {EntityListenerMetadata} from "./EntityListenerMetadata";
|
||||
import {PropertyTypeFactory} from "./types/PropertyTypeInFunction";
|
||||
import {Repository} from "../repository/Repository";
|
||||
import {SpecificRepository} from "../repository/SpecificRepository";
|
||||
|
||||
/**
|
||||
* Contains all entity metadata.
|
||||
@ -24,6 +26,16 @@ export class EntityMetadata {
|
||||
// Properties
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Repository used for this entity metadata.
|
||||
*/
|
||||
repository: Repository<any>;
|
||||
|
||||
/**
|
||||
* Specific repository used for this entity metadata.
|
||||
*/
|
||||
specificRepository: SpecificRepository<any>;
|
||||
|
||||
/**
|
||||
* Used to wrap lazy relations.
|
||||
*/
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
import {Repository} from "./Repository";
|
||||
import {EntityMetadata} from "../metadata/EntityMetadata";
|
||||
import {SpecificRepository} from "./SpecificRepository";
|
||||
import {Connection} from "../connection/Connection";
|
||||
import {TreeRepository} from "./TreeRepository";
|
||||
import {QueryRunnerProvider} from "../query-runner/QueryRunnerProvider";
|
||||
import {RepositoryFactory} from "./RepositoryFactory";
|
||||
import {getFromContainer} from "../container";
|
||||
|
||||
/**
|
||||
* Aggregates all repositories of the specific metadata.
|
||||
*/
|
||||
export class RepositoryAggregator {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Readonly properties
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Entity metadata which owns repositories.
|
||||
*/
|
||||
public readonly metadata: EntityMetadata;
|
||||
|
||||
/**
|
||||
* Ordinary repository.
|
||||
*/
|
||||
public readonly repository: Repository<any>;
|
||||
|
||||
/**
|
||||
* Tree repository.
|
||||
*/
|
||||
public readonly treeRepository?: TreeRepository<any>;
|
||||
|
||||
/**
|
||||
* Repository with specific functions.
|
||||
*/
|
||||
public readonly specificRepository: SpecificRepository<any>;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(connection: Connection, metadata: EntityMetadata, queryRunnerProvider?: QueryRunnerProvider) {
|
||||
this.metadata = metadata;
|
||||
|
||||
const factory = getFromContainer(RepositoryFactory);
|
||||
|
||||
if (metadata.isClosure) {
|
||||
this.repository = this.treeRepository = factory.createTreeRepository(connection.manager, metadata, queryRunnerProvider);
|
||||
} else {
|
||||
this.repository = factory.createRepository(connection.manager, metadata, queryRunnerProvider);
|
||||
}
|
||||
|
||||
this.specificRepository = factory.createSpecificRepository(connection, metadata, queryRunnerProvider);
|
||||
}
|
||||
|
||||
}
|
||||
@ -20,34 +20,32 @@ export class RepositoryFactory {
|
||||
/**
|
||||
* Creates a regular repository.
|
||||
*/
|
||||
createRepository(manager: EntityManager, metadata: EntityMetadata, queryRunnerProvider?: QueryRunnerProvider): Repository<any> {
|
||||
createRepository(connection: Connection, metadata: EntityMetadata, queryRunnerProvider?: QueryRunnerProvider): Repository<any> {
|
||||
|
||||
if (metadata.isClosure) {
|
||||
// NOTE: dynamic access to protected properties. We need this to prevent unwanted properties in those classes to be exposed,
|
||||
// however we need these properties for internal work of the class
|
||||
const repository = new TreeRepository<any>();
|
||||
(repository as any)["manager"] = connection.manager;
|
||||
(repository as any)["metadata"] = metadata;
|
||||
(repository as any)["queryRunnerProvider"] = queryRunnerProvider;
|
||||
return repository;
|
||||
|
||||
// NOTE: dynamic access to protected properties. We need this to prevent unwanted properties in those classes to be exposed,
|
||||
// however we need these properties for internal work of the class
|
||||
let repository: Repository<any>;
|
||||
if (manager.connection.driver instanceof MongoDriver) {
|
||||
repository = new MongoRepository();
|
||||
} else {
|
||||
repository = new Repository<any>();
|
||||
// NOTE: dynamic access to protected properties. We need this to prevent unwanted properties in those classes to be exposed,
|
||||
// however we need these properties for internal work of the class
|
||||
let repository: Repository<any>;
|
||||
if (connection.driver instanceof MongoDriver) {
|
||||
repository = new MongoRepository();
|
||||
} else {
|
||||
repository = new Repository<any>();
|
||||
}
|
||||
(repository as any)["manager"] = connection.manager;
|
||||
(repository as any)["metadata"] = metadata;
|
||||
(repository as any)["queryRunnerProvider"] = queryRunnerProvider;
|
||||
|
||||
return repository;
|
||||
}
|
||||
(repository as any)["manager"] = manager;
|
||||
(repository as any)["metadata"] = metadata;
|
||||
(repository as any)["queryRunnerProvider"] = queryRunnerProvider;
|
||||
return repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a tree repository.
|
||||
*/
|
||||
createTreeRepository(manager: EntityManager, metadata: EntityMetadata, queryRunnerProvider?: QueryRunnerProvider): TreeRepository<any> {
|
||||
|
||||
// NOTE: dynamic access to protected properties. We need this to prevent unwanted properties in those classes to be exposed,
|
||||
// however we need these properties for internal work of the class
|
||||
const repository = new TreeRepository<any>();
|
||||
(repository as any)["manager"] = manager;
|
||||
(repository as any)["metadata"] = metadata;
|
||||
(repository as any)["queryRunnerProvider"] = queryRunnerProvider;
|
||||
return repository;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -2,10 +2,10 @@ import {ObjectLiteral} from "../common/ObjectLiteral";
|
||||
|
||||
export class OrmUtils {
|
||||
|
||||
static splitStringsAndClasses<T>(strAndClses: string[]|T[]): [string[], T[]] {
|
||||
static splitClassesAndStrings<T>(clsesAndStrings: T[]|string[]): [T[], string[]] {
|
||||
return [
|
||||
(strAndClses as string[]).filter(str => typeof str === "string"),
|
||||
(strAndClses as T[]).filter(cls => typeof cls !== "string"),
|
||||
(clsesAndStrings as T[]).filter(cls => typeof cls !== "string"),
|
||||
(clsesAndStrings as string[]).filter(str => typeof str === "string"),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@ -4,19 +4,26 @@ import {expect} from "chai";
|
||||
import {setupTestingConnections} from "../../utils/test-utils";
|
||||
import {Connection} from "../../../src/connection/Connection";
|
||||
import {getConnectionManager} from "../../../src/index";
|
||||
import {ConnectionMetadataBuilder} from "../../../src/connection/ConnectionMetadataBuilder";
|
||||
import {EntityMetadataValidator} from "../../../src/metadata-builder/EntityMetadataValidator";
|
||||
|
||||
const should = chai.should();
|
||||
|
||||
describe("entity-metadata-validator", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(() => {
|
||||
connections = setupTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"] })
|
||||
.map(options => getConnectionManager().create(options));
|
||||
it("should throw error if relation count decorator used with ManyToOne or OneToOne relations", () => {
|
||||
const connection = new Connection({ // dummy connection options, connection won't be established anyway
|
||||
type: "mysql",
|
||||
host: "localhost",
|
||||
username: "test",
|
||||
password: "test",
|
||||
database: "test",
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"]
|
||||
});
|
||||
const connectionMetadataBuilder = new ConnectionMetadataBuilder(connection);
|
||||
const entityMetadatas = connectionMetadataBuilder.buildEntityMetadatas([__dirname + "/entity/*{.js,.ts}"], []);
|
||||
const entityMetadataValidator = new EntityMetadataValidator();
|
||||
expect(() => entityMetadataValidator.validateMany(entityMetadatas)).to.throw(Error);
|
||||
});
|
||||
|
||||
it("should throw error if relation count decorator used with ManyToOne or OneToOne relations", () => Promise.all(connections.map(async connection => {
|
||||
expect(() => connection.buildMetadatas()).to.throw(Error);
|
||||
})));
|
||||
|
||||
});
|
||||
@ -3,7 +3,10 @@ import {Post} from "./entity/Post";
|
||||
import {Counters} from "./entity/Counters";
|
||||
import {Connection} from "../../../src/connection/Connection";
|
||||
import {expect} from "chai";
|
||||
import {setupTestingConnections} from "../../utils/test-utils";
|
||||
import {
|
||||
closeTestingConnections, createTestingConnections, reloadTestingDatabases,
|
||||
setupTestingConnections
|
||||
} from "../../utils/test-utils";
|
||||
import {Subcounters} from "./entity/Subcounters";
|
||||
import {User} from "./entity/User";
|
||||
import {getConnectionManager} from "../../../src/index";
|
||||
@ -11,14 +14,13 @@ import {getConnectionManager} from "../../../src/index";
|
||||
describe("entity-metadata > property-map", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(() => {
|
||||
connections = setupTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"] })
|
||||
.map(options => getConnectionManager().create(options))
|
||||
.map(connection => {
|
||||
connection.buildMetadatas();
|
||||
return connection;
|
||||
});
|
||||
});
|
||||
before(async () => connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
schemaCreate: true,
|
||||
dropSchemaOnConnection: true,
|
||||
}));
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
it("should create correct property map object", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import "reflect-metadata";
|
||||
import * as chai from "chai";
|
||||
import {expect} from "chai";
|
||||
import {setupTestingConnections} from "../../../utils/test-utils";
|
||||
import {
|
||||
closeTestingConnections, createTestingConnections, reloadTestingDatabases,
|
||||
setupTestingConnections
|
||||
} from "../../../utils/test-utils";
|
||||
import {Connection} from "../../../../src/connection/Connection";
|
||||
import {Post} from "./entity/Post";
|
||||
import {Counters} from "./entity/Counters";
|
||||
@ -11,16 +14,15 @@ import {getConnectionManager} from "../../../../src/index";
|
||||
const should = chai.should();
|
||||
|
||||
describe("metadata-builder > ColumnMetadata", () => {
|
||||
|
||||
|
||||
let connections: Connection[];
|
||||
before(() => {
|
||||
connections = setupTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"] })
|
||||
.map(options => getConnectionManager().create(options))
|
||||
.map(connection => {
|
||||
connection.buildMetadatas();
|
||||
return connection;
|
||||
});
|
||||
});
|
||||
before(async () => connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
schemaCreate: true,
|
||||
dropSchemaOnConnection: true,
|
||||
}));
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
it("getValue", () => Promise.all(connections.map(async connection => {
|
||||
const post = new Post();
|
||||
|
||||
@ -1,23 +1,25 @@
|
||||
import "reflect-metadata";
|
||||
import {PostgresDriver} from "../../../src/driver/postgres/PostgresDriver";
|
||||
import {Logger} from "../../../src/logger/Logger";
|
||||
import {expect} from "chai";
|
||||
import {Connection} from "../../../src/connection/Connection";
|
||||
|
||||
describe("github issues > #114 Can not be parsed correctly the URL of pg.", () => {
|
||||
|
||||
let driver: PostgresDriver;
|
||||
before(() => driver = new PostgresDriver(new Connection({
|
||||
type: "postgres",
|
||||
url: "postgres://test:test@localhost:5432/test",
|
||||
})));
|
||||
let driver: PostgresDriver, connection: Connection;
|
||||
before(() => {
|
||||
connection = new Connection({
|
||||
type: "postgres",
|
||||
url: "postgres://test:test@localhost:5432/test",
|
||||
});
|
||||
driver = new PostgresDriver(connection);
|
||||
});
|
||||
|
||||
it("should not fail in url parser", () => {
|
||||
expect(driver.options.username).to.be.eq("test");
|
||||
expect(driver.options.password).to.be.eq("test");
|
||||
expect(driver.options.host).to.be.eq("localhost");
|
||||
expect(driver.options.port).to.be.eq(5432);
|
||||
expect(driver.options.database).to.be.eq("test");
|
||||
expect(connection.options.username).to.be.eq("test");
|
||||
expect(connection.options.password).to.be.eq("test");
|
||||
expect(connection.options.host).to.be.eq("localhost");
|
||||
expect(connection.options.port).to.be.eq(5432);
|
||||
expect(connection.options.database).to.be.eq("test");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user