typeorm
Version:
Data-Mapper ORM for TypeScript, ES7, ES6, ES5. Supports MySQL, PostgreSQL, MariaDB, SQLite, MS SQL Server, Oracle, WebSQL, MongoDB databases.
858 lines • 65.9 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [0, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
import { TransactionAlreadyStartedError } from "../../error/TransactionAlreadyStartedError";
import { TransactionNotStartedError } from "../../error/TransactionNotStartedError";
import { TableColumn } from "../../schema-builder/schema/TableColumn";
import { Table } from "../../schema-builder/schema/Table";
import { TableIndex } from "../../schema-builder/schema/TableIndex";
import { TableForeignKey } from "../../schema-builder/schema/TableForeignKey";
import { TablePrimaryKey } from "../../schema-builder/schema/TablePrimaryKey";
import { QueryRunnerAlreadyReleasedError } from "../../error/QueryRunnerAlreadyReleasedError";
import { QueryFailedError } from "../../error/QueryFailedError";
import { OrmUtils } from "../../util/OrmUtils";
/**
* Runs queries on a single postgres database connection.
*/
var PostgresQueryRunner = /** @class */ (function () {
// -------------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------------
function PostgresQueryRunner(driver, mode) {
if (mode === void 0) { mode = "master"; }
/**
* Indicates if connection for this query runner is released.
* Once its released, query runner cannot run queries anymore.
*/
this.isReleased = false;
/**
* Indicates if transaction is in progress.
*/
this.isTransactionActive = false;
/**
* Stores temporarily user data.
* Useful for sharing data with subscribers.
*/
this.data = {};
/**
* Indicates if special query runner mode in which sql queries won't be executed is enabled.
*/
this.sqlMemoryMode = false;
/**
* Sql-s stored if "sql in memory" mode is enabled.
*/
this.sqlsInMemory = [];
this.driver = driver;
this.connection = driver.connection;
this.mode = mode;
}
// -------------------------------------------------------------------------
// Public Methods
// -------------------------------------------------------------------------
/**
* Creates/uses database connection from the connection pool to perform further operations.
* Returns obtained database connection.
*/
PostgresQueryRunner.prototype.connect = function () {
var _this = this;
if (this.databaseConnection)
return Promise.resolve(this.databaseConnection);
if (this.databaseConnectionPromise)
return this.databaseConnectionPromise;
if (this.mode === "slave" && this.driver.isReplicated) {
this.databaseConnectionPromise = this.driver.obtainSlaveConnection().then(function (_a) {
var connection = _a[0], release = _a[1];
_this.driver.connectedQueryRunners.push(_this);
_this.databaseConnection = connection;
_this.releaseCallback = release;
return _this.databaseConnection;
});
}
else {
this.databaseConnectionPromise = this.driver.obtainMasterConnection().then(function (_a) {
var connection = _a[0], release = _a[1];
_this.driver.connectedQueryRunners.push(_this);
_this.databaseConnection = connection;
_this.releaseCallback = release;
return _this.databaseConnection;
});
}
return this.databaseConnectionPromise;
};
/**
* Releases used database connection.
* You cannot use query runner methods once its released.
*/
PostgresQueryRunner.prototype.release = function () {
this.isReleased = true;
if (this.releaseCallback)
this.releaseCallback();
var index = this.driver.connectedQueryRunners.indexOf(this);
if (index !== -1)
this.driver.connectedQueryRunners.splice(index);
return Promise.resolve();
};
/**
* Starts transaction.
*/
PostgresQueryRunner.prototype.startTransaction = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (this.isTransactionActive)
throw new TransactionAlreadyStartedError();
this.isTransactionActive = true;
return [4 /*yield*/, this.query("START TRANSACTION")];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
/**
* Commits transaction.
* Error will be thrown if transaction was not started.
*/
PostgresQueryRunner.prototype.commitTransaction = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!this.isTransactionActive)
throw new TransactionNotStartedError();
return [4 /*yield*/, this.query("COMMIT")];
case 1:
_a.sent();
this.isTransactionActive = false;
return [2 /*return*/];
}
});
});
};
/**
* Rollbacks transaction.
* Error will be thrown if transaction was not started.
*/
PostgresQueryRunner.prototype.rollbackTransaction = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!this.isTransactionActive)
throw new TransactionNotStartedError();
return [4 /*yield*/, this.query("ROLLBACK")];
case 1:
_a.sent();
this.isTransactionActive = false;
return [2 /*return*/];
}
});
});
};
/**
* Executes a given SQL query.
*/
PostgresQueryRunner.prototype.query = function (query, parameters) {
var _this = this;
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
// console.log("query: ", query);
// console.log("parameters: ", parameters);
return new Promise(function (ok, fail) { return __awaiter(_this, void 0, void 0, function () {
var _this = this;
var databaseConnection, queryStartTime;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.connect()];
case 1:
databaseConnection = _a.sent();
this.driver.connection.logger.logQuery(query, parameters, this);
queryStartTime = +new Date();
databaseConnection.query(query, parameters, function (err, result) {
// log slow queries if maxQueryExecution time is set
var maxQueryExecutionTime = _this.driver.connection.options.maxQueryExecutionTime;
var queryEndTime = +new Date();
var queryExecutionTime = queryEndTime - queryStartTime;
if (maxQueryExecutionTime && queryExecutionTime > maxQueryExecutionTime)
_this.driver.connection.logger.logQuerySlow(queryExecutionTime, query, parameters, _this);
if (err) {
_this.driver.connection.logger.logQueryError(err, query, parameters, _this);
fail(new QueryFailedError(query, parameters, err));
}
else {
ok(result.rows);
}
});
return [2 /*return*/];
}
});
}); });
};
/**
* Returns raw data stream.
*/
PostgresQueryRunner.prototype.stream = function (query, parameters, onEnd, onError) {
var _this = this;
var QueryStream = this.driver.loadStreamDependency();
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
return new Promise(function (ok, fail) { return __awaiter(_this, void 0, void 0, function () {
var databaseConnection, stream, err_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, this.connect()];
case 1:
databaseConnection = _a.sent();
this.driver.connection.logger.logQuery(query, parameters, this);
stream = databaseConnection.query(new QueryStream(query, parameters));
if (onEnd)
stream.on("end", onEnd);
if (onError)
stream.on("error", onError);
ok(stream);
return [3 /*break*/, 3];
case 2:
err_1 = _a.sent();
fail(err_1);
return [3 /*break*/, 3];
case 3: return [2 /*return*/];
}
});
}); });
};
/**
* Insert a new row with given values into the given table.
* Returns value of the generated column if given and generate column exist in the table.
*/
PostgresQueryRunner.prototype.insert = function (tablePath, keyValues) {
return __awaiter(this, void 0, void 0, function () {
var keys, columns, values, generatedColumns, generatedColumnNames, generatedColumnSql, sql, parameters, result, generatedMap;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
keys = Object.keys(keyValues);
columns = keys.map(function (key) { return "\"" + key + "\""; }).join(", ");
values = keys.map(function (key, index) { return "$" + (index + 1); }).join(",");
generatedColumns = this.connection.hasMetadata(tablePath) ? this.connection.getMetadata(tablePath).generatedColumns : [];
generatedColumnNames = generatedColumns.map(function (generatedColumn) { return "\"" + generatedColumn.databaseName + "\""; }).join(", ");
generatedColumnSql = generatedColumns.length > 0 ? " RETURNING " + generatedColumnNames : "";
sql = columns.length > 0
? "INSERT INTO " + this.escapeTablePath(tablePath) + "(" + columns + ") VALUES (" + values + ") " + generatedColumnSql
: "INSERT INTO " + this.escapeTablePath(tablePath) + " DEFAULT VALUES " + generatedColumnSql;
parameters = keys.map(function (key) { return keyValues[key]; });
return [4 /*yield*/, this.query(sql, parameters)];
case 1:
result = _a.sent();
generatedMap = generatedColumns.reduce(function (map, column) {
var valueMap = column.createValueMap(result[0][column.databaseName]);
return OrmUtils.mergeDeep(map, valueMap);
}, {});
return [2 /*return*/, {
result: result,
generatedMap: Object.keys(generatedMap).length > 0 ? generatedMap : undefined
}];
}
});
});
};
/**
* Updates rows that match given conditions in the given table.
*/
PostgresQueryRunner.prototype.update = function (tablePath, valuesMap, conditions) {
return __awaiter(this, void 0, void 0, function () {
var updateValues, conditionString, query, updateParams, conditionParams, allParameters;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
updateValues = this.parametrize(valuesMap).join(", ");
conditionString = this.parametrize(conditions, Object.keys(valuesMap).length).join(" AND ");
query = "UPDATE " + this.escapeTablePath(tablePath) + " SET " + updateValues + (conditionString ? (" WHERE " + conditionString) : "");
updateParams = Object.keys(valuesMap).map(function (key) { return valuesMap[key]; });
conditionParams = Object.keys(conditions).map(function (key) { return conditions[key]; });
allParameters = updateParams.concat(conditionParams);
return [4 /*yield*/, this.query(query, allParameters)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
/**
* Deletes from the given table by a given conditions.
*/
PostgresQueryRunner.prototype.delete = function (tablePath, conditions, maybeParameters) {
return __awaiter(this, void 0, void 0, function () {
var conditionString, parameters, sql;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
conditionString = typeof conditions === "string" ? conditions : this.parametrize(conditions).join(" AND ");
parameters = conditions instanceof Object ? Object.keys(conditions).map(function (key) { return conditions[key]; }) : maybeParameters;
sql = "DELETE FROM " + this.escapeTablePath(tablePath) + " WHERE " + conditionString;
return [4 /*yield*/, this.query(sql, parameters)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
/**
* Inserts rows into closure table.
*
* todo: rethink its place
*/
PostgresQueryRunner.prototype.insertIntoClosureTable = function (tablePath, newEntityId, parentId, hasLevel) {
return __awaiter(this, void 0, void 0, function () {
var sql, results;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
sql = "";
if (hasLevel) {
sql = "INSERT INTO " + this.escapeTablePath(tablePath) + "(\"ancestor\", \"descendant\", \"level\") " +
("SELECT \"ancestor\", " + newEntityId + ", \"level\" + 1 FROM " + this.escapeTablePath(tablePath) + " WHERE \"descendant\" = " + parentId + " ") +
("UNION ALL SELECT " + newEntityId + ", " + newEntityId + ", 1");
}
else {
sql = "INSERT INTO " + this.escapeTablePath(tablePath) + "(\"ancestor\", \"descendant\") " +
("SELECT \"ancestor\", " + newEntityId + " FROM " + this.escapeTablePath(tablePath) + " WHERE \"descendant\" = " + parentId + " ") +
("UNION ALL SELECT " + newEntityId + ", " + newEntityId);
}
return [4 /*yield*/, this.query(sql)];
case 1:
_a.sent();
if (!hasLevel) return [3 /*break*/, 3];
return [4 /*yield*/, this.query("SELECT MAX(level) as level FROM " + this.escapeTablePath(tablePath) + " WHERE descendant = " + parentId)];
case 2:
results = _a.sent();
return [2 /*return*/, results && results[0] && results[0]["level"] ? parseInt(results[0]["level"]) + 1 : 1];
case 3: return [2 /*return*/, -1];
}
});
});
};
/**
* Loads given table's data from the database.
*/
PostgresQueryRunner.prototype.getTable = function (tablePath) {
return __awaiter(this, void 0, void 0, function () {
var tables;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.getTables([tablePath])];
case 1:
tables = _a.sent();
return [2 /*return*/, tables.length > 0 ? tables[0] : undefined];
}
});
});
};
/**
* Loads all tables (with given names) from the database and creates a Table from them.
*/
PostgresQueryRunner.prototype.getTables = function (tablePaths) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
var tableNames, currentSchemaQuery, currentSchema, schemaNames, tableNamesString, schemaNamesString, tablesCondition, tablesSql, columnsSql, indicesSql, foreignKeysSql, uniqueKeysSql, primaryKeysSql, _a, dbTables, dbColumns, dbIndices, dbForeignKeys, dbUniqueKeys, primaryKeys;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
// if no tables given then no need to proceed
if (!tablePaths || !tablePaths.length)
return [2 /*return*/, []];
tableNames = tablePaths.map(function (tablePath) {
return tablePath.indexOf(".") === -1 ? tablePath : tablePath.split(".")[1];
});
return [4 /*yield*/, this.query("SELECT * FROM current_schema()")];
case 1:
currentSchemaQuery = _b.sent();
currentSchema = currentSchemaQuery[0]["current_schema"];
schemaNames = tablePaths
.filter(function (tablePath) { return tablePath.indexOf(".") !== -1; })
.map(function (tablePath) { return tablePath.split(".")[0]; });
schemaNames.push(this.driver.options.schema || currentSchema);
tableNamesString = tableNames.map(function (name) { return "'" + name + "'"; }).join(", ");
schemaNamesString = schemaNames.map(function (name) { return "'" + name + "'"; }).join(", ");
tablesCondition = tablePaths.map(function (tablePath) {
var _a = tablePath.split("."), schemaName = _a[0], tableName = _a[1];
if (!tableName) {
tableName = schemaName;
schemaName = _this.driver.options.schema || currentSchema;
}
return "table_schema = '" + schemaName + "' AND table_name = '" + tableName + "'";
}).join(" OR ");
tablesSql = "SELECT * FROM information_schema.tables WHERE " + tablesCondition;
columnsSql = "SELECT * FROM information_schema.columns WHERE table_schema IN (" + schemaNamesString + ")";
indicesSql = "SELECT t.relname AS table_name, i.relname AS index_name, a.attname AS column_name, ix.indisunique AS is_unique, a.attnum, ix.indkey FROM pg_class t, pg_class i, pg_index ix, pg_attribute a, pg_namespace ns\nWHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid\nAND a.attnum = ANY(ix.indkey) AND t.relkind = 'r' AND t.relname IN (" + tableNamesString + ") AND t.relnamespace = ns.OID AND ns.nspname IN (" + schemaNamesString + ") ORDER BY t.relname, i.relname";
foreignKeysSql = "SELECT table_name, constraint_name FROM information_schema.table_constraints WHERE table_schema IN (" + schemaNamesString + ") AND constraint_type = 'FOREIGN KEY'";
uniqueKeysSql = "SELECT * FROM information_schema.table_constraints WHERE table_schema IN (" + schemaNamesString + ") AND constraint_type = 'UNIQUE'";
primaryKeysSql = "SELECT c.column_name, tc.table_name, tc.constraint_name FROM information_schema.table_constraints tc\nJOIN information_schema.constraint_column_usage AS ccu USING (constraint_schema, constraint_name)\nJOIN information_schema.columns AS c ON c.table_schema = tc.constraint_schema AND tc.table_name = c.table_name AND ccu.column_name = c.column_name\nwhere constraint_type = 'PRIMARY KEY' AND c.table_schema IN (" + schemaNamesString + ")";
return [4 /*yield*/, Promise.all([
this.query(tablesSql),
this.query(columnsSql),
this.query(indicesSql),
this.query(foreignKeysSql),
this.query(uniqueKeysSql),
this.query(primaryKeysSql),
])];
case 2:
_a = _b.sent(), dbTables = _a[0], dbColumns = _a[1], dbIndices = _a[2], dbForeignKeys = _a[3], dbUniqueKeys = _a[4], primaryKeys = _a[5];
// if tables were not found in the db, no need to proceed
if (!dbTables.length)
return [2 /*return*/, []];
// create tables for loaded tables
return [2 /*return*/, dbTables.map(function (dbTable) {
var table = new Table(dbTable["table_name"]);
table.database = dbTable["table_catalog"];
table.schema = dbTable["table_schema"];
// create columns from the loaded columns
table.columns = dbColumns
.filter(function (dbColumn) { return dbColumn["table_name"] === table.name; })
.map(function (dbColumn) {
var seqName = table.schema === currentSchema
? dbColumn["table_name"] + "_" + dbColumn["column_name"] + "_seq"
: table.schema + "." + dbColumn["table_name"] + "_" + dbColumn["column_name"] + "_seq";
var isGenerated = !!dbColumn["column_default"]
&& (dbColumn["column_default"].replace(/"/gi, "") === "nextval('" + seqName + "'::regclass)" || /^uuid\_generate\_v\d\(\)/.test(dbColumn["column_default"]));
var tableColumn = new TableColumn();
tableColumn.name = dbColumn["column_name"];
tableColumn.type = dbColumn["data_type"].toLowerCase();
tableColumn.length = dbColumn["character_maximum_length"] ? dbColumn["character_maximum_length"].toString() : "";
tableColumn.precision = dbColumn["numeric_precision"];
tableColumn.scale = dbColumn["numeric_scale"];
tableColumn.default = dbColumn["column_default"] !== null && dbColumn["column_default"] !== undefined ? dbColumn["column_default"].replace(/::character varying/, "") : undefined;
tableColumn.isNullable = dbColumn["is_nullable"] === "YES";
// tableColumn.isPrimary = dbColumn["column_key"].indexOf("PRI") !== -1;
tableColumn.isGenerated = isGenerated;
tableColumn.comment = ""; // dbColumn["COLUMN_COMMENT"];
tableColumn.charset = dbColumn["character_set_name"];
tableColumn.collation = dbColumn["collation_name"];
tableColumn.isUnique = !!dbUniqueKeys.find(function (key) { return key["constraint_name"] === "uk_" + dbColumn["table_name"] + "_" + dbColumn["column_name"]; });
if (tableColumn.type === "array") {
tableColumn.isArray = true;
var type = dbColumn["udt_name"].substring(1);
tableColumn.type = _this.connection.driver.normalizeType({ type: type });
}
if (tableColumn.type === "time without time zone"
|| tableColumn.type === "time with time zone"
|| tableColumn.type === "timestamp without time zone"
|| tableColumn.type === "timestamp with time zone") {
tableColumn.precision = dbColumn["datetime_precision"];
}
return tableColumn;
});
// create primary key schema
table.primaryKeys = primaryKeys
.filter(function (primaryKey) { return primaryKey["table_name"] === table.name; })
.map(function (primaryKey) { return new TablePrimaryKey(primaryKey["constraint_name"], primaryKey["column_name"]); });
// create foreign key schemas from the loaded indices
table.foreignKeys = dbForeignKeys
.filter(function (dbForeignKey) { return dbForeignKey["table_name"] === table.name; })
.map(function (dbForeignKey) { return new TableForeignKey(dbForeignKey["constraint_name"], [], [], "", ""); }); // todo: fix missing params
// create unique key schemas from the loaded indices
/*table.uniqueKeys = dbUniqueKeys
.filter(dbUniqueKey => dbUniqueKey["table_name"] === table.name)
.map(dbUniqueKey => {
return new UniqueKeySchema(dbUniqueKey["TABLE_NAME"], dbUniqueKey["CONSTRAINT_NAME"], [/!* todo *!/]);
});*/
// create index schemas from the loaded indices
table.indices = dbIndices
.filter(function (dbIndex) {
return dbIndex["table_name"] === table.name &&
(!table.foreignKeys.find(function (foreignKey) { return foreignKey.name === dbIndex["index_name"]; })) &&
(!table.primaryKeys.find(function (primaryKey) { return primaryKey.name === dbIndex["index_name"]; })) &&
(!dbUniqueKeys.find(function (key) { return key["constraint_name"] === dbIndex["index_name"]; }));
})
.map(function (dbIndex) { return dbIndex["index_name"]; })
.filter(function (value, index, self) { return self.indexOf(value) === index; }) // unqiue
.map(function (dbIndexName) {
var dbIndicesInfos = dbIndices
.filter(function (dbIndex) { return dbIndex["table_name"] === table.name && dbIndex["index_name"] === dbIndexName; });
var columnPositions = dbIndicesInfos[0]["indkey"].split(" ")
.map(function (x) { return parseInt(x); });
var columnNames = columnPositions
.map(function (pos) { return dbIndicesInfos.find(function (idx) { return idx.attnum === pos; })["column_name"]; });
return new TableIndex(dbTable["table_name"], dbIndexName, columnNames, dbIndicesInfos[0]["is_unique"]);
});
return table;
})];
}
});
});
};
/**
* Checks if database with the given name exist.
*/
PostgresQueryRunner.prototype.hasDatabase = function (database) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, Promise.resolve(false)];
});
});
};
/**
* Checks if table with the given name exist in the database.
*/
PostgresQueryRunner.prototype.hasTable = function (tablePath) {
return __awaiter(this, void 0, void 0, function () {
var parsedTablePath, sql, result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
parsedTablePath = this.parseTablePath(tablePath);
sql = "SELECT * FROM information_schema.tables WHERE table_schema = " + parsedTablePath.schema + " AND table_name = " + parsedTablePath.tableName;
return [4 /*yield*/, this.query(sql)];
case 1:
result = _a.sent();
return [2 /*return*/, result.length ? true : false];
}
});
});
};
/**
* Creates a database if it's not created.
* Postgres does not supports database creation inside a transaction block.
*/
PostgresQueryRunner.prototype.createDatabase = function (database) {
return Promise.resolve([]);
};
/**
* Creates a schema if it's not created.
*/
PostgresQueryRunner.prototype.createSchema = function (schemas) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
if (this.driver.options.schema)
schemas.push(this.driver.options.schema);
return [2 /*return*/, Promise.all(schemas.map(function (schema) { return _this.query("CREATE SCHEMA IF NOT EXISTS \"" + schema + "\""); }))];
});
});
};
/**
* Creates a new table from the given table metadata and column metadatas.
*/
PostgresQueryRunner.prototype.createTable = function (table) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
var schema, columnDefinitions, up, primaryKeyColumns, down;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
schema = table.schema || this.driver.options.schema;
columnDefinitions = table.columns.map(function (column) { return _this.buildCreateColumnSql(column, false); }).join(", ");
up = "CREATE TABLE " + this.escapeTablePath(table) + " (" + columnDefinitions;
up += table.columns
.filter(function (column) { return column.isUnique; })
.map(function (column) {
return schema ? ", CONSTRAINT \"uk_" + schema + "_" + table.name + "_" + column.name + "\" UNIQUE (\"" + column.name + "\")"
: ", CONSTRAINT \"uk_" + table.name + "_" + column.name + "\" UNIQUE (\"" + column.name + "\")";
}).join(" ");
primaryKeyColumns = table.columns.filter(function (column) { return column.isPrimary; });
if (primaryKeyColumns.length > 0)
up += ", PRIMARY KEY(" + primaryKeyColumns.map(function (column) { return "\"" + column.name + "\""; }).join(", ") + ")";
up += ")";
down = "DROP TABLE \"" + table.name + "\"";
return [4 /*yield*/, this.schemaQuery(up, down)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
/**
* Drops the table.
*/
PostgresQueryRunner.prototype.dropTable = function (tablePath) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.query("DROP TABLE " + this.escapeTablePath(tablePath))];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
/**
* Checks if column with the given name exist in the given table.
*/
PostgresQueryRunner.prototype.hasColumn = function (tablePath, columnName) {
return __awaiter(this, void 0, void 0, function () {
var parsedTablePath, sql, result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
parsedTablePath = this.parseTablePath(tablePath);
sql = "SELECT * FROM information_schema.columns WHERE table_schema = " + parsedTablePath.schema + " AND table_name = '" + parsedTablePath.tableName + "' AND column_name = '" + columnName + "'";
return [4 /*yield*/, this.query(sql)];
case 1:
result = _a.sent();
return [2 /*return*/, result.length ? true : false];
}
});
});
};
/**
* Creates a new column from the column in the table.
*/
PostgresQueryRunner.prototype.addColumn = function (tableOrPath, column) {
return __awaiter(this, void 0, void 0, function () {
var up, down;
return __generator(this, function (_a) {
up = "ALTER TABLE " + this.escapeTablePath(tableOrPath) + " ADD " + this.buildCreateColumnSql(column, false);
down = "ALTER TABLE " + this.escapeTablePath(tableOrPath) + " DROP \"" + column.name + "\"";
return [2 /*return*/, this.schemaQuery(up, down)];
});
});
};
/**
* Creates a new columns from the column in the table.
*/
PostgresQueryRunner.prototype.addColumns = function (tableOrName, columns) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
var queries;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
queries = columns.map(function (column) { return _this.addColumn(tableOrName, column); });
return [4 /*yield*/, Promise.all(queries)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
/**
* Renames column in the given table.
*/
PostgresQueryRunner.prototype.renameColumn = function (tableOrName, oldTableColumnOrName, newTableColumnOrName) {
return __awaiter(this, void 0, void 0, function () {
var table, oldColumn, newColumn;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
table = undefined;
if (!(tableOrName instanceof Table)) return [3 /*break*/, 1];
table = tableOrName;
return [3 /*break*/, 3];
case 1: return [4 /*yield*/, this.getTable(tableOrName)];
case 2:
table = _a.sent();
_a.label = 3;
case 3:
if (!table)
throw new Error("Table " + tableOrName + " was not found.");
oldColumn = undefined;
if (oldTableColumnOrName instanceof TableColumn) {
oldColumn = oldTableColumnOrName;
}
else {
oldColumn = table.columns.find(function (column) { return column.name === oldTableColumnOrName; });
}
if (!oldColumn)
throw new Error("Column \"" + oldTableColumnOrName + "\" was not found in the \"" + tableOrName + "\" table.");
newColumn = undefined;
if (newTableColumnOrName instanceof TableColumn) {
newColumn = newTableColumnOrName;
}
else {
newColumn = oldColumn.clone();
newColumn.name = newTableColumnOrName;
}
return [2 /*return*/, this.changeColumn(table, oldColumn, newColumn)];
}
});
});
};
/**
* Changes a column in the table.
*/
PostgresQueryRunner.prototype.changeColumn = function (tableOrName, oldTableColumnOrName, newColumn) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
var table, sql, oldColumn, up, up, schema, up, up2, up, up2, up, up, up, up, up;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
table = undefined;
sql = [];
if (!(tableOrName instanceof Table)) return [3 /*break*/, 1];
table = tableOrName;
return [3 /*break*/, 3];
case 1: return [4 /*yield*/, this.getTable(tableOrName)];
case 2:
table = _a.sent();
_a.label = 3;
case 3:
if (!table)
throw new Error("Table " + tableOrName + " was not found.");
oldColumn = undefined;
if (oldTableColumnOrName instanceof TableColumn) {
oldColumn = oldTableColumnOrName;
}
else {
oldColumn = table.columns.find(function (column) { return column.name === oldTableColumnOrName; });
}
if (!oldColumn)
throw new Error("Column \"" + oldTableColumnOrName + "\" was not found in the \"" + tableOrName + "\" table.");
if (this.connection.driver.createFullType(oldColumn) !== this.connection.driver.createFullType(newColumn) ||
oldColumn.name !== newColumn.name) {
up = "ALTER TABLE " + this.escapeTablePath(tableOrName) + " ALTER COLUMN \"" + oldColumn.name + "\"";
if (this.connection.driver.createFullType(oldColumn) !== this.connection.driver.createFullType(newColumn)) {
up += " TYPE " + this.connection.driver.createFullType(newColumn);
}
if (oldColumn.name !== newColumn.name) {
up += " RENAME TO " + newColumn.name;
}
sql.push({ up: up, down: "-- TODO: revert " + up }); // TODO: Add revert logic
}
if (oldColumn.isNullable !== newColumn.isNullable) {
up = "ALTER TABLE " + this.escapeTablePath(tableOrName) + " ALTER COLUMN \"" + oldColumn.name + "\"";
if (newColumn.isNullable) {
up += " DROP NOT NULL";
}
else {
up += " SET NOT NULL";
}
sql.push({ up: up, down: "-- TODO: revert " + up }); // TODO: Add revert logic
}
// update sequence generation
if (oldColumn.isGenerated !== newColumn.isGenerated) {
schema = table.schema || this.driver.options.schema;
if (!oldColumn.isGenerated && newColumn.type !== "uuid") {
up = schema
? "CREATE SEQUENCE \"" + schema + "\".\"" + table.name + "_" + oldColumn.name + "_seq\" OWNED BY " + this.escapeTablePath(table) + ".\"" + oldColumn.name + "\""
: "CREATE SEQUENCE \"" + table.name + "_" + oldColumn.name + "_seq\" OWNED BY " + this.escapeTablePath(table) + ".\"" + oldColumn.name + "\"";
sql.push({ up: up, down: "-- TODO: revert " + up }); // TODO: Add revert logic
up2 = schema
? "ALTER TABLE " + this.escapeTablePath(table) + " ALTER COLUMN \"" + oldColumn.name + "\" SET DEFAULT nextval('\"" + schema + "." + table.name + "_" + oldColumn.name + "_seq\"')"
: "ALTER TABLE " + this.escapeTablePath(table) + " ALTER COLUMN \"" + oldColumn.name + "\" SET DEFAULT nextval('\"" + table.name + "_" + oldColumn.name + "_seq\"')";
sql.push({ up: up2, down: "-- TODO: revert " + up2 }); // TODO: Add revert logic
}
else {
up = "ALTER TABLE " + this.escapeTablePath(table) + " ALTER COLUMN \"" + oldColumn.name + "\" DROP DEFAULT";
sql.push({ up: up, down: "-- TODO: revert " + up }); // TODO: Add revert logic
up2 = schema
? "DROP SEQUENCE \"" + schema + "\".\"" + table.name + "_" + oldColumn.name + "_seq\""
: "DROP SEQUENCE \"" + table.name + "_" + oldColumn.name + "_seq\"";
sql.push({ up: up2, down: "-- TODO: revert " + up2 }); // TODO: Add revert logic
}
}
if (oldColumn.comment !== newColumn.comment) {
up = "COMMENT ON COLUMN " + this.escapeTablePath(tableOrName) + ".\"" + oldColumn.name + "\" is '" + newColumn.comment + "'";
sql.push({ up: up, down: "-- TODO: revert " + up }); // TODO: Add revert logic
}
if (oldColumn.isUnique !== newColumn.isUnique) {
if (newColumn.isUnique === true) {
up = "ALTER TABLE " + this.escapeTablePath(tableOrName) + " ADD CONSTRAINT \"uk_" + table.name + "_" + newColumn.name + "\" UNIQUE (\"" + newColumn.name + "\")";
sql.push({ up: up, down: "-- TODO: revert " + up }); // TODO: Add revert logic
}
else if (newColumn.isUnique === false) {
up = "ALTER TABLE " + this.escapeTablePath(tableOrName) + " DROP CONSTRAINT \"uk_" + table.name + "_" + newColumn.name + "\"";
sql.push({ up: up, down: "-- TODO: revert " + up }); // TODO: Add revert logic
}
}
if (newColumn.default !== oldColumn.default) {
if (newColumn.default !== null && newColumn.default !== undefined) {
up = "ALTER TABLE " + this.escapeTablePath(tableOrName) + " ALTER COLUMN \"" + newColumn.name + "\" SET DEFAULT " + newColumn.default;
sql.push({ up: up, down: "-- TODO: revert " + up }); // TODO: Add revert logic
}
else if (oldColumn.default !== null && oldColumn.default !== undefined) {
up = "ALTER TABLE " + this.escapeTablePath(tableOrName) + " ALTER COLUMN \"" + newColumn.name + "\" DROP DEFAULT";
sql.push({ up: up, down: "-- TODO: revert " + up }); // TODO: Add revert logic
}
}
return [4 /*yield*/, Promise.all(sql.map(function (_a) {
var up = _a.up, down = _a.down;
return _this.schemaQuery(up, down);
}))];
case 4:
_a.sent();
return [2 /*return*/];
}
});
});
};
/**
* Changes a column in the table.
*/
PostgresQueryRunner.prototype.changeColumns = function (table, changedColumns) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
var updatePromises;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
updatePromises = changedColumns.map(function (changedColumn) { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this.changeColumn(table, changedColumn.oldColumn, changedColumn.newColumn)];
});
}); });
return [4 /*yield*/, Promise.all(updatePromises)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
/**
* Drops column in the table.
*/
PostgresQueryRunner.prototype.dropColumn = function (table, column) {
return __awaiter(this, void 0, void 0, function () {
var up, down;
return __generator(this, function (_a) {
up = "ALTER TABLE " + this.escapeTablePath(table) + " DROP \"" + column.name + "\"";
down = "ALTER TABLE " + this.escapeTablePath(table) + " ADD " + this.buildCreateColumnSql(column, false);
return [2 /*return*/, this.schemaQuery(up, down)];
});
});
};
/**
* Drops the columns in the table.
*/
PostgresQueryRunner.prototype.dropColumns =