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

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]

Related

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

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.

Updating existing records with IDs of new rows while using a "with" clause

Platform: Ruby on Rails with PostgreSQL database.
Problem:
We are doing some backfilling to migrate our data to a new structure. It's created a rather convoluted situation, and we'd like to handle it as efficiently as possible. It's partially addressed with SQL similar to this:
with rows as (
insert into responses (prompt_id, answer, received_at, user_id, category_id)
select prompt_id, null as answer, received_at, user_id, category_id
from prompts
where user_status = 0 and skipped is not true
returning id, category_id
)
insert into category_responses (category_id, response_id)
select category_id, id as response_id
from rows;
The tables and columns have been obfuscated/simplified so the reasoning behind it may not be as clear, but category_responses is a many-to-many join table. What we're doing is grabbing existing prompts, and creating a set of empty responses (answer is NULL) for each.
The piece that's missing is to then associate the records in prompts with the newly created responses. Is there a way to do this within the query? I would like to avoid adding a prompt_id column to answers if possible, but I am guessing this would be one way to handle that, including it in the returning clause, then issuing a second query to update the prompts table - and anyway I'm not even sure you can run more than one query with the results of a single with clause.
What's the best way to accomplish this?
I have settled on adding the needed column, and updated the query as follows:
with tab1 as (
insert into responses (prompt_id, answer, received_at, user_id, category_id, prompt_id)
select prompt_id, null as answer, received_at, user_id, category_id
from prompts
where user_status = 0 and skipped is not true
returning id, category_id, prompt_id
),
tab2 as (
update prompts
set response_id = tab1.response_id,
category_id = tab1.category_id
from tab1
where prompts.id = tab1.prompt_id
returning prompts.response_id as response_id, prompts.category_id as category_id
)
insert into category_responses (category_id, response_id)
select category_id, id as response_id
from tab2;

Checking existence of a column before adding

This is a small part of the data in my table PLANT I'm having in database...
id name code
123 OFFICE1 A1234
456 OFFICE2 B4567
789 OFFICE3 C8989
When I get all the data from an api, before inserting them into the database, I want to check if any records are present already.
This is how I'm checking if a record is present..
let isExists = sharedInstance.plantExists(thePlantObject, id: 123)
func plantExists(_ items: plant,id: Int) -> Bool {
var isExists = false
sharedInstance.database!.open()
isExists = sharedInstance.database!.executeUpdate("EXISTS(SELECT * FROM PLANT WHERE PLANT.id = ?)", withArgumentsIn: [id])
sharedInstance.database!.close()
return isExists
}
But if I print isExists, then this message is printed... (Bool) isExists = <variable not available>
What am I doing wrong here..?
If you can change the schema of db then make sure id attribute is set as unique and insertion will fail if you are inserting id which already exists in the column.
Or Just do select query with id and see if any results come back to you
Select * from where id =
As per comment #Joakim Danielson, EXISTS should be a part of WHERE clause.
You can achieve it feature two way
1. The way you are approaching (checking existence and based on that insert).
Instead of using EXISTS use following query
SELECT COUNT(id) FROM PLANT WHERE PLANT.id = ?
This way you can get the count of specific id. Here i assume that you didn't put any UNIQUE constraints in id column. If you set UNIQUE constraint in id column, then second approach is the best approach for you.
2. Let the SQLite handle itself (based on a constraint)
While create the db schema, make the id unique. Assumed schema creation query is following
CREATE TABLE plant (
id INT(11) UNIQUE NOT NULL,
name VARCHAR(255)
);
use following query while inserting
INSERT OR IGNORE (`id`, `name`) VALUES (?, ?)
This way, it will ignore inserting if any sort of constraint fails.
Working demo is here.
NB: It won't report any failure.

Flutter DatabaseException(UNIQUE constraint failed)

I`m trying to insert some data into sqflite table but there is an error while executing insert query
await db.execute(
'CREATE TABLE $catrgoryTable($category_id INTEGER PRIMARY KEY UNIQUE , $colDeviceTypeId INTEGER, '
'$room_id INTEGER)');
print('category created!');
and here is the Error
SqfliteDatabaseException (DatabaseException(UNIQUE constraint failed: category_Table.category_id (code 1555)) sql 'INSERT INTO category_Table (category_id, device_type_id, room_id) VALUES (?, ?, ?)' args [1, 1, 1]})
Thanks for any help:)
The table category_Table has a unique constraint field on it, the error shows that you tried to enter a value for category_id that it already exists, which violates primary key's uniqueness constraint for this field. Only one row can exist with a given ID value. So If you're trying to insert a row, be sure that your category_id have a unique value, or if you don't care about generating ids by yourself, you can add AUTOINCREMENT setting to your category_id column definition. This way it will be filled automatically and each row will have its own unique value.
static Future<void> insert(String table, Map<String, dynamic> data) async {
final db = await DBHelper.database();
db.insert(table, data, conflictAlgorithm: sql.ConflictAlgorithm.replace);
}
here is my code is thought if I use conflict algorithm replace it would replace that unique value ?
In the insert function of database. Add
conflictAlgorithm: ConflictAlgorithm.replace.
it worked for me

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