refactored column types - now databases support their own column types individually

This commit is contained in:
Umed Khudoiberdiev 2017-06-13 18:07:02 +05:00
parent 87c94ee833
commit f1c566f2ef
149 changed files with 2309 additions and 1012 deletions

View File

@ -37,11 +37,18 @@ Now naming strategy should be registered by passing naming strategy instance dir
More env variable names you can find in `ConnectionOptionsEnvReader` class.
* some api changes in `ConnectionManager` and `createConnection` / `createConnections` methods of typeorm main entrypoint
* `usePool` option has been removed from connection options. Now connections are working only with connection pooling
* `simple_array` column type now is called `simple-array`
* some column types were removed. Now orm uses directly column types of underlying database
* now `number` type in column definitions (like `@Column() likes: number`) maps to `integer` instead of `double` as before.
This is more programmatic design. If you need to store float-pointing values there define a type explicitly
* `fixedLength` in column options has been removed. Now actual column types can be used, e.g. `@Column("char")` or `@Column("varchar")`
* `timezone` option has been removed from column options. Now corresponding database types can be used instead
* `localTimezone` has been removed from the column options
* `skipSchemaSync` in entity options has been renamed to `skipSync`
### OTHER API CHANGES
### DEPRECATIONS
* moved `query`, `transaction` and `createQueryBuilder` to the `Connection`.
`EntityManager` now simply use them from the connection.
* `Embedded` decorator is deprecated now. use `@Column(type => SomeEmbedded)` instead now
### NEW FEATURES
@ -53,6 +60,11 @@ More env variable names you can find in `ConnectionOptionsEnvReader` class.
* now relations for multiple primary keys are generated properly
* now ormconfig is read from `.env`, `.js`, `.json`, `.yml`, `.xml` formats
### OTHER API CHANGES
* moved `query`, `transaction` and `createQueryBuilder` to the `Connection`.
`EntityManager` now simply use them from the connection.
### BUG FIXES
* fixes [#285](https://github.com/typeorm/typeorm/issues/285) - issue when cli commands rise `CannotCloseNotConnectedError`

View File

@ -5,7 +5,7 @@ import {Index} from "../../../src/decorator/Index";
@Entity("sample01_post")
export class Post {
@PrimaryColumn("int", { generated: true })
@PrimaryColumn("integer", { generated: true })
id: number;
@Column()

View File

@ -10,7 +10,7 @@
"generated": true
},
"description": {
"type": "string",
"type": "varchar",
"nullable": false
}
},

View File

@ -10,11 +10,11 @@
"generated": true
},
"name": {
"type": "string",
"type": "varchar",
"nullable": false
},
"url": {
"type": "string",
"type": "varchar",
"nullable": false
}
},

View File

@ -10,11 +10,11 @@
"generated": true
},
"comment": {
"type": "string",
"type": "varchar",
"nullable": false
},
"metadata": {
"type": "string",
"type": "varchar",
"nullable": false
}
},

View File

@ -10,11 +10,11 @@
"generated": true
},
"title": {
"type": "string",
"type": "varchar",
"nullable": false
},
"text": {
"type": "string",
"type": "varchar",
"nullable": false
}
},

View File

@ -14,7 +14,7 @@ export class Post {
@Column()
text: string;
@Embedded(type => Counters)
@Column(type => Counters)
counters: Counters;
}

View File

@ -11,7 +11,7 @@ export class Question {
@Column()
title: string;
@Embedded(type => Counters)
@Column(type => Counters)
counters: Counters;
}

View File

