How to use jooq to express mysql REGEXP? - java

I have query like:
SELECT *
FROM uni_customer
WHERE mobile REGEXP '^(1[3,4,5,8]){1}\\d{9}$'
But there is no such function like REGEXP(String) in field,
and mysql don't support syntax like:
SELECT *
FROM uni_customer
WHERE regexp(mobile,'^(1[3,4,5,8]){1}\\d{9}$')

Official support for the REGEXP operator will be available soon in the upcoming jOOQ 2.5.0. In the mean time, you can extend jOOQ yourself, as such:
Condition regexp = Factory.condition("{0} REGEXP {1}",
UNI_CUSTOMER.MOBILE,
val("^(1[3,4,5,8]){1}\\d{9}$"));
Or in a query:
create.select()
.from(UNI_CUSTOMER)
.where(condition("{0} REGEXP {1}",
UNI_CUSTOMER.MOBILE, val("^(1[3,4,5,8]){1}\\d{9}$")));

Related

Hibernate Search Lucene query parser with Special Characters

FIRST QUESTION:
Can somebody explain to me how the lucene query in Hibernate Search handles special characters. I read the documentation about Hibernate search and also the Lucene Regexp Syntax but somehow they don't add up with the generated Queries and Results.
Lets assume i have following database entries:
name
Will
Will Smith
Will - Smith
Will-Smith
and i am using following Query:
Query query = queryBuilder
.keyword()
.onField("firstName")
.matching(input)
.createQuery();
Now I am looking for the following input:
Will -> returns all 4 entries, with the following generated query: FullTextQueryImpl(firstName:will)
Will Smith -> also returns all 4 entries with the following generated query: FullTextQueryImpl(firstName:will firstName:smith)
Will - Smith -> also returns all 4 entries with the following generated query: FullTextQueryImpl(firstName:will firstName:smith) ? Where is the "-" or shouldn't it forbid everything after the "-" according to Lucene Query Syntax?
Will-Smith -> same here
Will-Smith -> here i tried to use backslash but same result
Will -Smith -> Same here
SECOND QUESTION: Lets assume i have following database entries in which the entry without numerical ending always exists and the ones with numerical ending could be in the datebase.
How woul a lucene query for this look like?
name
Will
Will1
Will2
You can play around with Lucene analyzers and see what happens behind the scenes. Here is a tutorial: https://www.baeldung.com/lucene-analyzers
The tokenizer is pluggable, so you can change how special characters are treated.

How to check if a WHERE clause condition is VALID or not using JOOQ?

Lets say we have a SQL fragment like below:
String condition = "field_name > 10 asd field_name1 <= 20"
Shouldn't the following line throw an error instead of accepting it?
query.addConditions(DSL.condition(condition));
Is there a way to VALIDATE the condition grammar using JOOQ? Furthermore unlike an addLimit, the values are not replaced with ?, why is that?
Shouldn't the following line throw an error instead of accepting it?
Why should it? DSL.condition(String) is part of the plain SQL API, which allows you to pass any SQL string fragment to a jOOQ query element that you want, including:
Simple SQL fragments
Complex, vendor-specific expressions
Syntax errors, if you like
There's no validation on what you put inside a plain SQL fragment. The database will ultimately validate the query. But jOOQ doesn't know if by chance, there's an asd operator in your database.
Is there a way to VALIDATE the condition grammar using JOOQ?
There's an experimental Parser API in jOOQ 3.9, which is available through DSLContext.parser(). It allows you to parse SQL strings and construct expression trees from it. In this case, indeed, asd will be an unrecognised token and an exception will be thrown.
You can use it as such:
Condition condition =
ctx.parser().parseCondition("field_name > 10 asd field_name1 <= 20");
But as I said, as of jOOQ 3.9, it's experimental and there are still many bugs. jOOQ 3.10 will remove its experimental status.
Furthermore unlike an addLimit, the values are not replaced with ?, why is that?
Because that's how the plain SQL API works. If you wanted bind variables, you could have written:
Condition condition = DSL.condition("field_name > ? asd field_name1 <= ?", 10, 20);
Or:
Condition condition =
DSL.condition("field_name > {0} asd field_name1 <= {1}", val(10), val(20));

How to use Regex keyword in Spring Data Repository Method

