mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
Merge pull request #3700 from borremosch/add-simple-enum-type
Added simple-enum column type
This commit is contained in:
commit
d9f5581b22
@ -18,6 +18,7 @@ feel free to ask us and community.
|
||||
* added browser entry point to `package.json` ([3583](https://github.com/typeorm/typeorm/issues/3583))
|
||||
* replaced backend-only drivers by dummy driver in browser builds
|
||||
* added `useLocalForage` option to Sql.js connection options, which enables asynchronous load and save operations of the datatbase from the indexedDB ([#3554](https://github.com/typeorm/typeorm/issues/3554))
|
||||
* added simple-enum column type ([#1414](https://github.com/typeorm/typeorm/issues/1414))
|
||||
|
||||
## 0.2.13 (2019-02-10)
|
||||
|
||||
|
||||
@ -64,6 +64,12 @@ export function Column(type: WithPrecisionColumnType, options?: ColumnCommonOpti
|
||||
*/
|
||||
export function Column(type: "enum", options?: ColumnCommonOptions & ColumnEnumOptions): Function;
|
||||
|
||||
/**
|
||||
* Column decorator is used to mark a specific class property as a table column.
|
||||
* Only properties decorated with this decorator will be persisted to the database when entity be saved.
|
||||
*/
|
||||
export function Column(type: "simple-enum", options?: ColumnCommonOptions & ColumnEnumOptions): Function;
|
||||
|
||||
/**
|
||||
* Column decorator is used to mark a specific class property as a table column.
|
||||
* Only properties decorated with this decorator will be persisted to the database when entity be saved.
|
||||
|
||||
@ -439,7 +439,8 @@ export class MysqlDriver implements Driver {
|
||||
|
||||
} else if (columnMetadata.type === "simple-json") {
|
||||
return DateUtils.simpleJsonToString(value);
|
||||
} else if (columnMetadata.type === "enum") {
|
||||
|
||||
} else if (columnMetadata.type === "enum" || columnMetadata.type === "simple-enum") {
|
||||
return "" + value;
|
||||
}
|
||||
|
||||
@ -475,7 +476,10 @@ export class MysqlDriver implements Driver {
|
||||
value = DateUtils.stringToSimpleJson(value);
|
||||
|
||||
} else if (
|
||||
columnMetadata.type === "enum"
|
||||
(
|
||||
columnMetadata.type === "enum"
|
||||
|| columnMetadata.type === "simple-enum"
|
||||
)
|
||||
&& columnMetadata.enum
|
||||
&& !isNaN(value)
|
||||
&& columnMetadata.enum.indexOf(parseInt(value)) >= 0
|
||||
@ -515,6 +519,9 @@ export class MysqlDriver implements Driver {
|
||||
} else if (column.type === "simple-array" || column.type === "simple-json") {
|
||||
return "text";
|
||||
|
||||
} else if (column.type === "simple-enum") {
|
||||
return "enum";
|
||||
|
||||
} else if (column.type === "double precision" || column.type === "real") {
|
||||
return "double";
|
||||
|
||||
@ -541,7 +548,13 @@ export class MysqlDriver implements Driver {
|
||||
normalizeDefault(columnMetadata: ColumnMetadata): string {
|
||||
const defaultValue = columnMetadata.default;
|
||||
|
||||
if (columnMetadata.type === "enum" && defaultValue !== undefined) {
|
||||
if (
|
||||
(
|
||||
columnMetadata.type === "enum" ||
|
||||
columnMetadata.type === "simple-enum"
|
||||
) &&
|
||||
defaultValue !== undefined
|
||||
) {
|
||||
return `'${defaultValue}'`;
|
||||
}
|
||||
|
||||
|
||||
@ -1270,7 +1270,7 @@ export class MysqlQueryRunner extends BaseQueryRunner implements QueryRunner {
|
||||
tableColumn.scale = parseInt(dbColumn["NUMERIC_SCALE"]);
|
||||
}
|
||||
|
||||
if (tableColumn.type === "enum") {
|
||||
if (tableColumn.type === "enum" || tableColumn.type === "simple-enum") {
|
||||
const colType = dbColumn["COLUMN_TYPE"];
|
||||
const items = colType.substring(colType.indexOf("(") + 1, colType.indexOf(")")).split(",");
|
||||
tableColumn.enum = (items as string[]).map(item => {
|
||||
|
||||
@ -412,7 +412,13 @@ export class PostgresDriver implements Driver {
|
||||
} else if (columnMetadata.type === "simple-json") {
|
||||
return DateUtils.simpleJsonToString(value);
|
||||
|
||||
} else if (columnMetadata.type === "enum" && !columnMetadata.isArray) {
|
||||
} else if (
|
||||
(
|
||||
columnMetadata.type === "enum"
|
||||
|| columnMetadata.type === "simple-enum"
|
||||
)
|
||||
&& !columnMetadata.isArray
|
||||
) {
|
||||
return "" + value;
|
||||
}
|
||||
|
||||
@ -462,7 +468,8 @@ export class PostgresDriver implements Driver {
|
||||
|
||||
} else if (columnMetadata.type === "simple-json") {
|
||||
value = DateUtils.stringToSimpleJson(value);
|
||||
} else if (columnMetadata.type === "enum" ) {
|
||||
|
||||
} else if (columnMetadata.type === "enum" || columnMetadata.type === "simple-enum" ) {
|
||||
if (columnMetadata.isArray) {
|
||||
// manually convert enum array to array of values (pg does not support, see https://github.com/brianc/node-pg-types/issues/56)
|
||||
value = value !== "{}" ? (value as string).substr(1, (value as string).length - 2).split(",") : [];
|
||||
@ -565,6 +572,9 @@ export class PostgresDriver implements Driver {
|
||||
} else if (column.type === "simple-json") {
|
||||
return "text";
|
||||
|
||||
} else if (column.type === "simple-enum") {
|
||||
return "enum";
|
||||
|
||||
} else if (column.type === "int2") {
|
||||
return "smallint";
|
||||
|
||||
@ -598,7 +608,12 @@ export class PostgresDriver implements Driver {
|
||||
const defaultValue = columnMetadata.default;
|
||||
const arrayCast = columnMetadata.isArray ? `::${columnMetadata.type}[]` : "";
|
||||
|
||||
if (columnMetadata.type === "enum" && defaultValue !== undefined) {
|
||||
if (
|
||||
(
|
||||
columnMetadata.type === "enum"
|
||||
|| columnMetadata.type === "simple-enum"
|
||||
) && defaultValue !== undefined
|
||||
) {
|
||||
if (columnMetadata.isArray && Array.isArray(defaultValue)) {
|
||||
return `'{${defaultValue.map((val: string) => `${val}`).join(",")}}'`;
|
||||
}
|
||||
|
||||
@ -313,7 +313,7 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner
|
||||
|
||||
// if table have column with ENUM type, we must create this type in postgres.
|
||||
await Promise.all(table.columns
|
||||
.filter(column => column.type === "enum")
|
||||
.filter(column => column.type === "enum" || column.type === "simple-enum")
|
||||
.map(async column => {
|
||||
const hasEnum = await this.hasEnumType(table, column);
|
||||
if (!hasEnum) {
|
||||
@ -449,7 +449,7 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner
|
||||
|
||||
// rename ENUM types
|
||||
newTable.columns
|
||||
.filter(column => column.type === "enum")
|
||||
.filter(column => column.type === "enum" || column.type === "simple-enum")
|
||||
.forEach(column => {
|
||||
upQueries.push(`ALTER TYPE ${this.buildEnumName(oldTable, column)} RENAME TO ${this.buildEnumName(newTable, column, false)}`);
|
||||
downQueries.push(`ALTER TYPE ${this.buildEnumName(newTable, column)} RENAME TO ${this.buildEnumName(oldTable, column, false)}`);
|
||||
@ -467,7 +467,7 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner
|
||||
const upQueries: string[] = [];
|
||||
const downQueries: string[] = [];
|
||||
|
||||
if (column.type === "enum") {
|
||||
if (column.type === "enum" || column.type === "simple-enum") {
|
||||
const hasEnum = await this.hasEnumType(table, column);
|
||||
if (!hasEnum) {
|
||||
upQueries.push(this.createEnumTypeSql(table, column));
|
||||
@ -577,7 +577,7 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner
|
||||
downQueries.push(`ALTER TABLE ${this.escapeTableName(table)} RENAME COLUMN "${newColumn.name}" TO "${oldColumn.name}"`);
|
||||
|
||||
// rename ENUM type
|
||||
if (oldColumn.type === "enum") {
|
||||
if (oldColumn.type === "enum" || oldColumn.type === "simple-enum") {
|
||||
upQueries.push(`ALTER TYPE ${this.buildEnumName(table, oldColumn)} RENAME TO ${this.buildEnumName(table, newColumn, false)}`);
|
||||
downQueries.push(`ALTER TYPE ${this.buildEnumName(table, newColumn)} RENAME TO ${this.buildEnumName(table, oldColumn, false)}`);
|
||||
}
|
||||
@ -675,7 +675,11 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner
|
||||
downQueries.push(`ALTER TABLE ${this.escapeTableName(table)} ALTER COLUMN "${newColumn.name}" TYPE ${this.driver.createFullType(oldColumn)}`);
|
||||
}
|
||||
|
||||
if (newColumn.type === "enum" && oldColumn.type === "enum" && !OrmUtils.isArraysEqual(newColumn.enum!, oldColumn.enum!)) {
|
||||
if (
|
||||
(newColumn.type === "enum" || newColumn.type === "simple-enum")
|
||||
&& (oldColumn.type === "enum" || newColumn.type === "simple-enum")
|
||||
&& !OrmUtils.isArraysEqual(newColumn.enum!, oldColumn.enum!)
|
||||
) {
|
||||
const enumName = this.buildEnumName(table, newColumn);
|
||||
const enumNameWithoutSchema = this.buildEnumName(table, newColumn, false);
|
||||
const arraySuffix = newColumn.isArray ? "[]" : "";
|
||||
@ -901,7 +905,7 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner
|
||||
downQueries.push(`ALTER TABLE ${this.escapeTableName(table)} ADD ${this.buildCreateColumnSql(table, column)}`);
|
||||
|
||||
// drop enum type
|
||||
if (column.type === "enum") {
|
||||
if (column.type === "enum" || column.type === "simple-enum") {
|
||||
const hasEnum = await this.hasEnumType(table, column);
|
||||
if (hasEnum) {
|
||||
upQueries.push(this.dropEnumTypeSql(table, column));
|
||||
@ -1895,7 +1899,7 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner
|
||||
if (column.type === "bigint" || column.type === "int8")
|
||||
c += " BIGSERIAL";
|
||||
}
|
||||
if (column.type === "enum") {
|
||||
if (column.type === "enum" || column.type === "simple-enum") {
|
||||
c += " " + this.buildEnumName(table, column);
|
||||
if (column.isArray)
|
||||
c += " array";
|
||||
|
||||
@ -246,6 +246,8 @@ export abstract class AbstractSqliteDriver implements Driver {
|
||||
|
||||
} else if (columnMetadata.type === "simple-json") {
|
||||
return DateUtils.simpleJsonToString(value);
|
||||
} else if (columnMetadata.type === "simple-enum") {
|
||||
return DateUtils.simpleEnumToString(value);
|
||||
}
|
||||
|
||||
return value;
|
||||
@ -288,6 +290,10 @@ export abstract class AbstractSqliteDriver implements Driver {
|
||||
|
||||
} else if (columnMetadata.type === "simple-json") {
|
||||
value = DateUtils.stringToSimpleJson(value);
|
||||
|
||||
} else if ( columnMetadata.type === "simple-enum" ) {
|
||||
value = DateUtils.stringToSimpleEnum(value, columnMetadata);
|
||||
|
||||
}
|
||||
|
||||
if (columnMetadata.transformer)
|
||||
@ -385,6 +391,9 @@ export abstract class AbstractSqliteDriver implements Driver {
|
||||
} else if (column.type === "simple-json") {
|
||||
return "text";
|
||||
|
||||
} else if (column.type === "simple-enum") {
|
||||
return "varchar";
|
||||
|
||||
} else {
|
||||
return column.type as string || "";
|
||||
}
|
||||
|
||||
@ -762,6 +762,16 @@ export abstract class AbstractSqliteQueryRunner extends BaseQueryRunner implemen
|
||||
tableColumn.generationStrategy = "increment";
|
||||
}
|
||||
|
||||
if (tableColumn.type === "varchar") {
|
||||
// Check if this is an enum
|
||||
const enumMatch = sql.match(new RegExp("\"(" + tableColumn.name + ")\" varchar CHECK\\s*\\(\\s*\\1\\s+IN\\s*\\(('[^']+'(?:\\s*,\\s*'[^']+')+)\\s*\\)\\s*\\)"));
|
||||
if (enumMatch) {
|
||||
// This is an enum
|
||||
tableColumn.type = "simple-enum";
|
||||
tableColumn.enum = enumMatch[2].substr(1, enumMatch[2].length - 2).split("','");
|
||||
}
|
||||
}
|
||||
|
||||
// parse datatype and attempt to retrieve length
|
||||
let pos = tableColumn.type.indexOf("(");
|
||||
if (pos !== -1) {
|
||||
@ -972,6 +982,8 @@ export abstract class AbstractSqliteQueryRunner extends BaseQueryRunner implemen
|
||||
c += " " + this.connection.driver.createFullType(column);
|
||||
}
|
||||
|
||||
if (column.enum)
|
||||
c += " CHECK( " + column.name + " IN (" + column.enum.map(val => "'" + val + "'").join(",") + ") )";
|
||||
if (column.isPrimary && !skipPrimary)
|
||||
c += " PRIMARY KEY";
|
||||
if (column.isGenerated === true && column.generationStrategy === "increment") // don't use skipPrimary here since updates can update already exist primary without auto inc.
|
||||
|
||||
@ -381,6 +381,10 @@ export class SqlServerDriver implements Driver {
|
||||
|
||||
} else if (columnMetadata.type === "simple-json") {
|
||||
return DateUtils.simpleJsonToString(value);
|
||||
|
||||
} else if (columnMetadata.type === "simple-enum") {
|
||||
return DateUtils.simpleEnumToString(value);
|
||||
|
||||
}
|
||||
|
||||
return value;
|
||||
@ -414,6 +418,10 @@ export class SqlServerDriver implements Driver {
|
||||
|
||||
} else if (columnMetadata.type === "simple-json") {
|
||||
value = DateUtils.stringToSimpleJson(value);
|
||||
|
||||
} else if (columnMetadata.type === "simple-enum") {
|
||||
value = DateUtils.stringToSimpleEnum(value, columnMetadata);
|
||||
|
||||
}
|
||||
|
||||
if (columnMetadata.transformer)
|
||||
@ -447,6 +455,9 @@ export class SqlServerDriver implements Driver {
|
||||
} else if (column.type === "simple-array" || column.type === "simple-json") {
|
||||
return "ntext";
|
||||
|
||||
} else if (column.type === "simple-enum") {
|
||||
return "nvarchar";
|
||||
|
||||
} else if (column.type === "dec") {
|
||||
return "decimal";
|
||||
|
||||
|
||||
@ -1553,6 +1553,28 @@ export class SqlServerQueryRunner extends BaseQueryRunner implements QueryRunner
|
||||
tableColumn.scale = dbColumn["NUMERIC_SCALE"];
|
||||
}
|
||||
|
||||
if (tableColumn.type === "nvarchar") {
|
||||
// Check if this is an enum
|
||||
const columnCheckConstraints = columnConstraints.filter(constraint => constraint["CONSTRAINT_TYPE"] === "CHECK");
|
||||
if (columnCheckConstraints.length) {
|
||||
const isEnumRegexp = new RegExp("^\\(\\[" + tableColumn.name + "\\]='[^']+'(?: OR \\[" + tableColumn.name + "\\]='[^']+')*\\)$");
|
||||
for (const checkConstraint of columnCheckConstraints) {
|
||||
if (isEnumRegexp.test(checkConstraint["definition"])) {
|
||||
// This is an enum constraint, make column into an enum
|
||||
tableColumn.type = "simple-enum";
|
||||
tableColumn.enum = [];
|
||||
const enumValueRegexp = new RegExp("\\[" + tableColumn.name + "\\]='([^']+)'", "g");
|
||||
let result;
|
||||
while ((result = enumValueRegexp.exec(checkConstraint["definition"])) !== null) {
|
||||
tableColumn.enum.unshift(result[1]);
|
||||
}
|
||||
// Skip other column constraints
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tableColumn.default = dbColumn["COLUMN_DEFAULT"] !== null && dbColumn["COLUMN_DEFAULT"] !== undefined
|
||||
? this.removeParenthesisFromDefault(dbColumn["COLUMN_DEFAULT"])
|
||||
: undefined;
|
||||
@ -1895,6 +1917,10 @@ export class SqlServerQueryRunner extends BaseQueryRunner implements QueryRunner
|
||||
*/
|
||||
protected buildCreateColumnSql(table: Table, column: TableColumn, skipIdentity: boolean, createDefault: boolean) {
|
||||
let c = `"${column.name}" ${this.connection.driver.createFullType(column)}`;
|
||||
|
||||
if (column.enum)
|
||||
c += " CHECK( " + column.name + " IN (" + column.enum.map(val => "'" + val + "'").join(",") + ") )";
|
||||
|
||||
if (column.collation)
|
||||
c += " COLLATE " + column.collation;
|
||||
|
||||
|
||||
@ -81,6 +81,8 @@ export type SimpleColumnType =
|
||||
|
||||
|"simple-json" // typeorm-specific, automatically mapped to string
|
||||
|
||||
|"simple-enum" // typeorm-specific, automatically mapped to string
|
||||
|
||||
// numeric types
|
||||
|"bit" // mssql
|
||||
|"int2" // postgres, sqlite
|
||||
|
||||
@ -87,6 +87,9 @@ export class SubjectChangedColumnsComputer {
|
||||
} else if (column.type === "simple-array") {
|
||||
normalizedValue = DateUtils.simpleArrayToString(entityValue);
|
||||
databaseValue = DateUtils.simpleArrayToString(databaseValue);
|
||||
} else if (column.type === "simple-enum") {
|
||||
normalizedValue = DateUtils.simpleEnumToString(entityValue);
|
||||
databaseValue = DateUtils.simpleEnumToString(databaseValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { ColumnMetadata } from "../metadata/ColumnMetadata";
|
||||
|
||||
/**
|
||||
* Provides utilities to transform hydrated and persisted data.
|
||||
*/
|
||||
@ -171,6 +173,23 @@ export class DateUtils {
|
||||
return typeof value === "string" ? JSON.parse(value) : value;
|
||||
}
|
||||
|
||||
static simpleEnumToString(value: any) {
|
||||
return "" + value;
|
||||
}
|
||||
|
||||
static stringToSimpleEnum(value: any, columnMetadata: ColumnMetadata) {
|
||||
if (
|
||||
columnMetadata.enum
|
||||
&& !isNaN(value)
|
||||
&& columnMetadata.enum.indexOf(parseInt(value)) >= 0
|
||||
) {
|
||||
// convert to number if that exists in poosible enum options
|
||||
value = parseInt(value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Private Static Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@ -5,6 +5,7 @@ import {closeTestingConnections, createTestingConnections, reloadTestingDatabase
|
||||
import {PostWithOptions} from "./entity/PostWithOptions";
|
||||
import {PostWithoutTypes} from "./entity/PostWithoutTypes";
|
||||
import {DateUtils} from "../../../../../src/util/DateUtils";
|
||||
import {FruitEnum} from "./enum/FruitEnum";
|
||||
|
||||
describe("database schema > column types > mssql", () => { // https://github.com/tediousjs/tedious/issues/722
|
||||
|
||||
@ -66,6 +67,8 @@ describe("database schema > column types > mssql", () => { // https://github.com
|
||||
post.geometry3 = "GEOMETRYCOLLECTION (POINT (4 0), LINESTRING (4 2, 5 3), POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1)))";
|
||||
post.simpleArray = ["A", "B", "C"];
|
||||
post.simpleJson = { param: "VALUE" };
|
||||
post.simpleEnum = "A";
|
||||
post.simpleClassEnum1 = FruitEnum.Apple;
|
||||
await postRepository.save(post);
|
||||
|
||||
const loadedPost = (await postRepository.findOne(1))!;
|
||||
@ -112,6 +115,8 @@ describe("database schema > column types > mssql", () => { // https://github.com
|
||||
loadedPost.simpleArray[1].should.be.equal(post.simpleArray[1]);
|
||||
loadedPost.simpleArray[2].should.be.equal(post.simpleArray[2]);
|
||||
loadedPost.simpleJson.param.should.be.equal(post.simpleJson.param);
|
||||
loadedPost.simpleEnum.should.be.equal(post.simpleEnum);
|
||||
loadedPost.simpleClassEnum1.should.be.equal(post.simpleClassEnum1);
|
||||
|
||||
table!.findColumnByName("id")!.type.should.be.equal("int");
|
||||
table!.findColumnByName("name")!.type.should.be.equal("nvarchar");
|
||||
@ -150,6 +155,14 @@ describe("database schema > column types > mssql", () => { // https://github.com
|
||||
table!.findColumnByName("geometry1")!.type.should.be.equal("geometry");
|
||||
table!.findColumnByName("simpleArray")!.type.should.be.equal("ntext");
|
||||
table!.findColumnByName("simpleJson")!.type.should.be.equal("ntext");
|
||||
table!.findColumnByName("simpleEnum")!.type.should.be.equal("simple-enum");
|
||||
table!.findColumnByName("simpleEnum")!.enum![0].should.be.equal("A");
|
||||
table!.findColumnByName("simpleEnum")!.enum![1].should.be.equal("B");
|
||||
table!.findColumnByName("simpleEnum")!.enum![2].should.be.equal("C");
|
||||
table!.findColumnByName("simpleClassEnum1")!.type.should.be.equal("simple-enum");
|
||||
table!.findColumnByName("simpleClassEnum1")!.enum![0].should.be.equal("apple");
|
||||
table!.findColumnByName("simpleClassEnum1")!.enum![1].should.be.equal("pineapple");
|
||||
table!.findColumnByName("simpleClassEnum1")!.enum![2].should.be.equal("banana");
|
||||
|
||||
})));
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import {Entity} from "../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryColumn} from "../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {Column} from "../../../../../../src/decorator/columns/Column";
|
||||
import {FruitEnum} from "../enum/FruitEnum";
|
||||
|
||||
@Entity()
|
||||
export class Post {
|
||||
@ -138,4 +139,10 @@ export class Post {
|
||||
|
||||
@Column("simple-json")
|
||||
simpleJson: { param: string };
|
||||
|
||||
@Column("simple-enum", { enum: ["A", "B", "C"] })
|
||||
simpleEnum: string;
|
||||
|
||||
@Column("simple-enum", { enum: FruitEnum })
|
||||
simpleClassEnum1: FruitEnum;
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
export enum FruitEnum {
|
||||
Apple = "apple",
|
||||
Pineapple = "pineapple",
|
||||
Banana = "banana"
|
||||
}
|
||||
@ -80,6 +80,8 @@ describe("database schema > column types > mysql", () => {
|
||||
post.json = { id: 1, name: "Post" };
|
||||
post.simpleArray = ["A", "B", "C"];
|
||||
post.simpleJson = { param: "VALUE" };
|
||||
post.simpleEnum = "A";
|
||||
post.simpleClassEnum1 = FruitEnum.Apple;
|
||||
await postRepository.save(post);
|
||||
|
||||
const loadedPost = (await postRepository.findOne(1))!;
|
||||
@ -136,6 +138,8 @@ describe("database schema > column types > mysql", () => {
|
||||
loadedPost.simpleArray[1].should.be.equal(post.simpleArray[1]);
|
||||
loadedPost.simpleArray[2].should.be.equal(post.simpleArray[2]);
|
||||
loadedPost.simpleJson.param.should.be.equal(post.simpleJson.param);
|
||||
loadedPost.simpleEnum.should.be.equal(post.simpleEnum);
|
||||
loadedPost.simpleClassEnum1.should.be.equal(post.simpleClassEnum1);
|
||||
|
||||
table!.findColumnByName("id")!.type.should.be.equal("int");
|
||||
table!.findColumnByName("bit")!.type.should.be.equal("bit");
|
||||
@ -195,6 +199,14 @@ describe("database schema > column types > mysql", () => {
|
||||
table!.findColumnByName("json")!.type.should.be.equal("json");
|
||||
table!.findColumnByName("simpleArray")!.type.should.be.equal("text");
|
||||
table!.findColumnByName("simpleJson")!.type.should.be.equal("text");
|
||||
table!.findColumnByName("simpleEnum")!.type.should.be.equal("enum");
|
||||
table!.findColumnByName("simpleEnum")!.enum![0].should.be.equal("A");
|
||||
table!.findColumnByName("simpleEnum")!.enum![1].should.be.equal("B");
|
||||
table!.findColumnByName("simpleEnum")!.enum![2].should.be.equal("C");
|
||||
table!.findColumnByName("simpleClassEnum1")!.type.should.be.equal("enum");
|
||||
table!.findColumnByName("simpleClassEnum1")!.enum![0].should.be.equal("apple");
|
||||
table!.findColumnByName("simpleClassEnum1")!.enum![1].should.be.equal("pineapple");
|
||||
table!.findColumnByName("simpleClassEnum1")!.enum![2].should.be.equal("banana");
|
||||
|
||||
})));
|
||||
|
||||
|
||||
@ -192,4 +192,10 @@ export class Post {
|
||||
|
||||
@Column("simple-json")
|
||||
simpleJson: { param: string };
|
||||
|
||||
@Column("simple-enum", { enum: ["A", "B", "C"] })
|
||||
simpleEnum: string;
|
||||
|
||||
@Column("simple-enum", { enum: FruitEnum })
|
||||
simpleClassEnum1: FruitEnum;
|
||||
}
|
||||
|
||||
@ -11,6 +11,9 @@ export class Post {
|
||||
@Column("enum", { enum: ["A", "B", "C"] })
|
||||
enum: string;
|
||||
|
||||
@Column("simple-enum", { enum: ["A", "B", "C"] })
|
||||
simpleEnum: string;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
}
|
||||
@ -26,13 +26,16 @@ describe("database schema > column types > postgres-enum", () => {
|
||||
|
||||
const post = new Post();
|
||||
post.enum = "A";
|
||||
post.simpleEnum = "A";
|
||||
post.name = "Post #1";
|
||||
await postRepository.save(post);
|
||||
|
||||
const loadedPost = (await postRepository.findOne(1))!;
|
||||
loadedPost.enum.should.be.equal(post.enum);
|
||||
loadedPost.simpleEnum.should.be.equal(post.simpleEnum);
|
||||
|
||||
table!.findColumnByName("enum")!.type.should.be.equal("enum");
|
||||
table!.findColumnByName("simpleEnum")!.type.should.be.equal("enum");
|
||||
})));
|
||||
|
||||
it("should create ENUM column and revert creation", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
@ -89,6 +89,7 @@ describe("database schema > column types > postgres", () => {
|
||||
post.array = [1, 2, 3];
|
||||
post.simpleArray = ["A", "B", "C"];
|
||||
post.simpleJson = { param: "VALUE" };
|
||||
post.simpleEnum = "A";
|
||||
await postRepository.save(post);
|
||||
|
||||
const loadedPost = (await postRepository.findOne(1))!;
|
||||
@ -162,6 +163,7 @@ describe("database schema > column types > postgres", () => {
|
||||
loadedPost.simpleArray[1].should.be.equal(post.simpleArray[1]);
|
||||
loadedPost.simpleArray[2].should.be.equal(post.simpleArray[2]);
|
||||
loadedPost.simpleJson.param.should.be.equal(post.simpleJson.param);
|
||||
loadedPost.simpleEnum.should.be.equal(post.simpleEnum);
|
||||
|
||||
table!.findColumnByName("id")!.type.should.be.equal("integer");
|
||||
table!.findColumnByName("name")!.type.should.be.equal("character varying");
|
||||
@ -224,6 +226,7 @@ describe("database schema > column types > postgres", () => {
|
||||
table!.findColumnByName("array")!.isArray!.should.be.true;
|
||||
table!.findColumnByName("simpleArray")!.type.should.be.equal("text");
|
||||
table!.findColumnByName("simpleJson")!.type.should.be.equal("text");
|
||||
table!.findColumnByName("simpleEnum")!.type.should.be.equal("enum");
|
||||
|
||||
})));
|
||||
|
||||
|
||||
@ -251,4 +251,7 @@ export class Post {
|
||||
|
||||
@Column("simple-json")
|
||||
simpleJson: { param: string };
|
||||
|
||||
@Column("simple-enum", { enum: ["A", "B", "C"] })
|
||||
simpleEnum: string;
|
||||
}
|
||||
@ -3,6 +3,7 @@ import {Post} from "./entity/Post";
|
||||
import {Connection} from "../../../../../src/connection/Connection";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../../utils/test-utils";
|
||||
import {PostWithoutTypes} from "./entity/PostWithoutTypes";
|
||||
import {FruitEnum} from "./enum/FruitEnum";
|
||||
|
||||
describe("database schema > column types > sqlite", () => {
|
||||
|
||||
@ -56,6 +57,8 @@ describe("database schema > column types > sqlite", () => {
|
||||
post.datetime.setMilliseconds(0);
|
||||
post.simpleArray = ["A", "B", "C"];
|
||||
post.simpleJson = { param: "VALUE" };
|
||||
post.simpleEnum = "A";
|
||||
post.simpleClassEnum1 = FruitEnum.Apple;
|
||||
await postRepository.save(post);
|
||||
|
||||
const loadedPost = (await postRepository.findOne(1))!;
|
||||
@ -92,6 +95,8 @@ describe("database schema > column types > sqlite", () => {
|
||||
loadedPost.simpleArray[1].should.be.equal(post.simpleArray[1]);
|
||||
loadedPost.simpleArray[2].should.be.equal(post.simpleArray[2]);
|
||||
loadedPost.simpleJson.param.should.be.equal(post.simpleJson.param);
|
||||
loadedPost.simpleEnum.should.be.equal(post.simpleEnum);
|
||||
loadedPost.simpleClassEnum1.should.be.equal(post.simpleClassEnum1);
|
||||
|
||||
table!.findColumnByName("id")!.type.should.be.equal("integer");
|
||||
table!.findColumnByName("name")!.type.should.be.equal("varchar");
|
||||
@ -123,6 +128,14 @@ describe("database schema > column types > sqlite", () => {
|
||||
table!.findColumnByName("datetime")!.type.should.be.equal("datetime");
|
||||
table!.findColumnByName("simpleArray")!.type.should.be.equal("text");
|
||||
table!.findColumnByName("simpleJson")!.type.should.be.equal("text");
|
||||
table!.findColumnByName("simpleEnum")!.type.should.be.equal("simple-enum");
|
||||
table!.findColumnByName("simpleEnum")!.enum![0].should.be.equal("A");
|
||||
table!.findColumnByName("simpleEnum")!.enum![1].should.be.equal("B");
|
||||
table!.findColumnByName("simpleEnum")!.enum![2].should.be.equal("C");
|
||||
table!.findColumnByName("simpleClassEnum1")!.type.should.be.equal("simple-enum");
|
||||
table!.findColumnByName("simpleClassEnum1")!.enum![0].should.be.equal("apple");
|
||||
table!.findColumnByName("simpleClassEnum1")!.enum![1].should.be.equal("pineapple");
|
||||
table!.findColumnByName("simpleClassEnum1")!.enum![2].should.be.equal("banana");
|
||||
|
||||
})));
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import {Entity} from "../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryColumn} from "../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {Column} from "../../../../../../src/decorator/columns/Column";
|
||||
import {FruitEnum} from "../enum/FruitEnum";
|
||||
|
||||
@Entity()
|
||||
export class Post {
|
||||
@ -117,4 +118,10 @@ export class Post {
|
||||
|
||||
@Column("simple-json")
|
||||
simpleJson: { param: string };
|
||||
}
|
||||
|
||||
@Column("simple-enum", { enum: ["A", "B", "C"] })
|
||||
simpleEnum: string;
|
||||
|
||||
@Column("simple-enum", { enum: FruitEnum })
|
||||
simpleClassEnum1: FruitEnum;
|
||||
}
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
export enum FruitEnum {
|
||||
Apple = "apple",
|
||||
Pineapple = "pineapple",
|
||||
Banana = "banana"
|
||||
}
|
||||
@ -0,0 +1,105 @@
|
||||
import { Entity, Column, PrimaryColumn } from "../../../../../src";
|
||||
|
||||
|
||||
export enum NumericEnum {
|
||||
ADMIN,
|
||||
EDITOR,
|
||||
MODERATOR,
|
||||
GHOST
|
||||
}
|
||||
|
||||
export enum StringEnum {
|
||||
ADMIN = "a",
|
||||
EDITOR = "e",
|
||||
MODERATOR = "m",
|
||||
GHOST = "g"
|
||||
}
|
||||
|
||||
export enum StringNumericEnum {
|
||||
ONE = "1",
|
||||
TWO = "2",
|
||||
THREE = "3",
|
||||
FOUR = "4"
|
||||
}
|
||||
|
||||
export enum HeterogeneousEnum {
|
||||
NO = 0,
|
||||
YES = "YES",
|
||||
}
|
||||
|
||||
export type ArrayDefinedStringEnumType = "admin" | "editor" | "ghost";
|
||||
|
||||
export type ArrayDefinedNumericEnumType = 11 | 12 | 13;
|
||||
|
||||
|
||||
@Entity()
|
||||
export class EnumArrayEntity {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@Column({
|
||||
type: "simple-enum",
|
||||
enum: NumericEnum,
|
||||
array: true,
|
||||
default: [NumericEnum.GHOST, NumericEnum.ADMIN]
|
||||
})
|
||||
numericEnums: NumericEnum[];
|
||||
|
||||
@Column({
|
||||
type: "simple-enum",
|
||||
enum: StringEnum,
|
||||
array: true,
|
||||
default: []
|
||||
})
|
||||
stringEnums: StringEnum[];
|
||||
|
||||
@Column({
|
||||
type: "simple-enum",
|
||||
enum: StringNumericEnum,
|
||||
array: true,
|
||||
default: [StringNumericEnum.THREE, StringNumericEnum.ONE]
|
||||
})
|
||||
stringNumericEnums: StringNumericEnum[];
|
||||
|
||||
@Column({
|
||||
type: "simple-enum",
|
||||
enum: HeterogeneousEnum,
|
||||
array: true,
|
||||
default: [HeterogeneousEnum.YES]
|
||||
})
|
||||
heterogeneousEnums: HeterogeneousEnum[];
|
||||
|
||||
@Column({
|
||||
type: "simple-enum",
|
||||
enum: ["admin", "editor", "ghost"],
|
||||
array: true,
|
||||
default: ["admin"]
|
||||
})
|
||||
arrayDefinedStringEnums: ArrayDefinedStringEnumType[];
|
||||
|
||||
@Column({
|
||||
type: "simple-enum",
|
||||
enum: [11, 12, 13],
|
||||
array: true,
|
||||
default: [11, 13]
|
||||
})
|
||||
arrayDefinedNumericEnums: ArrayDefinedNumericEnumType[];
|
||||
|
||||
@Column({
|
||||
type: "simple-enum",
|
||||
enum: StringEnum,
|
||||
array: true,
|
||||
nullable: true
|
||||
})
|
||||
enumWithoutDefault: StringEnum[];
|
||||
|
||||
|
||||
@Column({
|
||||
type: "simple-enum",
|
||||
enum: StringEnum,
|
||||
array: true,
|
||||
default: "{}"
|
||||
})
|
||||
legacyDefaultAsString: StringEnum[];
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
import "reflect-metadata";
|
||||
import { Connection } from "../../../../src";
|
||||
import { closeTestingConnections, createTestingConnections, reloadTestingDatabases } from "../../../utils/test-utils";
|
||||
import { EnumArrayEntity, NumericEnum, StringEnum, HeterogeneousEnum, StringNumericEnum } from "./entity/EnumArrayEntity";
|
||||
|
||||
describe("database schema > simple enum arrays", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => {
|
||||
connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
enabledDrivers: ["postgres"]
|
||||
});
|
||||
});
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
it("should correctly create default values", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const enumEntityRepository = connection.getRepository(EnumArrayEntity);
|
||||
|
||||
const enumEntity = new EnumArrayEntity();
|
||||
enumEntity.id = 1;
|
||||
await enumEntityRepository.save(enumEntity);
|
||||
|
||||
const loadedEnumEntity = await enumEntityRepository.findOne(1);
|
||||
|
||||
loadedEnumEntity!.numericEnums.should.be.eql([NumericEnum.GHOST, NumericEnum.ADMIN]);
|
||||
loadedEnumEntity!.stringEnums.should.be.eql([]);
|
||||
loadedEnumEntity!.stringNumericEnums.should.be.eql([StringNumericEnum.THREE, StringNumericEnum.ONE]);
|
||||
loadedEnumEntity!.heterogeneousEnums.should.be.eql([HeterogeneousEnum.YES]);
|
||||
loadedEnumEntity!.arrayDefinedStringEnums.should.be.eql(["admin"]);
|
||||
loadedEnumEntity!.arrayDefinedNumericEnums.should.be.eql([11, 13]);
|
||||
|
||||
})));
|
||||
|
||||
it("should correctly save and retrieve", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const enumEntityRepository = connection.getRepository(EnumArrayEntity);
|
||||
|
||||
const enumEntity = new EnumArrayEntity();
|
||||
enumEntity.id = 1;
|
||||
enumEntity.numericEnums = [NumericEnum.GHOST, NumericEnum.EDITOR];
|
||||
enumEntity.stringEnums = [StringEnum.MODERATOR];
|
||||
enumEntity.stringNumericEnums = [StringNumericEnum.FOUR];
|
||||
enumEntity.heterogeneousEnums = [HeterogeneousEnum.NO];
|
||||
enumEntity.arrayDefinedStringEnums = ["editor"];
|
||||
enumEntity.arrayDefinedNumericEnums = [12, 13];
|
||||
await enumEntityRepository.save(enumEntity);
|
||||
|
||||
const loadedEnumEntity = await enumEntityRepository.findOne(1);
|
||||
|
||||
loadedEnumEntity!.numericEnums.should.be.eql([NumericEnum.GHOST, NumericEnum.EDITOR]);
|
||||
loadedEnumEntity!.stringEnums.should.be.eql([StringEnum.MODERATOR]);
|
||||
loadedEnumEntity!.stringNumericEnums.should.be.eql([StringNumericEnum.FOUR]);
|
||||
loadedEnumEntity!.heterogeneousEnums.should.be.eql([HeterogeneousEnum.NO]);
|
||||
loadedEnumEntity!.arrayDefinedStringEnums.should.be.eql(["editor"]);
|
||||
loadedEnumEntity!.arrayDefinedNumericEnums.should.be.eql([12, 13]);
|
||||
|
||||
})));
|
||||
|
||||
});
|
||||
@ -0,0 +1,89 @@
|
||||
import { Entity, Column, PrimaryColumn } from "../../../../../src";
|
||||
|
||||
|
||||
export enum NumericEnum {
|
||||
ADMIN,
|
||||
EDITOR,
|
||||
MODERATOR,
|
||||
GHOST
|
||||
}
|
||||
|
||||
export enum StringEnum {
|
||||
ADMIN = "a",
|
||||
EDITOR = "e",
|
||||
MODERATOR = "m",
|
||||
GHOST = "g"
|
||||
}
|
||||
|
||||
export enum StringNumericEnum {
|
||||
ONE = "1",
|
||||
TWO = "2",
|
||||
THREE = "3",
|
||||
FOUR = "4"
|
||||
}
|
||||
|
||||
export enum HeterogeneousEnum {
|
||||
NO = 0,
|
||||
YES = "YES",
|
||||
}
|
||||
|
||||
export type ArrayDefinedStringEnumType = "admin" | "editor" | "ghost";
|
||||
|
||||
export type ArrayDefinedNumericEnumType = 11 | 12 | 13;
|
||||
|
||||
|
||||
@Entity()
|
||||
export class SimpleEnumEntity {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@Column({
|
||||
type: "simple-enum",
|
||||
enum: NumericEnum,
|
||||
default: NumericEnum.MODERATOR
|
||||
})
|
||||
numericEnum: NumericEnum;
|
||||
|
||||
@Column({
|
||||
type: "simple-enum",
|
||||
enum: StringEnum,
|
||||
default: StringEnum.GHOST
|
||||
})
|
||||
stringEnum: StringEnum;
|
||||
|
||||
@Column({
|
||||
type: "simple-enum",
|
||||
enum: StringNumericEnum,
|
||||
default: StringNumericEnum.FOUR
|
||||
})
|
||||
stringNumericEnum: StringNumericEnum;
|
||||
|
||||
@Column({
|
||||
type: "simple-enum",
|
||||
enum: HeterogeneousEnum,
|
||||
default: HeterogeneousEnum.NO
|
||||
})
|
||||
heterogeneousEnum: HeterogeneousEnum;
|
||||
|
||||
@Column({
|
||||
type: "simple-enum",
|
||||
enum: ["admin", "editor", "ghost"],
|
||||
default: "ghost"
|
||||
})
|
||||
arrayDefinedStringEnum: ArrayDefinedStringEnumType;
|
||||
|
||||
@Column({
|
||||
type: "simple-enum",
|
||||
enum: [11, 12, 13],
|
||||
default: 12
|
||||
})
|
||||
arrayDefinedNumericEnum: ArrayDefinedNumericEnumType;
|
||||
|
||||
@Column({
|
||||
type: "simple-enum",
|
||||
enum: StringEnum,
|
||||
})
|
||||
enumWithoutdefault: StringEnum;
|
||||
|
||||
}
|
||||
63
test/functional/database-schema/simple-enums/enums.ts
Normal file
63
test/functional/database-schema/simple-enums/enums.ts
Normal file
@ -0,0 +1,63 @@
|
||||
import "reflect-metadata";
|
||||
import { Connection } from "../../../../src";
|
||||
import { closeTestingConnections, createTestingConnections, reloadTestingDatabases } from "../../../utils/test-utils";
|
||||
import { SimpleEnumEntity, NumericEnum, StringEnum, HeterogeneousEnum, StringNumericEnum } from "./entity/SimpleEnumEntity";
|
||||
|
||||
describe("database schema > simple-enums", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => {
|
||||
connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
enabledDrivers: ["mysql", "mariadb", "postgres", "sqlite", "mssql"]
|
||||
});
|
||||
});
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
it("should correctly use default values", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const enumEntityRepository = connection.getRepository(SimpleEnumEntity);
|
||||
|
||||
const enumEntity = new SimpleEnumEntity();
|
||||
enumEntity.id = 1;
|
||||
enumEntity.enumWithoutdefault = StringEnum.EDITOR;
|
||||
await enumEntityRepository.save(enumEntity);
|
||||
|
||||
const loadedEnumEntity = await enumEntityRepository.findOne(1);
|
||||
loadedEnumEntity!.numericEnum.should.be.eq(NumericEnum.MODERATOR);
|
||||
loadedEnumEntity!.stringEnum.should.be.eq(StringEnum.GHOST);
|
||||
loadedEnumEntity!.stringNumericEnum.should.be.eq(StringNumericEnum.FOUR);
|
||||
loadedEnumEntity!.heterogeneousEnum.should.be.eq(HeterogeneousEnum.NO);
|
||||
loadedEnumEntity!.arrayDefinedStringEnum.should.be.eq("ghost");
|
||||
loadedEnumEntity!.arrayDefinedNumericEnum.should.be.eq(12);
|
||||
|
||||
})));
|
||||
|
||||
|
||||
it("should correctly save and retrieve", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const enumEntityRepository = connection.getRepository(SimpleEnumEntity);
|
||||
|
||||
const enumEntity = new SimpleEnumEntity();
|
||||
enumEntity.id = 1;
|
||||
enumEntity.numericEnum = NumericEnum.EDITOR;
|
||||
enumEntity.stringEnum = StringEnum.ADMIN;
|
||||
enumEntity.stringNumericEnum = StringNumericEnum.TWO;
|
||||
enumEntity.heterogeneousEnum = HeterogeneousEnum.YES;
|
||||
enumEntity.arrayDefinedStringEnum = "editor";
|
||||
enumEntity.arrayDefinedNumericEnum = 13;
|
||||
enumEntity.enumWithoutdefault = StringEnum.ADMIN;
|
||||
await enumEntityRepository.save(enumEntity);
|
||||
|
||||
const loadedEnumEntity = await enumEntityRepository.findOne(1);
|
||||
loadedEnumEntity!.numericEnum.should.be.eq(NumericEnum.EDITOR);
|
||||
loadedEnumEntity!.stringEnum.should.be.eq(StringEnum.ADMIN);
|
||||
loadedEnumEntity!.stringNumericEnum.should.be.eq(StringNumericEnum.TWO);
|
||||
loadedEnumEntity!.heterogeneousEnum.should.be.eq(HeterogeneousEnum.YES);
|
||||
loadedEnumEntity!.arrayDefinedStringEnum.should.be.eq("editor");
|
||||
loadedEnumEntity!.arrayDefinedNumericEnum.should.be.eq(13);
|
||||
|
||||
})));
|
||||
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user