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
if OneToMany entity was updated right before, em.save() does not save entity attached in ManyToOne, resulting in parentId column <null> #1319
Comments
I need a reproduction repo to test your issue, also make sure to check on both 0.1.7 and |
@pleerock can I add your github public email to private bitbucket repo and share instruction to start app also via email? |
sorry my time is limited to do that, better if you create a PR with a failing test which I can quickly fix. |
np, will try to do that |
Interesting. Actually @next is saving entity nicely! But I will try to find a cause in 0.1.7 I'm afraid that (as always happens to me) repo to reproduce actually will not have this bug. Trying to figure out this by myself. What I discovered: Postgres actually getting proper insert statement with proper parameters: INSERT INTO "roast_attempt_reaction"("type", "createdAt", "updatedAt", "userId", "attemptId") VALUES ($1,DEFAULT,DEFAULT,$2,$3) [ 'upvote', 28, 6 ] But then, when I update RoastAttempt (just jsonb column value), which has reactions via
I'm getting this weird sql statement being send to postgresql (second statement) UPDATE "roast_attempt" SET "cachedReactions"=$1, "updatedAt"=$2 WHERE "id"=$3 [ '{"upvote":2}', 2017-12-08T07:55:46.179Z, 6 ]
UPDATE "roast_attempt_reaction" SET "attemptId"=$1 WHERE "id"=$2 [ null, 57 ] |
upd, found the solution for now (but not fix for the bug): It seems that problem somewhere where I'm doing this: const reaction = new RoastAttemptReaction();
reaction.attempt = a;
reaction.type = type;
reaction.user = u;
await this.entityManager.save(reaction);
a.modifyReaction(type, 1);
a = await this.entityManager.save(a); I suspect SubjectOperationExecutor somewhere sees Attempt (which has reactions) having 1 reaction and removes from this 1 reaction id to attempt (attemptId). If I swap code above, first update parent entity and than create new child entity - everything works fine. No additional update to set null. SOLUTION: a.modifyReaction(type, 1);
a = await this.entityManager.save(a);
const reaction = new RoastAttemptReaction();
reaction.attempt = a;
reaction.type = type;
reaction.user = u;
await this.entityManager.save(reaction); |
I don't have enough details to reproduce your issue and help, I'll able to help you only if you provide a git repo or better a failing test with minimal reproduction code, and only on |
@pleerock I think since this issue is not present in @next this simple trick would be enough for the moment. If it's possible - I don't think issue should be closed yet, maybe I will have time to dig deeper into the problem later or actually will manage to reproduce it. The most basic solution works. |
@pleerock it occured that this bug is easy to catch even in clean new project. I made repo to reproduce: https://github.com/idchlife/typeorm-bug1-repro Instructions: npm i
# replace values for postgresql in src/tests.ts
./tests.sh btw, can I ask you and @19majkel94 , what IDEs are you using to code for typeorm? I opened it in VSCode and it's intellisense was kinda dying every minute. |
Yes, I'm using VSCode, I had no problem with intellisense and performance but I noticed that sometimes the whole TypeScript language service hangs and don't check the code nor underline the error, I need to restart it or wait a moment 😕 |
You have this error because you have initialized array: @OneToMany(type => Child, c => c.parent)
children: Child[] = []; Remove When typeorm tries to save your |
@pleerock interesting. This is because by default typeorm would not even touch property "children", because no one told to load those relations, so the value is [] Wonderful! Is there way to warn about this stuff or something? Like "you loaded entity without relations from database and there is property initializer. Maybe check again?" Thanks for checking, this is definitely gone above my head. I remembered there were some errors with array initializer but just forgot about this caveat. |
value [] means everything was removed, just think how it would work if you wanted to really remove all children from your parent.
I have no idea how to warn about this thing.
yes this is tricky, unfortunately |
When you register entity class in metadata storage (using Of course you can limit this check only to relation fields to prevent false warning, eg. when someone have enum field with default value. |
what kind of warning it shall be? Shall we give an error of simply warning? And what if user wants to initialize property and disables entity updation from inverse side? |
Can we check that too? 😉 Ask yourself a question - is it better to print false warning on console or have this kind of issues and many angry developers because "this shit doesn't work" due to properties initialization? |
so, what do you think is better - give a warning in console or give an error? Or maybe there is some other solution like cli command |
It might be a solution but must be well documented, e.g. in issue template "please paste logs from |
yeah its kinda safe way, but what is the best way, Im seeking for opinions. Adding @daniel-lang @AlexMesser @NoNameProvided @mrkmg |
Hmmmm... I think a If we do emit warnings, we should also provide some sort of "suppressWarnings" flag that allows developers to turn off warnings. I was thinking, how cool would it be to have tslint, or even typescript give a compile-time warning about it, but after looking through the docs on how types work, I can not see a way to accomplish that, so a runtime warning is the only option I see. If we can come up with a few checks for best practice, then I can see the use-case of a full command like
That's my two cents. |
We could just have both as well. Emit warnings to STDERR (or STDOUT), and have the |
Thank you for your feedback @mrkmg . I decided not to do Regarding to warning in console - it will look very weird in my opinion, better to throw an error instead I think. This change will be available in the next |
Throwing error is ok but what about false positive? E.g. when user wants to initialize property and disables entity updation from inverse side? Supressing errors would be worse than |
I'm fine with an error as it seems like @pleerock only limited to If the list of things to check gets longer, I would be in favour of a |
It's very strange. I assume I did nothing wrong.
Here is column:
here is I'm saving:
I did console.log of reaction before saving - entity is there. in the attempt field.
I should also mention .user field on the other hand is populated and saved.
version: "typeorm": "^0.1.7"
edit: em.create() has the same behaviour
The text was updated successfully, but these errors were encountered: