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

fix: minified aliases are now properly referenced in subqueries (v6) #14852

Merged
merged 12 commits into from Aug 18, 2022

Conversation

sdepold
Copy link
Member

@sdepold sdepold commented Aug 7, 2022

Backport of #14804 to v6 + fix for mssql order duplication

@WikiRik
Copy link
Member

WikiRik commented Aug 7, 2022

Do we need the linting fixes? They're not in files related to this PR and I would prefer to limit the changes that we do in v6

@sdepold
Copy link
Member Author

sdepold commented Aug 7, 2022

Do we need the linting fixes? They're not in files related to this PR and I would prefer to limit the changes that we do in v6

Well. I just ran lint --fix and this was the result. I wonder how it could have worked before since I expected the linter to fail if there are things to change

@sdepold
Copy link
Member Author

sdepold commented Aug 7, 2022

I suppose I can remove the linting commit if we feel strong about it

@sdepold
Copy link
Member Author

sdepold commented Aug 7, 2022

@WikiRik better?

@WikiRik
Copy link
Member

WikiRik commented Aug 7, 2022

Linter still passes, so I'm fine with this. Thanks!

@WikiRik
Copy link
Member

WikiRik commented Aug 7, 2022

@tomquist Any chance you can test this on your project to make sure it works for your use case?

@tomquist
Copy link

tomquist commented Aug 8, 2022

@WikiRik Thanks! I tested it on our project. It all works fine if we enforce a subquery using subQuery:true 🎉.
However I ran into one bug now that when it isn't doing a subquery it doesn't minify the alias only at the place where the order by column is used.
E.g. this doesn't work:

await Foo.findAll({attributes: {include: [[sequelize.literal(`"Foo".my_name`), "order_0"]]}, order: ["order_0", "DESC"]})

The error is:

column _Foo.order_0 does not exist

@WikiRik
Copy link
Member

WikiRik commented Aug 8, 2022

@evanrittenhouse could you check this new case out?

@tomquist
Copy link

tomquist commented Aug 8, 2022

I think the issue I mentioned is an existing issue and nothing introduced by this bugfix. I can also open a new issue for the subQuery: false case if you like?

@sdepold
Copy link
Member Author

sdepold commented Aug 10, 2022

@WikiRik Thanks! I tested it on our project. It all works fine if we enforce a subquery using subQuery:true 🎉. However I ran into one bug now that when it isn't doing a subquery it doesn't minify the alias only at the place where the order by column is used. E.g. this doesn't work:

await Foo.findAll({attributes: {include: [[sequelize.literal(`"Foo".my_name`), "order_0"]]}, order: ["order_0", "DESC"]})

The error is:

column _Foo.order_0 does not exist

Do I understand the code right, that you want to have a query that aliases Foo.myname as order_0 and then you want to sort by order_0?

With this code in place, we are currently generating

SELECT "id", "my_name" AS "_0", "Foo".my_name AS "_1" FROM "Foos" AS "Foo" ORDER BY "Foo"."order_0", "Foo"."DESC";

@tomquist ?

@tomquist
Copy link

Ah I see some brackets are missing. So the issue is that this:

await Foo.findAll({attributes: {include: [[sequelize.literal(`"Foo".my_name`), "order_0"]]}, order: [["order_0", "DESC"]]})

generates this query:

SELECT "id", "my_name" AS "_0", "Foo".my_name AS "_1" FROM "Foos" AS "Foo" ORDER BY "Foo"."order_0" DESC;

@sdepold
Copy link
Member Author

sdepold commented Aug 10, 2022

@tomquist what would you expect instead?

@tomquist
Copy link

I'd expect this:

SELECT "id", "my_name" AS "_0", "Foo".my_name AS "_1" FROM "Foos" AS "Foo" ORDER BY "_1" DESC;

@sdepold
Copy link
Member Author

sdepold commented Aug 10, 2022

Excellent. Thanks for the clarification

@sdepold
Copy link
Member Author

sdepold commented Aug 10, 2022

Just pushed a change that might fix the issue. It's funny because I just removed a guard that was specifically targeting subQueries and enabled the logic in general.

@sdepold
Copy link
Member Author

sdepold commented Aug 10, 2022

