-
Notifications
You must be signed in to change notification settings - Fork 357
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
fix: Use CTE in Enrollment analytics queries [DHIS-16705] #19519
Conversation
|
||
void contributeCTE( | ||
ProgramIndicator programIndicator, | ||
RelationshipType relationshipType, |
Check notice
Code scanning / CodeQL
Useless parameter Note
...-analytics/src/main/java/org/hisp/dhis/analytics/common/ProgramIndicatorSubqueryBuilder.java
Fixed
Show fixed
Hide fixed
...alytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEnrollmentAnalyticsManager.java
Fixed
Show fixed
Hide fixed
...alytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEnrollmentAnalyticsManager.java
Fixed
Show fixed
Hide fixed
...alytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEnrollmentAnalyticsManager.java
Fixed
Show fixed
Hide fixed
...alytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEnrollmentAnalyticsManager.java
Fixed
Show fixed
Hide fixed
.../hisp/dhis/analytics/event/data/programindicator/DefaultProgramIndicatorSubqueryBuilder.java
Fixed
Show fixed
Hide fixed
8c33952
to
3e070ce
Compare
5170115
to
d8119c0
Compare
...services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/common/CTEContext.java
Fixed
Show fixed
Hide fixed
...services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/common/CTEContext.java
Fixed
Show fixed
Hide fixed
...services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/common/CTEContext.java
Fixed
Show fixed
Hide fixed
...services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/common/CTEContext.java
Fixed
Show fixed
Hide fixed
...tics/src/main/java/org/hisp/dhis/analytics/event/data/AbstractJdbcEventAnalyticsManager.java
Fixed
Show fixed
Hide fixed
...alytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEnrollmentAnalyticsManager.java
Fixed
Show fixed
Hide fixed
...alytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEnrollmentAnalyticsManager.java
Fixed
Show fixed
Hide fixed
.../hisp/dhis/analytics/event/data/programindicator/DefaultProgramIndicatorSubqueryBuilder.java
Fixed
Show fixed
Hide fixed
5c4dba5
to
ef43c5b
Compare
...vices/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/common/CteDefinition.java
Fixed
Show fixed
Hide fixed
this.cteDefinition = cteDefinition; | ||
this.offsets.add(offset); | ||
// one alias per offset | ||
this.alias = new RandomStringGenerator.Builder().withinRange('a', 'z').build().generate(5); |
Check notice
Code scanning / CodeQL
Deprecated method or constructor invocation Note
Builder.build
this.programIndicatorUid = programIndicatorUid; | ||
this.programStageUid = null; | ||
// ignore offset | ||
this.alias = new RandomStringGenerator.Builder().withinRange('a', 'z').build().generate(5); |
Check notice
Code scanning / CodeQL
Deprecated method or constructor invocation Note
Builder.build
this.programIndicatorUid = null; | ||
this.programStageUid = programStageUid; | ||
// ignore offset | ||
this.alias = new RandomStringGenerator.Builder().withinRange('a', 'z').build().generate(5); |
Check notice
Code scanning / CodeQL
Deprecated method or constructor invocation Note
Builder.build
...alytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEnrollmentAnalyticsManager.java
Fixed
Show fixed
Hide fixed
aa533b4
to
5f05bb5
Compare
...alytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEnrollmentAnalyticsManager.java
Fixed
Show fixed
Hide fixed
...services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/common/CTEContext.java
Outdated
Show resolved
Hide resolved
...services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/common/CTEContext.java
Outdated
Show resolved
Hide resolved
...services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/common/CTEContext.java
Outdated
Show resolved
Hide resolved
...alytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEnrollmentAnalyticsManager.java
Outdated
Show resolved
Hide resolved
...ces/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventQueryParams.java
Outdated
Show resolved
Hide resolved
4e085d3
to
62c2237
Compare
void contributeCTE( | ||
ProgramIndicator programIndicator, | ||
RelationshipType relationshipType, | ||
AnalyticsType outerSqlEntity, |
Check notice
Code scanning / CodeQL
Useless parameter Note
...tics/src/main/java/org/hisp/dhis/analytics/event/data/AbstractJdbcEventAnalyticsManager.java
Fixed
Show fixed
Hide fixed
...alytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEnrollmentAnalyticsManager.java
Fixed
Show fixed
Hide fixed
79f7563
to
94ab16e
Compare
...alytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEnrollmentAnalyticsManager.java
Outdated
Show resolved
Hide resolved
...alytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEnrollmentAnalyticsManager.java
Outdated
Show resolved
Hide resolved
...s-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/common/CTEUtils.java
Outdated
Show resolved
Hide resolved
...es/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/common/InQueryCteFilter.java
Outdated
Show resolved
Hide resolved
...alytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEnrollmentAnalyticsManager.java
Outdated
Show resolved
Hide resolved
...alytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEnrollmentAnalyticsManager.java
Outdated
Show resolved
Hide resolved
bc234ee
to
a4ff98c
Compare
8cb7b23
to
895d84c
Compare
.../dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/util/sql/SqlAliasReplacer.java
Fixed
Show fixed
Hide fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice changes @luciano-fiandesio. 👍
I left a few comments/suggestions, please take a look, thx!
...services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/common/CteContext.java
Show resolved
Hide resolved
...vices/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/common/CteDefinition.java
Outdated
Show resolved
Hide resolved
...vices/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/common/CteDefinition.java
Show resolved
Hide resolved
...s-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/common/CteUtils.java
Outdated
Show resolved
Hide resolved
...es/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/common/InQueryCteFilter.java
Outdated
Show resolved
Hide resolved
.../hisp/dhis/analytics/event/data/programindicator/DefaultProgramIndicatorSubqueryBuilder.java
Outdated
Show resolved
Hide resolved
...rvices/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/util/sql/QuoteUtils.java
Outdated
Show resolved
Hide resolved
...rvices/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/util/sql/QuoteUtils.java
Outdated
Show resolved
Hide resolved
...s/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/util/sql/SqlColumnParser.java
Show resolved
Hide resolved
...ervice-analytics/src/main/java/org/hisp/dhis/analytics/util/sql/SqlWhereClauseExtractor.java
Show resolved
Hide resolved
@Getter private final String cteDefinition; | ||
|
||
/** The calculated offset * */ | ||
@Getter private final List<Integer> offsets = new ArrayList<>(); |
Check notice
Code scanning / CodeQL
Exposing internal representation Note
after this call to getOffsets
} | ||
|
||
if (offset < 0) { | ||
return (-1 * offset); |
Check failure
Code scanning / CodeQL
User-controlled data in arithmetic expression High
user-provided value
This arithmetic expression depends on a
user-provided value
This arithmetic expression depends on a
user-provided value
This arithmetic expression depends on a
user-provided value
This arithmetic expression depends on a
user-provided value
This arithmetic expression depends on a
user-provided value
This arithmetic expression depends on a
user-provided value
This arithmetic expression depends on a
user-provided value
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix AI 5 days ago
To fix the problem, we need to validate the offset
value before performing the arithmetic operation. Specifically, we should ensure that the offset
value is within a safe range to prevent overflow or underflow. We can achieve this by adding a guard clause that checks if the offset
value is within the bounds of Integer.MIN_VALUE
and Integer.MAX_VALUE
.
- Add a validation check for the
offset
value in thecomputeRowNumberOffset
method. - If the
offset
value is outside the safe range, we can either throw an exception or clamp the value to the nearest safe value.
-
Copy modified lines R1419-R1421 -
Copy modified lines R1424-R1426
@@ -1418,4 +1418,10 @@ | ||
if (offset < 0) { | ||
if (offset == Integer.MIN_VALUE) { | ||
throw new IllegalArgumentException("Offset value is too small and may cause underflow."); | ||
} | ||
return (-1 * offset); | ||
} else { | ||
if (offset == Integer.MAX_VALUE) { | ||
throw new IllegalArgumentException("Offset value is too large and may cause overflow."); | ||
} | ||
return (offset - 1); |
Quality Gate failedFailed conditions See analysis details on SonarQube Cloud Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE |
Summary
This PR refactors the SQL query generation process for Enrollment analytics to enhance compatibility with Doris by utilizing Common Table Expressions (CTEs) instead of sub-queries.
Problem
Previously, SQL queries for Enrollment analytics leveraged sub-queries to fetch event values from
analytics_event_*
tables. While functional in Postgres, these queries were incompatible with Doris due to its limitations in handling nested sub-queries correlated with outer query layers.Example of the original query:
Mitigation
This refactor converts sub-queries into Common Table Expressions (CTEs), which are supported by Doris. CTEs simplify the queries, making them more modular and readable, thereby improving performance and compatibility.
Example of the refactored query using CTE:
Testing Strategy
The changes have been tested using the
e2e
project to ensure all tests pass successfully on both Postgres and Doris.Types of Queries Affected
Both aggregated and non-aggregated Enrollment queries are impacted by this refactor.
Experimental Flag
To prevent potential platform issues, the refactored CTE-based queries are not enabled by default. They can be activated by setting the following system configurations to
true
:experimentalAnalyticsSqlEngineEnabled
analytics.database
todoris
.Performance Comparison: