package org.gcube.accounting.aggregator.persistence; import java.io.Serializable; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.TimeZone; import org.gcube.accounting.aggregator.aggregation.AggregationInfo; import org.gcube.accounting.aggregator.aggregation.AggregationType; import org.gcube.accounting.aggregator.status.AggregationStateEvent; import org.gcube.accounting.aggregator.status.AggregationStatus; import org.gcube.accounting.analytics.persistence.AccountingPersistenceBackendQueryConfiguration; import org.gcube.accounting.analytics.persistence.postgresql.AccountingPersistenceQueryPostgreSQL; import org.gcube.accounting.persistence.AccountingPersistenceConfiguration; import org.postgresql.core.Utils; public class PostgreSQLConnector extends AccountingPersistenceQueryPostgreSQL { private static final String UTC_TIME_ZONE = "UTC"; public static final TimeZone DEFAULT_TIME_ZONE = TimeZone.getTimeZone(UTC_TIME_ZONE); public PostgreSQLConnector() throws Exception { this.configuration = new AccountingPersistenceBackendQueryConfiguration(AccountingPersistenceQueryPostgreSQL.class); } protected Connection getConnection() throws Exception { Class.forName("org.postgresql.Driver"); String url = configuration.getProperty(AccountingPersistenceQueryPostgreSQL.URL_PROPERTY_KEY); String username = configuration.getProperty(AccountingPersistenceConfiguration.USERNAME_PROPERTY_KEY); String password = configuration.getProperty(AccountingPersistenceConfiguration.PASSWORD_PROPERTY_KEY); Connection connection = DriverManager.getConnection(url, username, password); logger.trace("Database {} opened successfully", url); connection.setAutoCommit(false); return connection; } protected String getQuotedString(String string) throws SQLException { StringBuilder builder = new StringBuilder(); builder.append("'"); Utils.escapeLiteral(builder, string, false); builder.append("'"); return builder.toString(); } protected String getValue(Serializable serializable) throws SQLException { if(serializable == null) { return "null"; } if(serializable instanceof Number) { return serializable.toString(); } if(serializable instanceof Calendar) { Calendar calendar = (Calendar) serializable; SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATETIME_PATTERN); simpleDateFormat.setTimeZone(DEFAULT_TIME_ZONE); String date = simpleDateFormat.format(calendar.getTime()); return getQuotedString(date); } if(serializable instanceof Date) { Date date = (Date) serializable; SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATETIME_PATTERN); simpleDateFormat.setTimeZone(DEFAULT_TIME_ZONE); String dateString = simpleDateFormat.format(date); return getQuotedString(dateString); } if(serializable instanceof Enum) { Enum e = (Enum) serializable; return getQuotedString(e.name()); } // String, URI etc return getQuotedString(serializable.toString()); } public String getInsertAggregationStatusQuery(AggregationStatus aggregationStatus, boolean upsert) throws SQLException { StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append("INSERT INTO "); stringBuffer.append("aggregation_status"); stringBuffer.append(" (id, "); stringBuffer.append("record_type, aggregation_type, aggregation_start_date, aggregation_end_date, "); stringBuffer.append("original_records_number, aggregated_records_number, recovered_records_number, malformed_records_number, percentage, "); stringBuffer.append("context, current_aggregation_state, last_update_time, previous)"); stringBuffer.append(" VALUES ("); stringBuffer.append(getValue(aggregationStatus.getUUID().toString())); AggregationInfo aggregationInfo = aggregationStatus.getAggregationInfo(); stringBuffer.append(", "); stringBuffer.append(getValue(aggregationInfo.getRecordType())); stringBuffer.append(", "); stringBuffer.append(getValue(aggregationInfo.getAggregationType())); stringBuffer.append(", "); stringBuffer.append(getValue(aggregationInfo.getAggregationStartDate())); stringBuffer.append(", "); stringBuffer.append(getValue(aggregationInfo.getAggregationEndDate())); stringBuffer.append(", "); stringBuffer.append(getValue(aggregationStatus.getOriginalRecordsNumber())); stringBuffer.append(", "); stringBuffer.append(getValue(aggregationStatus.getAggregatedRecordsNumber())); stringBuffer.append(", "); stringBuffer.append(getValue(aggregationStatus.getRecoveredRecordNumber())); stringBuffer.append(", "); stringBuffer.append(getValue(aggregationStatus.getMalformedRecordNumber())); stringBuffer.append(", "); stringBuffer.append(getValue(aggregationStatus.getPercentage())); stringBuffer.append(", "); stringBuffer.append(getValue(aggregationStatus.getContext())); stringBuffer.append(", "); stringBuffer.append(getValue(aggregationStatus.getAggregationState())); stringBuffer.append(", "); stringBuffer.append(getValue(aggregationStatus.getLastUpdateTime())); stringBuffer.append(", "); AggregationStatus previous = aggregationStatus.getPrevious(); if(previous!=null) { stringBuffer.append(getValue(previous.getUUID().toString())); }else { stringBuffer.append(getValue(null)); } if(upsert) { stringBuffer.append(") ON CONFLICT (id) DO UPDATE SET "); stringBuffer.append("original_records_number=EXCLUDED.original_records_number, aggregated_records_number=EXCLUDED.aggregated_records_number, recovered_records_number=EXCLUDED.recovered_records_number, malformed_records_number=EXCLUDED.malformed_records_number, percentage=EXCLUDED.percentage, "); stringBuffer.append("current_aggregation_state=EXCLUDED.current_aggregation_state, last_update_time=EXCLUDED.last_update_time, previous=EXCLUDED.previous;"); }else { stringBuffer.append(");"); } return stringBuffer.toString(); } public String getInsertAggregationStateQuery(AggregationStatus aggregationStatus) throws SQLException { StringBuffer stringBuffer = new StringBuffer(); for(AggregationStateEvent aggregationStateEvent : aggregationStatus.getAggregationStateEvents()) { stringBuffer.append("INSERT INTO "); stringBuffer.append("aggregation_status_event"); stringBuffer.append(" ( aggregation_state, start_time, end_time, aggregation_status)"); stringBuffer.append(" VALUES ("); stringBuffer.append(getValue(aggregationStateEvent.getAggregationState())); stringBuffer.append(", "); stringBuffer.append(getValue(aggregationStateEvent.getStartTime())); stringBuffer.append(", "); stringBuffer.append(getValue(aggregationStateEvent.getEndTime())); stringBuffer.append(", "); stringBuffer.append(getValue(aggregationStatus.getUUID().toString())); stringBuffer.append(") ON CONFLICT DO NOTHING;"); } return stringBuffer.toString(); } public void upsertAggregationStatus(AggregationStatus aggregationStatus) throws Exception { Connection connection = getConnection(); Statement statement = connection.createStatement(); String sqlCommand = getInsertAggregationStatusQuery(aggregationStatus, true); statement.executeUpdate(sqlCommand); sqlCommand = getInsertAggregationStateQuery(aggregationStatus); statement.executeUpdate(sqlCommand); statement.close(); connection.commit(); connection.close(); } public AggregationStatus getLast(String recordType, AggregationType aggregationType, Date aggregationStartDate, Date aggregationEndDate) throws Exception{ /* * SELECT * * FROM aggregation_status * WHERE * `aggregationInfo`.`recordType` = "ServiceUsageRecord" AND * `aggregationInfo`.`aggregationType` = "DAILY" AND * `aggregationInfo`.`aggregationStartDate` >= "2017-05-01 00:00:00.000 +0000" * `aggregationInfo`.`aggregationStartDate` <= "2017-05-31 00:00:00.000 +0000" * ORDER BY `aggregationInfo`.`aggregationStartDate` DESC LIMIT 1 */ return null; } public List getUnterminated(Date aggregationStartDate, Date aggregationEndDate) throws Exception{ return getUnterminated(null, null, aggregationStartDate, aggregationEndDate); } public List getUnterminated(String recordType, AggregationType aggregationType, Date aggregationStartDate, Date aggregationEndDate) throws Exception{ /* * SELECT * * FROM AccountingManager * WHERE * `aggregationState` != "COMPLETED" AND * `lastUpdateTime` < "2017-07-31 09:31:10.984 +0000" AND * `aggregationInfo`.`recordType` = "ServiceUsageRecord" AND * `aggregationInfo`.`aggregationType` = "DAILY" AND * `aggregationInfo`.`aggregationStartDate` >= "2017-05-01 00:00:00.000 +0000" * `aggregationInfo`.`aggregationStartDate` <= "2017-05-31 00:00:00.000 +0000" * * ORDER BY `aggregationInfo`.`aggregationStartDate` ASC */ List aggregationStatuses = new ArrayList<>(); return aggregationStatuses; } public static List getAll() throws Exception{ /* * SELECT * * FROM AccountingManager * ORDER BY `aggregationInfo`.`aggregationStartDate` ASC */ List aggregationStatuses = new ArrayList<>(); return aggregationStatuses; } public static AggregationStatus getAggregationStatus(String recordType, AggregationType aggregationType, Date aggregationStartDate) throws Exception{ /* * SELECT * * FROM AccountingManager * WHERE * `aggregationInfo`.`recordType` = "ServiceUsageRecord" AND * `aggregationInfo`.`aggregationType` = "DAILY" AND * `aggregationInfo`.`aggregationStartDate` = "2017-06-24 00:00:00.000 +0000" */ return null; } }