Usage of SQL parsers for java for search scenarios - java

Can anyone suggest some good implementation examples or usage scenarios where SQL parsers can be used for java.
I have an application where we need to filter data to be presented on UI based on certain parameters, sort criteria etc.
I have some doubts regarding this:
1)Can this be an ideal solution for this?
2)How can UI play an role for providing query to the Java layer?

Do you want to construct sql query dynamically in your java app and then fetch data using this sql? Let's say you have a sql like this:
select salary from emp where dept='sales'
after users pick up some other filters from UI, such as age > 40, then sql will be like this:
select salary from emp where dept='sales' and age > 40
Of course, you maybe want to add more complicated filters or add sort clause as well.
In order to achieve this, a full SQL Parser is helpful, here is a demo that illustrate how to Deconstruct, Modify, Rebuild a SQL statement based on a Java SQL Parser.

I don't know what a SQL parser is supposed to be. Applications don't have to parse SQL. Thay have to execute SQL queries, and thus potentially generate SQL queries dynamically. But it's the database that parses the SQL, not the application.
The UI doesn't typically provide a query to the service layer. The UI doesn't have to know how the data is persisted and which queries to execute. It's not its responsibility. The UI should just pass Filter or Criteria objects to the service layer, which transforms the filter or criteria into a SQL query, executes the query, transforms the results into Java objects, and return those objects to the UI, which displays these objects.

Related

What is the easiest way to convert a query from an Update query to a Construct query using RDF4J?

I am trying to implement "dry run" functionality in my application for users who want to see what the result of a SPARQL Update query would be. Does RDF4J provide an easy way to convert an Update query to a Construct query so that I can display the potential results to the user. Ideally I would be able to convert the insert/delete portions of the query into two separate construct queries utilizing the where clause of their query.

How to implement Hierarchical queries in JPA?

I have a huge oracle database with large number of stored procedures which I need to convert in microservice. In one of those procedures there is a hierarchical query in the form of :-
Select column_names from table_name start with column_name in (subquery) connect by nocycle prior (condition)
I need to convert this functionality into java code as I don't know how to use this in JPA query and I also cannot use native query. As I understand, this sort of query returns data in a tree like structure. I need to maintain that same structure as I further want to join this to another view. I would like to know how can I implement such a functionality in java using simple JPA queries ?

dynamic sql generation design

Good Afternoon,
We are bulding a web application and as part of it building a search functionality, have a design question on "Search Functionality"
The field names on the UI vs DB are different .i.e. a field on the UI called as "Number" the same is called Text10 in the DB. following are the two issues
How to generate a SQL as user gives the UI field names, we have a table in the DB where we r maintaining configuration(UI name to DB Name)?
User selects the columns which he wants to search, say for example there fields are selected "Number, Description, Price" and once the sql is generated, how to know what data corresponds to what column? Do we have to maintain an index capturing position or a bean?
what is the better way to gather the data based on the resultset?
Thanks
A solution that promotes commonality between UI and database column names would be nice but probably not feasible.
Some sort of mapping table that captures the following will work:
META-DB-TABLE-NAME
META-DB-COLUMN-NAME
META-UI-COLUMN-NAME
Personally I would prefer to keep this mapping meta-data as close to the database as possible.
User-defined meta data is nicely described here from an Oracle perspective:
http://docs.oracle.com/cd/B28359_01/appdev.111/b28369/xdb_repos_meta.htm
Do some research on this and keep us informed with what you find. Very interesting question!
In such a dynamic SQL scenario, query builders like jOOQ really shine. See for example the jOOQ manual section about dynamic SQL.
In your specific case, assuming you're using generated code in jOOQ (which isn't a must, but certainly recommended), you'll be maintaining some sort of lookup between UI fields and SQL fields, such as:
Map<UIField, Field<?>> lookup = ...
lookup.put(UI.NUMBER, TABLE.NUMBER);
lookup.put(UI.DESCRIPTION, TABLE.DESCRIPTION);
lookup.put(UI.PRICE, TABLE.PRICE);
You can then construct your query dynamically according to user needs:
List<UIField> userRequestedFields = ...
List<Field<?>> queryFields = userRequestedFields
.stream()
.map(lookup::get)
.toList();
And then:
ctx.select(queryFields)
.from(TABLE)
.where(...)
.fetch();
There are other query builders, even JPA has the criteria API for these purposes. You could also roll your own, though you'll be re-inventing a lot of wheels.
Disclaimer: I work for the company behind jOOQ.

