mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
added postgres required driver classes
This commit is contained in:
parent
20afae93ef
commit
7252137ae6
@ -35,6 +35,7 @@
|
||||
"gulpclass": "0.1.1",
|
||||
"mocha": "^2.5.3",
|
||||
"mysql": "^2.10.2",
|
||||
"pg": "^4.5.5",
|
||||
"sinon": "^1.17.4",
|
||||
"sinon-chai": "^2.8.0",
|
||||
"tslint": "next",
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import "reflect-metadata";
|
||||
import {createConnection, CreateConnectionOptions} from "../../src/index";
|
||||
import {Post} from "./entity/Post";
|
||||
|
||||
@ -13,6 +14,21 @@ const options: CreateConnectionOptions = {
|
||||
},
|
||||
entities: [Post]
|
||||
};
|
||||
/*const options: CreateConnectionOptions = {
|
||||
driver: "postgres",
|
||||
connection: {
|
||||
host: "192.168.99.100",
|
||||
port: 5432,
|
||||
username: "test",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
autoSchemaCreate: true,
|
||||
logging: {
|
||||
logQueries: true
|
||||
}
|
||||
},
|
||||
entities: [Post]
|
||||
};*/
|
||||
|
||||
createConnection(options).then(connection => {
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import "reflect-metadata";
|
||||
import {createConnection, CreateConnectionOptions} from "../../src/index";
|
||||
import {Post} from "./entity/Post";
|
||||
import {PostDetails} from "./entity/PostDetails";
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import "reflect-metadata";
|
||||
import {createConnection, CreateConnectionOptions} from "../../src/index";
|
||||
import {EverythingEntity} from "./entity/EverythingEntity";
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import "reflect-metadata";
|
||||
import {createConnection, CreateConnectionOptions} from "../../src/index";
|
||||
import {Post} from "./entity/Post";
|
||||
import {CustomNamingStrategy} from "./naming-strategy/CustomNamingStrategy";
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import "reflect-metadata";
|
||||
import {createConnection, CreateConnectionOptions} from "../../src/index";
|
||||
import {Post} from "./entity/Post";
|
||||
import {PostCategory} from "./entity/PostCategory";
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import "reflect-metadata";
|
||||
import {CreateConnectionOptions, createConnection} from "../../src/index";
|
||||
import {Post} from "./entity/Post";
|
||||
import {PostAuthor} from "./entity/PostAuthor";
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import "reflect-metadata";
|
||||
import {createConnection, CreateConnectionOptions} from "../../src/index";
|
||||
import {Post} from "./entity/Post";
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import "reflect-metadata";
|
||||
import {createConnection, CreateConnectionOptions} from "../../src/index";
|
||||
import {Post} from "./entity/Post";
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import "reflect-metadata";
|
||||
import {createConnection, CreateConnectionOptions} from "../../src/index";
|
||||
import {Post} from "./entity/Post";
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import "reflect-metadata";
|
||||
import {createConnection, CreateConnectionOptions} from "../../src/index";
|
||||
import {Post} from "./entity/Post";
|
||||
import {Author} from "./entity/Author";
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import "reflect-metadata";
|
||||
import {createConnection, CreateConnectionOptions} from "../../src/index";
|
||||
import {Post} from "./entity/Post";
|
||||
import {Author} from "./entity/Author";
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import "reflect-metadata";
|
||||
import {createConnection, CreateConnectionOptions} from "../../src/index";
|
||||
import {Post} from "./entity/Post";
|
||||
import {Author} from "./entity/Author";
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import "reflect-metadata";
|
||||
import {createConnection, CreateConnectionOptions} from "../../src/index";
|
||||
import {Post} from "./entity/Post";
|
||||
import {Author} from "./entity/Author";
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import "reflect-metadata";
|
||||
import {createConnection, CreateConnectionOptions} from "../../src/index";
|
||||
import {Category} from "./entity/Category";
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import "reflect-metadata";
|
||||
import {createConnection, CreateConnectionOptions} from "../../src/index";
|
||||
import {Post} from "./entity/Post";
|
||||
import {Author} from "./entity/Author";
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import "reflect-metadata";
|
||||
import {createConnection, CreateConnectionOptions} from "../../src/index";
|
||||
import {Post} from "./entity/Post";
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import "reflect-metadata";
|
||||
import {CreateConnectionOptions, createConnection} from "../../src/index";
|
||||
import {Post} from "./entity/Post";
|
||||
import {PostDetails} from "./entity/PostDetails";
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import "reflect-metadata";
|
||||
import {CreateConnectionOptions, createConnection} from "../../src/index";
|
||||
import {Post} from "./entity/Post";
|
||||
import {PostDetails} from "./entity/PostDetails";
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import "reflect-metadata";
|
||||
import {createConnection, CreateConnectionOptions} from "../../src/index";
|
||||
import {Post} from "./entity/Post";
|
||||
import {PostCategory} from "./entity/PostCategory";
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import "reflect-metadata";
|
||||
import {createConnection, CreateConnectionOptions} from "../../src/index";
|
||||
import {Post} from "./entity/Post";
|
||||
import {PostCategory} from "./entity/PostCategory";
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import "reflect-metadata";
|
||||
import {createConnection, CreateConnectionOptions} from "../../src/index";
|
||||
import {Post} from "./entity/Post";
|
||||
import {PostCategory} from "./entity/PostCategory";
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import "reflect-metadata";
|
||||
import {createConnection, CreateConnectionOptions} from "../../src/index";
|
||||
import {Category} from "./entity/Category";
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import "reflect-metadata";
|
||||
import {CreateConnectionOptions, createConnection} from "../../src/index";
|
||||
import {Post} from "./entity/Post";
|
||||
import {PostCategory} from "./entity/PostCategory";
|
||||
|
||||
@ -5,6 +5,7 @@ import {CreateConnectionOptions} from "./CreateConnectionOptions";
|
||||
import {ConnectionOptions} from "../connection/ConnectionOptions";
|
||||
import {Driver} from "../driver/Driver";
|
||||
import {MissingDriverError} from "./error/MissingDriverError";
|
||||
import {PostgresDriver} from "../driver/PostgresDriver";
|
||||
|
||||
/**
|
||||
* Connection manager holds all connections made to the databases and providers helper management functions
|
||||
@ -74,10 +75,12 @@ export class ConnectionManager {
|
||||
// Private Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private createDriver(driverName: string) {
|
||||
private createDriver(driverName: string): Driver {
|
||||
switch (driverName) {
|
||||
case "mysql":
|
||||
return new MysqlDriver();
|
||||
case "postgres":
|
||||
return new PostgresDriver();
|
||||
default:
|
||||
throw new MissingDriverError(driverName);
|
||||
}
|
||||
|
||||
@ -7,9 +7,9 @@ import {EntitySchema} from "../metadata/entity-schema/EntitySchema";
|
||||
export interface CreateConnectionOptions {
|
||||
|
||||
/**
|
||||
* Driver type. Mysql is the only driver supported at this moment.
|
||||
* Driver type. Mysql and postgres are the only drivers supported at this moment.
|
||||
*/
|
||||
driver: "mysql";
|
||||
driver: "mysql"|"postgres";
|
||||
|
||||
/**
|
||||
* Database connection options.
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
import {ConnectionOptions} from "../connection/ConnectionOptions";
|
||||
import {ColumnMetadata} from "../metadata/ColumnMetadata";
|
||||
import {ColumnTypes} from "../metadata/types/ColumnTypes";
|
||||
import * as moment from "moment";
|
||||
|
||||
/**
|
||||
* Provides base functionality for all driver implementations.
|
||||
@ -11,6 +14,170 @@ export abstract class BaseDriver {
|
||||
|
||||
abstract connectionOptions: ConnectionOptions;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Abstract Protected Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
protected abstract checkIfConnectionSet(): void;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Abstract Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Executes a given SQL query and returns raw database results.
|
||||
*/
|
||||
abstract query<T>(query: string): Promise<T>;
|
||||
|
||||
/**
|
||||
* Escapes given value.
|
||||
*/
|
||||
abstract escape(value: any): any;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Updates rows that match given conditions in the given table.
|
||||
*/
|
||||
update(tableName: string, valuesMap: Object, conditions: Object): Promise<void> {
|
||||
this.checkIfConnectionSet();
|
||||
|
||||
const updateValues = this.escapeObjectMap(valuesMap).join(",");
|
||||
const conditionString = this.escapeObjectMap(conditions).join(" AND ");
|
||||
const query = `UPDATE ${tableName} SET ${updateValues} ${conditionString ? (" WHERE " + conditionString) : ""}`;
|
||||
// console.log("executing update: ", query);
|
||||
return this.query(query).then(() => {});
|
||||
}
|
||||
|
||||
private escapeObjectMap(objectMap: { [key: string]: any }): string[] {
|
||||
return Object.keys(objectMap).map(key => {
|
||||
const value = (<any> objectMap)[key];
|
||||
if (value === null || value === undefined) {
|
||||
return key + "=NULL";
|
||||
} else {
|
||||
return key + "=" + this.escape(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new row into given table.
|
||||
*/
|
||||
insert(tableName: string, keyValues: Object): Promise<any> {
|
||||
this.checkIfConnectionSet();
|
||||
|
||||
const columns = Object.keys(keyValues).join(",");
|
||||
const values = Object.keys(keyValues).map(key => this.escape((<any> keyValues)[key])).join(","); // todo: escape here
|
||||
const query = `INSERT INTO ${tableName}(${columns}) VALUES (${values})`;
|
||||
return this.query<any>(query).then(result => result.insertId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes from the given table by a given conditions.
|
||||
*/
|
||||
delete(tableName: string, conditions: Object): Promise<void> {
|
||||
this.checkIfConnectionSet();
|
||||
|
||||
const conditionString = this.escapeObjectMap(conditions).join(" AND ");
|
||||
const query = `DELETE FROM ${tableName} WHERE ${conditionString}`;
|
||||
return this.query(query).then(() => {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts postgres transaction.
|
||||
*/
|
||||
beginTransaction(): Promise<void> {
|
||||
return this.query("START TRANSACTION").then(() => {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends postgres transaction.
|
||||
*/
|
||||
endTransaction(): Promise<void> {
|
||||
return this.query("COMMIT").then(() => {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares given value to a value to be persisted, based on its column type and metadata.
|
||||
*/
|
||||
preparePersistentValue(value: any, column: ColumnMetadata): any {
|
||||
switch (column.type) {
|
||||
case ColumnTypes.BOOLEAN:
|
||||
return value === true ? 1 : 0;
|
||||
case ColumnTypes.DATE:
|
||||
return moment(value).format("YYYY-MM-DD");
|
||||
case ColumnTypes.TIME:
|
||||
return moment(value).format("HH:mm:ss");
|
||||
case ColumnTypes.DATETIME:
|
||||
return moment(value).format("YYYY-MM-DD HH:mm:ss");
|
||||
case ColumnTypes.JSON:
|
||||
return JSON.stringify(value);
|
||||
case ColumnTypes.SIMPLE_ARRAY:
|
||||
return (value as Array<any>)
|
||||
.map(i => String(i))
|
||||
.join(",");
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares given value to a value to be persisted, based on its column type and metadata.
|
||||
*/
|
||||
prepareHydratedValue(value: any, column: ColumnMetadata): any {
|
||||
switch (column.type) {
|
||||
case ColumnTypes.BOOLEAN:
|
||||
return value ? true : false;
|
||||
|
||||
case ColumnTypes.DATE:
|
||||
if (value instanceof Date)
|
||||
return value;
|
||||
|
||||
return moment(value, "YYYY-MM-DD").toDate();
|
||||
|
||||
case ColumnTypes.TIME:
|
||||
return moment(value, "HH:mm:ss").toDate();
|
||||
|
||||
case ColumnTypes.DATETIME:
|
||||
if (value instanceof Date)
|
||||
return value;
|
||||
|
||||
return moment(value, "YYYY-MM-DD HH:mm:ss").toDate();
|
||||
|
||||
case ColumnTypes.JSON:
|
||||
return JSON.parse(value);
|
||||
|
||||
case ColumnTypes.SIMPLE_ARRAY:
|
||||
return (value as string).split(",");
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts rows into closure table.
|
||||
*/
|
||||
insertIntoClosureTable(tableName: string, newEntityId: any, parentId: any, hasLevel: boolean): Promise<number> {
|
||||
let sql = "";
|
||||
if (hasLevel) {
|
||||
sql = `INSERT INTO ${tableName}(ancestor, descendant, level) ` +
|
||||
`SELECT ancestor, ${newEntityId}, level + 1 FROM ${tableName} WHERE descendant = ${parentId} ` +
|
||||
`UNION ALL SELECT ${newEntityId}, ${newEntityId}, 1`;
|
||||
} else {
|
||||
sql = `INSERT INTO ${tableName}(ancestor, descendant) ` +
|
||||
`SELECT ancestor, ${newEntityId} FROM ${tableName} WHERE descendant = ${parentId} ` +
|
||||
`UNION ALL SELECT ${newEntityId}, ${newEntityId}`;
|
||||
}
|
||||
return this.query(sql).then(() => {
|
||||
return this.query(`SELECT MAX(level) as level FROM ${tableName} WHERE descendant = ${parentId}`);
|
||||
|
||||
}).then((results: any) => {
|
||||
return results && results[0] && results[0]["level"] ? parseInt(results[0]["level"]) + 1 : 1;
|
||||
});
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Protected Methods
|
||||
// -------------------------------------------------------------------------
|
||||
@ -19,20 +186,20 @@ export abstract class BaseDriver {
|
||||
if (this.connectionOptions.logging && this.connectionOptions.logging.logQueries)
|
||||
this.log("executing query: " + query, "log");
|
||||
}
|
||||
|
||||
|
||||
protected logQueryError(error: any) {
|
||||
if (this.connectionOptions.logging && this.connectionOptions.logging.logFailedQueryError) {
|
||||
this.log("error during executing query:", "error");
|
||||
this.log(error, "error");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected logFailedQuery(query: string) {
|
||||
if (this.connectionOptions.logging &&
|
||||
if (this.connectionOptions.logging &&
|
||||
(this.connectionOptions.logging.logQueries || this.connectionOptions.logging.logOnlyFailedQueries))
|
||||
this.log("query failed: " + query, "error");
|
||||
}
|
||||
|
||||
|
||||
protected log(message: any, level: "log"|"debug"|"info"|"error") {
|
||||
if (!this.connectionOptions.logging) return;
|
||||
if (this.connectionOptions && this.connectionOptions.logging && this.connectionOptions.logging.logger) {
|
||||
|
||||
@ -27,13 +27,6 @@ export interface Driver {
|
||||
*/
|
||||
readonly db: string;
|
||||
|
||||
/**
|
||||
* todo: driver should not define which query builder to create, it should create its own helper for query builder.
|
||||
*
|
||||
* Creates a query builder which can be used to build an sql queries.
|
||||
*/
|
||||
readonly queryBuilderClass: Function;
|
||||
|
||||
/**
|
||||
* Creates a schema builder which can be used to build database/table schemas.
|
||||
*/
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import {Driver} from "./Driver";
|
||||
import {SchemaBuilder} from "../schema-builder/SchemaBuilder";
|
||||
import {QueryBuilder} from "../query-builder/QueryBuilder";
|
||||
import {MysqlSchemaBuilder} from "../schema-builder/MysqlSchemaBuilder";
|
||||
import {ConnectionIsNotSetError} from "./error/ConnectionIsNotSetError";
|
||||
import {BaseDriver} from "./BaseDriver";
|
||||
@ -95,13 +94,6 @@ export class MysqlDriver extends BaseDriver implements Driver {
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Creates a query builder which can be used to build an sql queries.
|
||||
*/
|
||||
get queryBuilderClass() {
|
||||
return QueryBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a schema builder which can be used to build database/table schemas.
|
||||
*/
|
||||
@ -117,7 +109,8 @@ export class MysqlDriver extends BaseDriver implements Driver {
|
||||
host: this.connectionOptions.host,
|
||||
user: this.connectionOptions.username,
|
||||
password: this.connectionOptions.password,
|
||||
database: this.connectionOptions.database
|
||||
database: this.connectionOptions.database,
|
||||
port: this.connectionOptions.port
|
||||
});
|
||||
return new Promise<void>((ok, fail) => {
|
||||
this.mysqlConnection.connect((err: any) => err ? fail(err) : ok());
|
||||
@ -128,23 +121,28 @@ export class MysqlDriver extends BaseDriver implements Driver {
|
||||
* Closes connection with database.
|
||||
*/
|
||||
disconnect(): Promise<void> {
|
||||
if (!this.mysqlConnection)
|
||||
throw new ConnectionIsNotSetError("mysql");
|
||||
this.checkIfConnectionSet();
|
||||
|
||||
return new Promise<void>((ok, fail) => {
|
||||
this.mysqlConnection.end((err: any) => err ? fail(err) : ok());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes given value.
|
||||
*/
|
||||
escape(value: any): any {
|
||||
return this.mysqlConnection.escape(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a given SQL query.
|
||||
*/
|
||||
query<T>(query: string): Promise<T> {
|
||||
if (!this.mysqlConnection)
|
||||
throw new ConnectionIsNotSetError("mysql");
|
||||
this.checkIfConnectionSet();
|
||||
|
||||
this.logQuery(query);
|
||||
return new Promise<any>((ok, fail) => this.mysqlConnection.query(query, (err: any, result: any) => {
|
||||
return new Promise<T>((ok, fail) => this.mysqlConnection.query(query, (err: any, result: any) => {
|
||||
if (err) {
|
||||
this.logFailedQuery(query);
|
||||
this.logQueryError(err);
|
||||
@ -159,8 +157,7 @@ export class MysqlDriver extends BaseDriver implements Driver {
|
||||
* Clears all tables in the currently connected database.
|
||||
*/
|
||||
clearDatabase(): Promise<void> {
|
||||
if (!this.mysqlConnection)
|
||||
throw new ConnectionIsNotSetError("mysql");
|
||||
this.checkIfConnectionSet();
|
||||
|
||||
const disableForeignKeysCheckQuery = `SET FOREIGN_KEY_CHECKS = 0;`;
|
||||
const dropTablesQuery = `SELECT concat('DROP TABLE IF EXISTS ', table_name, ';') AS q FROM ` +
|
||||
@ -174,161 +171,13 @@ export class MysqlDriver extends BaseDriver implements Driver {
|
||||
.then(() => {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates rows that match given conditions in the given table.
|
||||
*/
|
||||
update(tableName: string, valuesMap: Object, conditions: Object): Promise<void> {
|
||||
// -------------------------------------------------------------------------
|
||||
// Protected Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
protected checkIfConnectionSet() {
|
||||
if (!this.mysqlConnection)
|
||||
throw new ConnectionIsNotSetError("mysql");
|
||||
|
||||
const updateValues = this.escapeObjectMap(valuesMap).join(",");
|
||||
const conditionString = this.escapeObjectMap(conditions).join(" AND ");
|
||||
const query = `UPDATE ${tableName} SET ${updateValues} ${conditionString ? (" WHERE " + conditionString) : ""}`;
|
||||
// console.log("executing update: ", query);
|
||||
return this.query(query).then(() => {});
|
||||
// const qb = this.createQueryBuilder().update(tableName, valuesMap).from(tableName, "t");
|
||||
// Object.keys(conditions).forEach(key => qb.andWhere(key + "=:" + key, { [key]: (<any> conditions)[key] }));
|
||||
// return qb.execute().then(() => {});
|
||||
}
|
||||
|
||||
private escapeObjectMap(objectMap: { [key: string]: any }): string[] {
|
||||
return Object.keys(objectMap).map(key => {
|
||||
const value = (<any> objectMap)[key];
|
||||
if (value === null || value === undefined) {
|
||||
return key + "=NULL";
|
||||
} else {
|
||||
return key + "=" + this.escape(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new row into given table.
|
||||
*/
|
||||
insert(tableName: string, keyValues: Object): Promise<any> {
|
||||
if (!this.mysqlConnection)
|
||||
throw new ConnectionIsNotSetError("mysql");
|
||||
|
||||
const columns = Object.keys(keyValues).join(",");
|
||||
// const values = this.escapeObjectMap(keyValues).join(",");
|
||||
const values = Object.keys(keyValues).map(key => this.escape((<any> keyValues)[key])).join(","); // todo: escape here
|
||||
const query = `INSERT INTO ${tableName}(${columns}) VALUES (${values})`;
|
||||
return this.query<any>(query).then(result => result.insertId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes from the given table by a given conditions.
|
||||
*/
|
||||
delete(tableName: string, conditions: Object): Promise<void> {
|
||||
if (!this.mysqlConnection)
|
||||
throw new ConnectionIsNotSetError("mysql");
|
||||
|
||||
const conditionString = this.escapeObjectMap(conditions).join(" AND ");
|
||||
const query = `DELETE FROM ${tableName} WHERE ${conditionString}`;
|
||||
return this.query(query).then(() => {});
|
||||
// const qb = this.createQueryBuilder().delete(tableName);
|
||||
// Object.keys(conditions).forEach(key => qb.andWhere(key + "=:" + key, { [key]: (<any> conditions)[key] }));
|
||||
// return qb.execute().then(() => {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts mysql transaction.
|
||||
*/
|
||||
beginTransaction(): Promise<void> {
|
||||
return this.query("START TRANSACTION").then(() => {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends mysql transaction.
|
||||
*/
|
||||
endTransaction(): Promise<void> {
|
||||
return this.query("COMMIT").then(() => {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares given value to a value to be persisted, based on its column type and metadata.
|
||||
*/
|
||||
preparePersistentValue(value: any, column: ColumnMetadata): any {
|
||||
switch (column.type) {
|
||||
case ColumnTypes.BOOLEAN:
|
||||
return value === true ? 1 : 0;
|
||||
case ColumnTypes.DATE:
|
||||
return moment(value).format("YYYY-MM-DD");
|
||||
case ColumnTypes.TIME:
|
||||
return moment(value).format("HH:mm:ss");
|
||||
case ColumnTypes.DATETIME:
|
||||
return moment(value).format("YYYY-MM-DD HH:mm:ss");
|
||||
case ColumnTypes.JSON:
|
||||
return JSON.stringify(value);
|
||||
case ColumnTypes.SIMPLE_ARRAY:
|
||||
return (value as Array<any>)
|
||||
.map(i => String(i))
|
||||
.join(",");
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares given value to a value to be persisted, based on its column type and metadata.
|
||||
*/
|
||||
prepareHydratedValue(value: any, column: ColumnMetadata): any {
|
||||
switch (column.type) {
|
||||
case ColumnTypes.BOOLEAN:
|
||||
return value ? true : false;
|
||||
|
||||
case ColumnTypes.DATE:
|
||||
if (value instanceof Date)
|
||||
return value;
|
||||
|
||||
return moment(value, "YYYY-MM-DD").toDate();
|
||||
|
||||
case ColumnTypes.TIME:
|
||||
return moment(value, "HH:mm:ss").toDate();
|
||||
|
||||
case ColumnTypes.DATETIME:
|
||||
if (value instanceof Date)
|
||||
return value;
|
||||
|
||||
return moment(value, "YYYY-MM-DD HH:mm:ss").toDate();
|
||||
|
||||
case ColumnTypes.JSON:
|
||||
return JSON.parse(value);
|
||||
|
||||
case ColumnTypes.SIMPLE_ARRAY:
|
||||
return (value as string).split(",");
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes given value.
|
||||
*/
|
||||
escape(value: any): any {
|
||||
return this.mysqlConnection.escape(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts rows into closure table.
|
||||
*/
|
||||
insertIntoClosureTable(tableName: string, newEntityId: any, parentId: any, hasLevel: boolean): Promise<number> {
|
||||
let sql = "";
|
||||
if (hasLevel) {
|
||||
sql = `INSERT INTO ${tableName}(ancestor, descendant, level) ` +
|
||||
`SELECT ancestor, ${newEntityId}, level + 1 FROM ${tableName} WHERE descendant = ${parentId} ` +
|
||||
`UNION ALL SELECT ${newEntityId}, ${newEntityId}, 1`;
|
||||
} else {
|
||||
sql = `INSERT INTO ${tableName}(ancestor, descendant) ` +
|
||||
`SELECT ancestor, ${newEntityId} FROM ${tableName} WHERE descendant = ${parentId} ` +
|
||||
`UNION ALL SELECT ${newEntityId}, ${newEntityId}`;
|
||||
}
|
||||
return this.query(sql).then(() => {
|
||||
return this.query(`SELECT MAX(level) as level FROM ${tableName} WHERE descendant = ${parentId}`);
|
||||
|
||||
}).then((results: any) => {
|
||||
return results && results[0] && results[0]["level"] ? parseInt(results[0]["level"]) + 1 : 1;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
181
src/driver/PostgresDriver.ts
Normal file
181
src/driver/PostgresDriver.ts
Normal file
@ -0,0 +1,181 @@
|
||||
import {Driver} from "./Driver";
|
||||
import {SchemaBuilder} from "../schema-builder/SchemaBuilder";
|
||||
import {ConnectionIsNotSetError} from "./error/ConnectionIsNotSetError";
|
||||
import {BaseDriver} from "./BaseDriver";
|
||||
import {ConnectionOptions} from "../connection/ConnectionOptions";
|
||||
import {PostgresSchemaBuilder} from "../schema-builder/PostgresSchemaBuilder";
|
||||
|
||||
/**
|
||||
* This driver organizes work with postgres database.
|
||||
*/
|
||||
export class PostgresDriver extends BaseDriver implements Driver {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Properties
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Connection used in this driver.
|
||||
*/
|
||||
connectionOptions: ConnectionOptions;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Private Properties
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Postgres library.
|
||||
*/
|
||||
private postgres: any;
|
||||
|
||||
/**
|
||||
* Connection to postgres database.
|
||||
*/
|
||||
private postgresConnection: any;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Getter Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Access to the native implementation of the database.
|
||||
*/
|
||||
get native(): any {
|
||||
return this.postgres;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access to the native connection to the database.
|
||||
*/
|
||||
get nativeConnection(): any {
|
||||
return this.postgresConnection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Database name to which this connection is made.
|
||||
*/
|
||||
get db(): string {
|
||||
// if (this.postgresConnection && this.postgresConnection.config.database)
|
||||
// return this.postgresConnection.config.database;
|
||||
|
||||
if (this.connectionOptions.database)
|
||||
return this.connectionOptions.database;
|
||||
|
||||
throw new Error("Cannot get the database name. Since database name is not explicitly given in configuration " +
|
||||
"(maybe connection url is used?), database name cannot be retrieved until connection is made.");
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(postgres?: any) {
|
||||
super();
|
||||
|
||||
// if driver dependency is not given explicitly, then try to load it via "require"
|
||||
if (!postgres && require) {
|
||||
try {
|
||||
postgres = require("pg");
|
||||
|
||||
} catch (e) {
|
||||
throw new Error("Postgres package has not been found installed. Try to install it: npm install pg --save");
|
||||
}
|
||||
} else {
|
||||
throw new Error("Cannot load postgres driver dependencies. Try to install all required dependencies.");
|
||||
}
|
||||
|
||||
this.postgres = postgres;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Creates a schema builder which can be used to build database/table schemas.
|
||||
*/
|
||||
createSchemaBuilder(): SchemaBuilder {
|
||||
return new PostgresSchemaBuilder(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs connection to the database based on given connection options.
|
||||
*/
|
||||
connect(): Promise<void> {
|
||||
return new Promise<void>((ok, fail) => {
|
||||
this.postgresConnection = new this.postgres.Client({
|
||||
host: this.connectionOptions.host,
|
||||
user: this.connectionOptions.username,
|
||||
password: this.connectionOptions.password,
|
||||
database: this.connectionOptions.database,
|
||||
port: this.connectionOptions.port
|
||||
});
|
||||
this.postgresConnection.connect((err: any) => err ? fail(err) : ok());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes connection with database.
|
||||
*/
|
||||
disconnect(): Promise<void> {
|
||||
this.checkIfConnectionSet();
|
||||
|
||||
return new Promise<void>((ok, fail) => {
|
||||
this.postgresConnection.end(/*(err: any) => err ? fail(err) : ok()*/); // todo: check if it can emit errors
|
||||
ok();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes given value.
|
||||
*/
|
||||
escape(value: any): any {
|
||||
return this.postgresConnection.escape(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a given SQL query.
|
||||
*/
|
||||
query<T>(query: string): Promise<T> {
|
||||
this.checkIfConnectionSet();
|
||||
|
||||
this.logQuery(query);
|
||||
return new Promise<T>((ok, fail) => this.postgresConnection.query(query, (err: any, result: any) => {
|
||||
if (err) {
|
||||
this.logFailedQuery(query);
|
||||
this.logQueryError(err);
|
||||
fail(err);
|
||||
} else {
|
||||
ok(result.rows);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all tables in the currently connected database.
|
||||
*/
|
||||
clearDatabase(): Promise<void> {
|
||||
this.checkIfConnectionSet(); // todo:
|
||||
|
||||
const disableForeignKeysCheckQuery = `SET FOREIGN_KEY_CHECKS = 0;`;
|
||||
const dropTablesQuery = `SELECT concat('DROP TABLE IF EXISTS ', table_name, ';') AS q FROM ` +
|
||||
`information_schema.tables WHERE table_schema = '${this.db}';`;
|
||||
const enableForeignKeysCheckQuery = `SET FOREIGN_KEY_CHECKS = 1;`;
|
||||
|
||||
return this.query(disableForeignKeysCheckQuery)
|
||||
.then(() => this.query<any[]>(dropTablesQuery))
|
||||
.then(results => Promise.all(results.map(q => this.query(q["q"]))))
|
||||
.then(() => this.query(enableForeignKeysCheckQuery))
|
||||
.then(() => {});
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Protected Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
protected checkIfConnectionSet() {
|
||||
if (!this.postgresConnection)
|
||||
throw new ConnectionIsNotSetError("postgres");
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,4 +1,3 @@
|
||||
import {ColumnMode} from "../ColumnMetadata";
|
||||
import {ColumnType} from "../types/ColumnTypes";
|
||||
import {TableType} from "../TableMetadata";
|
||||
import {RelationType} from "../types/RelationTypes";
|
||||
@ -40,12 +39,12 @@ export interface EntitySchema {
|
||||
/**
|
||||
* Specifies array of properties that will be used in a composite primary key of the table.
|
||||
*/
|
||||
primaryKeys?: string|((object: any) => string|any)[];
|
||||
primaryKeys?: string[];
|
||||
|
||||
/**
|
||||
* Specifies a property name by which queries will perform ordering by default when fetching rows.
|
||||
*/
|
||||
orderBy?: string|((object: any) => string|any);
|
||||
orderBy?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
237
src/schema-builder/PostgresSchemaBuilder.ts
Normal file
237
src/schema-builder/PostgresSchemaBuilder.ts
Normal file
@ -0,0 +1,237 @@
|
||||
import {SchemaBuilder} from "./SchemaBuilder";
|
||||
import {PostgresDriver} from "../driver/PostgresDriver";
|
||||
import {ColumnMetadata} from "../metadata/ColumnMetadata";
|
||||
import {ForeignKeyMetadata} from "../metadata/ForeignKeyMetadata";
|
||||
import {TableMetadata} from "../metadata/TableMetadata";
|
||||
import {IndexMetadata} from "../metadata/IndexMetadata";
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export class PostgresSchemaBuilder extends SchemaBuilder {
|
||||
|
||||
constructor(private driver: PostgresDriver) {
|
||||
super();
|
||||
}
|
||||
|
||||
getChangedColumns(tableName: string, columns: ColumnMetadata[]): Promise<{columnName: string, hasPrimaryKey: boolean}[]> {
|
||||
const sql = `SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_CATALOG = '${this.driver.db}'` +
|
||||
` AND TABLE_NAME = '${tableName}'`;
|
||||
return this.query<any[]>(sql).then(results => {
|
||||
|
||||
return columns.filter(column => {
|
||||
const dbData = results.find(result => result.column_name === column.name);
|
||||
if (!dbData) return false;
|
||||
|
||||
const newType = this.normalizeType(column);
|
||||
const isNullable = column.isNullable === true ? "YES" : "NO";
|
||||
|
||||
let columnType = dbData.data_type.toLowerCase();
|
||||
if (dbData.character_maximum_length) {
|
||||
columnType += "(" + dbData.character_maximum_length + ")";
|
||||
}
|
||||
|
||||
// const hasDbColumnAutoIncrement = dbData.EXTRA.indexOf("auto_increment") !== -1;
|
||||
// const hasDbColumnPrimaryIndex = dbData.column_key.indexOf("PRI") !== -1;
|
||||
return columnType !== newType ||
|
||||
// dbData.COLUMN_COMMENT !== column.comment ||
|
||||
dbData.is_nullable !== isNullable; // ||
|
||||
// hasDbColumnAutoIncrement !== column.isGenerated ||
|
||||
// hasDbColumnPrimaryIndex !== column.isPrimary;
|
||||
|
||||
}).map(column => {
|
||||
// const dbData = results.find(result => result.column_name === column.name);
|
||||
// const hasDbColumnPrimaryIndex = dbData.column_key.indexOf("PRI") !== -1;
|
||||
return { columnName: column.name/*, hasPrimaryKey: hasDbColumnPrimaryIndex*/ };
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
checkIfTableExist(tableName: string): Promise<boolean> {
|
||||
const sql = `SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_CATALOG = '${this.driver.db}' AND TABLE_NAME = '${tableName}'`;
|
||||
return this.query<any[]>(sql).then(results => !!(results && results.length));
|
||||
}
|
||||
|
||||
addColumnQuery(tableName: string, column: ColumnMetadata): Promise<void> {
|
||||
const sql = `ALTER TABLE ${tableName} ADD ${this.buildCreateColumnSql(column, false)}`;
|
||||
return this.query(sql).then(() => {});
|
||||
}
|
||||
|
||||
dropColumnQuery(tableName: string, columnName: string): Promise<void> {
|
||||
const sql = `ALTER TABLE ${tableName} DROP ${columnName}`;
|
||||
return this.query(sql).then(() => {});
|
||||
}
|
||||
|
||||
addForeignKeyQuery(foreignKey: ForeignKeyMetadata): Promise<void> {
|
||||
let sql = `ALTER TABLE ${foreignKey.tableName} ADD CONSTRAINT \`${foreignKey.name}\` ` +
|
||||
`FOREIGN KEY (${foreignKey.columnNames.join(", ")}) ` +
|
||||
`REFERENCES ${foreignKey.referencedTable.name}(${foreignKey.referencedColumnNames.join(",")})`;
|
||||
if (foreignKey.onDelete)
|
||||
sql += " ON DELETE " + foreignKey.onDelete;
|
||||
return this.query(sql).then(() => {});
|
||||
}
|
||||
|
||||
dropForeignKeyQuery(foreignKey: ForeignKeyMetadata): Promise<void>;
|
||||
dropForeignKeyQuery(tableName: string, foreignKeyName: string): Promise<void>;
|
||||
dropForeignKeyQuery(tableNameOrForeignKey: string|ForeignKeyMetadata, foreignKeyName?: string): Promise<void> {
|
||||
let tableName = <string> tableNameOrForeignKey;
|
||||
if (tableNameOrForeignKey instanceof ForeignKeyMetadata) {
|
||||
tableName = tableNameOrForeignKey.tableName;
|
||||
foreignKeyName = tableNameOrForeignKey.name;
|
||||
}
|
||||
|
||||
const sql = `ALTER TABLE ${tableName} DROP FOREIGN KEY \`${foreignKeyName}\``;
|
||||
return this.query(sql).then(() => {});
|
||||
}
|
||||
|
||||
getTableForeignQuery(tableName: string): Promise<string[]> {
|
||||
const sql = `SELECT * FROM INFORMATION_SCHEMA.table_constraints WHERE TABLE_CATALOG = '${this.driver.db}' `
|
||||
+ `AND TABLE_NAME = '${tableName}' AND CONSTRAINT_TYPE='FOREIGN KEY'`;
|
||||
return this.query<any[]>(sql).then(results => results.map(result => result.CONSTRAINT_NAME));
|
||||
}
|
||||
|
||||
getTableUniqueKeysQuery(tableName: string): Promise<string[]> {
|
||||
const sql = `SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_CATALOG = '${this.driver.db}' ` +
|
||||
`AND TABLE_NAME = '${tableName}' AND CONSTRAINT_TYPE = 'UNIQUE'`;
|
||||
return this.query<any[]>(sql).then(results => results.map(result => result.CONSTRAINT_NAME));
|
||||
}
|
||||
|
||||
getTableIndicesQuery(tableName: string): Promise<{ key: string, sequence: number, column: string }[]> {
|
||||
const sql = `SHOW INDEX FROM ${tableName}`;
|
||||
return this.query<any[]>(sql).then(results => {
|
||||
// exclude foreign keys
|
||||
return this.getTableForeignQuery(tableName).then(foreignKeys => {
|
||||
|
||||
return results
|
||||
.filter(result => result.Key_name !== "PRIMARY" && foreignKeys.indexOf(result.Key_name) === -1)
|
||||
.map(result => ({
|
||||
key: result.Key_name,
|
||||
sequence: result.Seq_in_index,
|
||||
column: result.Column_name
|
||||
}));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getPrimaryConstraintName(tableName: string): Promise<string> {
|
||||
const sql = `SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_CATALOG = '${this.driver.db}'`
|
||||
+ ` AND TABLE_NAME = '${tableName}' AND CONSTRAINT_TYPE = 'PRIMARY KEY'`;
|
||||
return this.query<any[]>(sql).then(results => results && results.length ? results[0].CONSTRAINT_NAME : undefined);
|
||||
}
|
||||
|
||||
dropIndex(tableName: string, indexName: string): Promise<void> {
|
||||
const sql = `ALTER TABLE ${tableName} DROP INDEX \`${indexName}\``;
|
||||
return this.query(sql).then(() => {});
|
||||
}
|
||||
|
||||
createIndex(tableName: string, index: IndexMetadata): Promise<void> {
|
||||
const sql = `CREATE ${index.isUnique ? "UNIQUE" : ""} INDEX \`${index.name}\` ON ${tableName}(${index.columns.join(", ")})`;
|
||||
return this.query(sql).then(() => {});
|
||||
}
|
||||
|
||||
addUniqueKey(tableName: string, columnName: string, keyName: string): Promise<void> {
|
||||
const sql = `ALTER TABLE ${tableName} ADD CONSTRAINT ${keyName} UNIQUE (${columnName})`;
|
||||
return this.query(sql).then(() => {});
|
||||
}
|
||||
|
||||
getTableColumns(tableName: string): Promise<string[]> {
|
||||
const sql = `SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_CATALOG = '${this.driver.db}'` +
|
||||
` AND TABLE_NAME = '${tableName}'`;
|
||||
return this.query<any[]>(sql).then(results => results.map(result => result.column_name));
|
||||
}
|
||||
|
||||
changeColumnQuery(tableName: string, columnName: string, newColumn: ColumnMetadata, skipPrimary: boolean = false): Promise<void> {
|
||||
const sql = `ALTER TABLE ${tableName} CHANGE ${columnName} ${this.buildCreateColumnSql(newColumn, skipPrimary)}`;
|
||||
return this.query(sql).then(() => {});
|
||||
}
|
||||
|
||||
createTableQuery(table: TableMetadata, columns: ColumnMetadata[]): Promise<void> {
|
||||
const columnDefinitions = columns.map(column => this.buildCreateColumnSql(column, false)).join(", ");
|
||||
const sql = `CREATE TABLE "${table.name}" (${columnDefinitions})`;
|
||||
return this.query(sql).then(() => {});
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Private Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private query<T>(sql: string) {
|
||||
return this.driver.query<T>(sql);
|
||||
}
|
||||
|
||||
private buildCreateColumnSql(column: ColumnMetadata, skipPrimary: boolean) {
|
||||
let c = column.name + " " + this.normalizeType(column);
|
||||
if (column.isNullable !== true)
|
||||
c += " NOT NULL";
|
||||
if (column.isPrimary === true && !skipPrimary)
|
||||
c += " PRIMARY KEY";
|
||||
// if (column.isGenerated === true) // don't use skipPrimary here since updates can update already exist primary without auto inc.
|
||||
// c += " AUTO_INCREMENT";
|
||||
// TODO: implement auto increment
|
||||
if (column.comment)
|
||||
c += " COMMENT '" + column.comment + "'";
|
||||
if (column.columnDefinition)
|
||||
c += " " + column.columnDefinition;
|
||||
return c;
|
||||
}
|
||||
|
||||
private normalizeType(column: ColumnMetadata) {
|
||||
|
||||
let realType: string = "";
|
||||
if (typeof column.type === "string") {
|
||||
realType = column.type.toLowerCase();
|
||||
|
||||
// todo: remove casting to any after upgrade to typescript 2
|
||||
} else if (typeof column.type === "object" && (<any>column.type).name && typeof (<any>column.type).name === "string") {
|
||||
realType = (<any>column.type).toLowerCase();
|
||||
}
|
||||
|
||||
switch (realType) {
|
||||
case "string":
|
||||
return "character varying(" + (column.length ? column.length : 255) + ")";
|
||||
case "text":
|
||||
return "text";
|
||||
case "boolean":
|
||||
return "boolean";
|
||||
case "integer":
|
||||
case "int":
|
||||
return "integer";
|
||||
case "smallint":
|
||||
return "smallint";
|
||||
case "bigint":
|
||||
return "bigint";
|
||||
case "float":
|
||||
return "real";
|
||||
case "double":
|
||||
case "number":
|
||||
return "double precision";
|
||||
case "decimal":
|
||||
if (column.precision && column.scale) {
|
||||
return `decimal(${column.precision},${column.scale})`;
|
||||
|
||||
} else if (column.scale) {
|
||||
return `decimal(${column.scale})`;
|
||||
|
||||
} else if (column.precision) {
|
||||
return `decimal(${column.precision})`;
|
||||
|
||||
} else {
|
||||
return "decimal";
|
||||
|
||||
}
|
||||
case "date":
|
||||
return "date";
|
||||
case "time":
|
||||
return "time";
|
||||
case "datetime":
|
||||
return "timestamp";
|
||||
case "json":
|
||||
return "text";
|
||||
case "simple_array":
|
||||
return column.length ? "character varying(" + column.length + ")" : "text";
|
||||
}
|
||||
|
||||
throw new Error("Specified type (" + column.type + ") is not supported by current driver.");
|
||||
}
|
||||
|
||||
}
|
||||
@ -4,7 +4,6 @@ import {expect} from "chai";
|
||||
import {Connection} from "../../src/connection/Connection";
|
||||
import {createConnection, CreateConnectionOptions} from "../../src/index";
|
||||
import {Repository} from "../../src/repository/Repository";
|
||||
import {SchemaCreator} from "../../src/schema-creator/SchemaCreator";
|
||||
import {Post} from "../../sample/sample1-simple-entity/entity/Post";
|
||||
|
||||
chai.should();
|
||||
@ -26,6 +25,18 @@ describe("insertion", function() {
|
||||
},
|
||||
entities: [Post]
|
||||
};
|
||||
/*const parameters: CreateConnectionOptions = {
|
||||
driver: "postgres",
|
||||
connection: {
|
||||
host: "192.168.99.100",
|
||||
port: 5432,
|
||||
username: "test",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
autoSchemaCreate: true
|
||||
},
|
||||
entities: [Post]
|
||||
};*/
|
||||
|
||||
// connect to db
|
||||
let connection: Connection;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user