Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support specifying different data types per driver on entity columns #2590

Open
atifsyedali opened this issue Jul 26, 2018 · 10 comments
Open

Comments

@atifsyedali
Copy link

atifsyedali commented Jul 26, 2018

Issue type:

[] question
[ ] bug report
[x ] feature request
[ ] documentation issue

Database system/driver:

[x ] cordova
[ ] mongodb
[x ] mssql
[x ] mysql / mariadb
[x ] oracle
[x ] postgres
[x ] sqlite
[x ] sqljs
[x ] react-native
[x ] expo

TypeORM version:

[x ] latest
[ ] @next
[ ] 0.x.x (or put your version here)

Steps to reproduce or a small repository showing the problem:

Different databases have varying data types. For example, there is a tinyint in mysql and sqlite but not in postgresql. There needs to be a way to specify different data types for each column/field on the same entity class, so that we don't have different entities for each database type and switch statements for creation, especially when we want to support multiple databases in the same codebase.

E.g. today I do something like this:

@Entity
class MySqlEntity {
	@Column("tinyint")
	value: number;
}

@Entity
class PostgresEntity {
	@Column("smallint")
	value: number;
}

class MyDbManager {

	type: "mysql" | "postgres";

	constructor(config: MysqlConnectionOptions | PostgresConnectionOptions) {

		this.type = config.type;

		switch (config.type) {

			case "mysql":
				createConnection(_.extend({}, config, {
					...,
					entities: [MySqlEntity]
				}));
				break;

			case "postgres":
				createConnection(_.extend({}, config, {
					...,
					entities: [PostgresEntity]
				}));
				break;
		}
	}

	async add(value: number) {
		let someEntity: MySqlEntity | PostgresEntity;

		switch (this.type) {
			case "mysql":
				someEntity = new MySqlEntity();
				break;
			case "postgres":
				someEntity = new PostgresEntity();
				break;
		}

		someEntity.value = value;

		await getConnection().manager.save(someEntity);
	}

}

Note that I can probably use an interface to get rid of some boilerplate like so:

interface IMyEntity {
	value: number;
}

@Entity
class MySqlEntity implements IMyEntity {
	@Column("tinyint")
	value: number;
}

@Entity
class PostgresEntity implements IMyEntity {
	@Column("smallint")
	value: number;
}

type ObjectType<T> = { new (): T } | Function;

class MyDbManager {

	type: "mysql" | "postgres";
	classType: ObjectType<IMyEntity>;

	constructor(config: MysqlConnectionOptions | PostgresConnectionOptions) {

		this.type = config.type;

		switch (config.type) {

			case "mysql":
				this.classType = MySqlEntity;
				break;

			case "postgres":
				this.classType = PostgresEntity;
				break;
		}


		createConnection(_.extend({}, config, {
			...,
			entities: [this.classType]
		}));
	}

	async add(value: number) {
		const someEntity = new (this.classType)();
		someEntity.value = value;
		await getConnection().manager.save(someEntity);
	}

}

However, doing it this way would be nicer though:

@Entity()
class DbEntity {
	@Column({mysql: "tinyint", postgres: "smallint"})
	value: number;
}

// when creating a connection

class MyDbManager {

	constructor(config: MysqlConnectionOptions | PostgresConnectionOptions) {
		createConnection(_.extend({}, config, {
			entities: [DbEntity]
		}));
	}

	async add(value: number) {
		const someEntity: DbEntity = new DbEntity();
		someEntity.value = value;
		await getConnection().manager.save(someEntity);
	}

}

Maybe I am missing something obvious, or an alternative simpler way to do this, though.

@pleerock
Copy link
Member

what is the purpose of using two databases in the app?

@atifsyedali
Copy link
Author

Migration and benchmarking.

@thonythony
Copy link
Contributor

I would like deploy the same application in different server that have their own sql-like database.
For example :

  • Server A has a MySQL database
  • Server B has a Postgres database

@pleerock Do you see what I mean ?

@gerwinbrunner
Copy link
Contributor

Any news on this topic?

@tzellman
Copy link

Additionally, this is required if you run your tests with something like an in-memory sqlite database, which does not support json or jsonb. The recent change #4476 breaks support in production/dev (e.g. in my case postgres) if I specify simple-json as the type in the Column decorator (actual DB storage is jsonb).

@agustif
Copy link

agustif commented Jul 8, 2020

This would bee nice to support several db for different uses cases like dev/staging/prod +1

@KCFindstr
Copy link

Any news on this feature? I'd like to use mediumtext in my production environment but text in my development environment with sqlite which does not support mediumtext columns.

@tomastrajan
Copy link

I would also like to chime in as I need such thing to support multiple customers with their unique limitations about their internal infrastructure.

@grichards
Copy link

grichards commented Oct 10, 2022

Agree... this would be useful for instance:

For local dev environments, it's very convenient to simply package up SQLite with the repo for all devs to use.

For staging and production deployments, the environment would be an RDBMS.

@sfxdoluwasegun
Copy link

Was this discussion concluded with a solution?... My team recently switched to Typescript (from Java) and now are faced with this constraint. Somehow we never really had to deal with this while using Hibernate with Java. Would be great to figure this out on TypeOrm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment