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

Fixing issue #9 #48

Closed
wants to merge 4 commits into from
Closed

Fixing issue #9 #48

wants to merge 4 commits into from

Conversation

odbz
Copy link
Contributor

@odbz odbz commented Feb 14, 2024

No description provided.

@odbz odbz requested a review from wivern February 14, 2024 19:59
@odbz odbz self-assigned this Feb 14, 2024
@konstjar konstjar requested review from dmitrys-odysseus and removed request for wivern February 14, 2024 20:08
@OHDSI OHDSI deleted a comment from cr-gpt bot Feb 14, 2024
Copy link
Contributor

@dmitrys-odysseus dmitrys-odysseus left a comment

Choose a reason for hiding this comment

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

Multiple major defects, please see comments in code

(isSubmittedSort(pageable) ?"submitted":
(isStatusSort(pageable)?"status":""));
if(pageable.getSort() == null || "".equals(sortField))
{
Copy link
Contributor

Choose a reason for hiding this comment

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

Defect: Formatting. Please stick to existing de facto formatting style, specifically:

  • consistent spacing (e.g. single space) around operators and keywords, after comma
  • opening brace on the same line
  • comma not dropped to the next line
    While minor formatting issues might be overlooked, the current state is almost unreadable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ready

Copy link
Contributor

Choose a reason for hiding this comment

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

This issue is still not addressed, while he code was removed, similar problems exist in newly added code

" ELSE CAST(a.id as text)\n" +
" END \n" +
" END DESC",
countQuery =
Copy link
Contributor

Choose a reason for hiding this comment

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

The separate countQuery is unnecessary and is very bad for maintainability. We can use the FROM and WHERE for both queries and just alternate the prefix.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

when we use the paging and sorting of calculated fields with spring data it does not return the information as expected, that is why we use native queries combined with spring data paging, if I do the paging and sorting without using spring data, I would have to do countQuery separately to supply that information to the Page object that is being returned.

" END ASC,\n" +
" CASE WHEN :direction = 'DESC' THEN\n" +
" CASE :sortField \n" +
" WHEN 'submitted' THEN CAST(COALESCE(JS.submitted, CAST('epoch' as timestamp)) as text)\n" +
Copy link
Contributor

Choose a reason for hiding this comment

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

If there are any differences between these 2 blocks, this is "Defect: ASC and DESC sort order are in consistent"
otherwise,it is "Defect: code duplication"
In either case, there is a defect.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sorting is being done in the native query because when sorting by calculated field spring data does not return the data correctly, this change is only being done for those calculated fields.

" ELSE CAST(a.id as text)\n" +
" END \n" +
" END ASC,\n" +
" CASE WHEN :direction = 'DESC' THEN\n" +
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do you CASE over fields that is statically available during query construction?
There is no rule that prohibits you from building SQL via code rather than using spring data.
The only measure of what is better is complexity and the current SQL is already too complex.

" ORDER BY \n" +
" CASE WHEN :direction = 'ASC' THEN\n" +
" CASE :sortField \n" +
" WHEN 'submitted' THEN CAST(COALESCE(JS.submitted, CAST('epoch' as timestamp)) as text)\n" +
Copy link
Contributor

Choose a reason for hiding this comment

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

CAST('epoch' as timestamp) ?
Why is this?
What is epoch?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

query was changed optimizing this change

" ,JS.submitted \n" +
" ,JS.finished\n" +
" ,JS.status\n" +
" ,SV.id\n" +
Copy link
Contributor

Choose a reason for hiding this comment

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

SV.id? a also has id, so I think this is a conflict.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

query was changed optimizing this change

" else j.date \n" +
" end \n" +
" ) over(partition by j.analysis_id) as finished,\n" +
" FIRST_VALUE(j.state) over(partition by j.analysis_id order by j.date desc) status\n" +
Copy link
Contributor

Choose a reason for hiding this comment

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

We strive to keep any SQL compliant to the lowest reasonable standard (down to SQL2003).
A partition over window window function is something far beoynd that, so it has to be well-justified.
Since we are in subquery already, I think a trivial WHERE j.analysis_id=a.id would suffice.

General note: In most cases, you need either subquerty or partition over window function. A situation that justifies using both has to be much more complicated than what we have 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.

query was changed optimizing this change

Copy link
Contributor

@dmitrys-odysseus dmitrys-odysseus left a comment

Choose a reason for hiding this comment

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

Multiple blocking issues

super(userService);
initProps();
}
public static final int SUGGEST_LIMIT = 10;
Copy link
Contributor

