-
Notifications
You must be signed in to change notification settings - Fork 2.2k
feat: MSSQL onConflict/merge support #6050
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
base: master
Are you sure you want to change the base?
Conversation
test case changes test changes cleanup whoops
|
Is anything happening with this? Seems like a no-brainer and would be really helpful to MSSQL users |
|
@elhigu @kibertoad Patched my local knex with this and it seems to work |
|
@dustryder Been testing it for a little bit and everything works well except for unique composite indexes and tables with triggers. I ended up just using a Another issue is that I seem to be getting |
|
The code in the commit linked related to triggers is only hit if you add the includeTriggerModifications option in your insert or update statement. This just bypasses the output using a slower methodology but it's a simple way to get around the trigger issues for return values. You could use the same ideology for the upset I suspect though. If you need further clarifications let me know. |
|
@KalebMatthews Sorry for the late reply! I've tried a bunch of different fixes but none of them seem to work. Would you be able to provide some guidance on the exact changes to make? |
|
@KrisLau So you're issue is that you are treating the output like a return statement. As the error indicates if a table has a trigger the output statement must be pushed into a temp table of some sort. The main knex maintainers did not like the weight that this put on the normal query (which I agree with) which is why I added a modification option to enable to trigger specific insert, update, del returns. You can add the return feature only if the return is being utilized and generate the temp table and separate select statement (and delete temp table statement) if a return is specified. If one is not used then you can just return the count or exclude the output completely. That is my suggestion. |
|
@KalebMatthews Sorry for all the trouble! I looked through the const returningSql = returning
? ` ${this._returning('insert', returning, options.includeTriggerModifications)}`
: ''
// other code
sql += returningSql;
if (options && options.includeTriggerModifications) {
sql = this._buildTempTable(returning) + sql + this._buildReturningSelect(returning);
}So is the issue with my code have to do with me having to pass true to the The only other difference I could see was the return statement returning just the sql like this in this PR: return {
sql,
returning
}I tried changing the return to match the latter but that still resulted in the same error. I also tried changing all the returningSql to empty strings (which I assume just means it doesn't return anything from the statement?), removing anything top do with the temp tables, calling _returning with the includeTriggerModifications set to true manually, and they all seemed to either result in the same error or nothing changing in the DB Side note: I tried adding console.log to the functions but nothing seemed to be be printed to the console for some reason so I was having trouble trying to debug what exactly was changing. |
|
According to your testing scripts you are expecting results like The last output is where your error string is referring to. |
|
@KalebMatthews Managed to get rid of the error turns out I hadn't noticed that I fixed the error and was getting a different one related to something else (managed to fix that too), thanks so much for the help! |
Glad I could be of some help. |
|
@kibertoad Saw that this was merged, thanks! Just wanted to add that I ended up not using the method awhile back when I was researching and thought I'd add some notes for anyone in case they might want to use the method. It seems at least from some articles and StackOverflow posts I read that the usage of MERGE is not necessarily safe? From my understanding it causes locks and some other issues that would be bad for systems that have a lot of concurrent users as well as a number of other issues. Most articles seem to suggest against using it overall:
I think the method would still be very useful to a subset of people but a note on the method somewhere in the documentation and maybe a comment on the method specifying that mssql's implementation has some drawbacks on the MSSQL side.
|
|
@KrisLau would you recommend reverting feature overall, or adding documentation? |
|
@kibertoad I dont think I have enough expertise to give great advice haha but imo probably just add documentation? Most of my current knowledge was just those forums & articles. |
|
This looks close. Looking forward to it. |
|
will this be merged in sometime soon? would benefit from this functionality today. |
Ref: #5646, #3186
What
Support for onConflict/merge for MSSQL
Why
Because there there is no support for this in Knex for MSSQL. You'd have to either decide on an upsert approach and wrap it in raw or use individual statements to achieve the similar behaviour
How
Implementing (most) of the current onConflict/ignore/merge API via a subset of standard ansi sql merge statements. .raw inside onConflict has not been added.
Anything else
Because this approach uses standard syntax, other dialects should also be able implement this in a similar manner (given they too support standard syntax).