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

feat: add ability for escaping for Raw() find operator #6850

Merged
merged 6 commits into from
Oct 6, 2020

Conversation

temnov98
Copy link
Contributor

@temnov98 temnov98 commented Oct 5, 2020

Currently, find operator Raw() not supported escaping.
I have updated the code so that it is now possible to use an escaping.
The updated syntax is as follows:

await connection.getRepository(Post).find({
    likes: Raw((columnAlias, parameters) => {
        return `(${columnAlias} = ${parameters[0]}) OR (${columnAlias} = ${parameters[1]})`
    }, [2, 3]),
});

await connection.getRepository(Post).find({
    likes: Raw((columnAlias, parameters) => {
        return `(${columnAlias} = ANY(${parameters[0]})) AND (${columnAlias} < ${parameters[1]})`
    }, [[1, 4, 5, 6], 6]),
});

await connection.getRepository(Post).find({
    title: Raw((columnAlias, parameters) => {
        return `${columnAlias} = ANY(${parameters[0]})`;
    }, [["About #1", "About #3", "About #5"]]),
    likes: Raw((columnAlias, parameters) => `${columnAlias} IN (${parameters[0]}, ${parameters[1]})`, [5, 1]),
});

The tests for the new functionality have been written. The old functionality works unchanged.

@temnov98
Copy link
Contributor Author

temnov98 commented Oct 5, 2020

This functionality is useful in the case when it is necessary to pass user input in a raw query. Also you can create custom operators via Raw() operator.

For example, operator ILIKE() which is in the next branch, but not in master can be implemented as follows:

function ILike(value: string) {
    return Raw((columnAlias, parameters) => `${columnAlias} ILIKE ${parameters[0]}`, [value]);
}

@imnotjames
Copy link
Contributor

Aha! This is very nice! :) I've actually seen a few people asking about this BUT for the life of me I can't find the issues where that was.

I'll try to get to reviewing this over the next few days as I'm sure it would make a lotta people happy.

As I understand it - this is backwards compatible, as well? With the previous functionality? Looks to be the case there from the source.

@imnotjames
Copy link
Contributor

I think this Closes #2475

@temnov98
Copy link
Contributor Author

temnov98 commented Oct 5, 2020

I added the ability to specify parameters using an object literal parameters for Raw() find operator.

Example:

await connection.getRepository(Post).find({
    likes: Raw((columnAlias) => `${columnAlias} < :maxValue`, { maxValue: 6 }),
});

@temnov98
Copy link
Contributor Author

temnov98 commented Oct 5, 2020

As I understand it - this is backwards compatible, as well? With the previous functionality? Looks to be the case there from the source.

yes, all changes are backward compatible.

@@ -1,9 +1,47 @@
import {FindOperator} from "../FindOperator";
import {ObjectLiteral} from "../../common/ObjectLiteral";

/**
* Find Options Operator.
* Example: { someField: Raw([...]) }
Copy link
Member

Choose a reason for hiding this comment

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

I think example is incorrect here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think example is incorrect here

fixed

/**
* Find Options Operator.
* For escaping parameters use next syntax:
* Example: { someField: Raw((columnAlias, parameters) => `${columnAlias} = ${parameters[0]}`, [5]) }
Copy link
Member

Choose a reason for hiding this comment

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

I can't understand why do we need this syntax. Isn't it redundant?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can't understand why do we need this syntax. Isn't it redundant?

Do you suggest leaving only parameters via ObjectLiteral and remove via array? I can do it.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, it's just seems redundant. It's better to left only one syntax if they both do same and there are no technical issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it's just seems redundant. It's better to left only one syntax if they both do same and there are no technical issues.

Done. Waiting for the tests to complete.

@pleerock pleerock merged commit 91b85bf into typeorm:master Oct 6, 2020
@pleerock
Copy link
Member

pleerock commented Oct 6, 2020

Thank you a lot!

@sanderevers
Copy link

Having parameters with the Raw operator is a very welcome feature for us, thanks.

I did however encounter a little catch: what happens when you use the same :name in two Raw instances? To some people it will probably be obvious that this should map to the same $parameter in the generated SQL (as it currently does). But I think you could also argue that this parameter should be local to this Raw instance.
For example, in our project, these Raw instances are automatically generated, instead of specified by hand. When they use the same :name, the SQL produces unexpected results (or, in the best case, breaks because of type errors). In order to guarantee a unique parameter for each instance, I now use UUIDs as names.

Now, I'm not saying that it shouldn't be allowed to share parameters between Raw instances, but
(a) this represents a design choice which I don't know you were aware of, and
(b) it would be good to document this, so users know what to expect

@imnotjames
Copy link
Contributor

Unfortunately, there's only support in query builders (& thus find operators) for query-builder-global variable scopes.

We don't allow for local parameter scopes at this time - and making that change would be a breaking one but we're definitely accepting pull requests that want to explore that.

This is documented here

@bhaveshdaswani93
Copy link

I cannot use this change when installing using yarn add typeorm.
What would step to get this change

zaro pushed a commit to zaro/typeorm that referenced this pull request Jan 12, 2021
* feat: add ability for escaping for Raw() find operator

* fix: update Raw() find operator

* fix: fix tests for Raw() find operator

* feat: add ability for escaping with object literal parameters for Raw() find operator

* docs: correct the example comment of Raw() find operator

* fix: delete redundant functional
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
hacktoberfest-accepted label hacktoberfest
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants