mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
property implemented date types, escaping and types persisment/hydration
This commit is contained in:
parent
f686515646
commit
b919ef8bd7
@ -163,8 +163,6 @@ If you want to load photos from the database, you can use `repository.find*`
|
||||
methods:
|
||||
|
||||
```typescript
|
||||
let repository = connection.getRepository(Photo);
|
||||
|
||||
// here we load one photo by id:
|
||||
let photoId = 1;
|
||||
let repository = connection.getRepository(Photo);
|
||||
|
||||
@ -65,6 +65,7 @@ ColumnType can be one of:
|
||||
* `date` will be mapped to db's `datetime`
|
||||
* `time` will be mapped to db's `time`
|
||||
* `datetime` will be mapped to db's `datetime`
|
||||
* `timestamp` will be mapped to db's `timestamp`
|
||||
* `boolean` will be mapped to db's `boolean`
|
||||
* `json` will be mapped to db's `text`
|
||||
* `simple_array` will be mapped to db's `text`
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "typeorm",
|
||||
"private": true,
|
||||
"version": "0.0.2-alpha",
|
||||
"version": "0.0.2-alpha.1",
|
||||
"description": "Data-mapper ORM for Typescript",
|
||||
"license": "Apache-2.0",
|
||||
"readmeFilename": "README.md",
|
||||
@ -44,6 +44,7 @@
|
||||
"dependencies": {
|
||||
"fs": "^0.0.2",
|
||||
"lodash": "^4.11.1",
|
||||
"moment": "^2.13.0",
|
||||
"mysql": "^2.10.2",
|
||||
"path": "^0.12.7",
|
||||
"reflect-metadata": "^0.1.3",
|
||||
|
||||
95
sample/sample11-all-types-entity/app.ts
Normal file
95
sample/sample11-all-types-entity/app.ts
Normal file
@ -0,0 +1,95 @@
|
||||
import {createConnection, CreateConnectionOptions} from "../../src/typeorm";
|
||||
import {EverythingEntity} from "./entity/EverythingEntity";
|
||||
|
||||
const options: CreateConnectionOptions = {
|
||||
driver: "mysql",
|
||||
connection: {
|
||||
host: "192.168.99.100",
|
||||
port: 3306,
|
||||
username: "root",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
autoSchemaCreate: true,
|
||||
logging: {
|
||||
logOnlyFailedQueries: true
|
||||
}
|
||||
},
|
||||
entities: [EverythingEntity]
|
||||
};
|
||||
|
||||
createConnection(options).then(connection => {
|
||||
|
||||
let entity = new EverythingEntity();
|
||||
entity.date = new Date(1980, 11, 1);
|
||||
entity.name = "max 255 chars name";
|
||||
entity.text = "this is pretty long text";
|
||||
entity.shortTextColumn = "TJ";
|
||||
entity.numberColumn = 123.5;
|
||||
entity.intColumn = 1000000;
|
||||
entity.integerColumn = 2000000;
|
||||
entity.smallintColumn = 12345;
|
||||
entity.bigintColumn = 123456789012345;
|
||||
entity.floatColumn = 100.5;
|
||||
entity.doubleColumn = 200.6;
|
||||
entity.decimalColumn = 1000000;
|
||||
entity.dateColumn = new Date();
|
||||
entity.timeColumn = new Date();
|
||||
entity.isBooleanColumn = true;
|
||||
entity.isSecondBooleanColumn = false;
|
||||
entity.simpleArrayColumn = ["hello", "world", "of", "typescript"];
|
||||
entity.jsonColumn = [{ hello: "olleh" }, { world: "dlrow" }];
|
||||
entity.alsoJson = { hello: "olleh", world: "dlrow" };
|
||||
|
||||
let postRepository = connection.getRepository(EverythingEntity);
|
||||
|
||||
postRepository
|
||||
.persist(entity)
|
||||
.then(entity => {
|
||||
console.log("EverythingEntity has been saved. Lets insert a new one to update it later");
|
||||
entity.id = null;
|
||||
return postRepository.persist(entity);
|
||||
})
|
||||
.then(entity => {
|
||||
console.log("Second entity has been inserted. Lets update it");
|
||||
entity.date = new Date(2000, 12, 5);
|
||||
entity.name = "updated short name";
|
||||
entity.text = "loooooong text updated";
|
||||
entity.shortTextColumn = "RU";
|
||||
entity.numberColumn = 1.1;
|
||||
entity.intColumn = 1000001;
|
||||
entity.integerColumn = 2000002;
|
||||
entity.smallintColumn = 12342;
|
||||
entity.bigintColumn = 12345678922222;
|
||||
entity.floatColumn = 200.2;
|
||||
entity.doubleColumn = 400.12;
|
||||
entity.decimalColumn = 2000000;
|
||||
entity.dateColumn = new Date();
|
||||
entity.timeColumn = new Date();
|
||||
entity.isBooleanColumn = false;
|
||||
entity.isSecondBooleanColumn = true;
|
||||
entity.simpleArrayColumn = ["hello!", "world!", "of!", "typescript!"];
|
||||
entity.jsonColumn = [{ olleh: "hello" }, { dlrow: "world" }];
|
||||
entity.alsoJson = { olleh: "hello", dlrow: "world" };
|
||||
|
||||
return postRepository.persist(entity);
|
||||
})
|
||||
.then(entity => {
|
||||
console.log("Entity has been updated. Persist once again to make find and remove then");
|
||||
|
||||
entity.id = null;
|
||||
return postRepository.persist(entity);
|
||||
})
|
||||
.then(entity => {
|
||||
return postRepository.findById(entity.id);
|
||||
})
|
||||
.then(entity => {
|
||||
console.log("Entity is loaded: ", entity);
|
||||
console.log("Now remove it");
|
||||
return postRepository.remove(entity);
|
||||
})
|
||||
.then(entity => {
|
||||
console.log("Entity has been removed");
|
||||
})
|
||||
.catch(error => console.log("Cannot save. Error: ", error, error.stack));
|
||||
|
||||
}, error => console.log("Cannot connect: ", error));
|
||||
75
sample/sample11-all-types-entity/entity/EverythingEntity.ts
Normal file
75
sample/sample11-all-types-entity/entity/EverythingEntity.ts
Normal file
@ -0,0 +1,75 @@
|
||||
import {PrimaryColumn, Column} from "../../../src/decorator/columns";
|
||||
import {Table} from "../../../src/decorator/tables";
|
||||
import {CreateDateColumn} from "../../../src/decorator/columns/CreateDateColumn";
|
||||
import {UpdateDateColumn} from "../../../src/decorator/columns/UpdateDateColumn";
|
||||
|
||||
@Table("sample11_everything_entity")
|
||||
export class EverythingEntity {
|
||||
|
||||
@PrimaryColumn("int", { autoIncrement: true })
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@Column("text")
|
||||
text: string;
|
||||
|
||||
@Column({ length: "32" })
|
||||
shortTextColumn: string;
|
||||
|
||||
@Column()
|
||||
numberColumn: number;
|
||||
|
||||
@Column("integer")
|
||||
integerColumn: number;
|
||||
|
||||
@Column("int")
|
||||
intColumn: number;
|
||||
|
||||
@Column("smallint")
|
||||
smallintColumn: number;
|
||||
|
||||
@Column("bigint")
|
||||
bigintColumn: number;
|
||||
|
||||
@Column("float")
|
||||
floatColumn: number;
|
||||
|
||||
@Column("double")
|
||||
doubleColumn: number;
|
||||
|
||||
@Column("decimal")
|
||||
decimalColumn: number;
|
||||
|
||||
@Column()
|
||||
date: Date;
|
||||
|
||||
@Column("date")
|
||||
dateColumn: Date;
|
||||
|
||||
@Column("time")
|
||||
timeColumn: Date;
|
||||
|
||||
@Column("boolean")
|
||||
isBooleanColumn: boolean;
|
||||
|
||||
@Column("boolean")
|
||||
isSecondBooleanColumn: boolean;
|
||||
|
||||
@Column("json")
|
||||
jsonColumn: any;
|
||||
|
||||
@Column()
|
||||
alsoJson: Object;
|
||||
|
||||
@Column("simple_array")
|
||||
simpleArrayColumn: string[];
|
||||
|
||||
@CreateDateColumn()
|
||||
createdDate: Date;
|
||||
|
||||
@UpdateDateColumn()
|
||||
updatedDate: Date;
|
||||
|
||||
}
|
||||
@ -30,6 +30,8 @@ export function Column(typeOrOptions?: ColumnType|ColumnOptions, options?: Colum
|
||||
options = <ColumnOptions> typeOrOptions;
|
||||
}
|
||||
return function (object: Object, propertyName: string) {
|
||||
|
||||
const reflectedType = ColumnTypes.typeToString(Reflect.getMetadata("design:type", object, propertyName));
|
||||
|
||||
// if type is not given implicitly then try to guess it
|
||||
if (!type)
|
||||
@ -55,6 +57,7 @@ export function Column(typeOrOptions?: ColumnType|ColumnOptions, options?: Colum
|
||||
defaultMetadataStorage.addColumnMetadata(new ColumnMetadata({
|
||||
target: object.constructor,
|
||||
propertyName: propertyName,
|
||||
propertyType: reflectedType,
|
||||
options: options
|
||||
}));
|
||||
};
|
||||
|
||||
@ -11,6 +11,8 @@ import "reflect-metadata";
|
||||
export function CreateDateColumn(options?: ColumnOptions): Function {
|
||||
return function (object: Object, propertyName: string) {
|
||||
|
||||
const reflectedType = ColumnTypes.typeToString(Reflect.getMetadata("design:type", object, propertyName));
|
||||
|
||||
// if column options are not given then create a new empty options
|
||||
if (!options)
|
||||
options = {};
|
||||
@ -22,6 +24,7 @@ export function CreateDateColumn(options?: ColumnOptions): Function {
|
||||
defaultMetadataStorage.addColumnMetadata(new ColumnMetadata({
|
||||
target: object.constructor,
|
||||
propertyName: propertyName,
|
||||
propertyType: reflectedType,
|
||||
isCreateDate: true,
|
||||
options: options
|
||||
}));
|
||||
|
||||
@ -34,6 +34,8 @@ export function PrimaryColumn(typeOrOptions?: ColumnType|ColumnOptions, options?
|
||||
}
|
||||
return function (object: Object, propertyName: string) {
|
||||
|
||||
const reflectedType = ColumnTypes.typeToString(Reflect.getMetadata("design:type", object, propertyName));
|
||||
|
||||
// if type is not given implicitly then try to guess it
|
||||
if (!type)
|
||||
type = ColumnTypes.determineTypeFromFunction(Reflect.getMetadata("design:type", object, propertyName));
|
||||
@ -58,6 +60,7 @@ export function PrimaryColumn(typeOrOptions?: ColumnType|ColumnOptions, options?
|
||||
defaultMetadataStorage.addColumnMetadata(new ColumnMetadata({
|
||||
target: object.constructor,
|
||||
propertyName: propertyName,
|
||||
propertyType: reflectedType,
|
||||
isPrimaryKey: true,
|
||||
options: options
|
||||
}));
|
||||
|
||||
@ -11,6 +11,8 @@ import "reflect-metadata";
|
||||
export function UpdateDateColumn(options?: ColumnOptions): Function {
|
||||
return function (object: Object, propertyName: string) {
|
||||
|
||||
const reflectedType = ColumnTypes.typeToString(Reflect.getMetadata("design:type", object, propertyName));
|
||||
|
||||
// if column options are not given then create a new empty options
|
||||
if (!options)
|
||||
options = {};
|
||||
@ -22,6 +24,7 @@ export function UpdateDateColumn(options?: ColumnOptions): Function {
|
||||
defaultMetadataStorage.addColumnMetadata(new ColumnMetadata({
|
||||
target: object.constructor,
|
||||
propertyName: propertyName,
|
||||
propertyType: reflectedType,
|
||||
isUpdateDate: true,
|
||||
options: options
|
||||
}));
|
||||
|
||||
@ -2,6 +2,7 @@ import {ConnectionOptions} from "../connection/ConnectionOptions";
|
||||
import {SchemaBuilder} from "../schema-builder/SchemaBuilder";
|
||||
import {QueryBuilder} from "../query-builder/QueryBuilder";
|
||||
import {Connection} from "../connection/Connection";
|
||||
import {ColumnMetadata} from "../metadata-builder/metadata/ColumnMetadata";
|
||||
|
||||
/**
|
||||
* Driver communicates with specific database.
|
||||
@ -83,4 +84,19 @@ export interface Driver {
|
||||
*/
|
||||
endTransaction(): Promise<void>;
|
||||
|
||||
/**
|
||||
* Prepares given value to a value to be persisted, based on its column type and metadata.
|
||||
*/
|
||||
preparePersistentValue(value: any, column: ColumnMetadata): any;
|
||||
|
||||
/**
|
||||
* Prepares given value to a value to be hydrated, based on its column type and metadata.
|
||||
*/
|
||||
prepareHydratedValue(value: any, column: ColumnMetadata): any;
|
||||
|
||||
/**
|
||||
* Escapes given value.
|
||||
*/
|
||||
escape(value: any): any;
|
||||
|
||||
}
|
||||
@ -1,11 +1,13 @@
|
||||
import {Driver} from "./Driver";
|
||||
import {ConnectionOptions} from "../connection/ConnectionOptions";
|
||||
import {SchemaBuilder} from "../schema-builder/SchemaBuilder";
|
||||
import {QueryBuilder} from "../query-builder/QueryBuilder";
|
||||
import {MysqlSchemaBuilder} from "../schema-builder/MysqlSchemaBuilder";
|
||||
import {Connection} from "../connection/Connection";
|
||||
import {ConnectionIsNotSetError} from "./error/ConnectionIsNotSetError";
|
||||
import {BaseDriver} from "./BaseDriver";
|
||||
import {ColumnMetadata} from "../metadata-builder/metadata/ColumnMetadata";
|
||||
import {ColumnTypes} from "../metadata-builder/types/ColumnTypes";
|
||||
import * as moment from "moment";
|
||||
|
||||
/**
|
||||
* This driver organizes work with mysql database.
|
||||
@ -215,4 +217,65 @@ export class MysqlDriver extends BaseDriver implements Driver {
|
||||
return this.query("COMMIT").then(() => {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares given value to a value to be persisted, based on its column type and metadata.
|
||||
*/
|
||||
preparePersistentValue(value: any, column: ColumnMetadata): any {
|
||||
switch (column.type) {
|
||||
case ColumnTypes.BOOLEAN:
|
||||
return value === true ? 1 : 0;
|
||||
case ColumnTypes.DATE:
|
||||
return moment(value).format("YYYY-MM-DD");
|
||||
case ColumnTypes.TIME:
|
||||
return moment(value).format("hh:mm:ss");
|
||||
case ColumnTypes.DATETIME:
|
||||
return moment(value).format("YYYY-MM-DD hh:mm:ss");
|
||||
case ColumnTypes.JSON:
|
||||
return JSON.stringify(value);
|
||||
case ColumnTypes.SIMPLE_ARRAY:
|
||||
return (value as Array<any>)
|
||||
.map(i => String(i))
|
||||
.join(",");
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares given value to a value to be persisted, based on its column type and metadata.
|
||||
*/
|
||||
prepareHydratedValue(value: any, column: ColumnMetadata): any {
|
||||
switch (column.type) {
|
||||
case ColumnTypes.DATE:
|
||||
if (value instanceof Date)
|
||||
return value;
|
||||
|
||||
return moment(value, "YYYY-MM-DD").toDate();
|
||||
|
||||
case ColumnTypes.TIME:
|
||||
return moment(value, "hh:mm:ss").toDate();
|
||||
|
||||
case ColumnTypes.DATETIME:
|
||||
if (value instanceof Date)
|
||||
return value;
|
||||
|
||||
return moment(value, "YYYY-MM-DD hh:mm:ss").toDate();
|
||||
|
||||
case ColumnTypes.JSON:
|
||||
return JSON.parse(value);
|
||||
|
||||
case ColumnTypes.SIMPLE_ARRAY:
|
||||
return (value as string).split(",");
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes given value.
|
||||
*/
|
||||
escape(value: any): any {
|
||||
return this.mysqlConnection.escape(value);
|
||||
}
|
||||
|
||||
}
|
||||
@ -97,6 +97,7 @@ export class EntityMetadataBuilder {
|
||||
relationalColumn = new ColumnMetadata({
|
||||
target: metadata.target,
|
||||
propertyName: relation.name,
|
||||
propertyType: inverseSideMetadata.primaryColumn.type,
|
||||
isVirtual: true,
|
||||
options: options
|
||||
});
|
||||
@ -139,11 +140,13 @@ export class EntityMetadataBuilder {
|
||||
new ColumnMetadata({
|
||||
target: null,
|
||||
propertyName: null,
|
||||
propertyType: inverseSideMetadata.primaryColumn.type,
|
||||
options: column1options
|
||||
}),
|
||||
new ColumnMetadata({
|
||||
target: null,
|
||||
propertyName: null,
|
||||
propertyType: inverseSideMetadata.primaryColumn.type,
|
||||
options: column2options
|
||||
})
|
||||
];
|
||||
|
||||
@ -18,6 +18,11 @@ export interface ColumnMetadataArgs {
|
||||
*/
|
||||
propertyName: string;
|
||||
|
||||
/**
|
||||
* Class's property type (reflected) to which this column is applied.
|
||||
*/
|
||||
propertyType: string;
|
||||
|
||||
/**
|
||||
* Indicates if this column is primary key or not.
|
||||
*/
|
||||
@ -67,6 +72,11 @@ export class ColumnMetadata extends PropertyMetadata {
|
||||
*/
|
||||
private _name: string;
|
||||
|
||||
/**
|
||||
* The real reflected property type.
|
||||
*/
|
||||
private _propertyType: string;
|
||||
|
||||
/**
|
||||
* The type of the column.
|
||||
*/
|
||||
@ -159,6 +169,8 @@ export class ColumnMetadata extends PropertyMetadata {
|
||||
this._isUpdateDate = args.isUpdateDate;
|
||||
if (args.isVirtual)
|
||||
this._isVirtual = args.isVirtual;
|
||||
if (args.propertyType)
|
||||
this._propertyType = args.propertyType;
|
||||
if (args.options.name)
|
||||
this._name = args.options.name;
|
||||
if (args.options.type)
|
||||
@ -200,6 +212,13 @@ export class ColumnMetadata extends PropertyMetadata {
|
||||
return this.namingStrategy ? this.namingStrategy.columnName(this._name) : this._name;
|
||||
}
|
||||
|
||||
/**
|
||||
* The real reflected property type.
|
||||
*/
|
||||
get propertyType(): string {
|
||||
return this._propertyType.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Type of the column.
|
||||
*/
|
||||
|
||||
@ -29,7 +29,7 @@ export interface ColumnOptions {
|
||||
/**
|
||||
* Specifies if column's value must be unique or not.
|
||||
*/
|
||||
unique?: boolean;
|
||||
unique?: boolean;
|
||||
|
||||
/**
|
||||
* Indicates if column's value can be set to NULL.
|
||||
|
||||
@ -138,6 +138,10 @@ export class ColumnTypes {
|
||||
return ColumnTypes.BOOLEAN;
|
||||
case "string":
|
||||
return ColumnTypes.STRING;
|
||||
case "date":
|
||||
return ColumnTypes.DATETIME;
|
||||
case "object":
|
||||
return ColumnTypes.JSON;
|
||||
}
|
||||
|
||||
} else if (type instanceof Object) {
|
||||
@ -146,5 +150,9 @@ export class ColumnTypes {
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
static typeToString(type: Function) {
|
||||
return (<any>type).name.toLowerCase();
|
||||
}
|
||||
|
||||
}
|
||||
@ -215,10 +215,15 @@ export class PersistOperationExecutor {
|
||||
private update(updateOperation: UpdateOperation) {
|
||||
const entity = updateOperation.entity;
|
||||
const metadata = this.connection.getEntityMetadata(entity.constructor);
|
||||
const values = updateOperation.columns.reduce((object, column) => {
|
||||
(<any> object)[column.name] = entity[column.propertyName];
|
||||
const values: any = updateOperation.columns.reduce((object, column) => {
|
||||
const value = this.connection.driver.preparePersistentValue(entity[column.propertyName], column);
|
||||
(<any> object)[column.name] = value;
|
||||
return object;
|
||||
}, {});
|
||||
|
||||
if (metadata.updateDateColumn)
|
||||
values[metadata.updateDateColumn.name] = this.connection.driver.preparePersistentValue(new Date(), metadata.updateDateColumn);
|
||||
|
||||
return this.connection.driver.update(metadata.table.name, values, { [metadata.primaryColumn.name]: metadata.getEntityId(entity) });
|
||||
}
|
||||
|
||||
@ -244,7 +249,14 @@ export class PersistOperationExecutor {
|
||||
const values = metadata.columns
|
||||
.filter(column => !column.isVirtual)
|
||||
.filter(column => entity.hasOwnProperty(column.propertyName))
|
||||
.map(column => "'" + entity[column.propertyName] + "'");
|
||||
.map(column => this.connection.driver.preparePersistentValue(entity[column.propertyName], column))
|
||||
.map(value => {
|
||||
if (value === null || value === undefined) {
|
||||
return "NULL";
|
||||
} else {
|
||||
return this.connection.driver.escape(value);
|
||||
}
|
||||
});
|
||||
const relationColumns = metadata.relations
|
||||
.filter(relation => relation.isOwning && !!relation.relatedEntityMetadata)
|
||||
.filter(relation => entity.hasOwnProperty(relation.propertyName))
|
||||
@ -255,10 +267,20 @@ export class PersistOperationExecutor {
|
||||
.filter(relation => relation.isOwning && !!relation.relatedEntityMetadata)
|
||||
.filter(relation => entity.hasOwnProperty(relation.propertyName))
|
||||
.filter(relation => entity[relation.propertyName].hasOwnProperty(relation.relatedEntityMetadata.primaryColumn.name))
|
||||
.map(relation => "'" + entity[relation.propertyName][relation.relatedEntityMetadata.primaryColumn.name] + "'");
|
||||
.map(relation => this.connection.driver.escape(entity[relation.propertyName][relation.relatedEntityMetadata.primaryColumn.name]));
|
||||
|
||||
const allColumns = columns.concat(relationColumns);
|
||||
const allValues = values.concat(relationValues);
|
||||
|
||||
if (metadata.createDateColumn) {
|
||||
allColumns.push(metadata.createDateColumn.name);
|
||||
allValues.push(this.connection.driver.escape(this.connection.driver.preparePersistentValue(new Date(), metadata.createDateColumn)));
|
||||
}
|
||||
|
||||
if (metadata.updateDateColumn) {
|
||||
allColumns.push(metadata.updateDateColumn.name);
|
||||
allValues.push(this.connection.driver.escape(this.connection.driver.preparePersistentValue(new Date(), metadata.updateDateColumn)));
|
||||
}
|
||||
|
||||
return this.connection.driver.insert(metadata.table.name, this.zipObject(allColumns, allValues));
|
||||
}
|
||||
|
||||
@ -419,7 +419,7 @@ export class QueryBuilder<Entity> {
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
protected rawResultsToEntities(results: any[]) {
|
||||
const transformer = new RawSqlResultsToEntityTransformer(this._aliasMap);
|
||||
const transformer = new RawSqlResultsToEntityTransformer(this.connection, this._aliasMap);
|
||||
return transformer.transform(results);
|
||||
}
|
||||
|
||||
@ -576,8 +576,8 @@ export class QueryBuilder<Entity> {
|
||||
protected replaceParameters(sql: string) {
|
||||
// todo: proper escape values and prevent sql injection
|
||||
Object.keys(this.parameters).forEach(key => {
|
||||
const value = this.parameters[key] !== null && this.parameters[key] !== undefined ? "\"" + this.parameters[key] + "\"" : "NULL";
|
||||
sql = sql.replace(":" + key, value); // .replace('"', '')
|
||||
const value = this.parameters[key] !== null && this.parameters[key] !== undefined ? this.parameters[key] : "NULL";
|
||||
sql = sql.replace(":" + key, this.connection.driver.escape(value)); // .replace('"', '')
|
||||
});
|
||||
return sql;
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ import {AliasMap} from "../alias/AliasMap";
|
||||
import {Alias} from "../alias/Alias";
|
||||
import * as _ from "lodash";
|
||||
import {EntityMetadata} from "../../metadata-builder/metadata/EntityMetadata";
|
||||
import {Connection} from "../../connection/Connection";
|
||||
|
||||
/**
|
||||
* Transforms raw sql results returned from the database into entity object.
|
||||
@ -13,7 +14,8 @@ export class RawSqlResultsToEntityTransformer {
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(private aliasMap: AliasMap) {
|
||||
constructor(private connection: Connection,
|
||||
private aliasMap: AliasMap) {
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -55,7 +57,7 @@ export class RawSqlResultsToEntityTransformer {
|
||||
metadata.columns.forEach(column => {
|
||||
const valueInObject = alias.getColumnValue(rawSqlResults[0], column); // we use zero index since its grouped data
|
||||
if (valueInObject && column.propertyName && !column.isVirtual) {
|
||||
entity[column.propertyName] = valueInObject;
|
||||
entity[column.propertyName] = this.connection.driver.prepareHydratedValue(valueInObject, column);
|
||||
hasData = true;
|
||||
}
|
||||
});
|
||||
|
||||
@ -28,7 +28,11 @@ export class Repository<Entity> {
|
||||
* Checks if entity has an id.
|
||||
*/
|
||||
hasId(entity: Entity): boolean {
|
||||
return entity && this.metadata.primaryColumn && entity.hasOwnProperty(this.metadata.primaryColumn.propertyName);
|
||||
return entity &&
|
||||
this.metadata.primaryColumn &&
|
||||
entity.hasOwnProperty(this.metadata.primaryColumn.propertyName) &&
|
||||
(<any> entity)[this.metadata.primaryColumn.propertyName] !== null &&
|
||||
(<any> entity)[this.metadata.primaryColumn.propertyName] !== undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -19,7 +19,7 @@ export class MysqlSchemaBuilder extends SchemaBuilder {
|
||||
const dbData = results.find(result => result.COLUMN_NAME === column.name);
|
||||
if (!dbData) return false;
|
||||
|
||||
const newType = this.normalizeType(column.type, column.length);
|
||||
const newType = this.normalizeType(column);
|
||||
const isNullable = column.isNullable === true ? "YES" : "NO";
|
||||
const hasDbColumnAutoIncrement = dbData.EXTRA.indexOf("auto_increment") !== -1;
|
||||
const hasDbColumnPrimaryIndex = dbData.COLUMN_KEY.indexOf("PRI") !== -1;
|
||||
@ -126,7 +126,7 @@ export class MysqlSchemaBuilder extends SchemaBuilder {
|
||||
}
|
||||
|
||||
private buildCreateColumnSql(column: ColumnMetadata, skipPrimary: boolean) {
|
||||
let c = column.name + " " + this.normalizeType(column.type, column.length);
|
||||
let c = column.name + " " + this.normalizeType(column);
|
||||
if (column.isNullable !== true)
|
||||
c += " NOT NULL";
|
||||
if (column.isPrimary === true && !skipPrimary)
|
||||
@ -140,31 +140,63 @@ export class MysqlSchemaBuilder extends SchemaBuilder {
|
||||
return c;
|
||||
}
|
||||
|
||||
private normalizeType(type: any, length?: string) {
|
||||
private normalizeType(column: ColumnMetadata) {
|
||||
|
||||
let realType: string;
|
||||
if (typeof type === "string") {
|
||||
realType = type.toLowerCase();
|
||||
if (typeof column.type === "string") {
|
||||
realType = column.type.toLowerCase();
|
||||
|
||||
} else if (type.name && typeof type.name === "string") {
|
||||
realType = type.name.toLowerCase();
|
||||
// todo: remove casting to any after upgrade to typescript 2
|
||||
} else if (typeof column.type === "object" && (<any>column.type).name && typeof (<any>column.type).name === "string") {
|
||||
realType = (<any>column.type).toLowerCase();
|
||||
}
|
||||
|
||||
switch (realType) {
|
||||
case "string":
|
||||
return "varchar(" + (length ? length : 255) + ")";
|
||||
return "varchar(" + (column.length ? column.length : 255) + ")";
|
||||
case "text":
|
||||
return "text";
|
||||
case "number":
|
||||
return "double";
|
||||
case "boolean":
|
||||
return "boolean";
|
||||
case "integer":
|
||||
case "int":
|
||||
return "int(" + (length ? length : 11) + ")";
|
||||
return "INT(" + (column.length ? column.length : 11) + ")";
|
||||
case "smallint":
|
||||
return "SMALLINT(" + (column.length ? column.length : 11) + ")";
|
||||
case "bigint":
|
||||
return "BIGINT(" + (column.length ? column.length : 11) + ")";
|
||||
case "float":
|
||||
return "FLOAT";
|
||||
case "double":
|
||||
case "number":
|
||||
return "DOUBLE";
|
||||
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 column.length ? "varchar(" + column.length + ")" : "text";
|
||||
}
|
||||
|
||||
throw new Error("Specified type (" + type + ") is not supported by current driver.");
|
||||
throw new Error("Specified type (" + column.type + ") is not supported by current driver.");
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user