@tomquist @WikiRik @evanrittenhouse let's see if this works :)

@sdepold
Copy link
Member Author

sdepold commented Aug 11, 2022

interesting. so mssql is additionally adding a sorting in it's query generator on top of the abstract order by fragments.

@sdepold
Copy link
Member Author

sdepold commented Aug 11, 2022

@tomquist can you pleas test the new version? I'll figure out the mssql issue meanwhile

if (!options.order || !options.order.length) {
fragment += ` ORDER BY ${tablePkFragment}`;
} else {
const orderFieldNames = _.map(options.order, order => order[0]);
const primaryKeyFieldAlreadyPresent = _.includes(orderFieldNames, model.primaryKeyField);
const orderFieldNames = (options.order || []).map(order => {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a function that is doing this already? Taking a name like thing and returns its string content?

let primaryKey = model.primaryKeyField;

const tablePkFragment = `${this.quoteTable(options.tableAs || model.name)}.${this.quoteIdentifier(primaryKey)}`;
const aliasedAttribute = (options.attributes || []).find(attr => Array.isArray(attr)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a copy from the generic query generator. I was about to refactor this function but then wondered if _getAliasForField should somehow take care of this logic. I'm still not 100% sure what we are even doing here but I supposed, that this piece of code combined with getAliasForField is basically catering for 1) model definition based aliases (using the field property?) and 2) aliases that are introduced during the query calls (e.g. findAll).

Maybe instead of doing this manually, we should have a bit of code inside of _getAliasForField that is checking the options and extracts the call alias from them?

@sdepold
Copy link
Member Author

sdepold commented Aug 12, 2022

I'm a little bit lost on why MSSQL is having additional logic wrt order but it's probably there for good reasons. Anyway, because of this, it becomes a bit more convoluted and messy. We could clean up MSSQL but I wonder if that should happen in v7 only?

@tomquist
Copy link

@sdepold Just tested with af1a638, and it made all our tests pass 🥳 Thanks a lot!

@sdepold
Copy link
Member Author

sdepold commented Aug 12, 2022

@sdepold Just tested with af1a638, and it made all our tests pass 🥳 Thanks a lot!

Sweet. Thanks for the feedback!

});
const primaryKeyFieldAlreadyPresent = orderFieldNames.some(
fieldName => fieldName === (primaryKey.col || primaryKey)
);

if (!primaryKeyFieldAlreadyPresent) {
fragment += options.order && !isSubQuery ? ', ' : ' ORDER BY ';
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit crazy that this is done manually. I was tempted to somehow inject this idea into the incoming order options so that this.getQueryOrders would do the heavy lifting for us

@sdepold sdepold requested a review from WikiRik August 12, 2022 08:49
@sdepold
Copy link
Member Author

sdepold commented Aug 12, 2022

@WikiRik @evanrittenhouse ready for review

@WikiRik
Copy link
Member

WikiRik commented Aug 14, 2022

Let's review #14882 first and then get back to this one

@sdepold
Copy link
Member Author

sdepold commented Aug 18, 2022

@WikiRik @evanrittenhouse can you review this guy?

Copy link
Member

@WikiRik WikiRik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's not the prettiest but it seems to work for v6 so we should be good

@sdepold sdepold requested a review from WikiRik August 18, 2022 10:59
@sdepold sdepold merged commit 5a257bc into v6 Aug 18, 2022
@sdepold sdepold deleted the order-by-minify-aliases-v6 branch August 18, 2022 11:00
@sdepold
Copy link
Member Author

sdepold commented Aug 18, 2022

Thanks Rik!

@github-actions
Copy link
Contributor

🎉 This PR is included in version 6.21.4 🎉

The release is available on:

Your semantic-release bot 📦🚀

@pascuflow
Copy link

Was this the only change from 6.20.1? Am getting "No context available. ns.run() or ns.bind() must be called first." error when using transactions.

@ephys
Copy link
Member

ephys commented Sep 28, 2022

Sounds like a continuation local storage issue, but we haven't touched that part of the code in recent releases

@sdepold sdepold added the funded label Oct 3, 2022
@bminer
Copy link

bminer commented Dec 8, 2022

This PR seems to be causing an issue for me. See #15422

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

Successfully merging this pull request may close these issues.

None yet

6 participants