How to use native SQL as a fragment (where clause) of a bigger query made with Criteria API in Hibernate?

I have a following problem. In application, which I am developing, we use Hibernate and every query is written with Criteria API. Now, in some places, we want to add possibility for user to write some SQL code which will be used as part of where clause in a query. So basically, user can filter data displayed to him from database in his own way.
For a few days now, I am trying to find a way to modify our previous queries to acquire result described above. Here is what I know:
It looks like you cannot combine Criteria API with native SQL. You can either write whole query in SQL or use only criteria API. Is that right?
I am asking this question because it would be the easiest solution, just to use this SQL code as another predicate in where clause in our query. But I don't think it's possbile on this level.
I know on which table user wants to filter data. So I could just execute native SQL query and use result list as a parameter to IN clause in criteria query. But I don't know if it is efficient with many records in a result list.
So if I cannot do it on criteria API level, I thought that maybe I could somehow influence the SQL generetion process and put my SQL in a proper place but it seems to be impossible.
So my real question is: is it somehow possible to have access to SQL code of the query, after SQL generation phase but before actual execution of query? Just to manipulate with it manually? Can it be done safely and as far as possible simply?
Or maybe just try to parse this SQL written by user and use it in criteria query?
Changing existing criteria queries into native SQL queries is rather out of discussion.
Yes, you can get the SQL from the Hibernate criteria using the org.hibernate.loader.criteria.CriteriaQueryTranslator class.
This will allow you to append the additional SQL clause(s) to the end and execute it as a native SQL:
CriteriaQueryTranslator translator = new CriteriaQueryTranslator(factory, criteria, "myEntityName", CriteriaQueryTranslator.ROOT_SQL_ALIAS);
String select = translator.getSelect();
String whereClause = translator.getWhereCondition();
Personally though, if faced with this requirement I would shy away from accepting SQL from the end-user and give them a user interface to populate some type of filter object. This can then be converted into HQL criterion, which is much safer and doesn't tie your code as tightly to the database implementation.
Edit based on comments
Example of extracting SQL from a JPA query implemented with Hibernate:
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<MyEntity> q = builder.createQuery(MyEntity.class);
Root<MyEntity> entity = q.from(MyEntity.class);
q.select(entity).orderBy(builder.desc(entity.get("lastModified")));
TypedQuery<MyEntity> query = entityManager.createQuery(q);
String sql = query.unwrap(org.hibernate.Query.class).getQueryString();
criteria.add(Restrictions.sqlRestriction(" AND ID in (1,2,3)" ));

OpenJPA distinct on

In my DB schema I have conversations with several emails. I want to get the newest emails from a list of conversations. In PostgreSql the query:
select distinct on (conversation_id) *
from email
where conversation_id in (7085214, 7084964)
order by conversation_id, processing_date desc
OpenJPA:
(List<Email>) entityManager.createQuery("SELECT
distinct(email.conversation.id), email FROM Email email WHERE
email.conversation.id in :id ORDER BY email.conversation.id,
email.processingDate DESC").setParameter("id", conversationIds);
It gives back a map of the conversation ids and the whole list of emails in the conversations.
How could I make it right?
Thanks
Use native SQL.
The only other way to do what you want is to develop a patch to OpenJPA that "teaches" it how to use the PostgreSQL extension DISTINCT ON in its JPQL parser and query generator. Most ORMs accept such extensions via dialect hooks. Don't expect this to be a simple task, though - unless you're writing a lot of these queries, native SQL is almost certain to be much easier.
You can't just use DISTINCT or DISTINCT ON like functions. They aren't; they're completely separate syntax. A JPQL engine would try to convert it into a true function call that'd fail at runtime - or in the case of distinct on, just fail to parse it in the first place.
BTW, DISTINCT ON is a bit like GROUP BY in some other vendor databases like MySQL, where you're allowed to specify columns in the SELECT that don't appear in the GROUP BY or an aggregate. So in MySQL people probably do this by just producing a technically invalid query that MySQL accepts anyway - it's quite likely that the OpenJPA JPQL handler won't notice the problem, so it'll pass it through fine. This trick won't work for DISTINCT ON and PostgreSQL is strictly standards compliant about GROUP BY, it won't let you produce a non-deterministic query with GROUP BY.

Categories

Resources