What's TypeORM's default table column name rule? - typeorm

In a project using TypeORM, after prepareing ormconfig.ts and did a database migration, it created this type of column in the table:
deletedAt
But generally it should be this type
deleted_at
Is there a default setting for it?

The default is to simply use the name of the field with the #Column() annotation as name in the database.
If I use
#Column() deletedAt: number;
following migration is created:
await queryRunner.query(`ALTER TABLE "public"."test" ADD "deletedAt" integer NOT NULL`);
And for this
#Column() deleted_at: number;
you will get this migration
await queryRunner.query(`ALTER TABLE "public"."test" ADD "deleted_at" integer NOT NULL`);
EDIT: At least this is true for a postgres database with typeorm 0.3.6. I must admit that I don't know if there is dependency to the database used, since I don't know the limitations. Maybe there is a database out there which does not support case sensitive column names.

Related

TypeORM Entity #UpdateDateColumn is updated if any Column with relation is set to NULL on save

When saving an entity to update it I found that when all the columns with relationships have non-null values and nothing in the entity changes, the UpdateDateColumn does not update (which is the behavior I would expect).
However, if one of the columns is null and the entity does not change on save, the UpdateDateColumn updates to the current timestamp even though nothing changed. I checked the ORM logs and found that the column with the null value was the only column updated in the query.
My question is 2 parts:
Is this intentional by the developers of TypeORM library? (I have not found any documentation regarding this behavior).
I found that I can set the field to undefined if the column does not change and typeorm will ignore it when updating the row. Is there any other way to tell typeorm to not update the column if the column's value does not change in this usecase without needing to do this every for every nullable entity/column? Again, this seems to only be the case with null values.
Update Column
#UpdateDateColumn({ name: 'updated_at', default: () => 'CURRENT_TIMESTAMP', update: false, onUpdate: 'CURRENT_TIMESTAMP', precision: 0 })
updatedAt: Date;
Example Entity
#OneToOne(() => Product, product => product.item, { nullable: true })
#JoinColumn({ name: 'product_id' })
product?: Product | null;
Logs
[QUERY]: UPDATE `Item` SET `product_id` = ?, `updated_at` = CURRENT_TIMESTAMP WHERE `id` IN (?) -- PARAMETERS: [null,243]

TypeORM "find" only returning one result even with multiple results in the table

I have schema of
import { Entity, Column, PrimaryColumn } from "typeorm";
#Entity({ name: 'monthly_invoice_rollup' })
export class MonthlyInvoiceRollup {
#PrimaryColumn()
Invoiceno: string;
#Column()
ClientID: string;
#Column()
Rollup_code: string;
#Column()
Rollup_desc: string;
}
I have a class where I set it like
this.monthlyInvoiceRollup = getRepository(MonthlyInvoiceRollup)
and I call it like
const results = await this.monthlyInvoiceRollup.find({
where: { "Invoiceno": "134" },
});
but it only returns the first result in the table even though I know I have multiple results
The design is not correct. By definition: primary key constraint is simply a combination of a unique constraint and a not-null constraint. You can't have multiple entry in the same table with the same primary key. You must find another way to identify multiple entries given a common value. That is why TypeORM returns only one entry: given the primary key there can be only one or zero entry in the DB.
as it is said above the primary key is a combination of unique and not null constraints, in your given example your primary key is invoiceno, foreign key is clientID so your relation is that the client can have 1 or n invoices, invoice related to 1.1 client.
so lets say that ClientID = 134 that can be repeated because it is simply foreign key, so you can lookup your invoices based on the clientID

Rails ActiveRecord SQlite3 datatype mismatch error on change_column from string to text

