32 changed files with 830 additions and 420 deletions
@ -0,0 +1,93 @@ |
|||
/** |
|||
* Copyright © 2016-2017 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.service.install; |
|||
|
|||
import com.fasterxml.jackson.databind.ObjectMapper; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.csv.CSVFormat; |
|||
import org.apache.commons.csv.CSVParser; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import com.fasterxml.jackson.databind.JsonNode; |
|||
import org.thingsboard.server.common.data.UUIDConverter; |
|||
import org.thingsboard.server.common.data.id.CustomerId; |
|||
import org.thingsboard.server.common.data.id.DashboardId; |
|||
import org.thingsboard.server.dao.dashboard.DashboardService; |
|||
|
|||
import java.io.IOException; |
|||
import java.nio.file.Files; |
|||
import java.nio.file.Path; |
|||
import java.util.*; |
|||
|
|||
/** |
|||
* Created by igor on 2/27/18. |
|||
*/ |
|||
@Slf4j |
|||
public class DatabaseHelper { |
|||
|
|||
public static final CSVFormat CSV_DUMP_FORMAT = CSVFormat.DEFAULT.withNullString("\\N"); |
|||
|
|||
public static final String DEVICE = "device"; |
|||
public static final String TENANT_ID = "tenant_id"; |
|||
public static final String CUSTOMER_ID = "customer_id"; |
|||
public static final String SEARCH_TEXT = "search_text"; |
|||
public static final String ADDITIONAL_INFO = "additional_info"; |
|||
public static final String ASSET = "asset"; |
|||
public static final String DASHBOARD = "dashboard"; |
|||
public static final String ID = "id"; |
|||
public static final String TITLE = "title"; |
|||
public static final String ASSIGNED_CUSTOMERS = "assigned_customers"; |
|||
public static final String CONFIGURATION = "configuration"; |
|||
|
|||
public static final ObjectMapper objectMapper = new ObjectMapper(); |
|||
|
|||
public static void upgradeTo40_assignDashboards(Path dashboardsDump, DashboardService dashboardService, boolean sql) throws Exception { |
|||
String[] columns = new String[]{ID, TENANT_ID, CUSTOMER_ID, TITLE, SEARCH_TEXT, ASSIGNED_CUSTOMERS, CONFIGURATION}; |
|||
try (CSVParser csvParser = new CSVParser(Files.newBufferedReader(dashboardsDump), CSV_DUMP_FORMAT.withHeader(columns))) { |
|||
csvParser.forEach(record -> { |
|||
String customerIdString = record.get(CUSTOMER_ID); |
|||
String assignedCustomersString = record.get(ASSIGNED_CUSTOMERS); |
|||
DashboardId dashboardId = new DashboardId(toUUID(record.get(ID), sql)); |
|||
List<CustomerId> customerIds = new ArrayList<>(); |
|||
if (!StringUtils.isEmpty(assignedCustomersString)) { |
|||
try { |
|||
JsonNode assignedCustomersJson = objectMapper.readTree(assignedCustomersString); |
|||
Map<String,String> assignedCustomers = objectMapper.treeToValue(assignedCustomersJson, HashMap.class); |
|||
assignedCustomers.forEach((strCustomerId, title) -> { |
|||
customerIds.add(new CustomerId(UUID.fromString(strCustomerId))); |
|||
}); |
|||
} catch (IOException e) { |
|||
log.error("Unable to parse assigned customers field", e); |
|||
} |
|||
} |
|||
if (!StringUtils.isEmpty(customerIdString)) { |
|||
customerIds.add(new CustomerId(toUUID(customerIdString, sql))); |
|||
} |
|||
for (CustomerId customerId : customerIds) { |
|||
dashboardService.assignDashboardToCustomer(dashboardId, customerId); |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
|
|||
private static UUID toUUID(String src, boolean sql) { |
|||
if (sql) { |
|||
return UUIDConverter.fromString(src); |
|||
} else { |
|||
return UUID.fromString(src); |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,146 @@ |
|||
/** |
|||
* Copyright © 2016-2017 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.service.install.sql; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.csv.CSVParser; |
|||
import org.apache.commons.csv.CSVPrinter; |
|||
import org.apache.commons.csv.CSVRecord; |
|||
|
|||
import java.nio.file.Files; |
|||
import java.nio.file.Path; |
|||
import java.sql.*; |
|||
import java.util.ArrayList; |
|||
import java.util.HashMap; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
import static org.thingsboard.server.service.install.DatabaseHelper.CSV_DUMP_FORMAT; |
|||
|
|||
/** |
|||
* Created by igor on 2/27/18. |
|||
*/ |
|||
@Slf4j |
|||
public class SqlDbHelper { |
|||
|
|||
public static Path dumpTableIfExists(Connection conn, String tableName, |
|||
String[] columns, String[] defaultValues, String dumpPrefix) throws Exception { |
|||
|
|||
DatabaseMetaData metaData = conn.getMetaData(); |
|||
ResultSet res = metaData.getTables(null, null, tableName, |
|||
new String[] {"TABLE"}); |
|||
if (res.next()) { |
|||
res.close(); |
|||
Path dumpFile = Files.createTempFile(dumpPrefix, null); |
|||
Files.deleteIfExists(dumpFile); |
|||
try (CSVPrinter csvPrinter = new CSVPrinter(Files.newBufferedWriter(dumpFile), CSV_DUMP_FORMAT)) { |
|||
try (PreparedStatement stmt = conn.prepareStatement("SELECT * FROM " + tableName)) { |
|||
try (ResultSet tableRes = stmt.executeQuery()) { |
|||
ResultSetMetaData resMetaData = tableRes.getMetaData(); |
|||
Map<String, Integer> columnIndexMap = new HashMap<>(); |
|||
for (int i = 0; i < resMetaData.getColumnCount(); i++) { |
|||
String columnName = resMetaData.getColumnName(i); |
|||
columnIndexMap.put(columnName, i); |
|||
} |
|||
while(tableRes.next()) { |
|||
dumpRow(tableRes, columnIndexMap, columns, defaultValues, csvPrinter); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
return dumpFile; |
|||
} else { |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
public static void loadTable(Connection conn, String tableName, String[] columns, Path sourceFile) throws Exception { |
|||
PreparedStatement prepared = conn.prepareStatement(createInsertStatement(tableName, columns)); |
|||
prepared.getParameterMetaData(); |
|||
try (CSVParser csvParser = new CSVParser(Files.newBufferedReader(sourceFile), CSV_DUMP_FORMAT.withHeader(columns))) { |
|||
csvParser.forEach(record -> { |
|||
try { |
|||
for (int i=0;i<columns.length;i++) { |
|||
setColumnValue(i, columns[i], record, prepared); |
|||
} |
|||
prepared.execute(); |
|||
} catch (SQLException e) { |
|||
log.error("Unable to load table record!", e); |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
|
|||
private static void dumpRow(ResultSet res, Map<String, Integer> columnIndexMap, String[] columns, |
|||
String[] defaultValues, CSVPrinter csvPrinter) throws Exception { |
|||
List<String> record = new ArrayList<>(); |
|||
for (int i=0;i<columns.length;i++) { |
|||
String column = columns[i]; |
|||
String defaultValue; |
|||
if (defaultValues != null && i < defaultValues.length) { |
|||
defaultValue = defaultValues[i]; |
|||
} else { |
|||
defaultValue = ""; |
|||
} |
|||
record.add(getColumnValue(column, defaultValue, columnIndexMap, res)); |
|||
} |
|||
csvPrinter.printRecord(record); |
|||
} |
|||
|
|||
private static String getColumnValue(String column, String defaultValue, Map<String, Integer> columnIndexMap, ResultSet res) { |
|||
int index = columnIndexMap.containsKey(column) ? columnIndexMap.get(column) : -1; |
|||
if (index > -1) { |
|||
String str; |
|||
try { |
|||
Object obj = res.getObject(index); |
|||
if (obj == null) { |
|||
str = ""; |
|||
} else { |
|||
str = obj.toString(); |
|||
} |
|||
} catch (Exception e) { |
|||
str = ""; |
|||
} |
|||
return str; |
|||
} else { |
|||
return defaultValue; |
|||
} |
|||
} |
|||
|
|||
private static void setColumnValue(int index, String column, |
|||
CSVRecord record, PreparedStatement preparedStatement) throws SQLException { |
|||
String value = record.get(column); |
|||
int type = preparedStatement.getParameterMetaData().getParameterType(index + 1); |
|||
preparedStatement.setObject(index + 1, value, type); |
|||
} |
|||
|
|||
private static String createInsertStatement(String tableName, String[] columns) { |
|||
StringBuilder insertStatementBuilder = new StringBuilder(); |
|||
insertStatementBuilder.append("INSERT INTO ").append(tableName).append(" ("); |
|||
for (String column : columns) { |
|||
insertStatementBuilder.append(column).append(","); |
|||
} |
|||
insertStatementBuilder.deleteCharAt(insertStatementBuilder.length() - 1); |
|||
insertStatementBuilder.append(") VALUES ("); |
|||
for (String column : columns) { |
|||
insertStatementBuilder.append("?").append(","); |
|||
} |
|||
insertStatementBuilder.deleteCharAt(insertStatementBuilder.length() - 1); |
|||
insertStatementBuilder.append(")"); |
|||
return insertStatementBuilder.toString(); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
/** |
|||
* Copyright © 2016-2017 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.service; |
|||
|
|||
import org.thingsboard.server.common.data.id.IdBased; |
|||
import org.thingsboard.server.common.data.page.TimePageLink; |
|||
|
|||
import java.sql.Time; |
|||
import java.util.List; |
|||
import java.util.UUID; |
|||
|
|||
public abstract class TimePaginatedRemover<I, D extends IdBased<?>> { |
|||
|
|||
private static final int DEFAULT_LIMIT = 100; |
|||
|
|||
public void removeEntities(I id) { |
|||
TimePageLink pageLink = new TimePageLink(DEFAULT_LIMIT); |
|||
boolean hasNext = true; |
|||
while (hasNext) { |
|||
List<D> entities = findEntities(id, pageLink); |
|||
for (D entity : entities) { |
|||
removeEntity(entity); |
|||
} |
|||
hasNext = entities.size() == pageLink.getLimit(); |
|||
if (hasNext) { |
|||
int index = entities.size() - 1; |
|||
UUID idOffset = entities.get(index).getUuidId(); |
|||
pageLink.setIdOffset(idOffset); |
|||
} |
|||
} |
|||
} |
|||
|
|||
protected abstract List<D> findEntities(I id, TimePageLink pageLink); |
|||
|
|||
protected abstract void removeEntity(D entity); |
|||
|
|||
} |
|||
Loading…
Reference in new issue