Spring Data JPQL query: lower case for List param - spring-data

I use Spring Data REST in my project and I have a #Query tag, as such:
#Query("from Customer c where lower(c.customerId) = lower(:customerId) and lower(c.department.businessUnit.name) = lower(:businessUnit)")
List<Customer> findByCustomerIdAndBusinessUnit(#Param('customerId') String customerId, #Param('businessUnit') String businessUnit)
This works perfectly fine. But, I am not sure how to convert to lowercase when a List is passed in, such as:
#Query("SELECT c FROM Customer c WHERE LOWER(c.customerId) IN LOWER(:customerIds)")
Page<Customer> findByCustomerIdIn(#Param("customerIds") List<String> customerIds, Pageable pageable)
That gives me the following error:
Caused by: java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ( near line 1, column 94 [SELECT c FROM com.myapp.Customer c WHERE LOWER(c.customerId) IN LOWER(:customerIds)]
I understand this happening because Spring Data REST cannot cast a whole list of Strings to lower case (that is not possible in straight up TSQL / PLSQL either!). So, are my options limited to implementing my own repository and build a controller on top of it...? Any better ideas? :)

I believe, you have to transform the list.
Even if you plan to use Spring JPA findByQuery like
List<User> findByCustomerIdInIgnoreCase(List<String> customerIds);
You have to write some code to transform the list into a list of lowercase strings.
If you are looking for converting the list in place, it might not be possible as Strings in Java are immutable
However, if the intention is to do in a single line, with as much less code as possible.
You can do it in Java 8 as below.
List<String> customerIdsLC = customerIds.stream().map(String::toLowerCase).collect(Collectors.toList());
In case, you have a different transformation to do - just provide the right info to map() in the form, Class::method
For e.g.
map(String::toUpperCase) - to convert to Uppercase
map(Long::valueOf) - to convert to Long.

Related

Input string was not in correct formate while inserting data to postgresql through entityframework in .net core using dynamic query

I am getting error while inserting data to pgsql with .net core entity framework
error is Input string was not in correct format
this is my query executing
INSERT INTO public."MedQuantityVerification"("Id","MedId","ActivityBy","ActivityOn","Quantity","ActivityType","SupposedOn","Note") Values(7773866,248953,8887,'7/14/2018 10:43:43 PM','42.5 qty',5,NULL,'I counted forty two {point} five.')
anyhow when I run that query directly to postgresql browser it works fine
looks like issue on c# side it is but not know what?
also issue is with {point}
this is how I executing the dynamic query
db.Database.ExecuteSqlRaw(query);
You have to escape the curly brackets:
{point} should be {{point}}
ExecuteSqlRaw utilizes curly braces to parameterize the raw query so if your query naturally includes them like OP's does the function is going to try and parse them. Doubling up the braces like in Koen Schepens' answer acts as an escape sequence and tells the function not to parse it as a parameter.
The documentation for the function uses the following example as to the purpose of why it does what it does:
var userSuppliedSearchTerm = ".NET";
context.Database.ExecuteSqlRaw("UPDATE Blogs SET Rank = 50 WHERE Name = {0}", userSuppliedSearchTerm);
Note that you'll want to use this to your advantage any time you're accepting user-input and passing it to ExecuteSqlRaw. If the curly brace is in a parameter instead of the main string it doesn't need to be escaped.

EF Core raw query with Like clause

I want to create queries using EF FromSqlInterpolated or FromSqlRaw that allows me to use Like clauses, but I don't know what is the right way to do it without opening the application to SqlInjection attacks.
One first approach has took me to the following code
var results = _context.Categories.FromSqlInterpolated(
$"Select * from Category where name like {"%" + partialName + "%"}");
First test worked fine, it returns results when providing expected strings, and returns nothing when i provide something like ';select * from Category Where name='Notes'--%';
Still I don't know much about SqlInjection, at least not enough to feel safe with the query shown before.
Does someone know if the query is safe, or if there is a right way to do it?
Thanks
From this document
The FromSqlInterpolated and ExecuteSqlInterpolated methods allow using
string interpolation syntax in a way that protects against SQL injection attacks.
var results = _context.Categories.FromSqlInterpolated(
$"Select * from Category where name like {"%" + partialName + "%"}");
Or you can also change your query to Linq-to-Entity like this way
var results = _context.Categories.Where(p => p.name.Contains(partialName ));

How to isolate a list of URIs in a RDF file using CONSTRUCT or DESCRIBE in SPARQL?

I'm trying to get only a list of URIs in RDF instead of a list of triples:
PREFIX gr: <http://purl.org/goodrelations/v1#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
DESCRIBE ?product
WHERE
{
?product rdfs:subClassOf gr:ProductOrService .
}
Using SELECT, instead of DESCRIBE I receive only the subject (which I want), but not as an RDF but like a SPARQL Result with binds, vars, etc.
Using CONSTRUCT, I can't specify only the ?product, as above, so the closest I can get is:
PREFIX gr: <http://purl.org/goodrelations/v1#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
CONSTRUCT
WHERE
{
?product rdfs:subClassOf gr:ProductOrService .
}
Which returns an RDF with triples of different products, but the same properties and objects.
It looks like you should read over the SPARQL specification, which tells you that this is exactly as expected. To get the single column you wish, you must use SELECT.
SPARQL has four query forms. These query forms use the solutions from pattern matching to form result sets or RDF graphs. The query forms are:
SELECT
Returns all, or a subset of, the variables bound in a query pattern match.
CONSTRUCT
Returns an RDF graph constructed by substituting variables in a set of triple templates.
ASK
Returns a boolean indicating whether a query pattern matches or not.
DESCRIBE
Returns an RDF graph that describes the resources found.
I found a solution. I've used SELECT, but instead of binds and vars, as output received a "Comma-Separated Values (with fields in N-Triples syntax)" CSV file:
<http://www.productontology.org/id/Real_estate>
<http://www.productontology.org/id/Automobile>
<http://www.productontology.org/id/Auction>
<http://www.productontology.org/id/Video_game>
<http://www.productontology.org/id/Campsite>
<http://www.productontology.org/id/Car>
<http://www.productontology.org/id/Audiobook>
<http://www.productontology.org/id/Browser_game>
...
Representing the result of a SPARQL SELECT query as an RDF List is a tooling issue - it is not something that can be solved in SPARQL in general.
Some SPARQL tools may have ways to support rendering the query result as an RDF list. But it's not something you can fix by just formulating your query differently, you'll need to use a tool to (programmatically) format the result.
In Java, using Eclipse RDF4J, you can do it as follows (untested so you may need to tweak it to work properly, but it should give you a general idea):
String query = "SELECT ?product WHERE { ?product rdfs:subClassOf gr:ProductOrService . }";
// do the query on repo and convert to a Java list of URI objects
List<URI> results = Repositories.tupleQuery(
repo,
query,
r -> QueryResults.stream(r).map(bs -> (URI)bs.getValue("product")).collect(Collectors.toList()
);
// create a resource (bnode or URI) for the start of the rdf:List
Resource head = SimpleValueFactory.getInstance().createBNode();
// convert the Java list of results to an rdf:list and add it
// to a newly-created RDF Model
Model m = RDFCollections.asRDF(results, head, new LinkedHashModel());
Once you have your result as an RDF model you can use any of the existing RDF4J APIs to write it to file or to store it in a triplestore.
Now, I am not claiming that any of this is a good idea - I have never seen a use case for something like this. But this is how I would do it if it were necessary.

Spring data repository: findBySomething***In*** and result order

Is there any way to make those functions getting the results ordered like in the order of the list (or collection) given to the function for the in lookup?
Simple example of a spring data repository interface function:
public void List<Entity> findByColorIn(List<String> colors)
Now im creating a string list with the order "green", "blue", "cyan" and calling this function.
Assuming there is a unique match of all these three colors:
how can i make the function returning the results by the given order of property in the given list? In this example:
Entity[id=32, color="green"]
Entity[id=11, color="blue"]
Entity[id=22, color="cyan"]
Not sure whats the default order in this case but im assuming the id...
spring data has two variants with api how you can use standard order based on property.
1 variant :
public void List<Entity> findByColorInOrderByColorDesc(List<String> colors)
public void List<Entity> findByColorInOrderByColorAsc(List<String> colors)
2 variant
Sort sort= new Sort(Sort.Direction.ASC/DESC,"color");
public void List<Entity> findByColorIn(List<String> colors , Sort sort)
if you want to use custom order for case , sort order :
color="green" , color="blue", color="cyan"
you need use variant 2 with custom Sort implementation based on your sort logic.
Also you can get not sorted result and sort it in server side if you have small result set . spring data might return stream , so you can do something like :
findByColorIn(colors).stream().sorted(comparator....).collect(Collectors.toList());
In my case I just sorted it by hand since I wasn't dealing with a very long array of items.
First you retrieve the elements from database in whatever order they come, then compare with your color list and sort it accordingly.
If you want to retrieve Objects and keep order of ids in the same time, you can use this:
#Query("select p from Colour p where p.id in :colors order by FIELD(p.id,:colors)")
List<Color> getColorsByIdsOrdered(List<String> colors);
P.S.: In case IntelliJ or other platform marks ,,FIELD'' with RED, just ignore it. Application will compile and request will work fine.

Versant OQL Statement with an Arithmetic operator

I'm working on a c# project that use a Versant Object Database back end and I'm trying to build a query that contains an arithmetic operator. The documentation states that it is supported but lack any example.
I'm trying to build something like this:
SELECT * FROM _orderItemObject WHERE _qtyOrdered - _qtySent > 0
If I try this statement in the Object Inspector I get a synthax error near the '-'.
Anyone has an example of a working VQL with that kind of statement?
Thanks
I am not sure that the Object Inspector will know the syntax for the arithmtic expression. However, in your code you should be referring to the fully qualified class. Then the syntax you are using should be perfectly fine.
Query query = new Query( session,
"select * from com.yourCompany.yourClass where _qtyOrdered - _qtySent > 0 ");
QueryResult result = query.execute();
I just tried this out on one of my classes and it worked fine.
Cheers,
-Robert
With C# and OQL you have to make sure you select the proper class extent. This is done by adding the "Extent" suffix to the class name. For example, in my Pet class I would identify all the pets with "PetExtent" in the OQL string.
Class members are accessed in the predicate by defining a local moniker, p in the code below. Any arithmetic expressions will be evaluated by the query engine.
string query="SELECT * FROM PetExtent AS p WHERE p.Name = \"Ferris\" AND (p.age + 5) > 4";
IQueryResult result = scope.GetOqlQuery(query).Execute();
foreach (object o in result)
Out(o.ToString());
The best way to test OQL with Versant's C# binding is to use the OQL Query Browser integrated into Visual Studio. Look under the Versant Menu drop down in Visual Studio.
Best Regards,
Derek