I am trying to change the datatype of a column from string to id. But SQlite3 is giving me a hard time. This is the only line in my migration:
change_column :containers, :title, :text
When the migration is running I'm getting an error of datatype mismatch:
SQLite3::MismatchException: datatype mismatch: INSERT INTO "acontainers"
I am pretty sure this is because of ActiveRecord creating a temporary table that has a id field with datatype INT while the original table actually has a datatype VARCHAR as can be seen here:
CREATE TEMPORARY TABLE "acontainers" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
The problem is that I have no idea how to get around this. Any input is greatly appreciated!
Looks like a bug in the SQLite wrapper.
You can try to update to the latest version if you're not using the one
As a workaround you can do the migration in multiple steps:
Create a new column
Write to both columns
Backfill data from the old column to the new column
Move reads from the old column to the new column
Stop writing to the old column
Drop the old column
It is also a safer approach as change_column may cause downtimes and errors
You can read more about it in this gem description

How to migrate complex Rails database to use UUID primary keys Postgresql

I have a database I would like to convert to use UUID's as the primary key in postgresql.
I have roughly 30 tables with deep multi-level associations. Is there an 'easy' way to convert all current ID's to UUID?
From this: https://coderwall.com/p/n_0awq, I can see that I could alter the table in migration. I was thinking something like this:
for client in Client.all
# Retrieve children
underwritings = client.underwritings
# Change primary key
execute 'ALTER TABLE clients ALTER COLUMN id TYPE uuid;'
execute 'ALTER TABLE clients ALTER COLUMN id SET DEFAULT uuid_generate_v1();'
# Get new id - is this already generated?
client_id = client.id
for underwriting in underwritings
locations = underwriting.locations
other_record = underwriting.other_records...
execute 'ALTER TABLE underwritings ALTER COLUMN id TYPE uuid;'
execute 'ALTER TABLE underwritings ALTER COLUMN id SET DEFAULT uuid_generate_v1();'
underwriting.client_id = client_id
underwriting.saved
underwriting_id = underwriting.id
for location in locations
buildings = location.buildings
execute 'ALTER TABLE locations ALTER COLUMN id TYPE uuid;'
execute 'ALTER TABLE locations ALTER COLUMN id SET DEFAULT uuid_generate_v1();'
location.undewriting_id = underwriting_id
location.save
location_id = location.id
for building in buildings
...
end
end
for other_record in other_records
...
end
...
...
end
end
Questions:
Will this work?
Is there an easier way to do this?
Will child records be retrieved properly as long as they are retrieved before the primary key is changed?
Will the new primary key be already generated as soon as the alter table is called?
Thanks very much for any help or tips in doing this.
I found these to be quite tedious. It is possible to use direct queries to PostgreSQL to convert table with existing data.
For primary key:
ALTER TABLE students
ALTER COLUMN id DROP DEFAULT,
ALTER COLUMN id SET DATA TYPE UUID USING (uuid(lpad(replace(text(id),'-',''), 32, '0'))),
ALTER COLUMN id SET DEFAULT uuid_generate_v4()
For other references:
ALTER TABLE students
ALTER COLUMN city_id SET DATA TYPE UUID USING (uuid(lpad(replace(text(city_id),'-',''), 32, '0')))
The above left pads the integer value with zeros and converts to a UUID. This approach does not require id mapping and if needed old id could be retrieved.
As there is no data copying, this approach works quite fast.
To handle these and more complicated case of polymorphic associations please use https://github.com/kreatio-sw/webdack-uuid_migration. This gem adds additional helpers to ActiveRecord::Migration to ease these migrations.
I think trying to do something like this through Rails would just complicate matters. I'd ignore the Rails side of things completely and just do it in SQL.
Your first step is grab a complete backup of your database. Then restore that backup into another database to:
Make sure that your backup works.
Give you a realistic playpen where you can make mistakes without consequence.
First you'd want to clean up your data by adding real foreign keys to match all your Rails associations. There's a good chance that some of your FKs will fail, if they do you'll have to clean up your broken references.
Now that you have clean data, rename all your tables to make room for the new UUID versions. For a table t, we'll refer to the renamed table as t_tmp. For each t_tmp, create another table to hold the mapping from the old integer ids to the new UUID ids, something like this:
create table t_id_map (
old_id integer not null,
new_id uuid not null default uuid_generate_v1()
)
and then populate it:
insert into t_id_map (old_id)
select id from t_tmp
And you'll probably want to index t_id_map.old_id while you're here.
This gives us the old tables with integer ids and a lookup table for each t_tmp that maps the old id to the new one.
Now create the new tables with UUIDs replacing all the old integer and serial columns that held ids; I'd add real foreign keys at this point as well; you should be paranoid about your data: broken code is temporary, broken data is usually forever.
Populating the new tables is pretty easy at this point: simply use insert into ... select ... from constructs and JOIN to the appropriate t_id_map tables to map the old ids to the new ones. Once the data has been mapped and copied, you'll want to do some sanity checking to make sure everything still makes sense. Then you can drop your t_tmp and t_id_map tables and get on with your life.
Practice that process on a copy of your database, script it up, and away you go.
You would of course want to shut down any applications that access your database while you're doing this work.
Didn't want to add foreign keys, and wanted to to use a rails migration. Anyways, here is what I did if others are looking to do this (example for 2 tables, I did 32 total):
def change
execute 'CREATE EXTENSION "uuid-ossp";'
execute <<-SQL
ALTER TABLE buildings ADD COLUMN guid uuid DEFAULT uuid_generate_v1() NOT NULL;
ALTER TABLE buildings ALTER COLUMN guid SET DEFAULT uuid_generate_v1();
ALTER TABLE buildings ADD COLUMN location_guid uuid;
ALTER TABLE clients ADD COLUMN guid uuid DEFAULT uuid_generate_v1() NOT NULL;
ALTER TABLE clients ALTER COLUMN guid SET DEFAULT uuid_generate_v1();
ALTER TABLE clients ADD COLUMN agency_guid uuid;
ALTER TABLE clients ADD COLUMN account_executive_guid uuid;
ALTER TABLE clients ADD COLUMN account_representative_guid uuid;
SQL
for record in Building.all
location = record.location
record.location_guid = location.guid
record.save
end
for record in Client.all
agency = record.agency
record.agency_guid = agency.guid
account_executive = record.account_executive
record.account_executive_guid = account_executive.guid unless account_executive.blank?
account_representative = record.account_representative
record.account_representative_guid = account_representative.guid unless account_representative.blank?
record.save
end
execute <<-SQL
ALTER TABLE buildings DROP CONSTRAINT buildings_pkey;
ALTER TABLE buildings DROP COLUMN id;
ALTER TABLE buildings RENAME COLUMN guid TO id;
ALTER TABLE buildings ADD PRIMARY KEY (id);
ALTER TABLE buildings DROP COLUMN location_id;
ALTER TABLE buildings RENAME COLUMN location_guid TO location_id;
ALTER TABLE clients DROP CONSTRAINT clients_pkey;
ALTER TABLE clients DROP COLUMN id;
ALTER TABLE clients RENAME COLUMN guid TO id;
ALTER TABLE clients ADD PRIMARY KEY (id);
ALTER TABLE clients DROP COLUMN agency_id;
ALTER TABLE clients RENAME COLUMN agency_guid TO agency_id;
ALTER TABLE clients DROP COLUMN account_executive_id;
ALTER TABLE clients RENAME COLUMN account_executive_guid TO account_executive_id;
ALTER TABLE clients DROP COLUMN account_representative_id;
ALTER TABLE clients RENAME COLUMN account_representative_guid TO account_representative_id;
SQL
end

rails migration - update column with constraints

How to add new column and update its value from another table's column with conditions ?
I'm having two tables named user
id: integer
name: string
preferred_communication_channel_id: integer // stores the id of communication_channel
and table communication_channel stores different communication channels like Email,Telephone,etc.. of user
id: integer
user_id: integer
type: string
Now I need to add new column communication_mode in the user table
And update the column communication_mode value from communication_channel.type with some constraints
Here goes the mysql version of the update
update user as p
join communication_channel as cc
on p.preferred_communication_channel_id = cc.id and p.id=cc.user_id and cc.type="Telephone"
set p.communication_mode=3
I've created a migration to add new column but how to implement this query in rails migration ?
Please correct me if I missed anything
In migrations you can just write execute "SELECT * FROM bananas" and the SQL will be executed!

Resources