accounting-analytics-persis.../src/main/java/org/gcube/accounting/analytics/persistence/postgresql/Query.java

458 lines
12 KiB
Java
Raw Normal View History

2021-03-16 15:33:34 +01:00
package org.gcube.accounting.analytics.persistence.postgresql;
2021-04-09 23:39:42 +02:00
import java.sql.SQLException;
2021-03-16 15:33:34 +01:00
import java.text.SimpleDateFormat;
import java.util.ArrayList;
2021-03-16 15:33:34 +01:00
import java.util.Calendar;
2021-03-30 17:52:19 +02:00
import java.util.Collection;
import java.util.HashMap;
2021-03-17 17:55:56 +01:00
import java.util.HashSet;
import java.util.Map;
2021-03-16 15:33:34 +01:00
import java.util.Set;
import org.gcube.accounting.analytics.Filter;
import org.gcube.accounting.analytics.TemporalConstraint;
import org.gcube.accounting.analytics.TemporalConstraint.AggregationMode;
import org.gcube.accounting.analytics.TemporalConstraint.CalendarEnum;
2021-03-17 17:55:56 +01:00
import org.gcube.accounting.datamodel.UsageRecord;
2021-03-16 15:33:34 +01:00
import org.gcube.accounting.datamodel.aggregation.AggregatedServiceUsageRecord;
2021-11-22 15:07:29 +01:00
import org.gcube.accounting.datamodel.aggregation.AggregatedStorageStatusRecord;
2021-03-29 11:45:48 +02:00
import org.gcube.accounting.datamodel.aggregation.AggregatedStorageUsageRecord;
2021-03-18 16:36:22 +01:00
import org.gcube.accounting.utility.postgresql.PostgreSQLQuery;
2021-03-18 10:55:07 +01:00
import org.gcube.accounting.utility.postgresql.RecordToDBFields;
import org.gcube.accounting.utility.postgresql.RecordToDBMapping;
2021-03-16 15:33:34 +01:00
import org.gcube.documentstore.records.AggregatedRecord;
2021-03-18 16:36:22 +01:00
public class Query extends PostgreSQLQuery {
2021-03-16 15:33:34 +01:00
public static final String DATE_OF_TIMESERIES_AS_FIELD = AggregatedRecord.START_TIME;
2021-03-16 15:33:34 +01:00
2021-03-31 17:49:49 +02:00
public static final String NESTED_TABLE_NAME = "nested";
2021-03-16 15:33:34 +01:00
private Class<? extends AggregatedRecord<?, ?>> clz;
2021-03-18 17:05:33 +01:00
private final RecordToDBFields recordToDBFields;
2021-03-16 15:33:34 +01:00
2021-03-31 17:49:49 +02:00
private Set<String> requestedTableField;
2021-03-16 15:33:34 +01:00
protected TemporalConstraint temporalConstraint;
protected Map<String, Collection<String>> filters;
2021-03-16 15:33:34 +01:00
protected Set<String> contexts;
2021-03-19 15:55:06 +01:00
2021-03-22 19:08:31 +01:00
private String tableFieldToRequest;
2021-03-19 15:55:06 +01:00
private String orderByField;
private Integer limit;
2021-03-22 18:08:35 +01:00
private String recordId;
2021-03-16 15:33:34 +01:00
public Query(Class<? extends AggregatedRecord<?, ?>> clz) throws Exception {
2024-02-29 16:14:13 +01:00
super();
2021-03-16 15:33:34 +01:00
this.clz = clz;
2021-03-18 17:05:33 +01:00
this.recordToDBFields = RecordToDBMapping.getRecordToDBFields(clz);
2021-03-16 15:33:34 +01:00
}
2021-03-31 17:49:49 +02:00
public Set<String> getRequestedTableField() {
2021-03-16 15:33:34 +01:00
return requestedTableField;
}
public void setTemporalConstraint(TemporalConstraint temporalConstraint) {
this.temporalConstraint = temporalConstraint;
}
2021-11-22 14:19:12 +01:00
public void setFilters(Collection<? extends Filter> filters) {
this.filters = new HashMap<>();
if(filters!=null && filters.size()>0) {
for(Filter filter : filters) {
String key = filter.getKey();
String value = filter.getValue();
Collection<String> list = this.filters.get(key);
if(list == null) {
list = new ArrayList<>();
this.filters.put(key, list);
}
list.add(value);
}
}
2021-03-16 15:33:34 +01:00
}
2021-03-17 17:55:56 +01:00
2021-03-16 15:33:34 +01:00
public void setContexts(Set<String> contexts) {
this.contexts = contexts;
}
2021-03-17 17:55:56 +01:00
2021-03-22 19:08:31 +01:00
public void setTableFieldToRequest(String tableFieldToRequest) {
this.tableFieldToRequest = tableFieldToRequest;
2021-03-19 15:55:06 +01:00
}
public void setOrderByField(String orderByField) {
this.orderByField = orderByField;
}
public void setLimit(Integer limit) {
this.limit = limit;
}
2021-03-17 17:55:56 +01:00
public void addContext(String context) {
2021-03-23 10:46:42 +01:00
if(this.contexts == null) {
this.contexts = new HashSet<>();
2021-03-17 17:55:56 +01:00
}
2021-03-23 10:46:42 +01:00
this.contexts.add(context);
2021-03-17 17:55:56 +01:00
}
2021-03-22 18:08:35 +01:00
public void setRecordId(String recordId) {
this.recordId = recordId;
}
2024-02-29 16:14:13 +01:00
public RecordToDBFields getRecordToDBFields() {
2021-03-18 17:05:33 +01:00
return recordToDBFields;
2021-03-16 15:33:34 +01:00
}
protected String getTableField(String fieldName) {
2021-03-18 17:05:33 +01:00
return recordToDBFields.getTableField(fieldName);
2021-03-16 15:33:34 +01:00
}
protected void appendTableField(String fieldName) {
stringBuffer.append(getTableField(fieldName));
}
public static String getFormattedDate(Calendar calendar) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATETIME_PATTERN);
String date = simpleDateFormat.format(calendar.getTime());
return date;
}
2021-04-09 23:39:42 +02:00
protected void addFilters() throws SQLException {
2021-03-16 15:33:34 +01:00
if(filters!=null && filters.size()>0) {
2021-11-02 11:29:29 +01:00
if(filters.size()>1) {
stringBuffer.append("(");
}
2021-03-16 15:33:34 +01:00
boolean first = true;
for(String key : filters.keySet()) {
2021-03-16 15:33:34 +01:00
if(first) {
first = false;
}else {
stringBuffer.append(" AND ");
}
addOrConditions(key, filters.get(key));
2021-03-16 15:33:34 +01:00
}
2021-11-02 11:29:29 +01:00
if(filters.size()>1) {
stringBuffer.append(")");
}
2021-03-16 15:33:34 +01:00
}
}
protected void addOrConditions(String key, Collection<String> values) throws SQLException {
2021-03-30 17:52:19 +02:00
if(values!=null && values.size()>0) {
2021-11-02 11:29:29 +01:00
if(values.size()>1) {
stringBuffer.append("(");
}
2021-03-17 17:55:56 +01:00
boolean first = true;
2021-03-30 17:52:19 +02:00
for(String value : values) {
2021-03-17 17:55:56 +01:00
if(first) {
first = false;
}else {
stringBuffer.append(" OR ");
}
2021-03-30 17:52:19 +02:00
appendTableField(key);
2021-03-17 17:55:56 +01:00
stringBuffer.append("=");
2021-03-30 17:52:19 +02:00
appendValue(value);
2021-03-17 17:55:56 +01:00
}
2021-11-02 11:29:29 +01:00
if(values.size()>1) {
stringBuffer.append(")");
}
2021-03-17 17:55:56 +01:00
}
}
2021-04-09 23:39:42 +02:00
protected void addContextFilter() throws SQLException {
2021-03-30 17:52:19 +02:00
addOrConditions(UsageRecord.SCOPE, contexts);
}
2021-03-31 17:49:49 +02:00
protected void addEmittedFields(boolean addNested) throws Exception {
2021-03-16 15:33:34 +01:00
Set<String> aggregatedField = clz.newInstance().getAggregatedFields();
for(String fieldName : aggregatedField) {
String dbField = getTableField(fieldName);
switch (fieldName) {
case AggregatedRecord.START_TIME:
case AggregatedRecord.END_TIME:
case AggregatedRecord.AGGREGATED:
continue;
case AggregatedRecord.OPERATION_COUNT:
stringBuffer.append(", SUM(");
2021-03-31 17:49:49 +02:00
if(addNested) {
stringBuffer.append(NESTED_TABLE_NAME);
stringBuffer.append(".");
}
2021-03-16 15:33:34 +01:00
stringBuffer.append(dbField);
stringBuffer.append(") AS ");
break;
2021-11-22 15:07:29 +01:00
case AggregatedStorageStatusRecord.DATA_COUNT:
stringBuffer.append(", MAX(");
if(addNested) {
stringBuffer.append(NESTED_TABLE_NAME);
stringBuffer.append(".");
}
stringBuffer.append(dbField);
stringBuffer.append(") AS ");
break;
2021-03-29 11:45:48 +02:00
case AggregatedStorageUsageRecord.DATA_VOLUME:
2021-11-22 15:07:29 +01:00
if(clz.isAssignableFrom(AggregatedStorageUsageRecord.class)) {
stringBuffer.append(", SUM(");
}else if(clz.isAssignableFrom(AggregatedStorageStatusRecord.class)){
stringBuffer.append(", MAX(");
}
2021-03-31 17:49:49 +02:00
if(addNested) {
stringBuffer.append(NESTED_TABLE_NAME);
stringBuffer.append(".");
}
2021-03-29 11:45:48 +02:00
stringBuffer.append(dbField);
stringBuffer.append(") AS ");
break;
2021-03-16 15:33:34 +01:00
// WEIGHTED AVERAGE
case AggregatedServiceUsageRecord.DURATION:
stringBuffer.append(", ROUND(SUM(");
2021-03-31 17:49:49 +02:00
if(addNested) {
stringBuffer.append(NESTED_TABLE_NAME);
stringBuffer.append(".");
}
2021-03-16 15:33:34 +01:00
stringBuffer.append(dbField);
stringBuffer.append("*");
2021-03-31 17:49:49 +02:00
if(addNested) {
stringBuffer.append(NESTED_TABLE_NAME);
stringBuffer.append(".");
}
2021-03-16 15:33:34 +01:00
appendTableField(AggregatedRecord.OPERATION_COUNT);
stringBuffer.append(")/SUM(");
2021-03-31 17:49:49 +02:00
if(addNested) {
stringBuffer.append(NESTED_TABLE_NAME);
stringBuffer.append(".");
}
2021-03-16 15:33:34 +01:00
appendTableField(AggregatedRecord.OPERATION_COUNT);
stringBuffer.append(")) AS ");
2021-03-16 15:33:34 +01:00
break;
case AggregatedServiceUsageRecord.MAX_INVOCATION_TIME:
stringBuffer.append(", MAX(");
2021-03-31 17:49:49 +02:00
if(addNested) {
stringBuffer.append(NESTED_TABLE_NAME);
stringBuffer.append(".");
}
2021-03-16 15:33:34 +01:00
stringBuffer.append(dbField);
stringBuffer.append(") AS ");
break;
case AggregatedServiceUsageRecord.MIN_INVOCATION_TIME:
stringBuffer.append(", MIN(");
2021-03-31 17:49:49 +02:00
if(addNested) {
stringBuffer.append(NESTED_TABLE_NAME);
stringBuffer.append(".");
}
2021-03-16 15:33:34 +01:00
stringBuffer.append(dbField);
stringBuffer.append(") AS ");
break;
default:
stringBuffer.append(", ");
break;
}
stringBuffer.append(dbField);
requestedTableField.add(dbField);
}
}
protected String getTimeBucketCalendarInterval(AggregationMode aggregationMode) {
CalendarEnum calendarEnum = CalendarEnum.values()[aggregationMode.ordinal()];
return calendarEnum.name().toLowerCase();
}
private void newQuery() {
stringBuffer = new StringBuffer();
2021-03-31 17:49:49 +02:00
requestedTableField = new HashSet<>();
2021-03-16 15:33:34 +01:00
stringBuffer.append("SELECT ");
}
2021-04-09 23:39:42 +02:00
protected void addTemporalConstraintToQuery() throws SQLException {
2021-11-02 11:29:29 +01:00
stringBuffer.append(" WHERE (");
2021-03-16 15:33:34 +01:00
String tableField = getTableField(AggregatedRecord.START_TIME);
stringBuffer.append(tableField);
stringBuffer.append(" > ");
appendValue(temporalConstraint.getAlignedStartTime());
stringBuffer.append(" AND ");
2021-03-29 11:48:50 +02:00
tableField = getTableField(AggregatedRecord.END_TIME);
2021-03-16 15:33:34 +01:00
stringBuffer.append(tableField);
2021-11-26 17:24:33 +01:00
stringBuffer.append(" <= ");
2021-03-16 15:33:34 +01:00
appendValue(temporalConstraint.getAlignedEndTime());
2021-11-02 11:29:29 +01:00
stringBuffer.append(")");
2021-03-16 15:33:34 +01:00
}
2021-03-31 17:49:49 +02:00
protected void addDateGroupBy(boolean addNested) {
2021-03-16 15:33:34 +01:00
stringBuffer.append(" GROUP BY ");
2021-03-31 17:49:49 +02:00
if(addNested) {
stringBuffer.append(NESTED_TABLE_NAME);
stringBuffer.append(".");
}
2021-03-30 17:52:19 +02:00
appendTableField(DATE_OF_TIMESERIES_AS_FIELD);
2021-03-16 15:33:34 +01:00
}
2021-03-31 17:49:49 +02:00
protected void addDateOrderBy(boolean addNested) {
2021-03-16 15:33:34 +01:00
stringBuffer.append(" ORDER BY ");
2021-03-31 17:49:49 +02:00
if(addNested) {
stringBuffer.append(NESTED_TABLE_NAME);
stringBuffer.append(".");
}
2021-03-30 17:52:19 +02:00
appendTableField(DATE_OF_TIMESERIES_AS_FIELD);
2021-03-16 15:33:34 +01:00
stringBuffer.append(" ASC");
}
2021-03-19 15:55:06 +01:00
protected void addGroupAndOrderByForOrderByField() {
stringBuffer.append(" GROUP BY ");
2021-03-22 19:08:31 +01:00
String dbField = getTableField(tableFieldToRequest);
2021-03-19 15:55:06 +01:00
stringBuffer.append(dbField);
stringBuffer.append(" ORDER BY ");
2021-03-30 17:52:19 +02:00
dbField = getTableField(orderByField);
stringBuffer.append(dbField);
2021-03-19 15:55:06 +01:00
stringBuffer.append(" DESC");
}
protected void addLimit() {
if(limit != null) {
2021-11-25 16:59:33 +01:00
stringBuffer.append(" LIMIT ");
2021-03-19 15:55:06 +01:00
stringBuffer.append(limit.toString());
}
}
protected void addRequestedField() {
2021-03-22 19:08:31 +01:00
String dbField = getTableField(tableFieldToRequest);
2021-03-19 15:55:06 +01:00
stringBuffer.append(dbField);
requestedTableField.add(dbField);
stringBuffer.append(", SUM(");
dbField = getTableField(orderByField);
stringBuffer.append(dbField);
requestedTableField.add(dbField);
stringBuffer.append(") AS ");
2021-03-30 17:52:19 +02:00
stringBuffer.append(dbField);
2021-03-19 15:55:06 +01:00
}
2021-03-31 17:49:49 +02:00
protected void addRequestedDate() {
String calendarInterval = getTimeBucketCalendarInterval(temporalConstraint.getAggregationMode());
String tableField = getTableField(DATE_OF_TIMESERIES_AS_FIELD);
stringBuffer.append("date_trunc('");
stringBuffer.append(calendarInterval);
stringBuffer.append("', ");
stringBuffer.append(tableField);
stringBuffer.append(" AT TIME ZONE 'UTC') ");
stringBuffer.append(tableField);
requestedTableField.add(tableField);
}
2021-03-17 17:55:56 +01:00
public String getTimeSeriesQuery() throws Exception {
2021-03-16 15:33:34 +01:00
newQuery();
2021-03-31 17:49:49 +02:00
stringBuffer.append(NESTED_TABLE_NAME);
stringBuffer.append(".");
String tableField = getTableField(DATE_OF_TIMESERIES_AS_FIELD);
stringBuffer.append(tableField);
addEmittedFields(true);
2021-03-16 15:33:34 +01:00
2021-03-31 17:49:49 +02:00
/* Nested Query */
stringBuffer.append(" FROM ( SELECT ");
addRequestedDate();
addEmittedFields(false);
2021-03-16 15:33:34 +01:00
stringBuffer.append(" FROM ");
2021-03-18 17:05:33 +01:00
stringBuffer.append(recordToDBFields.getTableName());
2021-03-16 15:33:34 +01:00
addTemporalConstraintToQuery();
2021-11-22 15:07:29 +01:00
if(filters!=null && filters.size()>0) {
stringBuffer.append(" AND ");
addFilters();
}
if(contexts!=null && contexts.size()>0) {
stringBuffer.append(" AND ");
addContextFilter();
}
2021-03-16 15:33:34 +01:00
2021-03-31 17:49:49 +02:00
addDateGroupBy(false);
addDateOrderBy(false);
stringBuffer.append(") AS ");
stringBuffer.append(NESTED_TABLE_NAME);
/* Nested Query */
addDateGroupBy(true);
addDateOrderBy(true);
2021-03-19 15:55:06 +01:00
return stringBuffer.toString();
}
public String getNextPossibleValueQuery() throws Exception {
newQuery();
addRequestedField();
stringBuffer.append(" FROM ");
stringBuffer.append(recordToDBFields.getTableName());
2021-11-23 10:41:27 +01:00
boolean addAnd = false;
2021-11-22 15:07:29 +01:00
if(temporalConstraint!=null) {
addTemporalConstraintToQuery();
2021-11-23 10:41:27 +01:00
addAnd = true;
2021-11-22 15:07:29 +01:00
}
if(filters!=null && filters.size()>0) {
2021-11-23 10:41:27 +01:00
if(addAnd) {
stringBuffer.append(" AND ");
}
2021-11-22 15:07:29 +01:00
addFilters();
2021-11-23 10:41:27 +01:00
addAnd = true;
}
if(contexts!=null && contexts.size()>0) {
if(addAnd) {
stringBuffer.append(" AND ");
}
addContextFilter();
addAnd = false;
2021-11-22 15:07:29 +01:00
}
2021-03-19 15:55:06 +01:00
addGroupAndOrderByForOrderByField();
addLimit();
2021-03-16 15:33:34 +01:00
return stringBuffer.toString();
2021-03-17 17:55:56 +01:00
}
2021-03-30 17:52:19 +02:00
2021-03-22 18:08:35 +01:00
public String getRecordQuery(){
newQuery();
stringBuffer.append("* ");
stringBuffer.append(" FROM ");
stringBuffer.append(recordToDBFields.getTableName());
stringBuffer.append(" WHERE ");
stringBuffer.append(" id=");
appendString(recordId);
return stringBuffer.toString();
}
2021-03-22 19:08:31 +01:00
public String getDinstinctValuesQuery() {
2021-03-29 10:43:21 +02:00
newQuery();
2021-03-22 19:08:31 +01:00
String dbField = getTableField(tableFieldToRequest);
requestedTableField.add(dbField);
stringBuffer.append("DISTINCT ");
stringBuffer.append(dbField);
stringBuffer.append(" FROM ");
stringBuffer.append(recordToDBFields.getTableName());
return stringBuffer.toString();
}
2021-03-22 18:08:35 +01:00
2021-03-16 15:33:34 +01:00
}