@ -9,7 +9,7 @@ import {PrimaryColumn} from "../../../src/decorator/columns/PrimaryColumn";
@Entity("sample28_person")
@TableInheritance("single-table")
@DiscriminatorColumn({ name: "type", type: "string"})
@DiscriminatorColumn({ name: "type", type: "varchar" })
export abstract class Person {
@PrimaryColumn("int")

View File

@ -6,7 +6,7 @@ import {PrimaryColumn} from "../../../src/decorator/columns/PrimaryColumn";
@Entity("sample29_person")
@TableInheritance("class-table")
@DiscriminatorColumn({ name: "type", type: "string"})
@DiscriminatorColumn({ name: "type", type: "varchar" })
export abstract class Person {
@PrimaryColumn("int"/*, { generated: true }*/)

View File

@ -2,7 +2,7 @@ import {DriverOptions} from "../driver/DriverOptions";
import {EntitySchema} from "../entity-schema/EntitySchema";
import {LoggerOptions} from "../logger/LoggerOptions";
import {NamingStrategyInterface} from "../naming-strategy/NamingStrategyInterface";
import {DatabaseType} from "../driver/DatabaseType";
import {DatabaseType} from "../driver/types/DatabaseType";
/**
* BaseConnectionOptions is set of connection options shared by all database types.

View File

@ -8,6 +8,8 @@ import {EmbeddedMetadataArgs} from "../metadata-args/EmbeddedMetadataArgs";
* embedded will be mapped to it from the single table.
*
* Array option works only in monogodb.
*
* @deprecated use @Column(type => EmbeddedModel) instead
*/
export function Embedded<T>(typeFunction: (type?: any) => ObjectType<T>, options?: { prefix?: string|boolean, array?: boolean }) {
return function (object: Object, propertyName: string) {

View File

@ -1,8 +1,19 @@
import {ColumnOptions} from "../options/ColumnOptions";
import {GeneratedOnlyForPrimaryError} from "../error/GeneratedOnlyForPrimaryError";
import {getMetadataArgsStorage} from "../../index";
import {ColumnType, ColumnTypes} from "../../metadata/types/ColumnTypes";
import {
ColumnType,
SimpleColumnType,
WithLengthColumnType,
WithPrecisionColumnType
} from "../../driver/types/ColumnTypes";
import {ColumnMetadataArgs} from "../../metadata-args/ColumnMetadataArgs";
import {ColumnCommonOptions} from "../options/ColumnCommonOptions";
import {ColumnWithLengthOptions} from "../options/ColumnWithLengthOptions";
import {ColumnNumericOptions} from "../options/ColumnNumericOptions";
import {ColumnEnumOptions} from "../options/ColumnEnumOptions";
import {ColumnEmbeddedOptions} from "../options/ColumnEmbeddedOptions";
import {EmbeddedMetadataArgs} from "../../metadata-args/EmbeddedMetadataArgs";
/**
* Column decorator is used to mark a specific class property as a table column. Only properties decorated with this
@ -10,12 +21,6 @@ import {ColumnMetadataArgs} from "../../metadata-args/ColumnMetadataArgs";
*/
export function Column(): 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: ColumnType): 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.
@ -26,15 +31,43 @@ export function Column(options: ColumnOptions): 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: ColumnType, options: ColumnOptions): Function;
export function Column(type: SimpleColumnType, options?: ColumnCommonOptions): 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(typeOrOptions?: ColumnType|ColumnOptions, options?: ColumnOptions): Function {
export function Column(type: WithLengthColumnType, options?: ColumnCommonOptions & ColumnWithLengthOptions): 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: WithPrecisionColumnType, options?: ColumnCommonOptions & ColumnNumericOptions): 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: "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.
*
* Property in entity can be marked as Embedded, and on persist all columns from the embedded are mapped to the
* single table of the entity where Embedded is used. And on hydration all columns which supposed to be in the
* embedded will be mapped to it from the single table.
*/
export function Column(type: (type?: any) => Function, options?: ColumnEmbeddedOptions): 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(typeOrOptions?: ((type?: any) => Function)|ColumnType|(ColumnOptions&ColumnEmbeddedOptions), options?: (ColumnOptions&ColumnEmbeddedOptions)): Function {
let type: ColumnType|undefined;
if (typeof typeOrOptions === "string") {
if (typeof typeOrOptions === "string" || typeOrOptions instanceof Function) {
type = <ColumnType> typeOrOptions;
} else if (typeOrOptions) {
@ -43,39 +76,48 @@ export function Column(typeOrOptions?: ColumnType|ColumnOptions, options?: Colum
}
return function (object: Object, propertyName: string) {
// todo: need to store not string type, but original type instead? (like in relation metadata)
// const reflectedType = ColumnTypes.typeToString((Reflect as any).getMetadata("design:type", object, propertyName));
if (typeOrOptions instanceof Function) {
// if type is not given implicitly then try to guess it
if (!type) {
const reflectMetadataType = Reflect && (Reflect as any).getMetadata ? (Reflect as any).getMetadata("design:type", object, propertyName) : undefined;
if (reflectMetadataType)
type = ColumnTypes.determineTypeFromFunction(reflectMetadataType);
const isArray = reflectMetadataType === Array || (options && options.array === true) ? true : false;
const args: EmbeddedMetadataArgs = {
target: object.constructor,
propertyName: propertyName,
isArray: isArray,
prefix: options && options.prefix !== undefined ? options.prefix : undefined,
type: typeOrOptions as (type?: any) => Function
};
getMetadataArgsStorage().embeddeds.push(args);
} else {
// if type is not given implicitly then try to guess it
if (!type) {
const reflectMetadataType = Reflect && (Reflect as any).getMetadata ? (Reflect as any).getMetadata("design:type", object, propertyName) : undefined;
if (reflectMetadataType)
type = reflectMetadataType; // todo: need to determine later on driver level
}
// if column options are not given then create a new empty options
if (!options) options = {} as ColumnOptions;
// check if there is no type in column options then set type from first function argument, or guessed one
if (!options.type && type)
options = Object.assign({ type: type } as ColumnOptions, options);
// check if auto increment is not set for simple column
if (options.generated)
throw new GeneratedOnlyForPrimaryError(object, propertyName);
// create and register a new column metadata
const args: ColumnMetadataArgs = {
target: object.constructor,
propertyName: propertyName,
mode: "regular",
options: options
};
getMetadataArgsStorage().columns.push(args);
}
// if column options are not given then create a new empty options
if (!options) options = {} as ColumnOptions;
// check if there is no type in column options then set type from first function argument, or guessed one
if (!options.type && type)
options = Object.assign({ type: type } as ColumnOptions, options);
// 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.generated)
throw new GeneratedOnlyForPrimaryError(object, propertyName);
// create and register a new column metadata
const args: ColumnMetadataArgs = {
target: object.constructor,
propertyName: propertyName,
// propertyType: reflectedType,
mode: "regular",
options: options
};
getMetadataArgsStorage().columns.push(args);
};
}

View File

@ -1,5 +1,4 @@
import {ColumnOptions} from "../options/ColumnOptions";
import {ColumnTypes} from "../../metadata/types/ColumnTypes";
import {getMetadataArgsStorage} from "../../index";
import {ColumnMetadataArgs} from "../../metadata-args/ColumnMetadataArgs";
@ -17,7 +16,7 @@ export function CreateDateColumn(options?: ColumnOptions): Function {
if (!options) options = {} as ColumnOptions;
// implicitly set a type, because this column's type cannot be anything else except date
options = Object.assign({ type: ColumnTypes.DATETIME } as ColumnOptions, options);
// options = Object.assign({ type: Date } as ColumnOptions, options);
// create and register a new column metadata
const args: ColumnMetadataArgs = {

View File

@ -1,5 +1,5 @@
import {ColumnOptions} from "../options/ColumnOptions";
import {ColumnType} from "../../metadata/types/ColumnTypes";
import {ColumnType} from "../../driver/types/ColumnTypes";
import {getMetadataArgsStorage} from "../../index";
import {ColumnMetadataArgs} from "../../metadata-args/ColumnMetadataArgs";

View File

@ -1,5 +1,5 @@
import {ColumnOptions} from "../options/ColumnOptions";
import {ColumnType, ColumnTypes} from "../../metadata/types/ColumnTypes";
import {ColumnType} from "../../driver/types/ColumnTypes";
import {ColumnTypeUndefinedError} from "../error/ColumnTypeUndefinedError";
import {getMetadataArgsStorage} from "../../index";
import {PrimaryColumnCannotBeNullableError} from "../error/PrimaryColumnCannotBeNullableError";
@ -39,7 +39,7 @@ export function PrimaryColumn(typeOrOptions?: ColumnType|ColumnOptions, options?
if (!type) {
const reflectMetadataType = Reflect && (Reflect as any).getMetadata ? (Reflect as any).getMetadata("design:type", object, propertyName) : undefined;
if (reflectMetadataType)
type = ColumnTypes.determineTypeFromFunction(reflectMetadataType);
type = reflectMetadataType;
}
// if column options are not given then create a new empty options

View File

@ -1,5 +1,4 @@
import {ColumnOptions} from "../options/ColumnOptions";
import {ColumnTypes} from "../../metadata/types/ColumnTypes";
import {getMetadataArgsStorage} from "../../index";
import {ColumnMetadataArgs} from "../../metadata-args/ColumnMetadataArgs";
@ -16,7 +15,7 @@ export function UpdateDateColumn(options?: ColumnOptions): Function {
if (!options) options = {} as ColumnOptions;
// implicitly set a type, because this column's type cannot be anything else except date
options = Object.assign({ type: ColumnTypes.DATETIME } as ColumnOptions, options);
// options = Object.assign({ type: Date } as ColumnOptions, options);
// create and register a new column metadata
const args: ColumnMetadataArgs = {

View File

@ -1,5 +1,4 @@
import {ColumnOptions} from "../options/ColumnOptions";
import {ColumnTypes} from "../../metadata/types/ColumnTypes";
import {getMetadataArgsStorage} from "../../index";
import {ColumnMetadataArgs} from "../../metadata-args/ColumnMetadataArgs";
@ -11,21 +10,13 @@ import {ColumnMetadataArgs} from "../../metadata-args/ColumnMetadataArgs";
export function VersionColumn(options?: ColumnOptions): Function {
return function (object: Object, propertyName: string) {
// const reflectedType = ColumnTypes.typeToString((Reflect as any).getMetadata("design:type", object, propertyName));
// if column options are not given then create a new empty options
if (!options) options = {} as ColumnOptions;
// implicitly set a type, because this column's type cannot be anything else except date
options = Object.assign({ type: ColumnTypes.INTEGER } as ColumnOptions, options);
// todo: check if reflectedType is number too
// create and register a new column metadata
const args: ColumnMetadataArgs = {
target: object.constructor,
propertyName: propertyName,
// propertyType: reflectedType,
mode: "version",
options: options
};

View File

@ -12,7 +12,7 @@ export function ClassEntityChild(tableName?: string, options?: EntityOptions) {
name: tableName,
type: "class-table-child",
orderBy: options && options.orderBy ? options.orderBy : undefined,
skipSchemaSync: !!(options && options.skipSchemaSync === true)
skipSync: !!(options && options.skipSync === true)
};
getMetadataArgsStorage().tables.push(args);
};

View File

@ -12,7 +12,7 @@ export function ClosureEntity(name?: string, options?: EntityOptions) {
name: name,
type: "closure",
orderBy: options && options.orderBy ? options.orderBy : undefined,
skipSchemaSync: !!(options && options.skipSchemaSync === true)
skipSync: !!(options && options.skipSync === true)
};
getMetadataArgsStorage().tables.push(args);
};

View File

@ -14,7 +14,7 @@ export function Entity(name?: string, options?: EntityOptions) {
type: "regular",
orderBy: options && options.orderBy ? options.orderBy : undefined,
engine: options && options.engine ? options.engine : undefined,
skipSchemaSync: !!(options && options.skipSchemaSync === true)
skipSync: !!(options && options.skipSync === true)
};
getMetadataArgsStorage().tables.push(args);
};

View File

@ -0,0 +1,37 @@
/**
* Column options specific to all column types.
*/
export interface ColumnCommonOptions {
/**
* Column name in the database.
*/
name?: string;
/**
* Indicates if this column is a primary key.
* Same can be achieved when @PrimaryColumn decorator is used.
*/
primary?: boolean;
/**
* Specifies if column's value must be unique or not.
*/
unique?: boolean;
/**
* Indicates if column's value can be set to NULL.
*/
nullable?: boolean;
/**
* Default database value.
*/
default?: any;
/**
* Column comment. Not supported by all database types.
*/
comment?: string;
}

View File

@ -0,0 +1,16 @@
/**
* Column options specific to all column types.
*/
export interface ColumnEmbeddedOptions {
/**
* Embedded column prefix.
*/
prefix?: string;
/**
* Indicates if this embedded column is an array.
*/
array?: boolean;
}

View File

@ -0,0 +1,11 @@
/**
* Column options for enum-typed columns.
*/
export interface ColumnEnumOptions {
/**
* Array of possible enumerated values.
*/
enum?: any[];
}

View File

@ -0,0 +1,18 @@
/**
* Options for numeric column types where user can specify scale and precision.
*/
export interface ColumnNumericOptions {
/**
* 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;
}

View File

@ -1,4 +1,4 @@
import {ColumnType} from "../../metadata/types/ColumnTypes";
import {ColumnType} from "../../driver/types/ColumnTypes";
/**
* Describes all column's options.
@ -22,8 +22,8 @@ export interface ColumnOptions {
length?: string|number;
/**
* Indicates if this column is PRIMARY.
* Same can be achieved if @PrimaryColumn decorator will be used.
* Indicates if this column is a primary key.
* Same can be achieved when @PrimaryColumn decorator is used.
*/
primary?: boolean;
@ -45,7 +45,7 @@ export interface ColumnOptions {
nullable?: boolean;
/**
* Column comment.
* Column comment. Not supported by all database types.
*/
comment?: string;
@ -67,23 +67,8 @@ export interface ColumnOptions {
scale?: number;
/**
* Indicates if this date column will contain a timezone.
* Used only for date-typed column types.
* Note that timezone option is not supported by all databases (only postgres for now).
* Array of possible enumerated values.
*/
timezone?: boolean;
/**
* Indicates if date object must be stored in given date's timezone.
* By default date is saved in UTC timezone.
* Works only with "datetime" columns.
*/
localTimezone?: boolean;
/**
* Indicates if column's type will be set as a fixed-length data type.
* Works only with "string" columns.
*/
fixedLength?: boolean;
enum?: any[];
}

View File

@ -0,0 +1,12 @@
/**
* Options for columns that can define a length of the column type.
*/
export interface ColumnWithLengthOptions {
/**
* Column type's length.
* For example type = "varchar" and length = "100" means ORM will create a column with type varchar(100).
*/
length?: string|number;
}

View File

@ -21,6 +21,6 @@ export interface EntityOptions {
/**
* Specifies if this table will be skipped during schema synchronization.
*/
skipSchemaSync?: boolean;
skipSync?: boolean;
}

View File

@ -1,5 +1,4 @@
import {getMetadataArgsStorage} from "../../index";
import {ColumnTypes} from "../../metadata/types/ColumnTypes";
import {ColumnOptions} from "../options/ColumnOptions";
import {ColumnMetadataArgs} from "../../metadata-args/ColumnMetadataArgs";
@ -9,18 +8,12 @@ import {ColumnMetadataArgs} from "../../metadata-args/ColumnMetadataArgs";
export function TreeLevelColumn(): Function {
return function (object: Object, propertyName: string) {
// const reflectedType = ColumnTypes.typeToString((Reflect as any).getMetadata("design:type", object, propertyName));
// implicitly set a type, because this column's type cannot be anything else except number
const options: ColumnOptions = { type: ColumnTypes.INTEGER };
// create and register a new column metadata
const args: ColumnMetadataArgs = {
target: object.constructor,
propertyName: propertyName,
// propertyType: reflectedType,
mode: "treeLevel",
options: options
options: {}
};
getMetadataArgsStorage().columns.push(args);
};

View File

@ -1,12 +1,25 @@
import {QueryRunner} from "../query-runner/QueryRunner";
import {ColumnMetadata} from "../metadata/ColumnMetadata";
import {ObjectLiteral} from "../common/ObjectLiteral";
import {ColumnType} from "./types/ColumnTypes";
import {MappedColumnTypes} from "./types/MappedColumnTypes";
/**
* Driver organizes TypeORM communication with specific database management system.
*/
export interface Driver {
/**
* Gets list of supported column data types by a driver.
*/
supportedDataTypes: ColumnType[];
/**
* Orm has special columns and we need to know what database column types should be for those types.
* Column types are driver dependant.
*/
mappedDataTypes: MappedColumnTypes;
/**
* Performs connection to the database.
* Depend on driver type it may create a connection pool.
@ -59,15 +72,9 @@ export interface Driver {
*/
preparePersistentValue(value: any, column: ColumnMetadata): any;
/**
* Prepares given value to a value to be persisted, based on its column metadata.
*/
prepareHydratedValue(value: any, type: ColumnMetadata): any;
/**
* Prepares given value to a value to be persisted, based on its column type.
*/
prepareHydratedValue(value: any, column: ColumnMetadata): any;
}

View File

@ -1,4 +1,4 @@
import {DatabaseType} from "./DatabaseType";
import {DatabaseType} from "./types/DatabaseType";
/**
* Connectivity options used to connect to the database, and other database-driver-specific options.

View File

@ -11,6 +11,8 @@ import {DriverOptionNotSetError} from "../error/DriverOptionNotSetError";
import {PlatformTools} from "../../platform/PlatformTools";
import {Connection} from "../../connection/Connection";
import {MongoConnectionOptions} from "./MongoConnectionOptions";
import {MappedColumnTypes} from "../types/MappedColumnTypes";
import {ColumnType} from "../types/ColumnTypes";
/**
* Organizes communication with MongoDB.
@ -27,6 +29,27 @@ export class MongoDriver implements Driver {
*/
queryRunner: MongoQueryRunner;
// -------------------------------------------------------------------------
// Public Implemented Properties
// -------------------------------------------------------------------------
/**
* Mongodb does not need to have column types because they are not used in schema sync.
*/
supportedDataTypes: ColumnType[] = [];
/**
* Mongodb does not need to have a strong defined mapped column types because they are not used in schema sync.
*/
mappedDataTypes: MappedColumnTypes = {
createDate: "int",
updateDate: "int",
version: "int",
treeLevel: "int",
migrationName: "int",
migrationTimestamp: "int",
};
// -------------------------------------------------------------------------
// Protected Properties
// -------------------------------------------------------------------------

View File

@ -6,7 +6,7 @@ import {ColumnMetadata} from "../../metadata/ColumnMetadata";
import {TableSchema} from "../../schema-builder/schema/TableSchema";
import {ForeignKeySchema} from "../../schema-builder/schema/ForeignKeySchema";
import {IndexSchema} from "../../schema-builder/schema/IndexSchema";
import {ColumnType} from "../../metadata/types/ColumnTypes";
import {ColumnType} from "../types/ColumnTypes";
import {
AggregationCursor,
BulkWriteOpResultObject,
@ -648,7 +648,7 @@ export class MongoQueryRunner implements QueryRunner {
/**
* Creates a database type from a given column metadata.
*/
normalizeType(typeOptions: { type: ColumnType, length?: string|number, precision?: number, scale?: number, timezone?: boolean, fixedLength?: boolean }): string {
normalizeType(column: ColumnMetadata): string {
throw new Error(`Schema update queries are not supported by MongoDB driver.`);
}

View File

@ -0,0 +1,214 @@
// -------------------------------------------------------------------------
// Numeric Types
// -------------------------------------------------------------------------
/**
* A very small integer that can be signed or unsigned.
* If signed, the allowable range is from -128 to 127.
* If unsigned, the allowable range is from 0 to 255.
* You can specify a width of up to 4 digits.
*/
export type TinyintColumnType = "tinyint";
/**
* A small integer that can be signed or unsigned.
* If signed, the allowable range is from -32768 to 32767.
* If unsigned, the allowable range is from 0 to 65535.
* You can specify a width of up to 5 digits.
*/
export type SmallintColumnType = "smallint";
/**
* A medium-sized integer that can be signed or unsigned.
* If signed, the allowable range is from -8388608 to 8388607.
* If unsigned, the allowable range is from 0 to 16777215.
* You can specify a width of up to 9 digits.
*/
export type MediumintColumnType = "mediumint";
/**
* A normal-sized integer that can be signed or unsigned.
* If signed, the allowable range is from -2147483648 to 2147483647.
* If unsigned, the allowable range is from 0 to 4294967295.
* You can specify a width of up to 11 digits.
*/
export type IntegerColumnType = "int";
/**
* A large integer that can be signed or unsigned.
* If signed, the allowable range is from -9223372036854775808 to 9223372036854775807.
* If unsigned, the allowable range is from 0 to 18446744073709551615.
* You can specify a width of up to 20 digits.
*/
export type BigintColumnType = "bigint";
/**
* A floating-point number that cannot be unsigned.
* You can define the display length (M) and the number of decimals (D).
* This is not required and will default to 10,2,
* where 2 is the number of decimals and 10 is the total number of digits (including decimals).
* Decimal precision can go to 24 places for a FLOAT.
*/
export type FloatColumnType = "float";
/**
* A double precision floating-point number that cannot be unsigned.
* You can define the display length (M) and the number of decimals (D).
* This is not required and will default to 16,4, where 4 is the number of decimals.
* Decimal precision can go to 53 places for a DOUBLE. REAL is a synonym for DOUBLE.
*/
export type DoubleColumnType = "real"|"double";
/**
* An unpacked floating-point number that cannot be unsigned.
* In unpacked decimals, each decimal corresponds to one byte.
* Defining the display length (M) and the number of decimals (D) is required.
* NUMERIC is a synonym for DECIMAL.
*/
export type DecimalColumnType = "numeric"|"decimal";
// -------------------------------------------------------------------------
// Character Types
// -------------------------------------------------------------------------
/**
* A variable-length string between 1 and 255 characters in length; for example VARCHAR(25).
* You must define a length when creating a VARCHAR field.
*/
export type VarcharColumnType = "varchar";
/**
* A fixed-length string between 1 and 255 characters in length (for example CHAR(5)),
* right-padded with spaces to the specified length when stored.
* Defining a length is not required, but the default is 1.
*/
export type CharColumnType = "char";
/**
* A BLOB or TEXT column with a maximum length of 255 characters.
* You do not specify a length with TINYBLOB or TINYTEXT.
*/
export type TinyTextColumnType = "tinyblob"|"tinytext";
/**
* A BLOB or TEXT column with a maximum length of 16777215 characters.
* You do not specify a length with MEDIUMBLOB or MEDIUMTEXT.
*/
export type MediumTextColumnType = "mediumblob"|"mediumtext";
/**
* A field with a maximum length of 65535 characters.
* BLOBs are "Binary Large Objects" and are used to store large amounts of binary data, such as images or other types of files.
* Fields defined as TEXT also hold large amounts of data;
* the difference between the two is that sorts and comparisons on stored data are case sensitive on BLOBs and are not case sensitive in TEXT fields.
* You do not specify a length with BLOB or TEXT.
*/
export type TextColumnType = "blob"|"text";
/**
* A BLOB or TEXT column with a maximum length of 4294967295 characters.
* You do not specify a length with LONGBLOB or LONGTEXT.
*/
export type LongTextColumnType = "longblob"|"longtext";
// -------------------------------------------------------------------------
// Date/Time Types
// -------------------------------------------------------------------------
/**
* A date in YYYY-MM-DD format, between 1000-01-01 and 9999-12-31.
* For example, December 30th, 1973 would be stored as 1973-12-30.
*/
export type DateColumnType = "date";
/**
* A date and time combination in YYYY-MM-DD HH:MM:SS format,
* between 1000-01-01 00:00:00 and 9999-12-31 23:59:59.
* For example, 3:30 in the afternoon on December 30th, 1973 would be stored as 1973-12-30 15:30:00.
*/
export type DatetimeColumnType = "datetime";
/**
* A timestamp between midnight, January 1, 1970 and sometime in 2037.
* This looks like the previous DATETIME format, only without the hyphens between numbers;
* 3:30 in the afternoon on December 30th, 1973 would be stored as 19731230153000 ( YYYYMMDDHHMMSS ).
*/
export type TimestampColumnType = "timestamp";
/**
* Stores the time in HH:MM:SS format.
*/
export type TimeColumnType = "time";
/**
* Stores a year in 2-digit or 4-digit format.
* If the length is specified as 2 (for example YEAR(2)), YEAR can be 1970 to 2069 (70 to 69).
* If the length is specified as 4, YEAR can be 1901 to 2155.
* The default length is 4.
*/
export type YearColumnType = "year";
// -------------------------------------------------------------------------
// Enumerated Type
// -------------------------------------------------------------------------
/**
* An enumeration, which is a fancy term for list.
* When defining an ENUM, you are creating a list of items from which the value must be selected (or it can be NULL).
* For example, if you wanted your field to contain "A" or "B" or "C",
* you would define your ENUM as ENUM ('A', 'B', 'C') and only those values (or NULL) could ever populate that field.
*/
export type EnumColumnType = "enum";
// -------------------------------------------------------------------------
// Merged Types
// -------------------------------------------------------------------------
/**
* Column types where column length is used.
*/
export type WithLengthColumnType =
VarcharColumnType|
CharColumnType|
YearColumnType;
/**
* Column types where precision is used.
*/
export type NumericColumnType =
FloatColumnType|
DoubleColumnType|
DecimalColumnType;
/**
* Column types where time options are used.
*/
export type WithTimeColumnType =
DatetimeColumnType|
TimestampColumnType;
/**
* All other column types without extra options used.
*/
export type SimpleColumnType =
TinyintColumnType|
SmallintColumnType|
MediumintColumnType|
IntegerColumnType|
BigintColumnType|
TinyTextColumnType|
MediumTextColumnType|
TextColumnType|
LongTextColumnType|
DateColumnType|
TimeColumnType;
/**
* All column types supported by a database.
*/
export type AllColumnType =
SimpleColumnType|
WithLengthColumnType|
NumericColumnType|
WithTimeColumnType|
EnumColumnType;

View File

@ -5,7 +5,6 @@ import {DriverPackageNotInstalledError} from "../error/DriverPackageNotInstalled
import {DriverUtils} from "../DriverUtils";
import {QueryRunner} from "../../query-runner/QueryRunner";
import {MysqlQueryRunner} from "./MysqlQueryRunner";
import {ColumnTypes} from "../../metadata/types/ColumnTypes";
import {ObjectLiteral} from "../../common/ObjectLiteral";
import {ColumnMetadata} from "../../metadata/ColumnMetadata";
import {DriverOptionNotSetError} from "../error/DriverOptionNotSetError";
@ -14,12 +13,64 @@ import {PlatformTools} from "../../platform/PlatformTools";
import {Connection} from "../../connection/Connection";
import {SchemaBuilder} from "../../schema-builder/SchemaBuilder";
import {MysqlConnectionOptions} from "./MysqlConnectionOptions";
import {MappedColumnTypes} from "../types/MappedColumnTypes";
import {ColumnType} from "../types/ColumnTypes";
/**
* Organizes communication with MySQL DBMS.
*/
export class MysqlDriver implements Driver {
// -------------------------------------------------------------------------
// Public Implemented Properties
// -------------------------------------------------------------------------
/**
* Gets list of supported column data types by a driver.
*
* @see https://www.tutorialspoint.com/mysql/mysql-data-types.htm
* @see https://dev.mysql.com/doc/refman/5.7/en/data-types.html
*/
supportedDataTypes: ColumnType[] = [
"int",
"tinyint",
"smallint",
"mediumint",
"bigint",
"float",
"double",
"decimal",
"date",
"datetime",
"timestamp",
"time",
"year",
"char",
"varchar",
"blob",
"text",
"tinyblob",
"tinytext",
"mediumblob",
"mediumtext",
"longblob",
"longtext",
"enum"
];
/**
* Orm has special columns and we need to know what database column types should be for those types.
* Column types are driver dependant.
*/
mappedDataTypes: MappedColumnTypes = {
createDate: "datetime",
updateDate: "datetime",
version: "int",
treeLevel: "int",
migrationName: "varchar",
migrationTimestamp: "timestamp",
};
// -------------------------------------------------------------------------
// Protected Properties
// -------------------------------------------------------------------------
@ -176,30 +227,25 @@ export class MysqlDriver implements Driver {
*/
preparePersistentValue(value: any, columnMetadata: ColumnMetadata): any {
if (value === null || value === undefined)
return null;
return value;
switch (columnMetadata.type) {
case ColumnTypes.BOOLEAN:
return value === true ? 1 : 0;
if (columnMetadata.type === Boolean) {
return value === true ? 1 : 0;
case ColumnTypes.DATE:
return DataUtils.mixedDateToDateString(value);
} else if (columnMetadata.type === "date") {
return DataUtils.mixedDateToDateString(value);
case ColumnTypes.TIME:
return DataUtils.mixedDateToTimeString(value);
} else if (columnMetadata.type === "time") {
return DataUtils.mixedDateToTimeString(value);
case ColumnTypes.DATETIME:
if (columnMetadata.localTimezone) {
return DataUtils.mixedDateToDatetimeString(value);
} else {
return DataUtils.mixedDateToUtcDatetimeString(value);
}
} else if (columnMetadata.type === "datetime") {
return DataUtils.mixedDateToUtcDatetimeString(value);
case ColumnTypes.JSON:
return JSON.stringify(value);
} else if (columnMetadata.type === "json") {
return JSON.stringify(value);
case ColumnTypes.SIMPLE_ARRAY:
return DataUtils.simpleArrayToString(value);
} else if (columnMetadata.type === "simple-array") {
return DataUtils.simpleArrayToString(value);
}
return value;
@ -209,24 +255,23 @@ export class MysqlDriver implements Driver {
* Prepares given value to a value to be persisted, based on its column type or metadata.
*/
prepareHydratedValue(value: any, columnMetadata: ColumnMetadata): any {
switch (columnMetadata.type) {
case ColumnTypes.BOOLEAN:
return value ? true : false;
if (columnMetadata.type === Boolean) {
return value ? true : false;
case ColumnTypes.DATETIME:
return DataUtils.normalizeHydratedDate(value, columnMetadata.localTimezone === true);
} else if (columnMetadata.type === "datetime") {
return DataUtils.normalizeHydratedDate(value);
case ColumnTypes.DATE:
return DataUtils.mixedDateToDateString(value);
} else if (columnMetadata.type === "date") {
return DataUtils.mixedDateToDateString(value);
case ColumnTypes.TIME:
return DataUtils.mixedTimeToString(value);
} else if (columnMetadata.type === "time") {
return DataUtils.mixedTimeToString(value);
case ColumnTypes.JSON:
return JSON.parse(value);
} else if (columnMetadata.type === "json") {
return JSON.parse(value);
case ColumnTypes.SIMPLE_ARRAY:
return DataUtils.stringToSimpleArray(value);
} else if (columnMetadata.type === "simple-array") {
return DataUtils.stringToSimpleArray(value);
}
return value;

View File

@ -11,9 +11,10 @@ import {ForeignKeySchema} from "../../schema-builder/schema/ForeignKeySchema";
import {PrimaryKeySchema} from "../../schema-builder/schema/PrimaryKeySchema";
import {IndexSchema} from "../../schema-builder/schema/IndexSchema";
import {QueryRunnerAlreadyReleasedError} from "../../query-runner/error/QueryRunnerAlreadyReleasedError";
import {ColumnType} from "../../metadata/types/ColumnTypes";
import {ColumnType} from "../types/ColumnTypes";
import {Connection} from "../../connection/Connection";
import {MysqlConnectionOptions} from "./MysqlConnectionOptions";
import {ColumnOptions} from "../../decorator/options/ColumnOptions";
/**
* Runs queries on a single mysql database connection.
@ -691,58 +692,66 @@ export class MysqlQueryRunner implements QueryRunner {
/**
* Creates a database type from a given column metadata.
*/
normalizeType(typeOptions: { type: ColumnType, length?: string|number, precision?: number, scale?: number, timezone?: boolean, fixedLength?: boolean }): string {
normalizeType(column: ColumnMetadata): string {
let type = "";
if (column.type === Number) {
type += "int";
switch (typeOptions.type) {
case "string":
if (typeOptions.fixedLength) {
return "char(" + (typeOptions.length ? typeOptions.length : 255) + ")";
} else {
return "varchar(" + (typeOptions.length ? typeOptions.length : 255) + ")";
}
case "text":
return "text";
case "boolean":
return "tinyint(1)";
case "integer":
case "int":
return "int(" + (typeOptions.length ? typeOptions.length : 11) + ")";
case "smallint":
return "smallint(" + (typeOptions.length ? typeOptions.length : 11) + ")";
case "bigint":
return "bigint(" + (typeOptions.length ? typeOptions.length : 11) + ")";
case "float":
return "float";
case "double":
case "number":
return "double";
case "decimal":
if (typeOptions.precision && typeOptions.scale) {
return `decimal(${typeOptions.precision},${typeOptions.scale})`;
} else if (column.type === String) {
type += "varchar";
} else if (typeOptions.scale) {
return `decimal(${typeOptions.scale})`;
} else if (column.type === Date) {
type += "datetime";
} else if (typeOptions.precision) {
return `decimal(${typeOptions.precision})`;
} else if (column.type === Boolean) {
type += "tinyint(1)";
} else {
return "decimal";
} else if (column.type === Object) {
type += "text";
}
case "date":
return "date";
case "time":
return "time";
case "datetime":
return "datetime";
case "json":
return "text";
case "simple_array":
return typeOptions.length ? "varchar(" + typeOptions.length + ")" : "text";
} else if (column.type === "simple-array") {
type += "text";
} else {
type += column.type;
}
throw new DataTypeNotSupportedByDriverError(typeOptions.type, "MySQL/MariaDB");
if (column.length) {
type += "(" + column.length + ")";
} else if (column.precision && column.scale) {
type += "(" + column.precision + "," + column.scale + ")";
} else if (column.precision) {
type += "(" + column.precision + ")";
} else if (column.scale) {
type += "(" + column.scale + ")";
}
// set default required length if those were not specified
if (type === "varchar")
type += "(255)";
if (type === "int")
type += "(11)";
if (type === "tinyint")
type += "(4)";
if (type === "smallint")
type += "(5)";
if (type === "mediumint")
type += "(9)";
if (type === "bigint")
type += "(20)";
if (type === "year")
type += "(4)";
return type;
}
/**

View File

@ -4,7 +4,6 @@ import {DatabaseConnection} from "../DatabaseConnection";
import {DriverPackageNotInstalledError} from "../error/DriverPackageNotInstalledError";
import {QueryRunner} from "../../query-runner/QueryRunner";
import {OracleQueryRunner} from "./OracleQueryRunner";
import {ColumnTypes} from "../../metadata/types/ColumnTypes";
import {ObjectLiteral} from "../../common/ObjectLiteral";
import {ColumnMetadata} from "../../metadata/ColumnMetadata";
import {DriverOptionNotSetError} from "../error/DriverOptionNotSetError";
@ -13,6 +12,8 @@ import {PlatformTools} from "../../platform/PlatformTools";
import {Connection} from "../../connection/Connection";
import {SchemaBuilder} from "../../schema-builder/SchemaBuilder";
import {OracleConnectionOptions} from "./OracleConnectionOptions";
import {MappedColumnTypes} from "../types/MappedColumnTypes";
import {ColumnType} from "../types/ColumnTypes";
/**
* Organizes communication with Oracle RDBMS.
@ -21,6 +22,60 @@ import {OracleConnectionOptions} from "./OracleConnectionOptions";
*/
export class OracleDriver implements Driver {
// -------------------------------------------------------------------------
// Public Implemented Properties
// -------------------------------------------------------------------------
/**
* Gets list of supported column data types by a driver.
*
* @see https://www.techonthenet.com/oracle/datatypes.php
* @see https://docs.oracle.com/cd/B28359_01/server.111/b28318/datatype.htm#CNCPT012
*/
supportedDataTypes: ColumnType[] = [
"char",
"nchar",
"nvarchar2",
"varchar2",
"long",
"raw",
"long raw",
"number",
"numeric",
"dec",
"decimal",
"integer",
"int",
"smallint",
"real",
"double precision",
"date",
"timestamp",
"timestamp with time zone",
"timestamp with local time zone",
"interval year",
"interval day",
"bfile",
"blob",
"clob",
"nclob",
"rowid",
"urowid"
];
/**
* Orm has special columns and we need to know what database column types should be for those types.
* Column types are driver dependant.
*/
mappedDataTypes: MappedColumnTypes = {
createDate: "datetime",
updateDate: "datetime",
version: "number",
treeLevel: "number",
migrationName: "varchar",
migrationTimestamp: "timestamp",
};
// -------------------------------------------------------------------------
// Protected Properties
// -------------------------------------------------------------------------
@ -189,30 +244,25 @@ export class OracleDriver implements Driver {
*/
preparePersistentValue(value: any, columnMetadata: ColumnMetadata): any {
if (value === null || value === undefined)
return null;
return value;
switch (columnMetadata.type) {
case ColumnTypes.BOOLEAN:
return value === true ? 1 : 0;
if (columnMetadata.type === Boolean) {
return value === true ? 1 : 0;
case ColumnTypes.DATE:
return DataUtils.mixedDateToDateString(value);
} else if (columnMetadata.type === "date") {
return DataUtils.mixedDateToDateString(value);
case ColumnTypes.TIME:
return DataUtils.mixedDateToTimeString(value);
} else if (columnMetadata.type === "time") {
return DataUtils.mixedDateToTimeString(value);
case ColumnTypes.DATETIME:
if (columnMetadata.localTimezone) {
return DataUtils.mixedDateToDatetimeString(value);
} else {
return DataUtils.mixedDateToUtcDatetimeString(value);
}
} else if (columnMetadata.type === "datetime") {
return DataUtils.mixedDateToUtcDatetimeString(value);
case ColumnTypes.JSON:
return JSON.stringify(value);
} else if (columnMetadata.type === "json") {
return JSON.stringify(value);
case ColumnTypes.SIMPLE_ARRAY:
return DataUtils.simpleArrayToString(value);
} else if (columnMetadata.type === "simple-array") {
return DataUtils.simpleArrayToString(value);
}
return value;
@ -222,24 +272,23 @@ export class OracleDriver implements Driver {
* Prepares given value to a value to be persisted, based on its column type or metadata.
*/
prepareHydratedValue(value: any, columnMetadata: ColumnMetadata): any {
switch (columnMetadata.type) {
case ColumnTypes.BOOLEAN:
return value ? true : false;
if (columnMetadata.type === Boolean) {
return value ? true : false;
case ColumnTypes.DATETIME:
return DataUtils.normalizeHydratedDate(value, columnMetadata.localTimezone === true);
} else if (columnMetadata.type === "datetime") {
return DataUtils.normalizeHydratedDate(value);
case ColumnTypes.DATE:
return DataUtils.mixedDateToDateString(value);
} else if (columnMetadata.type === "date") {
return DataUtils.mixedDateToDateString(value);
case ColumnTypes.TIME:
return DataUtils.mixedTimeToString(value);
} else if (columnMetadata.type === "time") {
return DataUtils.mixedTimeToString(value);
case ColumnTypes.JSON:
return JSON.parse(value);
} else if (columnMetadata.type === "json") {
return JSON.parse(value);
case ColumnTypes.SIMPLE_ARRAY:
return DataUtils.stringToSimpleArray(value);
} else if (columnMetadata.type === "simple-array") {
return DataUtils.stringToSimpleArray(value);
}
return value;

View File

@ -11,9 +11,10 @@ import {ForeignKeySchema} from "../../schema-builder/schema/ForeignKeySchema";
import {PrimaryKeySchema} from "../../schema-builder/schema/PrimaryKeySchema";
import {IndexSchema} from "../../schema-builder/schema/IndexSchema";
import {QueryRunnerAlreadyReleasedError} from "../../query-runner/error/QueryRunnerAlreadyReleasedError";
import {ColumnType} from "../../metadata/types/ColumnTypes";
import {ColumnType} from "../types/ColumnTypes";
import {Connection} from "../../connection/Connection";
import {OracleConnectionOptions} from "./OracleConnectionOptions";
import {ColumnOptions} from "../../decorator/options/ColumnOptions";
/**
* Runs queries on a single mysql database connection.
@ -749,72 +750,42 @@ AND cons.constraint_name = cols.constraint_name AND cons.owner = cols.owner ORDE
/**
* Creates a database type from a given column metadata.
*/
normalizeType(typeOptions: { type: ColumnType, length?: string|number, precision?: number, scale?: number, timezone?: boolean, fixedLength?: boolean }): string {
switch (typeOptions.type) {
case "string":
if (typeOptions.fixedLength) {
return "char(" + (typeOptions.length ? typeOptions.length : 255) + ")";
} else {
return "varchar2(" + (typeOptions.length ? typeOptions.length : 255) + ")";
}
case "text":
return "clob";
case "boolean":
return "number(1)";
case "integer":
case "int":
// if (column.isGenerated)
// return `number(22)`;
if (typeOptions.precision && typeOptions.scale)
return `number(${typeOptions.precision},${typeOptions.scale})`;
if (typeOptions.precision)
return `number(${typeOptions.precision},0)`;
if (typeOptions.scale)
return `number(0,${typeOptions.scale})`;
normalizeType(column: ColumnMetadata): string {
let type = "";
if (column.type === Number) {
type += "integer";
return "number(10,0)";
case "smallint":
return "number(5)";
case "bigint":
return "number(20)";
case "float":
if (typeOptions.precision && typeOptions.scale)
return `float(${typeOptions.precision},${typeOptions.scale})`;
if (typeOptions.precision)
return `float(${typeOptions.precision},0)`;
if (typeOptions.scale)
return `float(0,${typeOptions.scale})`;
} else if (column.type === String) {
type += "nvarchar2";
return `float(126)`;
case "double":
case "number":
return "float(126)";
case "decimal":
if (typeOptions.precision && typeOptions.scale) {
return `decimal(${typeOptions.precision},${typeOptions.scale})`;
} else if (column.type === Date) {
type += "timestamp(0)";
} else if (typeOptions.scale) {
return `decimal(0,${typeOptions.scale})`;
} else if (column.type === Boolean) {
type += "number(1)";
} else if (typeOptions.precision) {
return `decimal(${typeOptions.precision})`;
} else if (column.type === Object) {
type += "text";
} else {
return "decimal";
}
case "date":
return "date";
case "time":
return "date";
case "datetime":
return "timestamp(0)";
case "json":
return "clob";
case "simple_array":
return typeOptions.length ? "varchar2(" + typeOptions.length + ")" : "text";
} else if (column.type === "simple-array") {
type += "text";
} else {
type += column.type;
}
if (column.length) {
type += "(" + column.length + ")";
throw new DataTypeNotSupportedByDriverError(typeOptions.type, "Oracle");
} else if (column.precision && column.scale) {
type += "(" + column.precision + "," + column.scale + ")";
} else if (column.precision) {
type += "(" + column.precision + ")";
} else if (column.scale) {
type += "(" + column.scale + ")";
}
return type;
}
/**

View File

@ -0,0 +1,379 @@
// -------------------------------------------------------------------------
// Numeric Types
// -------------------------------------------------------------------------
/**
* Numeric type.
* Small-range integer type.
* Size: 2 bytes.
* Range: -32768 to +32767.
*/
export type SmallintColumnType = "smallint"|"int2";
/**
* Integer type.
* Size: 4 bytes.
* Range: -2147483648 to +2147483647.
*/
export type IntegerColumnType = "integer"|"int"|"int4";
/**
* Numeric type.
* Large-range integer type.
* Size: 8 bytes.
* Range: -9223372036854775808 to 9223372036854775807.
*/
export type BigintColumnType = "bigint"|"int8";
/**
* Numeric type.
* User-specified precision, exact.
* Size: variable.
* Range: up to 131072 digits before the decimal point; up to 16383 digits after the decimal point.
*/
export type DecimalColumnType = "decimal";
/**
* Numeric type.
* User-specified precision, exact.
* Size: variable.
* Range: up to 131072 digits before the decimal point; up to 16383 digits after the decimal point.
*/
export type NumericColumnType = "numeric"|"decimal";
/**
* Numeric type.
* Variable-precision, inexact.
* Size: 4 bytes.
* Range: 6 decimal digits precision.
*/
export type RealColumnType = "real"|"float4";
/**
* Numeric type.
* Variable-precision, inexact.
* Size: 8 bytes.
* Range: 15 decimal digits precision.
*/
export type DoublePrecisionColumnType = "double precision"|"float8";
/**
* Numeric type.
* Small autoincrementing integer.
* Size: 2 bytes.
* Range: 1 to 32767.
*/
export type SmallserialColumnType = "smallserial"|"serial2";
/**
* Numeric type.
* Autoincrementing integer.
* Size: 4 bytes.
* Range: 1 to 2147483647.
*/
export type SerialColumnType = "serial"|"serial4";
/**
* Numeric type.
* Large autoincrementing integer.
* Size: 8 bytes.
* Range: -92233720368547758.08 to +92233720368547758.07
*/
export type BigserialColumnType = "bigserial"|"serial8";
// -------------------------------------------------------------------------
// Monetary Types
// -------------------------------------------------------------------------
/**
* Monetary type.
* Currency amount.
* Size: 8 bytes.
* Range: 1 to 9223372036854775807.
*/
export type MoneyColumnType = "money";
// -------------------------------------------------------------------------
// Character Types
// -------------------------------------------------------------------------
/**
* Character type.
* Variable-length with limit type.
*/
export type VarcharColumnType = "character varying"|"varchar";
/**
* Character type.
* Fixed-length, blank padded type.
*/
export type CharColumnType = "character"|"char";
/**
* Character type.
* Variable-length character string.
*/
export type TextColumnType = "text";
// -------------------------------------------------------------------------
// Binary Data Types
// -------------------------------------------------------------------------
/**
* Variable-length binary string type.
* Size: 1 or 4 bytes plus the actual binary string.
*/
export type ByteaColumnType = "bytea";
// -------------------------------------------------------------------------
// Date/Time Types
// -------------------------------------------------------------------------
/**
* Both date and time type.
* With or without timezone.
* Size: 8 bytes.
* Value range: from 4713 BC to 294276 AD.
*/
export type TimestampColumnType = "timestamp";
/**
* Date (no time of day) type.
* With or without timezone.
* Size: 4 bytes.
* Value range: from 4713 BC to 5874897 AD.
*
* This column type has additional options.
*/
export type DateColumnType = "date";
/**
* Time of day (no date) type.
* With or without timezone.
* Size: 8 bytes or 12 bytes (depend on timezone).
* Value range: from 00:00:00+1459 BC to 24:00:00-1459.
*
* This column type has additional options.
*/
export type TimeColumnType = "time";
/**
* Time interval type.
* Size: 12 bytes.
* Value range: from -178000000 years to 178000000 years.
*/
export type IntervalColumnType = "interval";
// -------------------------------------------------------------------------
// Boolean Type
// -------------------------------------------------------------------------
/**
* Boolean type.
* Size: 1 byte.
*/
export type BooleanColumnType = "boolean"|"bool";
// -------------------------------------------------------------------------
// Enumerated Type
// -------------------------------------------------------------------------
/**
* Enumerated type.
* Enumerated (enum) types are data types that comprise a static, ordered set of values.
* This column type has additional options.
*/
export type EnumColumnType = "enum";
// -------------------------------------------------------------------------
// Geometric Types
// -------------------------------------------------------------------------
/**
* Geometric type - point.
* Stores values in a (x,y) format.
* Size: 16 bytes.
*/
export type PointColumnType = "point";
/**
* Geometric type - infinite line.
* Stores values in a ((x1,y1),(x2,y2)) format.
* Size: 32 bytes.
*/
export type LineColumnType = "line";
/**
* Geometric type - finite line segment.
* Stores values in a ((x1,y1),(x2,y2)) format.
* Size: 32 bytes.
*/
export type LsegColumnType = "lseg";
/**
* Geometric type - rectangular box.
* Stores values in a ((x1,y1),(x2,y2)) format.
* Size: 32 bytes.
*/
export type BoxColumnType = "box";
/**
* Geometric type - circle.
* Stores values in a <(x,y),r> format.
* Size: 24 bytes.
*/
export type CircleColumnType = "circle";
/**
* Geometric type - path.
* Size: 40+16n bytes.
*/
export type PathColumnType = "path";
/**
* Geometric type - path (similar to polygon).
*/
export type PolygonColumnType = "polygon";
// -------------------------------------------------------------------------
// Network Address Types
// -------------------------------------------------------------------------
/**
* IPv4 and IPv6 networks.
* Size: 7 or 19 bytes.
*/
export type CidrColumnType = "cidr";
/**
* IPv4 and IPv6 hosts and networks type.
* Size: 7 or 19 bytes.
*/
export type InetColumnType = "inet";
/**
* MAC addresses type.
* Size: 6 bytes.
*/
export type MacaddrColumnType = "macaddr";
// -------------------------------------------------------------------------
// Bit String Types
// -------------------------------------------------------------------------
/**
* Bit types are used to store bit masks with fixed length.
*/
export type BitColumnType = "bit";
/**
* Bit type are used to store bit masks with variable length.
*/
export type VarbitColumnType = "bit varying"|"varbit";
// -------------------------------------------------------------------------
// Text Search Types
// -------------------------------------------------------------------------
/**
* This is a sorted list of distinct words that have been normalized
* to merge different variants of the same word, called as "lexemes".
*/
export type TsvectorColumnType = "tsvector";
/**
* This stores lexemes that are to be searched for,
* and combines them honoring the Boolean operators & (AND), | (OR), and ! (NOT).
* Parentheses can be used to enforce grouping of the operators.
*/
export type TsqueryColumnType = "tsquery";
// -------------------------------------------------------------------------
// Other Types
// -------------------------------------------------------------------------
/**
* Universally Unique Identifier type.
*/
export type UUIDColumnType = "UUID";
/**
* The xml data type can be used to store XML data.
*/
export type XmlColumnType = "xml";
/**
* The json data type can be used to store JSON (JavaScript Object Notation) data.
*/
export type JsonColumnType = "json";
/**
* The jsonb data type can be used to store JSON (JavaScript Object Notation) in a binary format.
*/
export type JsonbColumnType = "jsonb";
// -------------------------------------------------------------------------
// Merged Types
// -------------------------------------------------------------------------
/**
* Column types where column length is used.
*/
export type WithLengthColumnType =
VarcharColumnType|
CharColumnType|
IntervalColumnType|
BitColumnType|
VarbitColumnType;
/**
* Column types where time options are used.
*/
export type WithTimeColumnType =
TimeColumnType|
TimestampColumnType;
/**
* All other column types without extra options used.
*/
export type SimpleColumnType =
SmallintColumnType|
IntegerColumnType|
BigintColumnType|
DecimalColumnType|
RealColumnType|
DoublePrecisionColumnType|
SmallserialColumnType|
SerialColumnType|
BigserialColumnType|
MoneyColumnType|
TextColumnType|
ByteaColumnType|
DateColumnType|
BooleanColumnType|
PointColumnType|
LineColumnType|
LsegColumnType|
BoxColumnType|
CircleColumnType|
PathColumnType|
PolygonColumnType|
CidrColumnType|
InetColumnType|
MacaddrColumnType|
TsvectorColumnType|
TsqueryColumnType|
UUIDColumnType|
XmlColumnType|
JsonColumnType|
JsonbColumnType;
/**
* All column types supported by a database.
*/
export type AllColumnType =
SimpleColumnType|
WithLengthColumnType|
WithTimeColumnType|
NumericColumnType|
EnumColumnType;

View File

@ -4,9 +4,7 @@ import {ObjectLiteral} from "../../common/ObjectLiteral";
import {DatabaseConnection} from "../DatabaseConnection";
import {DriverPackageNotInstalledError} from "../error/DriverPackageNotInstalledError";
import {DriverUtils} from "../DriverUtils";
import {ColumnTypes} from "../../metadata/types/ColumnTypes";
import {ColumnMetadata} from "../../metadata/ColumnMetadata";
import {Logger} from "../../logger/Logger";
import {PostgresQueryRunner} from "./PostgresQueryRunner";
import {QueryRunner} from "../../query-runner/QueryRunner";
import {DriverOptionNotSetError} from "../error/DriverOptionNotSetError";
@ -15,12 +13,83 @@ import {PlatformTools} from "../../platform/PlatformTools";
import {Connection} from "../../connection/Connection";
import {SchemaBuilder} from "../../schema-builder/SchemaBuilder";
import {PostgresConnectionOptions} from "./PostgresConnectionOptions";
import {MappedColumnTypes} from "../types/MappedColumnTypes";
import {ColumnType} from "../types/ColumnTypes";
/**
* Organizes communication with PostgreSQL DBMS.
*/
export class PostgresDriver implements Driver {
// -------------------------------------------------------------------------
// Public Implemented Properties
// -------------------------------------------------------------------------
/**
* Gets list of supported column data types by a driver.
*
* @see https://www.tutorialspoint.com/postgresql/postgresql_data_types.htm
* @see https://www.postgresql.org/docs/9.2/static/datatype.html
*/
supportedDataTypes: ColumnType[] = [
"smallint",
"integer",
"bigint",
"decimal",
"numeric",
"real",
"double precision",
"smallserial",
"serial",
"bigserial",
"money",
"character varying",
"varchar",
"character",
"char",
"text",
"bytea",
"timestamp",
"timestamp without time zone",
"timestamp with time zone",
"date",
"time",
"time without time zone",
"time with time zone",
"interval",
"boolean",
"enum",
"point",
"line",
"lseg",
"box",
"path",
"polygon",
"circle",
"cidr",
"inet",
"macaddr",
"tsvector",
"tsquery",
"uuid",
"xml",
"json",
"jsonb"
];
/**
* Orm has special columns and we need to know what database column types should be for those types.
* Column types are driver dependant.
*/
mappedDataTypes: MappedColumnTypes = {
createDate: "timestamp",
updateDate: "timestamp",
version: "int",
treeLevel: "int",
migrationName: "varchar",
migrationTimestamp: "timestamp",
};
// -------------------------------------------------------------------------
// Protected Properties
// -------------------------------------------------------------------------
@ -147,33 +216,29 @@ export class PostgresDriver implements Driver {
/**
* Prepares given value to a value to be persisted, based on its column type and metadata.
*/
preparePersistentValue(value: any, column: ColumnMetadata): any {
preparePersistentValue(value: any, columnMetadata: ColumnMetadata): any {
if (value === null || value === undefined)
return null;
return value;
switch (column.type) {
case ColumnTypes.BOOLEAN:
return value === true ? 1 : 0;
if (columnMetadata.type === Boolean) {
return value === true ? 1 : 0;
case ColumnTypes.DATE:
return DataUtils.mixedDateToDateString(value);
} else if (columnMetadata.type === "date") {
return DataUtils.mixedDateToDateString(value);
case ColumnTypes.TIME:
return DataUtils.mixedDateToTimeString(value);
} else if (columnMetadata.type === "time") {
return DataUtils.mixedDateToTimeString(value);
case ColumnTypes.DATETIME:
if (column.localTimezone) {
return DataUtils.mixedDateToDatetimeString(value);
} else {
return DataUtils.mixedDateToUtcDatetimeString(value);
}
} else if (columnMetadata.type === "timestamp"
|| columnMetadata.type === "timestamp with time zone"
|| columnMetadata.type === "timestamp without time zone") {
return DataUtils.mixedDateToUtcDatetimeString(value);
case ColumnTypes.JSON:
case ColumnTypes.JSONB:
return JSON.stringify(value);
} else if (columnMetadata.type === "json" || columnMetadata.type === "jsonb") {
return JSON.stringify(value);
case ColumnTypes.SIMPLE_ARRAY:
return DataUtils.simpleArrayToString(value);
} else if (columnMetadata.type === "simple-array") {
return DataUtils.simpleArrayToString(value);
}
return value;
@ -183,32 +248,26 @@ export class PostgresDriver implements Driver {
* Prepares given value to a value to be persisted, based on its column type or metadata.
*/
prepareHydratedValue(value: any, columnMetadata: ColumnMetadata): any {
switch (columnMetadata.type) {
case ColumnTypes.BOOLEAN:
return value ? true : false;
if (columnMetadata.type === Boolean) {
return value ? true : false;
case ColumnTypes.DATETIME:
return DataUtils.normalizeHydratedDate(value, columnMetadata.localTimezone === true);
} else if (columnMetadata.type === "timestamp"
|| columnMetadata.type === "timestamp with time zone"
|| columnMetadata.type === "timestamp without time zone") {
return DataUtils.normalizeHydratedDate(value);
case ColumnTypes.DATE:
return DataUtils.mixedDateToDateString(value);
} else if (columnMetadata.type === "date") {
return DataUtils.mixedDateToDateString(value);
case ColumnTypes.TIME:
return DataUtils.mixedTimeToString(value);
} else if (columnMetadata.type === "time") {
return DataUtils.mixedTimeToString(value);
case ColumnTypes.JSON:
case ColumnTypes.JSONB:
// pg(pg-types) have done JSON.parse conversion
// https://github.com/brianc/node-pg-types/blob/ed2d0e36e33217b34530727a98d20b325389e73a/lib/textParsers.js#L170
return value;
case ColumnTypes.SIMPLE_ARRAY:
return DataUtils.stringToSimpleArray(value);
} else if (columnMetadata.type === "simple-array") {
return DataUtils.stringToSimpleArray(value);
}
return value;
}
/**
* Replaces parameters in the given sql with special escaping character
* and an array of parameter names to be passed to a query.

View File

@ -11,9 +11,10 @@ import {IndexSchema} from "../../schema-builder/schema/IndexSchema";
import {ForeignKeySchema} from "../../schema-builder/schema/ForeignKeySchema";
import {PrimaryKeySchema} from "../../schema-builder/schema/PrimaryKeySchema";
import {QueryRunnerAlreadyReleasedError} from "../../query-runner/error/QueryRunnerAlreadyReleasedError";
import {ColumnType} from "../../metadata/types/ColumnTypes";
import {ColumnType} from "../types/ColumnTypes";
import {Connection} from "../../connection/Connection";
import {PostgresConnectionOptions} from "./PostgresConnectionOptions";
import {ColumnOptions} from "../../decorator/options/ColumnOptions";
/**
* Runs queries on a single postgres database connection.
@ -752,69 +753,42 @@ where constraint_type = 'PRIMARY KEY' AND c.table_schema = '${this.schemaName}'
/**
* Creates a database type from a given column metadata.
*/
normalizeType(typeOptions: { type: ColumnType, length?: string|number, precision?: number, scale?: number, timezone?: boolean, fixedLength?: boolean }): string {
switch (typeOptions.type) {
case "string":
if (typeOptions.fixedLength) {
return "character(" + (typeOptions.length ? typeOptions.length : 255) + ")";
} else {
return "character varying(" + (typeOptions.length ? typeOptions.length : 255) + ")";
}
case "text":
return "text";
case "boolean":
return "boolean";
case "integer":
case "int":
return "integer";
case "smallint":
return "smallint";
case "bigint":
return "bigint";
case "float":
return "real";
case "double":
case "number":
return "double precision";
case "decimal":
if (typeOptions.precision && typeOptions.scale) {
return `decimal(${typeOptions.precision},${typeOptions.scale})`;
normalizeType(column: ColumnMetadata): string {
let type = "";
if (column.type === Number) {
type += "integer";
} else if (typeOptions.scale) {
return `decimal(${typeOptions.scale})`;
} else if (column.type === String) {
type += "character varying";
} else if (typeOptions.precision) {
return `decimal(${typeOptions.precision})`;
} else if (column.type === Date) {
type += "timestamp";
} else {
return "decimal";
} else if (column.type === Boolean) {
type += "boolean";
}
case "date":
return "date";
case "time":
if (typeOptions.timezone) {
return "time with time zone";
} else {
return "time without time zone";
}
case "datetime":
if (typeOptions.timezone) {
return "timestamp with time zone";
} else {
return "timestamp without time zone";
}
case "json":
return "json";
case "jsonb":
return "jsonb";
case "simple_array":
return typeOptions.length ? "character varying(" + typeOptions.length + ")" : "text";
case "uuid":
return "uuid";
} else if (column.type === Object) {
type += "text";
} else if (column.type === "simple-array") {
type += "text";
} else {
type += column.type;
}
if (column.length) {
type += "(" + column.length + ")";
throw new DataTypeNotSupportedByDriverError(typeOptions.type, "Postgres");
} else if (column.precision && column.scale) {
type += "(" + column.precision + "," + column.scale + ")";
} else if (column.precision) {
type += "(" + column.precision + ")";
} else if (column.scale) {
type += "(" + column.scale + ")";
}
return type;
}
/**

View File

@ -3,7 +3,6 @@ import {ConnectionIsNotSetError} from "../error/ConnectionIsNotSetError";
import {ObjectLiteral} from "../../common/ObjectLiteral";
import {DatabaseConnection} from "../DatabaseConnection";
import {DriverPackageNotInstalledError} from "../error/DriverPackageNotInstalledError";
import {ColumnTypes} from "../../metadata/types/ColumnTypes";
import {ColumnMetadata} from "../../metadata/ColumnMetadata";
import {SqliteQueryRunner} from "./SqliteQueryRunner";
import {QueryRunner} from "../../query-runner/QueryRunner";
@ -13,12 +12,69 @@ import {PlatformTools} from "../../platform/PlatformTools";
import {Connection} from "../../connection/Connection";
import {SchemaBuilder} from "../../schema-builder/SchemaBuilder";
import {SqliteConnectionOptions} from "./SqliteConnectionOptions";
import {MappedColumnTypes} from "../types/MappedColumnTypes";
import {ColumnType} from "../types/ColumnTypes";
/**
* Organizes communication with sqlite DBMS.
*/
export class SqliteDriver implements Driver {
// -------------------------------------------------------------------------
// Public Implemented Properties
// -------------------------------------------------------------------------
/**
* Gets list of supported column data types by a driver.
*
* @see https://www.tutorialspoint.com/sqlite/sqlite_data_types.htm
* @see https://sqlite.org/datatype3.html
*/
supportedDataTypes: ColumnType[] = [
"int",
"integer",
"tinyint",
"smallint",
"mediumint",
"bigint",
"int2",
"int8",
"integer",
"character",
"varchar",
"varying character",
"nchar",
"native character",
"nvarchar",
"text",
"clob",
"text",
"blob",
"real",
"double",
"double precision",
"float",
"real",
"numeric",
"decimal",
"boolean",
"date",
"datetime",
];
/**
* Orm has special columns and we need to know what database column types should be for those types.
* Column types are driver dependant.
*/
mappedDataTypes: MappedColumnTypes = {
createDate: "datetime",
updateDate: "datetime",
version: "integer",
treeLevel: "integer",
migrationName: "varchar",
migrationTimestamp: "timestamp",
};
// -------------------------------------------------------------------------
// Protected Properties
// -------------------------------------------------------------------------
@ -129,30 +185,25 @@ export class SqliteDriver implements Driver {
*/
preparePersistentValue(value: any, columnMetadata: ColumnMetadata): any {
if (value === null || value === undefined)
return null;
return value;
switch (columnMetadata.type) {
case ColumnTypes.BOOLEAN:
return value === true ? 1 : 0;
if (columnMetadata.type === Boolean) {
return value === true ? 1 : 0;
case ColumnTypes.DATE:
return DataUtils.mixedDateToDateString(value);
} else if (columnMetadata.type === "date") {
return DataUtils.mixedDateToDateString(value);
case ColumnTypes.TIME:
return DataUtils.mixedDateToTimeString(value);
} else if (columnMetadata.type === "time") {
return DataUtils.mixedDateToTimeString(value);
case ColumnTypes.DATETIME:
if (columnMetadata.localTimezone) {
return DataUtils.mixedDateToDatetimeString(value);
} else {
return DataUtils.mixedDateToUtcDatetimeString(value);
}
} else if (columnMetadata.type === "datetime") {
return DataUtils.mixedDateToUtcDatetimeString(value);
case ColumnTypes.JSON:
return JSON.stringify(value);
} else if (columnMetadata.type === "json") {
return JSON.stringify(value);
case ColumnTypes.SIMPLE_ARRAY:
return DataUtils.simpleArrayToString(value);
} else if (columnMetadata.type === "simple-array") {
return DataUtils.simpleArrayToString(value);
}
return value;
@ -162,24 +213,23 @@ export class SqliteDriver implements Driver {
* Prepares given value to a value to be persisted, based on its column type or metadata.
*/
prepareHydratedValue(value: any, columnMetadata: ColumnMetadata): any {
switch (columnMetadata.type) {
case ColumnTypes.BOOLEAN:
return value ? true : false;
if (columnMetadata.type === Boolean) {
return value ? true : false;
case ColumnTypes.DATETIME:
return DataUtils.normalizeHydratedDate(value, columnMetadata.localTimezone === true);
} else if (columnMetadata.type === "datetime") {
return DataUtils.normalizeHydratedDate(value);
case ColumnTypes.DATE:
return DataUtils.mixedDateToDateString(value);
} else if (columnMetadata.type === "date") {
return DataUtils.mixedDateToDateString(value);
case ColumnTypes.TIME:
return DataUtils.mixedTimeToString(value);
} else if (columnMetadata.type === "time") {
return DataUtils.mixedTimeToString(value);
case ColumnTypes.JSON:
return JSON.parse(value);
} else if (columnMetadata.type === "json") {
return JSON.parse(value);
case ColumnTypes.SIMPLE_ARRAY:
return DataUtils.stringToSimpleArray(value);
} else if (columnMetadata.type === "simple-array") {
return DataUtils.stringToSimpleArray(value);
}
return value;

View File

@ -11,9 +11,10 @@ import {IndexSchema} from "../../schema-builder/schema/IndexSchema";
import {ForeignKeySchema} from "../../schema-builder/schema/ForeignKeySchema";
import {PrimaryKeySchema} from "../../schema-builder/schema/PrimaryKeySchema";
import {QueryRunnerAlreadyReleasedError} from "../../query-runner/error/QueryRunnerAlreadyReleasedError";
import {ColumnType} from "../../metadata/types/ColumnTypes";
import {ColumnType} from "../types/ColumnTypes";
import {RandomGenerator} from "../../util/RandomGenerator";
import {Connection} from "../../connection/Connection";
import {ColumnOptions} from "../../decorator/options/ColumnOptions";
/**
* Runs queries on a single sqlite database connection.
@ -737,61 +738,50 @@ export class SqliteQueryRunner implements QueryRunner {
/**
* Creates a database type from a given column metadata.
*/
normalizeType(typeOptions: { type: ColumnType, length?: string|number, precision?: number, scale?: number, timezone?: boolean, fixedLength?: boolean }): string {
switch (typeOptions.type) {
case "string":
return "character varying(" + (typeOptions.length ? typeOptions.length : 255) + ")";
case "text":
return "text";
case "boolean":
return "boolean";
case "integer":
case "int":
return "integer";
case "smallint":
return "smallint";
case "bigint":
return "bigint";
case "float":
return "real";
case "double":
case "number":
return "double precision";
case "decimal":
if (typeOptions.precision && typeOptions.scale) {
return `decimal(${typeOptions.precision},${typeOptions.scale})`;
normalizeType(column: ColumnMetadata): string {
let type = "";
if (column.type === Number || column.type === "int") {
type += "integer";
} else if (typeOptions.scale) {
return `decimal(${typeOptions.scale})`;
} else if (column.type === String) {
type += "varchar";
} else if (typeOptions.precision) {
return `decimal(${typeOptions.precision})`;
} else if (column.type === Date) {
type += "datetime";
} else {
return "decimal";
} else if (column.type === Boolean) {
type += "boolean";
}
case "date":
return "date";
case "time":
if (typeOptions.timezone) {
return "time with time zone";
} else {
return "time without time zone";
}
case "datetime":
if (typeOptions.timezone) {
return "timestamp with time zone";
} else {
return "timestamp without time zone";
}
case "json":
return "json";
case "simple_array":
return typeOptions.length ? "character varying(" + typeOptions.length + ")" : "text";
} else if (column.type === Object) {
type += "text";
} else if (column.type === "simple-array") {
type += "text";
} else {
type += column.type;
}
if (column.length) {
type += "(" + column.length + ")";
} else if (column.precision && column.scale) {
type += "(" + column.precision + "," + column.scale + ")";
} else if (column.precision) {
type += "(" + column.precision + ")";
} else if (column.scale) {
type += "(" + column.scale + ")";
}
throw new DataTypeNotSupportedByDriverError(typeOptions.type, "SQLite");
// set default required length if those were not specified
if (type === "varchar")
type += "(255)";
if (type === "int")
type += "(11)";
return type;
}
/**
@ -843,6 +833,7 @@ export class SqliteQueryRunner implements QueryRunner {
c += " UNIQUE";
if (column.isGenerated === true) // don't use skipPrimary here since updates can update already exist primary without auto inc.
c += " PRIMARY KEY AUTOINCREMENT";
if (column.default !== undefined && column.default !== null) { // todo: same code in all drivers. make it DRY
if (typeof column.default === "number") {
c += " DEFAULT " + column.default + "";

View File

@ -5,7 +5,6 @@ import {DriverPackageNotInstalledError} from "../error/DriverPackageNotInstalled
import {DriverUtils} from "../DriverUtils";
import {QueryRunner} from "../../query-runner/QueryRunner";
import {SqlServerQueryRunner} from "./SqlServerQueryRunner";
import {ColumnTypes} from "../../metadata/types/ColumnTypes";
import {ObjectLiteral} from "../../common/ObjectLiteral";
import {ColumnMetadata} from "../../metadata/ColumnMetadata";
import {DriverOptionNotSetError} from "../error/DriverOptionNotSetError";
@ -14,12 +13,72 @@ import {PlatformTools} from "../../platform/PlatformTools";
import {Connection} from "../../connection/Connection";
import {SchemaBuilder} from "../../schema-builder/SchemaBuilder";
import {SqlServerConnectionOptions} from "./SqlServerConnectionOptions";
import {MappedColumnTypes} from "../types/MappedColumnTypes";
import {ColumnType} from "../types/ColumnTypes";
/**
* Organizes communication with SQL Server DBMS.
*/
export class SqlServerDriver implements Driver {
// -------------------------------------------------------------------------
// Public Implemented Properties
// -------------------------------------------------------------------------
/**
* Gets list of supported column data types by a driver.
*
* @see https://docs.microsoft.com/en-us/sql/t-sql/data-types/data-types-transact-sql
*/
supportedDataTypes: ColumnType[] = [
"bigint",
"bit",
"decimal",
"int",
"money",
"numeric",
"smallint",
"smallmoney",
"tinyint",
"float",
"real",
"date",
"datetime2",
"datetime",
"datetimeoffset",
"smalldatetime",
"time",
"char",
"text",
"varchar",
"nchar",
"ntext",
"nvarchar",
"binary",
"image",
"varbinary",
"cursor",
"hierarchyid",
"sql_variant",
"table",
"timestamp",
"uniqueidentifier",
"xml"
];
/**
* Orm has special columns and we need to know what database column types should be for those types.
* Column types are driver dependant.
*/
mappedDataTypes: MappedColumnTypes = {
createDate: "datetime",
updateDate: "datetime",
version: "int",
treeLevel: "int",
migrationName: "varchar",
migrationTimestamp: "timestamp",
};
// -------------------------------------------------------------------------
// Protected Properties
// -------------------------------------------------------------------------
@ -190,30 +249,25 @@ export class SqlServerDriver implements Driver {
*/
preparePersistentValue(value: any, columnMetadata: ColumnMetadata): any {
if (value === null || value === undefined)
return null;
return value;
switch (columnMetadata.type) {
case ColumnTypes.BOOLEAN:
return value === true ? 1 : 0;
if (columnMetadata.type === Boolean) {
return value === true ? 1 : 0;
case ColumnTypes.DATE:
return DataUtils.mixedDateToDateString(value);
} else if (columnMetadata.type === "date") {
return DataUtils.mixedDateToDateString(value);
case ColumnTypes.TIME:
return DataUtils.mixedDateToTimeString(value);
} else if (columnMetadata.type === "time") {
return DataUtils.mixedDateToTimeString(value);
case ColumnTypes.DATETIME:
if (columnMetadata.localTimezone) {
return DataUtils.mixedDateToDatetimeString(value);
} else {
return DataUtils.mixedDateToUtcDatetimeString(value);
}
} else if (columnMetadata.type === "datetime") {
return DataUtils.mixedDateToUtcDatetimeString(value);
case ColumnTypes.JSON:
return JSON.stringify(value);
} else if (columnMetadata.type === "json") {
return JSON.stringify(value);
case ColumnTypes.SIMPLE_ARRAY:
return DataUtils.simpleArrayToString(value);
} else if (columnMetadata.type === "simple-array") {
return DataUtils.simpleArrayToString(value);
}
return value;
@ -223,29 +277,27 @@ export class SqlServerDriver implements Driver {
* Prepares given value to a value to be persisted, based on its column type or metadata.
*/
prepareHydratedValue(value: any, columnMetadata: ColumnMetadata): any {
switch (columnMetadata.type) {
case ColumnTypes.BOOLEAN:
return value ? true : false;
if (columnMetadata.type === Boolean) {
return value ? true : false;
case ColumnTypes.DATETIME:
return DataUtils.normalizeHydratedDate(value, columnMetadata.localTimezone === true);
} else if (columnMetadata.type === "datetime") {
return DataUtils.normalizeHydratedDate(value);
case ColumnTypes.DATE:
return DataUtils.mixedDateToDateString(value);
} else if (columnMetadata.type === "date") {
return DataUtils.mixedDateToDateString(value);
case ColumnTypes.TIME:
return DataUtils.mixedTimeToString(value);
} else if (columnMetadata.type === "time") {
return DataUtils.mixedTimeToString(value);
case ColumnTypes.JSON:
return JSON.parse(value);
} else if (columnMetadata.type === "json") {
return JSON.parse(value);
case ColumnTypes.SIMPLE_ARRAY:
return DataUtils.stringToSimpleArray(value);
} else if (columnMetadata.type === "simple-array") {
return DataUtils.stringToSimpleArray(value);
}
return value;
}
// -------------------------------------------------------------------------
// Protected Methods
// -------------------------------------------------------------------------

View File

@ -11,9 +11,10 @@ import {ForeignKeySchema} from "../../schema-builder/schema/ForeignKeySchema";
import {PrimaryKeySchema} from "../../schema-builder/schema/PrimaryKeySchema";
import {IndexSchema} from "../../schema-builder/schema/IndexSchema";
import {QueryRunnerAlreadyReleasedError} from "../../query-runner/error/QueryRunnerAlreadyReleasedError";
import {ColumnType} from "../../metadata/types/ColumnTypes";
import {ColumnType} from "../types/ColumnTypes";
import {Connection} from "../../connection/Connection";
import {SqlServerConnectionOptions} from "./SqlServerConnectionOptions";
import {ColumnOptions} from "../../decorator/options/ColumnOptions";
/**
* Runs queries on a single mysql database connection.
@ -798,56 +799,42 @@ WHERE columnUsages.TABLE_CATALOG = '${this.dbName}' AND tableConstraints.TABLE_C
/**
* Creates a database type from a given column metadata.
*/
normalizeType(typeOptions: { type: ColumnType, length?: string|number, precision?: number, scale?: number, timezone?: boolean, fixedLength?: boolean }): string {
switch (typeOptions.type) {
case "string":
if (typeOptions.fixedLength) {
return "nchar(" + (typeOptions.length ? typeOptions.length : 255) + ")";
} else {
return "nvarchar(" + (typeOptions.length ? typeOptions.length : 255) + ")";
}
case "text":
return "ntext";
case "boolean":
return "bit";
case "integer":
case "int":
return "int";
case "smallint":
return "smallint";
case "bigint":
return "bigint";
case "float":
return "float";
case "double":
case "number":
return "real";
case "decimal":
// if (column.precision && column.scale) {
// return `decimal(${column.precision},${column.scale})`;
//
// } else if (column.scale) {
// return `decimal(${column.scale})`;
//
// } else if (column.precision) {
// return `decimal(${column.precision})`;
//
// } else {
return "decimal";
// }
case "date":
return "date";
case "time":
return "time";
case "datetime":
return "datetime";
case "json":
return "text";
case "simple_array":
return typeOptions.length ? "nvarchar(" + typeOptions.length + ")" : "text";
}
normalizeType(column: ColumnMetadata): string {
let type = "";
if (column.type === Number) {
type += "int";
throw new DataTypeNotSupportedByDriverError(typeOptions.type, "SQLServer");
} else if (column.type === String) {
type += "nvarchar";
} else if (column.type === Date) {
type += "datetime";
} else if (column.type === Boolean) {
type += "bit";
} else if (column.type === Object) {
type += "ntext";
} else if (column.type === "simple-array") {
type += "ntext";
} else {
type += column.type;
}
if (column.length) {
type += "(" + column.length + ")";
} else if (column.precision && column.scale) {
type += "(" + column.precision + "," + column.scale + ")";
} else if (column.precision) {
type += "(" + column.precision + ")";
} else if (column.scale) {
type += "(" + column.scale + ")";
}
return type;
}
/**

View File

@ -0,0 +1,417 @@
/**
* Column types where precision and scale properties are used.
*/
export type WithPrecisionColumnType = "float" // mysql, mssql, oracle, sqlite
|"double" // mysql, sqlite
|"dec" // oracle
|"decimal" // mysql, postgres, mssql, sqlite
|"numeric" // postgres, mssql, sqlite
|"real" // mysql, postgres, mssql, oracle, sqlite
|"double precision" // postgres, oracle, sqlite
|"number"; // oracle
/**
* Column types where column length is used.
*/
export type WithLengthColumnType = "int" // mysql, postgres, mssql, oracle, sqlite
|"tinyint" // mysql, mssql, sqlite
|"smallint" // mysql, postgres, mssql, oracle, sqlite
|"mediumint" // mysql, sqlite
|"bigint" // mysql, postgres, mssql, sqlite
|"character varying" // postgres
|"varying character" // sqlite
|"nvarchar" // mssql
|"character" // mysql, postgres, sqlite
|"native character" // sqlite
|"varchar" // mysql, postgres, mssql, sqlite
|"char" // mysql, postgres, mssql, oracle
|"nchar" // mssql, oracle, sqlite
|"varchar2" // oracle
|"nvarchar2" // oracle, sqlite
|"year"; // mysql
/**
* All other regular column types.
*/
export type SimpleColumnType =
"simple-array" // typeorm-specific, automatically mapped to string
// |"string" // typeorm-specific, automatically mapped to varchar depend on platform
// numeric types
|"bit" // mssql
|"int2" // postgres, sqlite
|"integer" // postgres, oracle, sqlite
|"int4" // postgres
|"int8" // postgres, sqlite
|"float4" // postgres
|"float8" // postgres
|"smallserial" // postgres
|"serial2" // postgres
|"serial" // postgres
|"serial4" // postgres
|"bigserial" // postgres
|"serial8" // postgres
|"smallmoney" // mssql
|"money" // postgres, mssql
// boolean types
|"boolean" // postgres, sqlite
|"bool" // postgres
// text/binary types
|"tinyblob" // mysql
|"tinytext" // mysql
|"mediumblob" // mysql
|"mediumtext" // mysql
|"blob" // mysql, oracle, sqlite
|"text" // mysql, postgres, mssql, sqlite
|"ntext" // mssql
|"longblob" // mysql
|"longtext" // mysql
|"bytea" // postgres
|"long" // oracle
|"raw" // oracle
|"long raw" // oracle
|"bfile" // oracle
|"clob" // oracle, sqlite
|"nclob" // oracle
|"binary" // mssql
|"varbinary" // mssql
|"image" // mssql
// date types
|"timestamp" // mysql, postgres, mssql, oracle
|"timestamp without time zone" // postgres
|"timestamp with time zone" // postgres, oracle
|"timestamp with local time zone" // oracle
|"datetime" // mssql, mysql, sqlite
|"datetime2" // mssql
|"datetimeoffset" // mssql
|"smalldatetime" // mssql
|"date" // mysql, postgres, mssql, oracle, sqlite
|"time" // mysql, postgres, mssql
|"time with time zone" // postgres
|"time without time zone" // postgres
|"interval year" // oracle
|"interval day" // oracle
|"interval" // postgres
// geometric types
|"point" // postgres
|"line" // postgres
|"lseg" // postgres
|"box" // postgres
|"circle" // postgres
|"path" // postgres
|"polygon" // postgres
// other types
|"enum" // mysql, postgres
|"cidr" // postgres
|"inet" // postgres
|"macaddr"// postgres
|"bit" // postgres
|"bit varying" // postgres
|"varbit"// postgres
|"tsvector" // postgres
|"tsquery" // postgres
|"uuid" // postgres
|"xml" // mssql, postgres
|"json" // postgres
|"jsonb" // postgres
|"varbinary" // mssql
|"cursor" // mssql
|"hierarchyid" // mssql
|"sql_variant" // mssql
|"table" // mssql
|"rowid" // oracle
|"urowid" // oracle
|"uniqueidentifier"; // mssql
/**
* Any column type column can be.
*/
export type ColumnType = WithPrecisionColumnType
|WithLengthColumnType
|SimpleColumnType
|BooleanConstructor
|DateConstructor
|NumberConstructor
|StringConstructor
|ObjectConstructor;
// "string"|"text"|"number"|"integer"|"int"|"smallint"|"bigint"|"float"|"double"|
// "decimal"|"date"|"time"|"datetime"|"boolean"|"json"|"jsonb"|"simple_array"|"uuid";
// -------------------------------------------------------------------------
// Merged Types
// -------------------------------------------------------------------------
/*
/!**
* Column types where column length is used.
*!/
export type WithLengthColumnType =
VarcharColumnType|
CharColumnType|
IntervalColumnType|
BitColumnType|
VarbitColumnType;
/!**
* Column types where time options are used.
*!/
export type WithTimeColumnType =
TimeColumnType|
TimestampColumnType;
/!**
* All other column types without extra options used.
*!/
export type SimpleColumnType =
SmallintColumnType|
IntegerColumnType|
BigintColumnType|
DecimalColumnType|
RealColumnType|
DoublePrecisionColumnType|
SmallserialColumnType|
SerialColumnType|
BigserialColumnType|
MoneyColumnType|
TextColumnType|
ByteaColumnType|
DateColumnType|
BooleanColumnType|
PointColumnType|
LineColumnType|
LsegColumnType|
BoxColumnType|
CircleColumnType|
PathColumnType|
PolygonColumnType|
CidrColumnType|
InetColumnType|
MacaddrColumnType|
TsvectorColumnType|
TsqueryColumnType|
UUIDColumnType|
XmlColumnType|
JsonColumnType|
JsonbColumnType;
/!**
* All column types supported by a database.
*!/
export type AllColumnType =
SimpleColumnType|
WithLengthColumnType|
WithTimeColumnType|
NumericColumnType|
EnumColumnType;
/!**
* All data types that column can be.
*!/
export type ColumnType =
"tinyint"|
"smallint"|
"int2"|
"mediumint"|
"integer"|
"int"|
"int4"|
"bigint"|
"int8"|
"decimal"|
"numeric"|
"real"|
"float4"|
"float"|
"double"|
"double precision"|
"numeric"|
"decimal"|
"string"|"text"|"number"|"integer"|"int"|"smallint"|"bigint"|"float"|"double"|
"decimal"|"date"|"time"|"datetime"|"boolean"|"json"|"jsonb"|"simple_array"|"uuid";*/
/*
/!**
* All data types that column can be.
*!/
export class ColumnTypes {
/!**
* SQL VARCHAR type. Your class's property type should be a "string".
*!/
static STRING: ColumnType = "string";
/!**
* SQL CLOB type. Your class's property type should be a "string".
*!/
static TEXT: ColumnType = "text";
/!**
* SQL FLOAT type. Your class's property type should be a "number".
*!/
static NUMBER: ColumnType = "number";
/!**
* SQL INT type. Your class's property type should be a "number".
*!/
static INTEGER: ColumnType = "integer";
/!**
* SQL INT type. Your class's property type should be a "number".
*!/
static INT: ColumnType = "int";
/!**
* SQL SMALLINT type. Your class's property type should be a "number".
*!/
static SMALLINT: ColumnType = "smallint";
/!**
* SQL BIGINT type. Your class's property type should be a "number".
*!/
static BIGINT: ColumnType = "bigint";
/!**
* SQL FLOAT type. Your class's property type should be a "number".
*!/
static FLOAT: ColumnType = "float";
/!**
* SQL FLOAT type. Your class's property type should be a "number".
*!/
static DOUBLE: ColumnType = "double";
/!**
* SQL DECIMAL type. Your class's property type should be a "string".
*!/
static DECIMAL: ColumnType = "decimal";
/!**
* SQL DATETIME type. Your class's property type should be a "Date" object.
*!/
static DATE: ColumnType = "date";
/!**
* SQL TIME type. Your class's property type should be a "Date" object.
*!/
static TIME: ColumnType = "time";
/!**
* SQL DATETIME/TIMESTAMP type. Your class's property type should be a "Date" object.
*!/
static DATETIME: ColumnType = "datetime";
/!**
* SQL BOOLEAN type. Your class's property type should be a "boolean".
*!/
static BOOLEAN: ColumnType = "boolean";
/!**
* SQL CLOB type. Your class's property type should be any Object.
*!/
static JSON: ColumnType = "json";
/!**
* Postgres jsonb type. Your class's property type should be any Object.
*!/
static JSONB: ColumnType = "jsonb";
/!**
* 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: ColumnType = "simple_array";
/!**
* UUID type. Serialized to a string in typescript or javascript
*!/
static UUID: ColumnType = "uuid";
/!**
* Checks if given type in a string format is supported by ORM.
*!/
static isTypeSupported(type: string) {
return this.supportedTypes.indexOf(<ColumnType> 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.JSONB,
this.SIMPLE_ARRAY,
this.UUID
];
}
/!**
* Tries to guess a column type from the given function.
*!/
static determineTypeFromFunction(type: Function): ColumnType|undefined {
if (type instanceof Date) {
return ColumnTypes.DATETIME;
} else if (type instanceof Function) {
const typeName = (<any>type).name.toLowerCase();
switch (typeName) {
case "number":
return ColumnTypes.NUMBER;
case "boolean":
return ColumnTypes.BOOLEAN;
case "string":
return ColumnTypes.STRING;
case "date":
return ColumnTypes.DATETIME;
case "object":
return ColumnTypes.JSON;
}
} else if (type instanceof Object) {
return ColumnTypes.JSON;
}
return undefined;
}
static typeToString(type: Function): string {
return (type as any).name.toLowerCase();
}
/!**
* Checks if column type is numeric.
*!/
static isNumeric(type: ColumnType) {
return type === ColumnTypes.NUMBER ||
type === ColumnTypes.INT ||
type === ColumnTypes.INTEGER ||
type === ColumnTypes.BIGINT ||
type === ColumnTypes.SMALLINT ||
type === ColumnTypes.DOUBLE ||
type === ColumnTypes.FLOAT;
}
}*/

View File

@ -0,0 +1,39 @@
import {ColumnType} from "./ColumnTypes";
/**
* Orm has special columns and we need to know what database column types should be for those types.
* Column types are driver dependant.
*/
export interface MappedColumnTypes {
/**
* Column type for the create date column.
*/
createDate: ColumnType;
/**
* Column type for the update date column.
*/
updateDate: ColumnType;
/**
* Column type for the version column.
*/
version: ColumnType;
/**
* Column type for the tree level column.
*/
treeLevel: ColumnType;
/**
* Column type of timestamp column used for migrations table.
*/
migrationTimestamp: ColumnType;
/**
* Column type for migration name column used for migrations table.
*/
migrationName: ColumnType;
}

View File

@ -3,7 +3,6 @@ import {ConnectionIsNotSetError} from "../error/ConnectionIsNotSetError";
import {DatabaseConnection} from "../DatabaseConnection";
import {DriverUtils} from "../DriverUtils";
import {QueryRunner} from "../../query-runner/QueryRunner";
import {ColumnTypes} from "../../metadata/types/ColumnTypes";
import {ObjectLiteral} from "../../common/ObjectLiteral";
import {ColumnMetadata} from "../../metadata/ColumnMetadata";
import {DriverOptionNotSetError} from "../error/DriverOptionNotSetError";
@ -12,6 +11,8 @@ import {WebsqlQueryRunner} from "./WebsqlQueryRunner";
import {Connection} from "../../connection/Connection";
import {SchemaBuilder} from "../../schema-builder/SchemaBuilder";
import {WebSqlConnectionOptions} from "./WebSqlConnectionOptions";
import {MappedColumnTypes} from "../types/MappedColumnTypes";
import {ColumnType} from "../types/ColumnTypes";
/**
* Declare a global function that is only available in browsers that support WebSQL.
@ -23,6 +24,61 @@ declare function openDatabase(...params: any[]): any;
*/
export class WebsqlDriver implements Driver {
// -------------------------------------------------------------------------
// Public Implemented Properties
// -------------------------------------------------------------------------
/**
* Gets list of supported column data types by a driver.
*
* @see https://www.tutorialspoint.com/sqlite/sqlite_data_types.htm
* @see https://sqlite.org/datatype3.html
*/
supportedDataTypes: ColumnType[] = [
"int",
"integer",
"tinyint",
"smallint",
"mediumint",
"bigint",
"int2",
"int8",
"integer",
"character",
"varchar",
"varying character",
"nchar",
"native character",
"nvarchar",
"text",
"clob",
"text",
"blob",
"real",
"double",
"double precision",
"float",
"real",
"numeric",
"decimal",
"boolean",
"date",
"datetime",
];
/**
* Orm has special columns and we need to know what database column types should be for those types.
* Column types are driver dependant.
*/
mappedDataTypes: MappedColumnTypes = {
createDate: "datetime",
updateDate: "datetime",
version: "number",
treeLevel: "number",
migrationName: "varchar",
migrationTimestamp: "timestamp",
};
// -------------------------------------------------------------------------
// Protected Properties
// -------------------------------------------------------------------------
@ -172,30 +228,25 @@ export class WebsqlDriver implements Driver {
*/
preparePersistentValue(value: any, columnMetadata: ColumnMetadata): any {
if (value === null || value === undefined)
return null;
return value;
switch (columnMetadata.type) {
case ColumnTypes.BOOLEAN:
return value === true ? 1 : 0;
if (columnMetadata.type === Boolean) {
return value === true ? 1 : 0;
case ColumnTypes.DATE:
return DataUtils.mixedDateToDateString(value);
} else if (columnMetadata.type === "date") {
return DataUtils.mixedDateToDateString(value);
case ColumnTypes.TIME:
return DataUtils.mixedDateToTimeString(value);
} else if (columnMetadata.type === "time") {
return DataUtils.mixedDateToTimeString(value);
case ColumnTypes.DATETIME:
if (columnMetadata.localTimezone) {
return DataUtils.mixedDateToDatetimeString(value);
} else {
return DataUtils.mixedDateToUtcDatetimeString(value);
}
} else if (columnMetadata.type === "datetime") {
return DataUtils.mixedDateToUtcDatetimeString(value);
case ColumnTypes.JSON:
return JSON.stringify(value);
} else if (columnMetadata.type === "json") {
return JSON.stringify(value);
case ColumnTypes.SIMPLE_ARRAY:
return DataUtils.simpleArrayToString(value);
} else if (columnMetadata.type === "simple-array") {
return DataUtils.simpleArrayToString(value);
}
return value;
@ -205,29 +256,27 @@ export class WebsqlDriver implements Driver {
* Prepares given value to a value to be persisted, based on its column type or metadata.
*/
prepareHydratedValue(value: any, columnMetadata: ColumnMetadata): any {
switch (columnMetadata.type) {
case ColumnTypes.BOOLEAN:
return value ? true : false;
if (columnMetadata.type === Boolean) {
return value ? true : false;
case ColumnTypes.DATETIME:
return DataUtils.normalizeHydratedDate(value, columnMetadata.localTimezone === true);
} else if (columnMetadata.type === "datetime") {
return DataUtils.normalizeHydratedDate(value);
case ColumnTypes.DATE:
return DataUtils.mixedDateToDateString(value);
} else if (columnMetadata.type === "date") {
return DataUtils.mixedDateToDateString(value);
case ColumnTypes.TIME:
return DataUtils.mixedTimeToString(value);
} else if (columnMetadata.type === "time") {
return DataUtils.mixedTimeToString(value);
case ColumnTypes.JSON:
return JSON.parse(value);
} else if (columnMetadata.type === "json") {
return JSON.parse(value);
case ColumnTypes.SIMPLE_ARRAY:
return DataUtils.stringToSimpleArray(value);
} else if (columnMetadata.type === "simple-array") {
return DataUtils.stringToSimpleArray(value);
}
return value;
}
// -------------------------------------------------------------------------
// Protected Methods
// -------------------------------------------------------------------------

View File

@ -10,8 +10,9 @@ import {TableSchema} from "../../schema-builder/schema/TableSchema";
import {ForeignKeySchema} from "../../schema-builder/schema/ForeignKeySchema";
import {IndexSchema} from "../../schema-builder/schema/IndexSchema";
import {QueryRunnerAlreadyReleasedError} from "../../query-runner/error/QueryRunnerAlreadyReleasedError";
import {ColumnType} from "../../metadata/types/ColumnTypes";
import {ColumnType} from "../types/ColumnTypes";
import {Connection} from "../../connection/Connection";
import {ColumnOptions} from "../../decorator/options/ColumnOptions";
/**
* Runs queries on a single websql database connection.
@ -740,64 +741,46 @@ export class WebsqlQueryRunner implements QueryRunner {
await this.query(sql);
}
/**
* Creates a database type from a given column metadata.
*/
normalizeType(typeOptions: { type: ColumnType, length?: string|number, precision?: number, scale?: number, timezone?: boolean, fixedLength?: boolean }): string {
switch (typeOptions.type) {
case "string":
return "character varying(" + (typeOptions.length ? typeOptions.length : 255) + ")";
case "text":
return "text";
case "boolean":
return "boolean";
case "integer":
case "int":
return "integer";
case "smallint":
return "smallint";
case "bigint":
return "bigint";
case "float":
return "real";
case "double":
case "number":
return "double precision";
case "decimal":
if (typeOptions.precision && typeOptions.scale) {
return `decimal(${typeOptions.precision},${typeOptions.scale})`;
normalizeType(column: ColumnMetadata): string {
let type = "";
if (column.type === Number) {
type += "integer";
} else if (typeOptions.scale) {
return `decimal(${typeOptions.scale})`;
} else if (column.type === String) {
type += "varchar";
} else if (typeOptions.precision) {
return `decimal(${typeOptions.precision})`;
} else if (column.type === Date) {
type += "datetime";
} else {
return "decimal";
} else if (column.type === Boolean) {
type += "boolean";
}
case "date":
return "date";
case "time":
if (typeOptions.timezone) {
return "time with time zone";
} else {
return "time without time zone";
}
case "datetime":
if (typeOptions.timezone) {
return "timestamp with time zone";
} else {
return "timestamp without time zone";
}
case "json":
return "json";
case "simple_array":
return typeOptions.length ? "character varying(" + typeOptions.length + ")" : "text";
} else if (column.type === Object) {
type += "text";
} else if (column.type === "simple-array") {
type += "text";
} else {
type += column.type;
}
if (column.length) {
type += "(" + column.length + ")";
throw new DataTypeNotSupportedByDriverError(typeOptions.type, "WebSQL");
} else if (column.precision && column.scale) {
type += "(" + column.precision + "," + column.scale + ")";
} else if (column.precision) {
type += "(" + column.precision + ")";
} else if (column.scale) {
type += "(" + column.scale + ")";
}
return type;
}
/**

View File

@ -1,7 +1,7 @@
import {TableType} from "../metadata/types/TableTypes";
import {OrderByCondition} from "../find-options/OrderByCondition";
import {JoinColumnOptions} from "../decorator/options/JoinColumnOptions";
import {ColumnType} from "../metadata/types/ColumnTypes";
import {ColumnType} from "../driver/types/ColumnTypes";
import {RelationType} from "../metadata/types/RelationTypes";
import {JoinTableMultipleColumnsOptions} from "../decorator/options/JoinTableMuplipleColumnsOptions";
import {OnDeleteType} from "../metadata/types/OnDeleteType";

View File

@ -1,36 +0,0 @@
import {ColumnMetadata} from "../metadata/ColumnMetadata";
import {NamingStrategyInterface} from "../naming-strategy/NamingStrategyInterface";
import {RelationMetadata} from "../metadata/RelationMetadata";
import {IndexMetadata} from "../metadata/IndexMetadata";
import {ForeignKeyMetadata} from "../metadata/ForeignKeyMetadata";
import {EmbeddedMetadata} from "../metadata/EmbeddedMetadata";
import {RelationIdMetadata} from "../metadata/RelationIdMetadata";
import {RelationCountMetadata} from "../metadata/RelationCountMetadata";
import {OrderByCondition} from "../find-options/OrderByCondition";
import {TableType} from "../metadata/types/TableTypes";
/**
* Arguments for EntityMetadata class.
*/
export interface EntityMetadataArgs {
readonly junction: boolean;
readonly target: Function|string;
readonly tablesPrefix?: string;
readonly tableName?: string;
readonly tableType: TableType;
readonly inheritanceType?: "single-table"|"class-table";
readonly discriminatorValue?: string;
readonly namingStrategy: NamingStrategyInterface;
readonly columnMetadatas?: ColumnMetadata[];
readonly relationMetadatas?: RelationMetadata[];
readonly relationIdMetadatas?: RelationIdMetadata[];
readonly relationCountMetadatas?: RelationCountMetadata[];
readonly indexMetadatas?: IndexMetadata[];
readonly foreignKeyMetadatas?: ForeignKeyMetadata[];
readonly embeddedMetadatas?: EmbeddedMetadata[];
readonly engine?: string;
readonly skipSchemaSync?: boolean;
readonly orderBy?: OrderByCondition|((object: any) => OrderByCondition|any);
}

View File

@ -36,6 +36,6 @@ export interface TableMetadataArgs {
/**
* Whether table must be synced during schema build or not
*/
skipSchemaSync?: boolean;
skipSync?: boolean;
}

View File

@ -1,9 +1,7 @@
import {EntityMetadata} from "../metadata/EntityMetadata";
import {ColumnMetadata} from "../metadata/ColumnMetadata";
import {ForeignKeyMetadata} from "../metadata/ForeignKeyMetadata";
import {ColumnTypes} from "../metadata/types/ColumnTypes";
import {Connection} from "../connection/Connection";
import {LazyRelationsWrapper} from "../lazy-loading/LazyRelationsWrapper";
/**
* Creates EntityMetadata for junction tables of the closure entities.
@ -41,6 +39,7 @@ export class ClosureJunctionEntityMetadataBuilder {
// create ancestor and descendant columns for new closure junction table
parentClosureEntityMetadata.primaryColumns.forEach(primaryColumn => {
entityMetadata.ownColumns.push(new ColumnMetadata({
connection: this.connection,
entityMetadata: entityMetadata,
args: {
target: "",
@ -53,6 +52,7 @@ export class ClosureJunctionEntityMetadataBuilder {
}
}));
entityMetadata.ownColumns.push(new ColumnMetadata({
connection: this.connection,
entityMetadata: entityMetadata,
args: {
target: "",
@ -69,13 +69,14 @@ export class ClosureJunctionEntityMetadataBuilder {
// if tree level column was defined by a closure entity then add it to the junction columns as well
if (parentClosureEntityMetadata.treeLevelColumn) {
entityMetadata.ownColumns.push(new ColumnMetadata({
connection: this.connection,
entityMetadata: entityMetadata,
args: {
target: "",
mode: "virtual",
propertyName: "level",
options: {
type: ColumnTypes.INTEGER,
type: this.connection.driver.mappedDataTypes.treeLevel,
}
}
}));

View File

@ -170,6 +170,7 @@ export class EntityMetadataBuilder {
const parentRelationColumns = parentPrimaryColumns.map(parentPrimaryColumn => {
const columnName = this.connection.namingStrategy.classTableInheritanceParentColumnName(metadata.parentEntityMetadata.tableName, parentPrimaryColumn.propertyPath);
const column = new ColumnMetadata({
connection: this.connection,
entityMetadata: metadata,
referencedColumn: parentPrimaryColumn,
args: {
@ -265,7 +266,7 @@ export class EntityMetadataBuilder {
entityMetadata.embeddeds = this.createEmbeddedsRecursively(entityMetadata, this.metadataArgsStorage.filterEmbeddeds(inheritanceTree));
entityMetadata.ownColumns = this.metadataArgsStorage.filterColumns(inheritanceTree).map(args => {
const column = new ColumnMetadata({ entityMetadata, args });
const column = new ColumnMetadata({ connection: this.connection, entityMetadata, args });
// console.log(column.propertyName);
// if single table inheritance used, we need to mark all inherit table columns as nullable
if (singleTableChildrenTargets && singleTableChildrenTargets.indexOf(args.target) !== -1)
@ -299,7 +300,7 @@ export class EntityMetadataBuilder {
return embeddedArgs.map(embeddedArgs => {
const embeddedMetadata = new EmbeddedMetadata({ entityMetadata: entityMetadata, args: embeddedArgs });
embeddedMetadata.columns = this.metadataArgsStorage.filterColumns(embeddedMetadata.type).map(args => {
return new ColumnMetadata({ entityMetadata, embeddedMetadata, args});
return new ColumnMetadata({ connection: this.connection, entityMetadata, embeddedMetadata, args});
});
embeddedMetadata.relations = this.metadataArgsStorage.filterRelations(embeddedMetadata.type).map(args => {
return new RelationMetadata({ entityMetadata, embeddedMetadata, args });

View File

@ -56,6 +56,7 @@ export class JunctionEntityMetadataBuilder {
const columnName = joinColumn && joinColumn.name ? joinColumn.name : this.connection.namingStrategy.joinTableColumnName(relation.entityMetadata.tableNameWithoutPrefix, referencedColumn.propertyName, referencedColumn.databaseName);
return new ColumnMetadata({
connection: this.connection,
entityMetadata: entityMetadata,
referencedColumn: referencedColumn,
args: {
@ -82,6 +83,7 @@ export class JunctionEntityMetadataBuilder {
const columnName = joinColumn && joinColumn.name ? joinColumn.name : this.connection.namingStrategy.joinTableColumnName(relation.inverseEntityMetadata.tableNameWithoutPrefix, inverseReferencedColumn.propertyName, inverseReferencedColumn.databaseName);
return new ColumnMetadata({
connection: this.connection,
entityMetadata: entityMetadata,
referencedColumn: inverseReferencedColumn,
args: {

View File

@ -107,6 +107,7 @@ export class RelationJoinColumnBuilder {
let relationalColumn = relation.entityMetadata.ownColumns.find(column => column.databaseName === joinColumnName);
if (!relationalColumn) {
relationalColumn = new ColumnMetadata({
connection: this.connection,
entityMetadata: relation.entityMetadata,
args: {
target: "",

View File

@ -1,10 +1,11 @@
import {ColumnType} from "./types/ColumnTypes";
import {ColumnType} from "../driver/types/ColumnTypes";
import {EntityMetadata} from "./EntityMetadata";
import {EmbeddedMetadata} from "./EmbeddedMetadata";
import {RelationMetadata} from "./RelationMetadata";
import {ObjectLiteral} from "../common/ObjectLiteral";
import {NamingStrategyInterface} from "../naming-strategy/NamingStrategyInterface";
import {ColumnMetadataArgs} from "../metadata-args/ColumnMetadataArgs";
import {Connection} from "../connection/Connection";
/**
* This metadata contains all information about entity's column.
@ -93,24 +94,9 @@ export class ColumnMetadata {
scale?: number;
/**
* Indicates if date column will contain a timezone.
* Used only for date-typed column types.
* Note that timezone option is not supported by all databases (only postgres for now).
* Array of possible enumerated values.
*/
timezone: boolean = false;
/**
* Indicates if date object must be stored in given date's timezone.
* By default date is saved in UTC timezone.
* Works only with "datetime" columns.
*/
localTimezone: boolean = false;
/**
* Indicates if column's type will be set as a fixed-length data type.
* Works only with "string" columns.
*/
fixedLength: boolean = false;
enum?: any[];
/**
* Gets full path to this column property (including column property name).
@ -186,6 +172,7 @@ export class ColumnMetadata {
// ---------------------------------------------------------------------
constructor(options: {
connection: Connection,
entityMetadata: EntityMetadata,
embeddedMetadata?: EmbeddedMetadata,
referencedColumn?: ColumnMetadata,
@ -208,6 +195,8 @@ export class ColumnMetadata {
this.isGenerated = options.args.options.generated;
if (options.args.options.unique)
this.isUnique = options.args.options.unique;
if (options.args.options.default === null) // to make sure default: null is the same as nullable: true
this.isNullable = true;
if (options.args.options.nullable)
this.isNullable = options.args.options.nullable;
if (options.args.options.comment)
@ -218,12 +207,8 @@ export class ColumnMetadata {
this.scale = options.args.options.scale;
if (options.args.options.precision)
this.precision = options.args.options.precision;
if (options.args.options.timezone)
this.timezone = options.args.options.timezone;
if (options.args.options.localTimezone)
this.localTimezone = options.args.options.localTimezone;
if (options.args.options.fixedLength)
this.fixedLength = options.args.options.fixedLength;
if (options.args.options.enum)
this.enum = options.args.options.enum;
if (options.args.mode) {
this.isVirtual = options.args.mode === "virtual";
this.isParentId = options.args.mode === "parentId";
@ -234,6 +219,14 @@ export class ColumnMetadata {
this.isVersion = options.args.mode === "version";
this.isObjectId = options.args.mode === "objectId";
}
if (this.isTreeLevel)
this.type = options.connection.driver.mappedDataTypes.treeLevel;
if (this.isCreateDate)
this.type = options.connection.driver.mappedDataTypes.createDate;
if (this.isUpdateDate)
this.type = options.connection.driver.mappedDataTypes.updateDate;
if (this.isVersion)
this.type = options.connection.driver.mappedDataTypes.version;
}
// ---------------------------------------------------------------------

View File

@ -118,7 +118,7 @@ export class EntityMetadata {
/**
* Indicates if schema sync is skipped for this entity.
*/
skipSchemaSync: boolean;
skipSync: boolean;
/**
* Table's database engine type (like "InnoDB", "MyISAM", etc).
@ -362,7 +362,7 @@ export class EntityMetadata {
this.tableType = options.args.type;
this.engine = options.args.engine;
this.givenTableName = options.args.name;
this.skipSchemaSync = options.args.skipSchemaSync || false;
this.skipSync = options.args.skipSync || false;
this.targetName = options.args.target instanceof Function ? (options.args.target as any).name : options.args.target;
this.tableNameWithoutPrefix = this.tableType === "closure-junction" ? namingStrategy.closureJunctionTableName(this.givenTableName!) : namingStrategy.tableName(this.targetName, this.givenTableName);
this.tableName = tablesPrefix ? namingStrategy.prefixTableName(tablesPrefix, this.tableNameWithoutPrefix) : this.tableNameWithoutPrefix;

View File

@ -1,183 +0,0 @@
/**
* All data types that column can be.
*/
export type ColumnType = "string"|"text"|"number"|"integer"|"int"|"smallint"|"bigint"|"float"|"double"|
"decimal"|"date"|"time"|"datetime"|"boolean"|"json"|"jsonb"|"simple_array"|"uuid";
/**
* All data types that column can be.
*/
export class ColumnTypes {
/**
* SQL VARCHAR type. Your class's property type should be a "string".
*/
static STRING: ColumnType = "string";
/**
* SQL CLOB type. Your class's property type should be a "string".
*/
static TEXT: ColumnType = "text";
/**
* SQL FLOAT type. Your class's property type should be a "number".
*/
static NUMBER: ColumnType = "number";
/**
* SQL INT type. Your class's property type should be a "number".
*/
static INTEGER: ColumnType = "integer";
/**
* SQL INT type. Your class's property type should be a "number".
*/
static INT: ColumnType = "int";
/**
* SQL SMALLINT type. Your class's property type should be a "number".
*/
static SMALLINT: ColumnType = "smallint";
/**
* SQL BIGINT type. Your class's property type should be a "number".
*/
static BIGINT: ColumnType = "bigint";
/**
* SQL FLOAT type. Your class's property type should be a "number".
*/
static FLOAT: ColumnType = "float";
/**
* SQL FLOAT type. Your class's property type should be a "number".
*/
static DOUBLE: ColumnType = "double";
/**
* SQL DECIMAL type. Your class's property type should be a "string".
*/
static DECIMAL: ColumnType = "decimal";
/**
* SQL DATETIME type. Your class's property type should be a "Date" object.
*/
static DATE: ColumnType = "date";
/**
* SQL TIME type. Your class's property type should be a "Date" object.
*/
static TIME: ColumnType = "time";
/**
* SQL DATETIME/TIMESTAMP type. Your class's property type should be a "Date" object.
*/
static DATETIME: ColumnType = "datetime";
/**
* SQL BOOLEAN type. Your class's property type should be a "boolean".
*/
static BOOLEAN: ColumnType = "boolean";
/**
* SQL CLOB type. Your class's property type should be any Object.
*/
static JSON: ColumnType = "json";
/**
* Postgres jsonb type. Your class's property type should be any Object.
*/
static JSONB: ColumnType = "jsonb";
/**
* 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: ColumnType = "simple_array";
/**
* UUID type. Serialized to a string in typescript or javascript
*/
static UUID: ColumnType = "uuid";
/**
* Checks if given type in a string format is supported by ORM.
*/
static isTypeSupported(type: string) {
return this.supportedTypes.indexOf(<ColumnType> 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.JSONB,
this.SIMPLE_ARRAY,
this.UUID
];
}
/**
* Tries to guess a column type from the given function.
*/
static determineTypeFromFunction(type: Function): ColumnType|undefined {
if (type instanceof Date) {
return ColumnTypes.DATETIME;
} else if (type instanceof Function) {
const typeName = (<any>type).name.toLowerCase();
switch (typeName) {
case "number":
return ColumnTypes.NUMBER;
case "boolean":
return ColumnTypes.BOOLEAN;
case "string":
return ColumnTypes.STRING;
case "date":
return ColumnTypes.DATETIME;
case "object":
return ColumnTypes.JSON;
}
} else if (type instanceof Object) {
return ColumnTypes.JSON;
}
return undefined;
}
static typeToString(type: Function): string {
return (type as any).name.toLowerCase();
}
/**
* Checks if column type is numeric.
*/
static isNumeric(type: ColumnType) {
return type === ColumnTypes.NUMBER ||
type === ColumnTypes.INT ||
type === ColumnTypes.INTEGER ||
type === ColumnTypes.BIGINT ||
type === ColumnTypes.SMALLINT ||
type === ColumnTypes.DOUBLE ||
type === ColumnTypes.FLOAT;
}
}

View File

@ -1,7 +1,5 @@
import {TableSchema} from "../schema-builder/schema/TableSchema";
import {ColumnSchema} from "../schema-builder/schema/ColumnSchema";
import {ColumnTypes} from "../metadata/types/ColumnTypes";
import {QueryBuilder} from "../query-builder/QueryBuilder";
import {Connection} from "../connection/Connection";
import {QueryRunnerProvider} from "../query-runner/QueryRunnerProvider";
import {Migration} from "./Migration";
@ -186,17 +184,13 @@ export class MigrationExecutor {
await queryRunner.createTable(new TableSchema("migrations", [
new ColumnSchema({
name: "timestamp",
type: queryRunner.normalizeType({
type: ColumnTypes.NUMBER
}),
type: this.connection.driver.mappedDataTypes.migrationTimestamp as string,
isPrimary: true,
isNullable: false
}),
new ColumnSchema({
name: "name",
type: queryRunner.normalizeType({
type: ColumnTypes.STRING
}),
type: this.connection.driver.mappedDataTypes.migrationName as string,
isNullable: false
}),
]));

View File

@ -2,7 +2,6 @@ import {ObjectLiteral} from "../common/ObjectLiteral";
import {EntityMetadata} from "../metadata/EntityMetadata";
import {ColumnMetadata} from "../metadata/ColumnMetadata";
import {RelationMetadata} from "../metadata/RelationMetadata";
import {ColumnTypes} from "../metadata/types/ColumnTypes";
import {DataUtils} from "../util/DataUtils";
/**
@ -324,29 +323,24 @@ export class Subject {
if (entityValue === undefined)
return false;
// normalize special values to make proper comparision
// normalize special values to make proper comparision (todo: arent they already normalized at this point?!)
if (entityValue !== null && entityValue !== undefined) {
if (column.type === ColumnTypes.DATE) {
if (column.type === "date") {
entityValue = DataUtils.mixedDateToDateString(entityValue);
} else if (column.type === ColumnTypes.TIME) {
} else if (column.type === "time") {
entityValue = DataUtils.mixedDateToTimeString(entityValue);
} else if (column.type === ColumnTypes.DATETIME) {
// if (column.loadInLocalTimezone) {
// entityValue = DataTransformationUtils.mixedDateToDatetimeString(entityValue);
// databaseValue = DataTransformationUtils.mixedDateToDatetimeString(databaseValue);
// } else {
entityValue = DataUtils.mixedDateToUtcDatetimeString(entityValue);
databaseValue = DataUtils.mixedDateToUtcDatetimeString(databaseValue);
// }
} else if (column.type === "datetime" || column.type === Date) {
entityValue = DataUtils.mixedDateToUtcDatetimeString(entityValue);
databaseValue = DataUtils.mixedDateToUtcDatetimeString(databaseValue);
} else if (column.type === ColumnTypes.JSON) {
} else if (column.type === "json" || column.type === "jsonb" || column.type === Object) {
entityValue = JSON.stringify(entityValue);
if (databaseValue !== null && databaseValue !== undefined)
databaseValue = JSON.stringify(databaseValue);
} else if (column.type === ColumnTypes.SIMPLE_ARRAY) {
} else if (column.type === "sample-array") {
entityValue = DataUtils.simpleArrayToString(entityValue);
databaseValue = DataUtils.simpleArrayToString(databaseValue);
}

View File

@ -3,7 +3,8 @@ import {ColumnMetadata} from "../metadata/ColumnMetadata";
import {TableSchema} from "../schema-builder/schema/TableSchema";
import {ForeignKeySchema} from "../schema-builder/schema/ForeignKeySchema";
import {IndexSchema} from "../schema-builder/schema/IndexSchema";
import {ColumnType} from "../metadata/types/ColumnTypes";
import {ColumnType} from "../driver/types/ColumnTypes";
import {ColumnOptions} from "../decorator/options/ColumnOptions";
/**
* Runs queries on a single database connection.
@ -78,8 +79,10 @@ export interface QueryRunner {
/**
* Converts a column type of the metadata to the database column's type.
*
* todo: move to driver?
*/
normalizeType(typeOptions: { type: ColumnType, length?: string|number, precision?: number, scale?: number, timezone?: boolean, fixedLength?: boolean }): string;
normalizeType(column: ColumnMetadata): string;
/**
* Checks if "DEFAULT" values in the column metadata and in the database schema are equal.

View File

@ -88,7 +88,7 @@ export class SchemaBuilder {
// -------------------------------------------------------------------------
protected get entityToSyncMetadatas(): EntityMetadata[] {
return this.connection.entityMetadatas.filter(metadata => !metadata.skipSchemaSync && metadata.tableType !== "single-table-child");
return this.connection.entityMetadatas.filter(metadata => !metadata.skipSync && metadata.tableType !== "single-table-child");
}
/**

View File

@ -10,22 +10,22 @@ export class DataUtils {
/**
* Normalizes date object hydrated from the database.
*/
static normalizeHydratedDate(mixedDate: Date|string|undefined, storedInLocal: boolean): Date|string|undefined {
static normalizeHydratedDate(mixedDate: Date|string|undefined): Date|string|undefined {
if (!mixedDate)
return mixedDate;
const date = typeof mixedDate === "string" ? new Date(mixedDate) : mixedDate as Date;
if (!storedInLocal) {
// if (!storedInLocal) {
// else if it was not stored in local timezone, means it was stored in UTC
// because driver hydrates it with timezone applied why we need to add timezone hours to match a local timezone
// else if it was not stored in local timezone, means it was stored in UTC
// because driver hydrates it with timezone applied why we need to add timezone hours to match a local timezone
const correctedDate = new Date();
correctedDate.setUTCFullYear(date.getFullYear(), date.getMonth(), date.getDate());
correctedDate.setUTCHours(date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds());
return correctedDate;
}
return date;
const correctedDate = new Date();
correctedDate.setUTCFullYear(date.getFullYear(), date.getMonth(), date.getDate());
correctedDate.setUTCHours(date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds());
return correctedDate;
// }
// return date;
}
/**

View File

@ -213,7 +213,7 @@ describe("Connection", () => {
});
describe("skip schema generation when skipSchemaSync option is used", function() {
describe("skip schema generation when skipSync option is used", function() {
let connections: Connection[];
beforeEach(() => createTestingConnections({ entities: [View], dropSchemaOnConnection: true }).then(all => connections = all));

View File

@ -2,7 +2,7 @@ import {Entity} from "../../../../src/decorator/entity/Entity";
import {PrimaryColumn} from "../../../../src/decorator/columns/PrimaryColumn";
import {Column} from "../../../../src/decorator/columns/Column";
@Entity("view", {skipSchemaSync: true})
@Entity("view", {skipSync: true})
export class View {
@PrimaryColumn()

View File

@ -10,7 +10,7 @@
"generated": true
},
"name": {
"type": "string",
"type": "varchar",
"nullable": false
}
}

View File

@ -10,7 +10,7 @@
"generated": true
},
"name": {
"type": "string",
"type": "varchar",
"nullable": false
}
}

View File

@ -10,7 +10,7 @@
"generated": true
},
"name": {
"type": "string",
"type": "varchar",
"nullable": false
}
}

View File

@ -10,11 +10,11 @@
"generated": true
},
"description": {
"type": "string",
"type": "varchar",
"nullable": false
},
"url": {
"type": "string",
"type": "varchar",
"nullable": false
}
}

View File

@ -10,11 +10,11 @@
"generated": true
},
"firstName": {
"type": "string",
"type": "varchar",
"nullable": false
},
"secondName": {
"type": "string",
"type": "varchar",
"nullable": false
}
}

View File

@ -0,0 +1,25 @@
import "reflect-metadata";
import {expect} from "chai";
import {Post} from "./entity/Post";
import {Connection} from "../../../../../src/connection/Connection";
import {closeTestingConnections, createTestingConnections} from "../../../../utils/test-utils";
// todo: finish those tests
describe.skip("database schema > column types > mysql", () => {
let connections: Connection[];
before(async () => {
connections = await createTestingConnections({
entities: [Post],
enabledDrivers: ["mysql"]
});
});
// beforeEach(() => reloadTestingDatabases(connections));
after(() => closeTestingConnections(connections));
it("all types should work correctly - persist and hydrate", () => Promise.all(connections.map(async connection => {
const post = new Post();
})));
});

View File

@ -0,0 +1,86 @@
import {Entity} from "../../../../../../src/decorator/entity/Entity";
import {PrimaryColumn} from "../../../../../../src/decorator/columns/PrimaryColumn";
import {Column} from "../../../../../../src/decorator/columns/Column";
@Entity()
export class Post {
@PrimaryColumn()
id: string;
@Column()
name: string;
@Column("int")
int: number;
@Column("tinyint")
tinyint: number;
@Column("smallint")
smallint: number;
@Column("mediumint")
mediumint: number;
@Column("bigint")
bigint: number;
@Column("float")
float: number;
@Column("double")
double: number;
@Column("decimal")
decimal: number;
@Column("date")
date: string;
@Column("datetime")
datetime: Date;
@Column("timestamp")
timestamp: number;
@Column("time")
time: string;
@Column("year")
year: number;
@Column("char")
char: string;
@Column("varchar")
varchar: string;
@Column("blob")
blob: string;
@Column("text")
text: string;
@Column("tinyblob")
tinyblob: string;
@Column("tinytext")
tinytext: string;
@Column("mediumblob")
mediumblob: string;
@Column("mediumtext")
mediumtext: string;
@Column("longblob")
longblob: string;
@Column("longtext")
longtext: string;
@Column("enum")
enum: string[];
}

View File

@ -16,7 +16,7 @@ export class Post {
@Column()
text: string;
@Embedded(() => Counters)
@Column(() => Counters)
counters: Counters;
}

View File

@ -16,7 +16,7 @@ export class Post {
@Column()
text: string;
@Embedded(() => Counters)
@Column(() => Counters)
counters: Counters;
}

View File

@ -19,7 +19,7 @@ export class Counters {
@Column()
favorites: number;
@Embedded(() => Subcounters)
@Column(() => Subcounters)
subcounters: Subcounters;
@ManyToMany(type => User, user => user.likedPosts)

View File

@ -13,7 +13,7 @@ export class Post {
@Column()
title: string;
@Embedded(() => Counters)
@Column(() => Counters)
counters: Counters;
}

View File

@ -18,7 +18,7 @@ export class Counters {
@Column()
favorites: number;
@Embedded(() => Subcounters)
@Column(() => Subcounters)
subcounters: Subcounters;
@ManyToMany(type => User, user => user.likedPosts)

View File

@ -13,7 +13,7 @@ export class Post {
@Column()
title: string;
@Embedded(() => Counters)
@Column(() => Counters)
counters: Counters;
}

View File

@ -20,7 +20,7 @@ export class Counters {
@Column()
favorites: number;
@Embedded(() => Subcounters)
@Column(() => Subcounters)
subcounters: Subcounters;
@ManyToMany(type => User, user => user.likedPosts)

View File

@ -15,7 +15,7 @@ export class Post {
@Column()
title: string;
@Embedded(() => Counters)
@Column(() => Counters)
counters: Counters;
}

View File

@ -19,7 +19,7 @@ export class Counters {
@Column()
favorites: number;
@Embedded(() => Subcounters)
@Column(() => Subcounters)
subcounters: Subcounters;
@ManyToMany(type => User, user => user.likedPosts)

View File

@ -13,7 +13,7 @@ export class Post {
@Column()
title: string;
@Embedded(() => Counters)
@Column(() => Counters)
counters: Counters;
}

View File

@ -20,7 +20,7 @@ export class Counters {
@Column()
favorites: number;
@Embedded(() => Subcounters)
@Column(() => Subcounters)
subcounters: Subcounters;
@ManyToMany(type => User, user => user.likedPosts)

View File

@ -15,7 +15,7 @@ export class Post {
@Column()
title: string;
@Embedded(() => Counters)
@Column(() => Counters)
counters: Counters;
}

View File

@ -19,7 +19,7 @@ export class Counters {
@Column()
favorites: number;
@Embedded(() => Subcounters)
@Column(() => Subcounters)
subcounters: Subcounters;
@ManyToOne(type => User)

View File

@ -13,7 +13,7 @@ export class Post {
@Column()
title: string;
@Embedded(() => Counters)
@Column(() => Counters)
counters: Counters;
}

View File

@ -18,7 +18,7 @@ export class Counters {
@Column()
favorites: number;
@Embedded(() => Subcounters)
@Column(() => Subcounters)
subcounters: Subcounters;
@OneToMany(type => User, user => user.likedPost)

View File

@ -13,7 +13,7 @@ export class Post {
@Column()
title: string;
@Embedded(() => Counters)
@Column(() => Counters)
counters: Counters;
}

View File

@ -20,7 +20,7 @@ export class Counters {
@Column()
favorites: number;
@Embedded(() => Subcounters)
@Column(() => Subcounters)
subcounters: Subcounters;
@ManyToOne(type => User)

View File

@ -15,7 +15,7 @@ export class Post {
@Column()
title: string;
@Embedded(() => Counters)
@Column(() => Counters)
counters: Counters;
}

View File

@ -19,7 +19,7 @@ export class Counters {
@Column()
favorites: number;
@Embedded(() => Subcounters)
@Column(() => Subcounters)
subcounters: Subcounters;
@ManyToOne(type => User)

View File

@ -13,7 +13,7 @@ export class Post {
@Column()
title: string;
@Embedded(() => Counters)
@Column(() => Counters)
counters: Counters;
}

View File

@ -20,7 +20,7 @@ export class Counters {
@Column()
favorites: number;
@Embedded(() => Subcounters)
@Column(() => Subcounters)
subcounters: Subcounters;
@ManyToOne(type => User)

View File

@ -15,7 +15,7 @@ export class Post {
@Column()
title: string;
@Embedded(() => Counters)
@Column(() => Counters)
counters: Counters;
}

View File

@ -19,7 +19,7 @@ export class Counters {
@Column()
favorites: number;
@Embedded(() => Subcounters)
@Column(() => Subcounters)
subcounters: Subcounters;
@OneToOne(type => User)

View File

@ -13,7 +13,7 @@ export class Post {
@Column()
title: string;
@Embedded(() => Counters)
@Column(() => Counters)
counters: Counters;
}

View File

@ -15,7 +15,7 @@ export class Counters {
@Column()
favorites: number;
@Embedded(() => Subcounters)
@Column(() => Subcounters)
subcounters: Subcounters;
@CreateDateColumn()

View File

@ -13,7 +13,7 @@ export class Post {
@Column()
title: string;
@Embedded(() => Counters)
@Column(() => Counters)
counters: Counters;
}

Some files were not shown because too many files have changed in this diff Show More