Skip to content

Commit a022a51

Browse files
committed
FINERACT-2076: SQL query optimization
1 parent 039bca4 commit a022a51

File tree

85 files changed

+1186
-1193
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+1186
-1193
lines changed

fineract-accounting/src/main/java/org/apache/fineract/accounting/provisioning/api/ProvisioningEntriesApiResource.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ public String retrieveProviioningEntries(@QueryParam("entryId") final Long entry
147147
@QueryParam("productId") final Long productId, @QueryParam("categoryId") final Long categoryId,
148148
@Context final UriInfo uriInfo) {
149149
this.platformSecurityContext.authenticatedUser();
150-
SearchParameters params = SearchParameters.forProvisioningEntries(entryId, officeId, productId, categoryId, offset, limit);
150+
SearchParameters params = SearchParameters.builder().limit(limit).offset(offset).provisioningEntryId(entryId).officeId(officeId)
151+
.productId(productId).categoryId(categoryId).build();
151152
Page<LoanProductProvisioningEntryData> entries = this.provisioningEntriesReadPlatformService.retrieveProvisioningEntries(params);
152153
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
153154
return this.entriesApiJsonSerializer.serialize(settings, entries, PROVISIONING_ENTRY_PARAMETERS);

fineract-accounting/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesReadPlatformServiceImpl.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -319,33 +319,33 @@ public Page<LoanProductProvisioningEntryData> retrieveProvisioningEntries(Search
319319
String whereClose = " where ";
320320
List<Object> items = new ArrayList<>();
321321

322-
if (searchParams.isProvisioningEntryIdPassed()) {
322+
if (searchParams.hasProvisioningEntryId()) {
323323
sqlBuilder.append(whereClose + " entry.history_id = ?");
324324
items.add(searchParams.getProvisioningEntryId());
325325
whereClose = " and ";
326326
}
327327

328-
if (searchParams.isOfficeIdPassed()) {
328+
if (searchParams.hasOfficeId()) {
329329
sqlBuilder.append(whereClose + " entry.office_id = ?");
330330
items.add(searchParams.getOfficeId());
331331
whereClose = " and ";
332332
}
333333

334-
if (searchParams.isProductIdPassed()) {
334+
if (searchParams.hasProductId()) {
335335
sqlBuilder.append(whereClose + " entry.product_id = ?");
336336
items.add(searchParams.getProductId());
337337
whereClose = " and ";
338338
}
339339

340-
if (searchParams.isCategoryIdPassed()) {
340+
if (searchParams.hasCategoryId()) {
341341
sqlBuilder.append(whereClose + " entry.category_id = ?");
342342
items.add(searchParams.getCategoryId());
343343
}
344344
sqlBuilder.append(" order by entry.id");
345345

346-
if (searchParams.isLimited()) {
346+
if (searchParams.hasLimit()) {
347347
sqlBuilder.append(" limit ").append(searchParams.getLimit());
348-
if (searchParams.isOffset()) {
348+
if (searchParams.hasOffset()) {
349349
sqlBuilder.append(" offset ").append(searchParams.getOffset());
350350
}
351351
}

fineract-branch/src/main/java/org/apache/fineract/organisation/teller/api/TellerApiResource.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import org.apache.fineract.infrastructure.core.service.Page;
5151
import org.apache.fineract.infrastructure.core.service.SearchParameters;
5252
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
53+
import org.apache.fineract.infrastructure.security.service.SqlValidator;
5354
import org.apache.fineract.organisation.teller.data.CashierData;
5455
import org.apache.fineract.organisation.teller.data.CashierTransactionData;
5556
import org.apache.fineract.organisation.teller.data.CashierTransactionsWithSummaryData;
@@ -70,6 +71,7 @@ public class TellerApiResource {
7071
private final DefaultToApiJsonSerializer<TellerData> jsonSerializer;
7172
private final TellerManagementReadPlatformService readPlatformService;
7273
private final PortfolioCommandSourceWritePlatformService commandWritePlatformService;
74+
private final SqlValidator sqlValidator;
7375

7476
@GET
7577
@Consumes({ MediaType.TEXT_HTML, MediaType.APPLICATION_JSON })
@@ -315,7 +317,10 @@ public String getTransactionsForCashier(@PathParam("tellerId") @Parameter(descri
315317

316318
final LocalDate fromDate = null;
317319
final LocalDate toDate = null;
318-
final SearchParameters searchParameters = SearchParameters.forPagination(offset, limit, orderBy, sortOrder);
320+
sqlValidator.validate(orderBy);
321+
sqlValidator.validate(sortOrder);
322+
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).orderBy(orderBy)
323+
.sortOrder(sortOrder).build();
319324
final Page<CashierTransactionData> cashierTxns = this.readPlatformService.retrieveCashierTransactions(cashierId, false, fromDate,
320325
toDate, currencyCode, searchParameters);
321326

@@ -344,7 +349,10 @@ public String getTransactionsWtihSummaryForCashier(@PathParam("tellerId") @Param
344349
final LocalDate fromDate = null;
345350
final LocalDate toDate = null;
346351

347-
final SearchParameters searchParameters = SearchParameters.forPagination(offset, limit, orderBy, sortOrder);
352+
sqlValidator.validate(orderBy);
353+
sqlValidator.validate(sortOrder);
354+
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).orderBy(orderBy)
355+
.sortOrder(sortOrder).build();
348356

349357
final CashierTransactionsWithSummaryData cashierTxnWithSummary = this.readPlatformService
350358
.retrieveCashierTransactionsWithSummary(cashierId, false, fromDate, toDate, currencyCode, searchParameters);

fineract-branch/src/main/java/org/apache/fineract/organisation/teller/data/CashierTransactionDataValidator.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,9 @@ public CashierTransactionDataValidator(final TellerManagementReadPlatformService
5656
}
5757

5858
public void validateSettleCashAndCashOutTransactions(final Long cashierId, String currencyCode, final BigDecimal transactionAmount) {
59-
final Integer offset = null;
60-
final Integer limit = null;
61-
final String orderBy = null;
62-
final String sortOrder = null;
63-
final LocalDate fromDate = null;
64-
final LocalDate toDate = null;
65-
final SearchParameters searchParameters = SearchParameters.forPagination(offset, limit, orderBy, sortOrder);
59+
final SearchParameters searchParameters = SearchParameters.builder().build();
6660
final CashierTransactionsWithSummaryData cashierTxnWithSummary = this.tellerManagementReadPlatformService
67-
.retrieveCashierTransactionsWithSummary(cashierId, false, fromDate, toDate, currencyCode, searchParameters);
61+
.retrieveCashierTransactionsWithSummary(cashierId, false, null, null, currencyCode, searchParameters);
6862
if (MathUtil.isGreaterThan(transactionAmount, cashierTxnWithSummary.getNetCash())) {
6963
throw new CashierInsufficientAmountException();
7064
}

fineract-core/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ public class FineractProperties {
7676

7777
private FineractModulesProperties module;
7878

79+
private FineractSqlValidationProperties sqlValidation;
80+
7981
@Getter
8082
@Setter
8183
public static class FineractTenantProperties {
@@ -533,4 +535,38 @@ public static class FineractModulesProperties {
533535
public static class FineractInvestorModuleProperties extends AbstractFineractModuleProperties {
534536

535537
}
538+
539+
@Getter
540+
@Setter
541+
public static class FineractSqlValidationProperties {
542+
543+
private List<FineractSqlValidationPatternProperties> patterns;
544+
private List<FineractSqlValidationProfileProperties> profiles;
545+
}
546+
547+
@Getter
548+
@Setter
549+
public static class FineractSqlValidationProfileProperties {
550+
551+
private String name;
552+
private String description;
553+
private List<FineractSqlValidationPatternReferenceProperties> patternRefs;
554+
private Boolean enabled = true;
555+
}
556+
557+
@Getter
558+
@Setter
559+
public static class FineractSqlValidationPatternReferenceProperties {
560+
561+
private String name;
562+
private Integer order;
563+
}
564+
565+
@Getter
566+
@Setter
567+
public static class FineractSqlValidationPatternProperties {
568+
569+
private String name;
570+
private String pattern;
571+
}
536572
}

fineract-core/src/main/java/org/apache/fineract/infrastructure/core/data/PaginationParameters.java

Lines changed: 34 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -18,101 +18,62 @@
1818
*/
1919
package org.apache.fineract.infrastructure.core.data;
2020

21+
import lombok.AccessLevel;
22+
import lombok.Builder;
23+
import lombok.Getter;
2124
import org.apache.commons.lang3.StringUtils;
22-
import org.apache.fineract.infrastructure.security.utils.SQLInjectionValidator;
2325

24-
/**
25-
* <p>
26-
* Immutable data object representing pagination parameter values.
27-
* </p>
28-
*/
29-
public final class PaginationParameters {
30-
31-
private final boolean paged;
32-
private final Integer offset;
33-
private final Integer limit;
34-
private final String orderBy;
35-
private final String sortOrder;
36-
37-
public static PaginationParameters instance(Boolean paged, Integer offset, Integer limit, String orderBy, String sortOrder) {
38-
if (null == paged) {
39-
paged = false;
40-
}
41-
42-
final Integer maxLimitAllowed = getCheckedLimit(limit);
26+
@Builder
27+
@Getter
28+
public class PaginationParameters {
4329

44-
return new PaginationParameters(paged, offset, maxLimitAllowed, orderBy, sortOrder);
45-
}
46-
47-
private PaginationParameters(boolean paged, Integer offset, Integer limit, String orderBy, String sortOrder) {
48-
SQLInjectionValidator.validateSQLInput(orderBy);
49-
SQLInjectionValidator.validateSQLInput(sortOrder);
50-
51-
this.paged = paged;
52-
this.offset = offset;
53-
this.limit = limit;
54-
this.orderBy = orderBy;
55-
this.sortOrder = sortOrder;
56-
}
57-
58-
public static Integer getCheckedLimit(final Integer limit) {
30+
// TODO: why do we really need this class? SearchParameters seems to provide similar functionality
5931

60-
final Integer maxLimitAllowed = 200;
61-
// default to max limit first off
62-
Integer checkedLimit = maxLimitAllowed;
32+
public static final int DEFAULT_MAX_LIMIT = 200;
6333

64-
if (limit != null && limit > 0) {
65-
checkedLimit = limit;
66-
} else if (limit != null) {
67-
// unlimited case: limit provided and 0 or less
68-
checkedLimit = null;
69-
}
70-
71-
return checkedLimit;
72-
}
73-
74-
public boolean isPaged() {
75-
return this.paged;
76-
}
77-
78-
public Integer getOffset() {
79-
return this.offset;
80-
}
34+
private boolean paged;
35+
private Integer offset;
36+
@Getter(AccessLevel.NONE)
37+
private Integer limit;
38+
private String orderBy;
39+
private String sortOrder;
8140

8241
public Integer getLimit() {
83-
return this.limit;
84-
}
42+
if (limit == null) {
43+
return DEFAULT_MAX_LIMIT;
44+
}
8545

86-
public String getOrderBy() {
87-
return this.orderBy;
88-
}
46+
if (limit > 0) {
47+
return limit;
48+
}
8949

90-
public String getSortOrder() {
91-
return this.sortOrder;
50+
return null; // unlimited (0 or less)
9251
}
9352

94-
public boolean isOrderByRequested() {
53+
public boolean hasOrderBy() {
9554
return StringUtils.isNotBlank(this.orderBy);
9655
}
9756

98-
public boolean isSortOrderProvided() {
57+
public boolean hasSortOrder() {
9958
return StringUtils.isNotBlank(this.sortOrder);
10059
}
10160

102-
public boolean isLimited() {
103-
return this.limit != null && this.limit.intValue() > 0;
61+
public boolean hasLimit() {
62+
return this.limit != null && this.limit > 0;
10463
}
10564

106-
public boolean isOffset() {
65+
public boolean hasOffset() {
10766
return this.offset != null;
10867
}
10968

69+
// TODO: following functions are just doing too much in one place; will disappear with type safe queries
70+
11071
public String orderBySql() {
11172
final StringBuilder sql = new StringBuilder();
11273

113-
if (this.isOrderByRequested()) {
74+
if (this.hasOrderBy()) {
11475
sql.append(" order by ").append(this.getOrderBy());
115-
if (this.isSortOrderProvided()) {
76+
if (this.hasSortOrder()) {
11677
sql.append(' ').append(this.getSortOrder());
11778
}
11879
}
@@ -121,9 +82,9 @@ public String orderBySql() {
12182

12283
public String limitSql() {
12384
final StringBuilder sql = new StringBuilder();
124-
if (this.isLimited()) {
85+
if (this.hasLimit()) {
12586
sql.append(" limit ").append(this.getLimit());
126-
if (this.isOffset()) {
87+
if (this.hasOffset()) {
12788
sql.append(" offset ").append(this.getOffset());
12889
}
12990
}
@@ -132,10 +93,10 @@ public String limitSql() {
13293

13394
public String paginationSql() {
13495
final StringBuilder sqlBuilder = new StringBuilder(50);
135-
if (this.isOrderByRequested()) {
96+
if (this.hasOrderBy()) {
13697
sqlBuilder.append(' ').append(this.orderBySql());
13798
}
138-
if (this.isLimited()) {
99+
if (this.hasLimit()) {
139100
sqlBuilder.append(' ').append(this.limitSql());
140101
}
141102

fineract-core/src/main/java/org/apache/fineract/infrastructure/core/data/PaginationParametersDataValidator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public class PaginationParametersDataValidator {
3434
public void validateParameterValues(PaginationParameters parameters, final Set<String> supportedOrdeByValues,
3535
final String resourceName) {
3636
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
37-
if (parameters.isOrderByRequested() && !supportedOrdeByValues.contains(parameters.getOrderBy())) {
37+
if (parameters.hasOrderBy() && !supportedOrdeByValues.contains(parameters.getOrderBy())) {
3838
final String defaultUserMessage = "The orderBy value '" + parameters.getOrderBy()
3939
+ "' is not supported. The supported orderBy values are " + supportedOrdeByValues;
4040
final ApiParameterError error = ApiParameterError.parameterError(
@@ -43,7 +43,7 @@ public void validateParameterValues(PaginationParameters parameters, final Set<S
4343
dataValidationErrors.add(error);
4444
}
4545

46-
if (parameters.isSortOrderProvided() && !sortOrderValues.contains(parameters.getSortOrder().toUpperCase())) {
46+
if (parameters.hasSortOrder() && !sortOrderValues.contains(parameters.getSortOrder().toUpperCase())) {
4747
final String defaultUserMessage = "The sortOrder value '" + parameters.getSortOrder()
4848
+ "' is not supported. The supported sortOrder values are " + sortOrderValues;
4949
final ApiParameterError error = ApiParameterError.parameterError(

0 commit comments

Comments
 (0)