Choose a reason for hiding this comment

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

Please revert unnecessary formatting changes. For java code is de facto standard is 4 spaces, why are you putting in 2?

});
propertiesMap.put("analysis", p -> p.add("title"));
propertiesMap.put("study", p -> p.add("studyTitle"));
propertiesMap.put("status", p -> p.add("journal.state"));
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this line removed?

(isSubmittedSort(pageable) ?"submitted":
(isStatusSort(pageable)?"status":""));
if(pageable.getSort() == null || "".equals(sortField))
{
Copy link
Contributor

Choose a reason for hiding this comment

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

This issue is still not addressed, while he code was removed, similar problems exist in newly added code

sqlBuilder.append("CASE WHEN J.state IN('EXECUTING','CREATED') ")
.append("THEN null ")
.append("ELSE JS.finished END ");
}else if(sortField!=null && sortField.equals("status"))
Copy link
Contributor

Choose a reason for hiding this comment

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

Defect: code duplication. (sortField != null) only needs to be checked once, checking for specific values can go into the nested block

.append("MIN(J.date) AS submitted ")
.append("FROM analysis_state_journal J ")
.append("GROUP BY J.analysis_id) JS ON J.analysis_id=JS.analysis_id AND J.date = JS.finished ")
.append("ORDER BY ");
Copy link
Contributor

Choose a reason for hiding this comment

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

When sortField == null ORDER BY is still added. Is there a reason for that?

List<Analysis> content =query.getResultList();

countBuilder =
(sortField != null && (sortField.equals("finished") || sortField.equals("status"))) ?
Copy link
Contributor

Choose a reason for hiding this comment

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

Why does count query depend on sortField?

countBuilder =
(sortField != null && (sortField.equals("finished") || sortField.equals("status"))) ?
countBuilder.append("select count(a.*) from analyses a ")
.append("JOIN analysis_state_journal AS journal ON journal.analysis_id = a.id ")
Copy link
Contributor

Choose a reason for hiding this comment

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

Normally, you want to reuse the exact same FROM and WHERE clauses for count query to make sure that the count matched the query. You are not really doing it here and clauses are slightly different. Why?

StringBuilder countBuilder = new StringBuilder();

sqlBuilder.append("SELECT a.* FROM analyses a ")
.append("JOIN analysis_state_journal AS J ON J.analysis_id = a.id ")
Copy link
Contributor

Choose a reason for hiding this comment

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

Reading .append( on each line doesn't help with understanding, polluting the view.
Java compiler optimizes string concatenation via "+" replacing it with StringBuilder automatically since JDK 1.6 (since 2006!), so unless concatenation happens in a loop, explicit usage of StringBuilder yields zero performance benefit.

.append("MAX(J.date) AS finished, ")
.append("MIN(J.date) AS submitted ")
.append("FROM analysis_state_journal J ")
.append("GROUP BY J.analysis_id) JS ON J.analysis_id=JS.analysis_id AND J.date = JS.finished ")
Copy link
Contributor

Choose a reason for hiding this comment

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

I had to use Ctrl-F to find that closing brace on the join. When breaking the lines, "prefer to break at a higher syntactic level". Or just group the fragments logically extracting variables:

String select = ...
String from = ...
String orderBy = ...
String query = "SELECT a.*"  + from + orderBy;
...
String countsQuery = "SELECT count(a.*) + from;

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

Successfully merging this pull request may close these issues.

3 participants