mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
refactored columns decorators
This commit is contained in:
parent
2f5a79a1a6
commit
da8963c5e4
70
docs/tables-and-columns.md
Normal file
70
docs/tables-and-columns.md
Normal file
@ -0,0 +1,70 @@
|
||||
## Tables and columns
|
||||
|
||||
### Creating a basic table
|
||||
|
||||
Every object that you want to be saved in the database must have `@Table`
|
||||
decorator and each property you want to be saved from your object must
|
||||
have `@Column` decorator. Let's start with an example:
|
||||
|
||||
```typescript
|
||||
@Table("photo")
|
||||
class Photo {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@Column()
|
||||
filename: string;
|
||||
|
||||
@Column()
|
||||
description: string;
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
* `@Table` decorator registers your class in ORM, and allows you to make
|
||||
different operations with instances of this class directly in the db.
|
||||
After you mark your class with this decorator and run schema update
|
||||
process, ORM will create a table in the db for you, with all proper
|
||||
columns, keys and so on. After you define your class as a @Table you
|
||||
can do various operations like inserting, updating, removing, fining
|
||||
objects of this class in the database. In this example we also specified
|
||||
a name for this table (`@Table("photo")`). ORM will create a table in
|
||||
the database with such name - "photos".
|
||||
|
||||
* `@Column` decorator marks properties of your class to be persisted into
|
||||
the database. For each property of your class decorated by `@Table`
|
||||
decorator ORM will create a column in the table, and this property's
|
||||
value will be saved to database when you'll save a class instance.
|
||||
|
||||
* `@PrimaryColumn` decorator marks a property of your class that must
|
||||
be a primary-key in your table. It works the same way as @Column decorator,
|
||||
but the main difference is that it also creates a PRIMARY KEY for this
|
||||
column. This decorator is always used when you want to create an id-based
|
||||
column, including auto-increment id.
|
||||
|
||||
### Primary and regular columns
|
||||
|
||||
By default column type used in the database is automatically guessed
|
||||
from property type. But type that is set for property is not desirable
|
||||
for the type used in the database. For example type `number
|
||||
You can specify a type of column that will be used `@Column`
|
||||
|
||||
```typescript
|
||||
@Table("photo")
|
||||
class Photo {
|
||||
|
||||
@Column("string")
|
||||
name: string;
|
||||
|
||||
@Column()
|
||||
filename: string;
|
||||
|
||||
@Column()
|
||||
description: string;
|
||||
|
||||
}
|
||||
```
|
||||
@ -1,72 +1,2 @@
|
||||
import "reflect-metadata";
|
||||
import {defaultMetadataStorage} from "../metadata-builder/MetadataStorage";
|
||||
import {ColumnMetadata} from "../metadata-builder/metadata/ColumnMetadata";
|
||||
import {ColumnOptions} from "../metadata-builder/options/ColumnOptions";
|
||||
|
||||
/**
|
||||
* Column decorator is used to mark a specific class property as a table column. Only table columns will be
|
||||
* persisted to the database when document is being saved.
|
||||
*/
|
||||
export function Column(options?: ColumnOptions): Function;
|
||||
export function Column(type?: string, options?: ColumnOptions): Function;
|
||||
export function Column(typeOrOptions?: string|ColumnOptions, options?: ColumnOptions): Function {
|
||||
let type: string;
|
||||
if (typeof typeOrOptions === "string") {
|
||||
type = <string> typeOrOptions;
|
||||
} else {
|
||||
options = <ColumnOptions> typeOrOptions;
|
||||
}
|
||||
return function (object: Object, propertyName: string) {
|
||||
|
||||
if (!type)
|
||||
type = Reflect.getMetadata("design:type", object, propertyName);
|
||||
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
if (!options.type)
|
||||
options.type = type;
|
||||
|
||||
if (options.autoIncrement)
|
||||
throw new Error(`Column for property ${propertyName} in ${(<any>object.constructor).name} cannot have auto increment. To have this ability you need to use @PrimaryColumn decorator.`);
|
||||
|
||||
// todo: need proper type validation here
|
||||
|
||||
const metadata = new ColumnMetadata(object.constructor, propertyName, false, false, false, false, options);
|
||||
defaultMetadataStorage.addColumnMetadata(metadata);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Column decorator is used to mark a specific class property as a table column. Only table columns will be
|
||||
* persisted to the database when document is being saved.
|
||||
*/
|
||||
export function PrimaryColumn(options?: ColumnOptions): Function;
|
||||
export function PrimaryColumn(type?: string, options?: ColumnOptions): Function;
|
||||
export function PrimaryColumn(typeOrOptions?: string|ColumnOptions, options?: ColumnOptions): Function {
|
||||
let type: string;
|
||||
if (typeof typeOrOptions === "string") {
|
||||
type = <string> typeOrOptions;
|
||||
} else {
|
||||
options = <ColumnOptions> typeOrOptions;
|
||||
}
|
||||
return function (object: Object, propertyName: string) {
|
||||
|
||||
if (!type)
|
||||
type = Reflect.getMetadata("design:type", object, propertyName);
|
||||
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
if (!options.type)
|
||||
options.type = type;
|
||||
|
||||
if (options.nullable)
|
||||
throw new Error(`Primary column for property ${propertyName} in ${(<any>object.constructor).name} cannot be nullable. Its not allowed for primary keys. Please remove isNullable option.`);
|
||||
|
||||
// todo: need proper type validation here
|
||||
|
||||
const metadata = new ColumnMetadata(object.constructor, propertyName, true, false, false, false, options);
|
||||
defaultMetadataStorage.addColumnMetadata(metadata);
|
||||
};
|
||||
}
|
||||
export * from "./columns/Column";
|
||||
export * from "./columns/PrimaryColumn";
|
||||
50
src/decorator/columns/Column.ts
Normal file
50
src/decorator/columns/Column.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import "reflect-metadata";
|
||||
import {ColumnOptions, ColumnTypeString, ColumnTypes} from "../../metadata-builder/options/ColumnOptions";
|
||||
import {ColumnTypeUndefinedError} from "../error/ColumnTypeUndefinedError";
|
||||
import {AutoIncrementOnlyForPrimaryError} from "../error/AutoIncrementOnlyForPrimaryError";
|
||||
import {defaultMetadataStorage} from "../../metadata-builder/MetadataStorage";
|
||||
import {ColumnMetadata} from "../../metadata-builder/metadata/ColumnMetadata";
|
||||
|
||||
/**
|
||||
* 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(options?: ColumnOptions): Function;
|
||||
export function Column(type?: ColumnTypeString, options?: ColumnOptions): Function;
|
||||
export function Column(typeOrOptions?: ColumnTypeString|ColumnOptions, options?: ColumnOptions): Function {
|
||||
let type: ColumnTypeString;
|
||||
if (typeof typeOrOptions === "string") {
|
||||
type = <ColumnTypeString> typeOrOptions;
|
||||
} else {
|
||||
options = <ColumnOptions> typeOrOptions;
|
||||
}
|
||||
return function (object: Object, propertyName: string) {
|
||||
|
||||
// if type is not given implicitly then try to guess it
|
||||
if (!type)
|
||||
type = ColumnTypes.determineTypeFromFunction(Reflect.getMetadata("design:type", object, propertyName));
|
||||
|
||||
// if column options are not given then create a new empty options
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
// check if there is no type in column options then set type from first function argument, or guessed one
|
||||
if (!options.type)
|
||||
options.type = type;
|
||||
|
||||
// if we still don't have a type then we need to give error to user that type is required
|
||||
if (!options.type)
|
||||
throw new ColumnTypeUndefinedError(object, propertyName);
|
||||
|
||||
// check if auto increment is not set for simple column
|
||||
if (options.autoIncrement)
|
||||
throw new AutoIncrementOnlyForPrimaryError(object, propertyName);
|
||||
|
||||
// create and register a new column metadata
|
||||
defaultMetadataStorage.addColumnMetadata(new ColumnMetadata({
|
||||
target: object.constructor,
|
||||
propertyName: propertyName,
|
||||
options: options
|
||||
}));
|
||||
};
|
||||
}
|
||||
53
src/decorator/columns/PrimaryColumn.ts
Normal file
53
src/decorator/columns/PrimaryColumn.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import "reflect-metadata";
|
||||
import {ColumnOptions, ColumnTypeString, ColumnTypes} from "../../metadata-builder/options/ColumnOptions";
|
||||
import {ColumnTypeUndefinedError} from "../error/ColumnTypeUndefinedError";
|
||||
import {defaultMetadataStorage} from "../../metadata-builder/MetadataStorage";
|
||||
import {ColumnMetadata} from "../../metadata-builder/metadata/ColumnMetadata";
|
||||
import {PrimaryColumnCannotBeNullableError} from "../error/PrimaryColumnCannotBeNullableError";
|
||||
|
||||
/**
|
||||
* 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. Primary columns also creates a PRIMARY KEY for
|
||||
* this column in a db.
|
||||
*/
|
||||
export function PrimaryColumn(options?: ColumnOptions): Function;
|
||||
export function PrimaryColumn(type?: ColumnTypeString, options?: ColumnOptions): Function;
|
||||
export function PrimaryColumn(typeOrOptions?: ColumnTypeString|ColumnOptions, options?: ColumnOptions): Function {
|
||||
let type: ColumnTypeString;
|
||||
if (typeof typeOrOptions === "string") {
|
||||
type = <ColumnTypeString> typeOrOptions;
|
||||
} else {
|
||||
options = <ColumnOptions> typeOrOptions;
|
||||
}
|
||||
return function (object: Object, propertyName: string) {
|
||||
|
||||
// if type is not given implicitly then try to guess it
|
||||
if (!type)
|
||||
type = ColumnTypes.determineTypeFromFunction(Reflect.getMetadata("design:type", object, propertyName));
|
||||
|
||||
// if column options are not given then create a new empty options
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
// check if there is no type in column options then set type from first function argument, or guessed one
|
||||
if (!options.type)
|
||||
options.type = type;
|
||||
|
||||
// if we still don't have a type then we need to give error to user that type is required
|
||||
if (!options.type)
|
||||
throw new ColumnTypeUndefinedError(object, propertyName);
|
||||
|
||||
// check if column is not nullable, because we cannot allow a primary key to be nullable
|
||||
if (options.nullable)
|
||||
throw new PrimaryColumnCannotBeNullableError(object, propertyName);
|
||||
|
||||
// create and register a new column metadata
|
||||
defaultMetadataStorage.addColumnMetadata(new ColumnMetadata({
|
||||
target: object.constructor,
|
||||
propertyName: propertyName,
|
||||
isPrimaryKey: true,
|
||||
options: options
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
10
src/decorator/error/AutoIncrementOnlyForPrimaryError.ts
Normal file
10
src/decorator/error/AutoIncrementOnlyForPrimaryError.ts
Normal file
@ -0,0 +1,10 @@
|
||||
export class AutoIncrementOnlyForPrimaryError extends Error {
|
||||
name = "AutoIncrementOnlyForPrimaryError";
|
||||
|
||||
constructor(object: Object, propertyName: string) {
|
||||
super();
|
||||
this.message = `Column for property ${(<any>object.constructor).name}#${propertyName} cannot have an auto ` +
|
||||
`increment because its not a primary column. Try to use @PrimaryColumn decorator.`;
|
||||
}
|
||||
|
||||
}
|
||||
10
src/decorator/error/ColumnTypeUndefinedError.ts
Normal file
10
src/decorator/error/ColumnTypeUndefinedError.ts
Normal file
@ -0,0 +1,10 @@
|
||||
export class ColumnTypeUndefinedError extends Error {
|
||||
name = "ColumnTypeUndefinedError";
|
||||
|
||||
constructor(object: Object, propertyName: string) {
|
||||
super();
|
||||
this.message = `Column type for ${(<any>object.constructor).name}#${propertyName} is not defined or cannot be guessed. ` +
|
||||
`Try to implicitly provide a column type to @Column decorator.`;
|
||||
}
|
||||
|
||||
}
|
||||
10
src/decorator/error/PrimaryColumnCannotBeNullableError.ts
Normal file
10
src/decorator/error/PrimaryColumnCannotBeNullableError.ts
Normal file
@ -0,0 +1,10 @@
|
||||
export class PrimaryColumnCannotBeNullableError extends Error {
|
||||
name = "PrimaryColumnCannotBeNullableError";
|
||||
|
||||
constructor(object: Object, propertyName: string) {
|
||||
super();
|
||||
this.message = `Primary column ${(<any>object.constructor).name}#${propertyName} cannot be nullable. ` +
|
||||
`Its not allowed for primary keys. Try to remove nullable option.`;
|
||||
}
|
||||
|
||||
}
|
||||
@ -108,7 +108,12 @@ export class EntityMetadataBuilder {
|
||||
oldColumnName: relation.oldColumnName,
|
||||
nullable: relation.isNullable
|
||||
};
|
||||
relationalColumn = new ColumnMetadata(metadata.target, relation.name, false, false, false, true, options);
|
||||
relationalColumn = new ColumnMetadata({
|
||||
target: metadata.target,
|
||||
propertyName: relation.name,
|
||||
isVirtual: true,
|
||||
options: options
|
||||
});
|
||||
metadata.columns.push(relationalColumn);
|
||||
}
|
||||
|
||||
@ -145,8 +150,16 @@ export class EntityMetadataBuilder {
|
||||
name: inverseSideMetadata.table.name + "_" + inverseSideMetadata.primaryColumn.name
|
||||
};
|
||||
const columns = [
|
||||
new ColumnMetadata(null, null, false, false, false, false, column1options),
|
||||
new ColumnMetadata(null, null, false, false, false, false, column2options)
|
||||
new ColumnMetadata({
|
||||
target: null,
|
||||
propertyName: null,
|
||||
options: column1options
|
||||
}),
|
||||
new ColumnMetadata({
|
||||
target: null,
|
||||
propertyName: null,
|
||||
options: column2options
|
||||
})
|
||||
];
|
||||
const foreignKeys = [
|
||||
new ForeignKeyMetadata(tableMetadata, [columns[0]], metadata.table, [metadata.primaryColumn]),
|
||||
|
||||
@ -1,9 +1,22 @@
|
||||
import {PropertyMetadata} from "./PropertyMetadata";
|
||||
import {ColumnOptions} from "../options/ColumnOptions";
|
||||
import {ColumnOptions, ColumnTypeString} from "../options/ColumnOptions";
|
||||
import {NamingStrategy} from "../../naming-strategy/NamingStrategy";
|
||||
|
||||
/**
|
||||
* This metadata interface contains all information about some document's column.
|
||||
* Constructor arguments for ColumnMetadata class.
|
||||
*/
|
||||
export interface ColumnMetadataArgs {
|
||||
target: Function;
|
||||
propertyName: string;
|
||||
isPrimaryKey?: boolean;
|
||||
isCreateDate?: boolean;
|
||||
isUpdateDate?: boolean;
|
||||
isVirtual?: boolean;
|
||||
options: ColumnOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* This metadata contains all information about class's column.
|
||||
*/
|
||||
export class ColumnMetadata extends PropertyMetadata {
|
||||
|
||||
@ -11,6 +24,9 @@ export class ColumnMetadata extends PropertyMetadata {
|
||||
// Public Properties
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Naming strategy to be used to generate column name.
|
||||
*/
|
||||
namingStrategy: NamingStrategy;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
@ -25,112 +41,132 @@ export class ColumnMetadata extends PropertyMetadata {
|
||||
/**
|
||||
* The type of the column.
|
||||
*/
|
||||
private _type: string = "";
|
||||
private _type: ColumnTypeString;
|
||||
|
||||
/**
|
||||
* Maximum length in the database.
|
||||
*/
|
||||
private _length: string = "";
|
||||
private _length = "";
|
||||
|
||||
/**
|
||||
* Indicates if this column is primary key.
|
||||
*/
|
||||
private _isPrimary: boolean = false;
|
||||
private _isPrimary = false;
|
||||
|
||||
/**
|
||||
* Indicates if this column is auto increment.
|
||||
*/
|
||||
private _isAutoIncrement: boolean = false;
|
||||
private _isAutoIncrement = false;
|
||||
|
||||
/**
|
||||
* Indicates if value should be unqiue or not.
|
||||
* Indicates if value should be unique or not.
|
||||
*/
|
||||
private _isUnique: boolean = false;
|
||||
private _isUnique = false;
|
||||
|
||||
/**
|
||||
* Indicates if can contain nulls or not.
|
||||
*/
|
||||
private _isNullable: boolean = false;
|
||||
private _isNullable = false;
|
||||
|
||||
/**
|
||||
* Indicates if column will contain a created date or not.
|
||||
*/
|
||||
private _isCreateDate: boolean = false;
|
||||
private _isCreateDate = false;
|
||||
|
||||
/**
|
||||
* Indicates if column will contain an updated date or not.
|
||||
*/
|
||||
private _isUpdateDate: boolean = false;
|
||||
private _isUpdateDate = false;
|
||||
|
||||
/**
|
||||
* Indicates if column will contain an updated date or not.
|
||||
*/
|
||||
private _isVirtual: boolean = false;
|
||||
private _isVirtual = false;
|
||||
|
||||
/**
|
||||
* Extra sql definition for the given column.
|
||||
*/
|
||||
private _columnDefinition: string = "";
|
||||
private _columnDefinition = "";
|
||||
|
||||
/**
|
||||
* Column comment.
|
||||
*/
|
||||
private _comment: string = "";
|
||||
private _comment = "";
|
||||
|
||||
/**
|
||||
* Old column name. Used to correctly alter tables when column name is changed.
|
||||
*/
|
||||
private _oldColumnName: string;
|
||||
|
||||
/**
|
||||
* The precision for a decimal (exact numeric) column (applies only for decimal column), which is the maximum
|
||||
* number of digits that are stored for the values.
|
||||
*/
|
||||
private _precision: number;
|
||||
|
||||
/**
|
||||
* The scale for a decimal (exact numeric) column (applies only for decimal column), which represents the number
|
||||
* of digits to the right of the decimal point and must not be greater than precision.
|
||||
*/
|
||||
private _scale: number;
|
||||
|
||||
/**
|
||||
* Column collation. Note that not all databases support it.
|
||||
*/
|
||||
private _collation: string;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Constructor
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
constructor(target: Function,
|
||||
propertyName: string,
|
||||
isPrimaryKey: boolean,
|
||||
isCreateDate: boolean,
|
||||
isUpdateDate: boolean,
|
||||
isVirtual: boolean,
|
||||
options: ColumnOptions) {
|
||||
super(target, propertyName);
|
||||
constructor(args: ColumnMetadataArgs) {
|
||||
super(args.target, args.propertyName);
|
||||
|
||||
if (isPrimaryKey)
|
||||
this._isPrimary = isPrimaryKey;
|
||||
if (isCreateDate)
|
||||
this._isCreateDate = isCreateDate;
|
||||
if (isUpdateDate)
|
||||
this._isUpdateDate = isUpdateDate;
|
||||
if (isVirtual)
|
||||
this._isVirtual = isVirtual;
|
||||
if (options.name)
|
||||
this._name = options.name;
|
||||
if (options.type)
|
||||
this._type = this.convertType(options.type);
|
||||
if (args.isPrimaryKey)
|
||||
this._isPrimary = args.isPrimaryKey;
|
||||
if (args.isCreateDate)
|
||||
this._isCreateDate = args.isCreateDate;
|
||||
if (args.isUpdateDate)
|
||||
this._isUpdateDate = args.isUpdateDate;
|
||||
if (args.isVirtual)
|
||||
this._isVirtual = args.isVirtual;
|
||||
if (args.options.name)
|
||||
this._name = args.options.name;
|
||||
if (args.options.type)
|
||||
this._type = args.options.type;
|
||||
|
||||
if (options.length)
|
||||
this._length = options.length;
|
||||
if (options.autoIncrement)
|
||||
this._isAutoIncrement = options.autoIncrement;
|
||||
if (options.unique)
|
||||
this._isUnique = options.unique;
|
||||
if (options.nullable)
|
||||
this._isNullable = options.nullable;
|
||||
if (options.columnDefinition)
|
||||
this._columnDefinition = options.columnDefinition;
|
||||
if (options.comment)
|
||||
this._comment = options.comment;
|
||||
if (options.oldColumnName)
|
||||
this._oldColumnName = options.oldColumnName;
|
||||
if (args.options.length)
|
||||
this._length = args.options.length;
|
||||
if (args.options.autoIncrement)
|
||||
this._isAutoIncrement = args.options.autoIncrement;
|
||||
if (args.options.unique)
|
||||
this._isUnique = args.options.unique;
|
||||
if (args.options.nullable)
|
||||
this._isNullable = args.options.nullable;
|
||||
if (args.options.columnDefinition)
|
||||
this._columnDefinition = args.options.columnDefinition;
|
||||
if (args.options.comment)
|
||||
this._comment = args.options.comment;
|
||||
if (args.options.oldColumnName)
|
||||
this._oldColumnName = args.options.oldColumnName;
|
||||
if (args.options.scale)
|
||||
this._scale = args.options.scale;
|
||||
if (args.options.precision)
|
||||
this._precision = args.options.precision;
|
||||
if (args.options.collation)
|
||||
this._collation = args.options.collation;
|
||||
|
||||
if (!this._name)
|
||||
this._name = propertyName;
|
||||
this._name = args.propertyName;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Accessors
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Column name in the database.
|
||||
*/
|
||||
get name(): string {
|
||||
return this.namingStrategy ? this.namingStrategy.columnName(this._name) : this._name;
|
||||
}
|
||||
@ -138,70 +174,111 @@ export class ColumnMetadata extends PropertyMetadata {
|
||||
/**
|
||||
* Type of the column.
|
||||
*/
|
||||
get type(): string {
|
||||
get type(): ColumnTypeString {
|
||||
return this._type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Column type's length. For example type = "string" and length = 100 means that ORM will create a column with
|
||||
* type varchar(100).
|
||||
*/
|
||||
get length(): string {
|
||||
return this._length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this column is a primary key.
|
||||
*/
|
||||
get isPrimary(): boolean {
|
||||
return this._isPrimary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this column's value is auto incremented.
|
||||
*/
|
||||
get isAutoIncrement(): boolean {
|
||||
return this._isAutoIncrement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this column has unique key.
|
||||
*/
|
||||
get isUnique(): boolean {
|
||||
return this._isUnique;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this column can have a NULL value.
|
||||
*/
|
||||
get isNullable(): boolean {
|
||||
return this._isNullable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this column is special and contains object create date.
|
||||
*/
|
||||
get isCreateDate(): boolean {
|
||||
return this._isCreateDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this column is special and contains object last update date.
|
||||
*/
|
||||
get isUpdateDate(): boolean {
|
||||
return this._isUpdateDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this column is virtual. Virtual column mean that it does not really exist in class. Virtual columns
|
||||
* are used for many-to-many tables.
|
||||
*/
|
||||
get isVirtual(): boolean {
|
||||
return this._isVirtual;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra column definition value.
|
||||
*/
|
||||
get columnDefinition(): string {
|
||||
return this._columnDefinition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra column's comment.
|
||||
*/
|
||||
get comment(): string {
|
||||
return this._comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Column name used previously for this column. Used to make safe schema updates. Experimental and most probably
|
||||
* will be removed in the future. Avoid using it.
|
||||
*/
|
||||
get oldColumnName(): string {
|
||||
return this._oldColumnName;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Private Methods
|
||||
// ---------------------------------------------------------------------
|
||||
/**
|
||||
* The precision for a decimal (exact numeric) column (applies only for decimal column), which is the maximum
|
||||
* number of digits that are stored for the values.
|
||||
*/
|
||||
get precision(): number {
|
||||
return this._precision;
|
||||
}
|
||||
|
||||
private convertType(type: Function|string): string {
|
||||
// todo: throw exception if no type in type function
|
||||
if (type instanceof Function) {
|
||||
let typeName = (<any>type).name.toLowerCase();
|
||||
switch (typeName) {
|
||||
case "number":
|
||||
case "boolean":
|
||||
case "string":
|
||||
return typeName;
|
||||
}
|
||||
}
|
||||
return <string> type;
|
||||
/**
|
||||
* The scale for a decimal (exact numeric) column (applies only for decimal column), which represents the number
|
||||
* of digits to the right of the decimal point and must not be greater than precision.
|
||||
*/
|
||||
get scale(): number {
|
||||
return this._scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Column collation. Note that not all databases support it.
|
||||
*/
|
||||
get collation(): string {
|
||||
return this._collation;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,11 +1,220 @@
|
||||
/**
|
||||
* Describes all column's options.
|
||||
*/
|
||||
export interface ColumnOptions {
|
||||
|
||||
/**
|
||||
* Column name.
|
||||
*/
|
||||
name?: string;
|
||||
type?: string;
|
||||
|
||||
/**
|
||||
* Column type. Must be one of the value from the ColumnTypes class.
|
||||
*/
|
||||
type?: ColumnTypeString;
|
||||
|
||||
/**
|
||||
* Column type's length. For example type = "string" and length = 100 means that ORM will create a column with
|
||||
* type varchar(100).
|
||||
*/
|
||||
length?: string;
|
||||
|
||||
/**
|
||||
* Specifies if this column will use AUTO_INCREMENT or not (e.g. generated number).
|
||||
*/
|
||||
autoIncrement?: boolean;
|
||||
|
||||
/**
|
||||
* Specifies if column's value must be unqiue or not.
|
||||
*/
|
||||
unique?: boolean;
|
||||
|
||||
/**
|
||||
* Indicates if column must be nullable or not.
|
||||
*/
|
||||
nullable?: boolean;
|
||||
|
||||
/**
|
||||
* Extra column definition. Should be used only in emergency situations. Note that if you'll use this property
|
||||
* auto schema generation will not work properly anymore.
|
||||
*/
|
||||
columnDefinition?: string;
|
||||
|
||||
/**
|
||||
* Column comment.
|
||||
*/
|
||||
comment?: string;
|
||||
|
||||
/**
|
||||
* Column name used previously for this column. Used to make safe schema updates. Experimental and most probably
|
||||
* will be removed in the future. Avoid using it.
|
||||
*/
|
||||
oldColumnName?: string;
|
||||
|
||||
/**
|
||||
* The precision for a decimal (exact numeric) column (applies only for decimal column), which is the maximum
|
||||
* number of digits that are stored for the values.
|
||||
*/
|
||||
precision?: number;
|
||||
|
||||
/**
|
||||
* The scale for a decimal (exact numeric) column (applies only for decimal column), which represents the number
|
||||
* of digits to the right of the decimal point and must not be greater than precision.
|
||||
*/
|
||||
scale?: number;
|
||||
|
||||
/**
|
||||
* Column collation. Note that not all databases support it.
|
||||
*/
|
||||
collation?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* All types that column can be.
|
||||
*/
|
||||
export type ColumnTypeString = "string"|"text"|"number"|"integer"|"int"|"smallint"|"bigint"|"float"|"double"|
|
||||
"decimal"|"date"|"time"|"datetime"|"boolean"|"json"|"simple_array";
|
||||
|
||||
/**
|
||||
* All types that column can be.
|
||||
*/
|
||||
export class ColumnTypes {
|
||||
|
||||
/**
|
||||
* SQL VARCHAR type. Your class's property type should be a "string".
|
||||
*/
|
||||
static STRING = "string";
|
||||
|
||||
/**
|
||||
* SQL CLOB type. Your class's property type should be a "string".
|
||||
*/
|
||||
static TEXT = "text";
|
||||
|
||||
/**
|
||||
* SQL FLOAT type. Your class's property type should be a "number".
|
||||
*/
|
||||
static NUMBER = "number";
|
||||
|
||||
/**
|
||||
* SQL INT type. Your class's property type should be a "number".
|
||||
*/
|
||||
static INTEGER = "integer";
|
||||
|
||||
/**
|
||||
* SQL INT type. Your class's property type should be a "number".
|
||||
*/
|
||||
static INT = "int";
|
||||
|
||||
/**
|
||||
* SQL SMALLINT type. Your class's property type should be a "number".
|
||||
*/
|
||||
static SMALLINT = "smallint";
|
||||
|
||||
/**
|
||||
* SQL BIGINT type. Your class's property type should be a "number".
|
||||
*/
|
||||
static BIGINT = "bigint";
|
||||
|
||||
/**
|
||||
* SQL FLOAT type. Your class's property type should be a "number".
|
||||
*/
|
||||
static FLOAT = "float";
|
||||
|
||||
/**
|
||||
* SQL FLOAT type. Your class's property type should be a "number".
|
||||
*/
|
||||
static DOUBLE = "double";
|
||||
|
||||
/**
|
||||
* SQL DECIMAL type. Your class's property type should be a "string".
|
||||
*/
|
||||
static DECIMAL = "decimal";
|
||||
|
||||
/**
|
||||
* SQL DATETIME type. Your class's property type should be a "Date" object.
|
||||
*/
|
||||
static DATE = "date";
|
||||
|
||||
/**
|
||||
* SQL TIME type. Your class's property type should be a "Date" object.
|
||||
*/
|
||||
static TIME = "time";
|
||||
|
||||
/**
|
||||
* SQL DATETIME/TIMESTAMP type. Your class's property type should be a "Date" object.
|
||||
*/
|
||||
static DATETIME = "datetime";
|
||||
|
||||
/**
|
||||
* SQL BOOLEAN type. Your class's property type should be a "boolean".
|
||||
*/
|
||||
static BOOLEAN = "boolean";
|
||||
|
||||
/**
|
||||
* SQL CLOB type. Your class's property type should be any Object.
|
||||
*/
|
||||
static JSON = "json";
|
||||
|
||||
/**
|
||||
* SQL CLOB type. Your class's property type should be array of string. Note: value in this column should not contain
|
||||
* a comma (",") since this symbol is used to create a string from the array, using .join(",") operator.
|
||||
*/
|
||||
static SIMPLE_ARRAY = "simple_array";
|
||||
|
||||
/**
|
||||
* Checks if given type in a string format is supported by ORM.
|
||||
*/
|
||||
static isTypeSupported(type: string) {
|
||||
return this.supportedTypes.indexOf(type) !== -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of all supported types by the ORM.
|
||||
*/
|
||||
static get supportedTypes() {
|
||||
return [
|
||||
this.STRING,
|
||||
this.TEXT,
|
||||
this.NUMBER,
|
||||
this.INTEGER,
|
||||
this.INT,
|
||||
this.SMALLINT,
|
||||
this.BIGINT,
|
||||
this.FLOAT,
|
||||
this.DOUBLE,
|
||||
this.DECIMAL,
|
||||
this.DATE,
|
||||
this.TIME,
|
||||
this.DATETIME,
|
||||
this.BOOLEAN,
|
||||
this.JSON,
|
||||
this.SIMPLE_ARRAY
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to guess a column type from the given function.
|
||||
*/
|
||||
static determineTypeFromFunction(type: Function): ColumnTypeString {
|
||||
if (type instanceof Date) {
|
||||
return "datetime";
|
||||
|
||||
} else if (type instanceof Function) {
|
||||
const typeName = (<any>type).name.toLowerCase();
|
||||
switch (typeName) {
|
||||
case "number":
|
||||
return "number";
|
||||
case "boolean":
|
||||
return "boolean";
|
||||
case "string":
|
||||
return "string";
|
||||
}
|
||||
|
||||
} else if (type instanceof Object) {
|
||||
return "json";
|
||||
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
}
|
||||
@ -6,8 +6,8 @@ export class CascadesNotAllowedError extends Error {
|
||||
|
||||
constructor(type: "insert"|"update"|"remove", metadata: EntityMetadata, relation: RelationMetadata) {
|
||||
super();
|
||||
const name = entityClassOrName instanceof Function ? (<any> entityClassOrName).name : entityClassOrName;
|
||||
this.message = `No broadcaster for "${name}" was found. Looks like this entity is not registered in your connection?`;
|
||||
const cls = (<any> metadata.target).name;
|
||||
this.message = `Cascades (${type}) are not allowed for the given relation ${cls}#${relation.name}`;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user