I am currently using spring-data-jpa version 1.9.4.
I have a MySql table with columns project(integer), summary(varchar), and description(varchar).
I have a regex that I would like to use to search the summary and/or description field meaning that if it finds it in summary does not need to apply regex to description.
The repository method I am attempting to use is:
List<Issue> findByProjectAndSummaryOrDescriptionRegex(long project, String regex)
The error I am receiving is:
java.lang.IllegalArgumentException: Unsupported keyword REGEX (1):
[MatchesRegex, Matches, Regex]
It is difficult in my company environment to update/upgrade versions, so if the issue is NOT my syntax but rather the then if someone knows which version now supports 'Regex' for query derivation or where I could find that specific information I would be grateful. I have looked at the Changelog and it appears that 1.9.4 should support but it appears not.
Thanks for your help!
JD
EDIT 1: I am aware of the #Query annotation but have been asked by my lead to only use that as a last resort if I cannot find the correct version which supports keyword REGEX [MatchesRegex, Matches, Regex]
I would recommend using native query (with #Query annotation) if the Spring data syntax does not work, e.g.:
#Query(nativeQuery=true, value="SELECT * FROM table WHERE project = ?1 AND (summary regexp ?2 OR description regexp ?2)")
List<Issue> findByProjectAndSummaryOrDescription(long project, String regex);
Update
If native query is not an option then (a) could you try it with single column and see if that works and (b) could you try by appending regex to both the columns, e.g.:
List<Issue> findByProjectAndDescriptionRegex(long project, String regex);
List<Issue> findByProjectAndSummaryRegexOrDescriptionRegex(long project, String regex, String regex);
In a followup, I discovered by doing some digging that the authoratative list will reside in the org.springframework.data.jpa.repository.query.JpaQueryCreator class. So for future folks that want to know which keywords from the 'Documented' list are ACTUALLY implemented, look inside JpaQueryCreator and you will the keywords supported as case arguments inside a switch!
Hope this helps!
PS - as suspected, REGEX was not supported in my version
try tu use #Query with param nativeQuery = true inside You can use database regexp_like function :
#Query(value = "select t.* from TABLE_NAME t where regexp_like(t.column, ?1)", nativeQuery = true)
Documentation :
https://www.techonthenet.com/oracle/regexp_like.php

Mockrunner(Java) query with Regex

I am using Mockrunner to mock Sql DB for my unit tests. Following is my query:-
"select * from table where userId in (" + userIds + ")"
Now my userIds is state dependent. I don't need my test cases dependent on the arrangement inside the list - userIds. So I don't need exact match but regex matching. I have already enabled regex matching by below code:-
StatementResultSetHandler statementHandler = connection.getStatementResultSetHandler();
usersResult = statementHandler.createResultSet("users");
statementHandler.setUseRegularExpressions(true);
//How to write this regex query?
statementHandler.prepareResultSet("select * from table where userId in .*", campaignsResult);
But as it is noted, I have no idea about the regex syntax supported by Mockrunner.
Edit: I unable to match queries like "Select * from tables" with "Select * from tab .*". So It has to do something with the way I using regex with Mockrunner
There are some helpful examples available here. For instance:
public void testCorrectSQL() throws Exception {
MockResultSet result = getStatementResultSetHandler().createResultSet();
getStatementResultSetHandler().prepareResultSet("select.*isbn,.*quantity.*", result);
List orderList = new ArrayList();
orderList.add("1234567890");
orderList.add("1111111111");
Bookstore.order(getJDBCMockObjectFactory().getMockConnection(), orderList);
verifySQLStatementExecuted("select.*isbn,.*quantity.*\\(isbn='1234567890'.*or.*isbn='1111111111'\\)");
}
From this, I surmise that it's using standard Java regex syntax. In which case, you probably want:
prepareResultSet("select \\* from table where userId in \\(.*\\)", campaignsResult);
...or perhaps more succinctly (and depending upon exactly how fine-grained your tests need to be):
prepareResultSet("select .* from table where userId in .*", campaignsResult);
The main caveat to be aware of when enabling the regex matching is that any literal special characters that you want in your query (such as *, (, and ) literals) need to be escaped in your regex before it will work properly.

OJB / Oracle XE sql debug-display problem

I have a Java application, and use OJB as my ORM technology. I have an Oracle XE installation locally to develop against. The problem is when I need to debug a problem, I like looking at the SQL output. Here is an example of SQL I can view through the "Top SQL" interface in Oracle XE:
select a_bunch_of_fields
from KREW_DOC_TYP_T A0
WHERE ((UPPER(A0.DOC_TYP_NM) LIKE :1) AND A0.ACTV_IND = :2) AND A0.CUR_IND = :3
The problem is I would like to see the real value instead of ":1". I can't seem to find how I can configure this. I know the real values are working, because the application is responding as expected, for the most part (hence the bugs I am working on).
Thanks,
Jay
One quick and dirty way is to look in the provided database views (v$sql_bind_capture and v$sqlarea). In the SQL below, I just added a like clause to match the sql statement you have above, you will then get a row for each bind variable and it's value. To target a very specific SQL statement you want the sql_id for your query.
SELECT a.sql_text, b.NAME, b.POSITION, b.datatype_string, b.value_string
FROM v$sql_bind_capture b, v$sqlarea b
WHERE b.sql_id = a.sql_id
and a.sql_text like '%UPPER(A0.DOC_TYP_NM) LIKE :1%'
Output (without the SQL the result would look look something like this):
"NAME","POSITION","DATATYPE_STRING","VALUE_STRING"
":B1","2","NUMBER","1001"

Categories

Resources