From 004cc216d265f42db91e971ad7379ba0bd082820 Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Mon, 22 Jun 2020 11:10:28 +0300 Subject: [PATCH 1/3] Refactoing of UUIDs storage --- .../data/upgrade/2.4.3/schema_update_ttl.sql | 14 +- .../upgrade/3.0.1/schema_update_to_uuid.sql | 41 ++++++ ...efaultTbEntityDataSubscriptionService.java | 79 +++++++++++- .../telemetry/cmd/v2/EntityDataUpdate.java | 16 ++- .../PsqlTimeseriesCleanUpService.java | 2 +- .../TimescaleTimeseriesCleanUpService.java | 2 +- .../controller/BaseWebsocketApiTest.java | 58 +++++++++ .../controller/sql/WebsocketApiSqlTest.java | 1 - .../server/common/data/page/TimePageLink.java | 8 -- .../server/common/data/UUIDConverterTest.java | 15 +++ .../org/thingsboard/server/dao/DaoUtil.java | 11 +- .../server/dao/alarm/AlarmDao.java | 1 - .../server/dao/alarm/BaseAlarmService.java | 2 +- .../server/dao/audit/AuditLogServiceImpl.java | 2 - .../dao/audit/DummyAuditLogServiceImpl.java | 2 - .../BaseComponentDescriptorService.java | 1 - .../dao/component/ComponentDescriptorDao.java | 1 - .../server/dao/customer/CustomerDao.java | 1 - .../dao/customer/CustomerServiceImpl.java | 1 - .../dao/dashboard/DashboardInfoDao.java | 3 - .../dao/entityview/EntityViewServiceImpl.java | 7 +- .../server/dao/model/BaseEntity.java | 4 + .../server/dao/model/BaseSqlEntity.java | 27 ++-- .../server/dao/model/ModelConstants.java | 3 +- .../dao/model/sql/AbstractAlarmEntity.java | 24 ++-- .../dao/model/sql/AbstractAssetEntity.java | 21 +-- .../dao/model/sql/AbstractDeviceEntity.java | 24 ++-- .../model/sql/AbstractEntityViewEntity.java | 28 ++-- .../dao/model/sql/AdminSettingsEntity.java | 7 +- .../model/sql/AttributeKvCompositeKey.java | 5 +- .../server/dao/model/sql/AuditLogEntity.java | 29 +++-- .../model/sql/ComponentDescriptorEntity.java | 2 + .../server/dao/model/sql/CustomerEntity.java | 13 +- .../server/dao/model/sql/DashboardEntity.java | 11 +- .../dao/model/sql/DashboardInfoEntity.java | 11 +- .../model/sql/DeviceCredentialsEntity.java | 11 +- .../dao/model/sql/DeviceInfoEntity.java | 2 +- .../server/dao/model/sql/EventEntity.java | 19 ++- .../dao/model/sql/RelationCompositeKey.java | 10 +- .../server/dao/model/sql/RelationEntity.java | 18 +-- .../server/dao/model/sql/RuleChainEntity.java | 18 +-- .../server/dao/model/sql/RuleNodeEntity.java | 11 +- .../server/dao/model/sql/TenantEntity.java | 4 +- .../dao/model/sql/UserCredentialsEntity.java | 11 +- .../server/dao/model/sql/UserEntity.java | 20 ++- .../dao/model/sql/WidgetTypeEntity.java | 11 +- .../dao/model/sql/WidgetsBundleEntity.java | 14 +- .../sqlts/latest/TsKvLatestCompositeKey.java | 1 - .../model/sqlts/latest/TsKvLatestEntity.java | 4 - .../server/dao/model/sqlts/ts/TsKvEntity.java | 4 - .../dao/nosql/CassandraAbstractAsyncDao.java | 6 - .../nosql/CassandraBufferedRateExecutor.java | 1 - .../server/dao/relation/RelationDao.java | 2 - .../server/dao/rule/BaseRuleChainService.java | 1 - .../server/dao/rule/RuleChainDao.java | 1 - .../server/dao/service/PaginatedRemover.java | 3 - .../dao/service/TimePaginatedRemover.java | 3 - .../settings/AdminSettingsServiceImpl.java | 1 - .../server/dao/sql/JpaAbstractDao.java | 22 ++-- .../dao/sql/JpaAbstractSearchTimeDao.java | 1 + .../server/dao/sql/alarm/AlarmRepository.java | 25 ++-- .../server/dao/sql/alarm/JpaAlarmDao.java | 14 +- .../server/dao/sql/asset/AssetRepository.java | 38 +++--- .../server/dao/sql/asset/JpaAssetDao.java | 40 +++--- .../AttributeKvInsertRepository.java | 5 +- .../sql/attributes/AttributeKvRepository.java | 5 +- .../HsqlAttributesInsertRepository.java | 2 +- .../dao/sql/attributes/JpaAttributeDao.java | 11 +- .../dao/sql/audit/AuditLogRepository.java | 17 +-- .../server/dao/sql/audit/JpaAuditLogDao.java | 17 ++- ...ctComponentDescriptorInsertRepository.java | 4 +- .../ComponentDescriptorRepository.java | 5 +- ...qlComponentDescriptorInsertRepository.java | 7 +- .../JpaBaseComponentDescriptorDao.java | 12 +- ...qlComponentDescriptorInsertRepository.java | 5 +- .../dao/sql/customer/CustomerRepository.java | 9 +- .../dao/sql/customer/JpaCustomerDao.java | 7 +- .../dashboard/DashboardInfoRepository.java | 11 +- .../sql/dashboard/DashboardRepository.java | 4 +- .../dao/sql/dashboard/JpaDashboardDao.java | 4 +- .../sql/dashboard/JpaDashboardInfoDao.java | 7 +- .../device/DeviceCredentialsRepository.java | 6 +- .../dao/sql/device/DeviceRepository.java | 39 +++--- .../sql/device/JpaDeviceCredentialsDao.java | 5 +- .../server/dao/sql/device/JpaDeviceDao.java | 42 +++--- .../sql/entityview/EntityViewRepository.java | 36 +++--- .../dao/sql/entityview/JpaEntityViewDao.java | 41 +++--- .../event/AbstractEventInsertRepository.java | 4 +- .../server/dao/sql/event/EventRepository.java | 39 +++--- .../sql/event/HsqlEventInsertRepository.java | 23 +++- .../server/dao/sql/event/JpaBaseEventDao.java | 59 ++++++--- .../sql/event/PsqlEventInsertRepository.java | 8 +- .../query/DefaultEntityQueryRepository.java | 21 ++- .../dao/sql/query/EntityDataAdapter.java | 7 +- .../dao/sql/query/EntityKeyMapping.java | 18 ++- .../HsqlRelationInsertRepository.java | 22 +++- .../dao/sql/relation/JpaRelationDao.java | 37 ++---- .../dao/sql/relation/RelationRepository.java | 13 +- .../server/dao/sql/rule/JpaRuleChainDao.java | 7 +- .../dao/sql/rule/RuleChainRepository.java | 7 +- .../sql/settings/AdminSettingsRepository.java | 4 +- .../dao/sql/settings/JpaAdminSettingsDao.java | 4 +- .../server/dao/sql/tenant/JpaTenantDao.java | 3 +- .../dao/sql/tenant/TenantRepository.java | 5 +- .../dao/sql/user/JpaUserCredentialsDao.java | 5 +- .../server/dao/sql/user/JpaUserDao.java | 13 +- .../sql/user/UserCredentialsRepository.java | 6 +- .../server/dao/sql/user/UserRepository.java | 9 +- .../dao/sql/widget/JpaWidgetTypeDao.java | 7 +- .../dao/sql/widget/JpaWidgetsBundleDao.java | 15 +-- .../dao/sql/widget/WidgetTypeRepository.java | 7 +- .../sql/widget/WidgetsBundleRepository.java | 15 +-- .../server/dao/tenant/TenantDao.java | 2 - .../server/dao/tenant/TenantServiceImpl.java | 3 - .../AggregatePartitionsFunction.java | 1 - .../thingsboard/server/dao/user/UserDao.java | 1 - .../server/dao/user/UserServiceImpl.java | 1 - .../util/AbstractBufferedRateExecutor.java | 10 +- .../server/dao/widget/WidgetsBundleDao.java | 1 - .../resources/sql/schema-entities-hsql.sql | 112 +++++++++------- .../main/resources/sql/schema-entities.sql | 120 +++++++++++------- .../main/resources/sql/schema-timescale.sql | 14 +- dao/src/main/resources/sql/schema-ts-hsql.sql | 5 + dao/src/main/resources/sql/schema-ts-psql.sql | 14 +- .../server/dao/SqlDaoServiceTestSuite.java | 26 ++-- .../dao/service/BaseEntityServiceTest.java | 1 + dao/src/test/resources/sql-test.properties | 42 +++--- .../resources/sql/hsql/drop-all-tables.sql | 1 + dao/src/test/resources/sql/system-data.sql | 16 +-- 129 files changed, 1046 insertions(+), 776 deletions(-) create mode 100644 application/src/main/data/upgrade/3.0.1/schema_update_to_uuid.sql diff --git a/application/src/main/data/upgrade/2.4.3/schema_update_ttl.sql b/application/src/main/data/upgrade/2.4.3/schema_update_ttl.sql index dda3bd7b1c..5e20e1c664 100644 --- a/application/src/main/data/upgrade/2.4.3/schema_update_ttl.sql +++ b/application/src/main/data/upgrade/2.4.3/schema_update_ttl.sql @@ -22,37 +22,37 @@ BEGIN END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION delete_device_records_from_ts_kv(tenant_id varchar, customer_id varchar, ttl bigint, +CREATE OR REPLACE FUNCTION delete_device_records_from_ts_kv(tenant_id uuid, customer_id uuid, ttl bigint, OUT deleted bigint) AS $$ BEGIN EXECUTE format( - 'WITH deleted AS (DELETE FROM ts_kv WHERE entity_id IN (SELECT to_uuid(device.id) as entity_id FROM device WHERE tenant_id = %L and customer_id = %L) AND ts < %L::bigint RETURNING *) SELECT count(*) FROM deleted', + 'WITH deleted AS (DELETE FROM ts_kv WHERE entity_id IN (SELECT device.id as entity_id FROM device WHERE tenant_id = %L and customer_id = %L) AND ts < %L::bigint RETURNING *) SELECT count(*) FROM deleted', tenant_id, customer_id, ttl) into deleted; END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION delete_asset_records_from_ts_kv(tenant_id varchar, customer_id varchar, ttl bigint, +CREATE OR REPLACE FUNCTION delete_asset_records_from_ts_kv(tenant_id uuid, customer_id uuid, ttl bigint, OUT deleted bigint) AS $$ BEGIN EXECUTE format( - 'WITH deleted AS (DELETE FROM ts_kv WHERE entity_id IN (SELECT to_uuid(asset.id) as entity_id FROM asset WHERE tenant_id = %L and customer_id = %L) AND ts < %L::bigint RETURNING *) SELECT count(*) FROM deleted', + 'WITH deleted AS (DELETE FROM ts_kv WHERE entity_id IN (SELECT asset.id as entity_id FROM asset WHERE tenant_id = %L and customer_id = %L) AND ts < %L::bigint RETURNING *) SELECT count(*) FROM deleted', tenant_id, customer_id, ttl) into deleted; END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION delete_customer_records_from_ts_kv(tenant_id varchar, customer_id varchar, ttl bigint, +CREATE OR REPLACE FUNCTION delete_customer_records_from_ts_kv(tenant_id uuid, customer_id uuid, ttl bigint, OUT deleted bigint) AS $$ BEGIN EXECUTE format( - 'WITH deleted AS (DELETE FROM ts_kv WHERE entity_id IN (SELECT to_uuid(customer.id) as entity_id FROM customer WHERE tenant_id = %L and id = %L) AND ts < %L::bigint RETURNING *) SELECT count(*) FROM deleted', + 'WITH deleted AS (DELETE FROM ts_kv WHERE entity_id IN (SELECT customer.id as entity_id FROM customer WHERE tenant_id = %L and id = %L) AND ts < %L::bigint RETURNING *) SELECT count(*) FROM deleted', tenant_id, customer_id, ttl) into deleted; END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE PROCEDURE cleanup_timeseries_by_ttl(IN null_uuid varchar(31), +CREATE OR REPLACE PROCEDURE cleanup_timeseries_by_ttl(IN null_uuid uuid, IN system_ttl bigint, INOUT deleted bigint) LANGUAGE plpgsql AS $$ diff --git a/application/src/main/data/upgrade/3.0.1/schema_update_to_uuid.sql b/application/src/main/data/upgrade/3.0.1/schema_update_to_uuid.sql new file mode 100644 index 0000000000..a71c7f8da7 --- /dev/null +++ b/application/src/main/data/upgrade/3.0.1/schema_update_to_uuid.sql @@ -0,0 +1,41 @@ +-- +-- Copyright © 2016-2020 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. +-- + +CREATE OR REPLACE FUNCTION extract_ts(uuid UUID) RETURNS BIGINT AS +$$ +DECLARE + bytes bytea; +BEGIN + bytes := uuid_send(uuid); + RETURN + ( + ( + (get_byte(bytes, 0)::bigint << 24) | + (get_byte(bytes, 1)::bigint << 16) | + (get_byte(bytes, 2)::bigint << 8) | + (get_byte(bytes, 3)::bigint << 0) + ) + ( + ((get_byte(bytes, 4)::bigint << 8 | + get_byte(bytes, 5)::bigint)) << 32 + ) + ( + (((get_byte(bytes, 6)::bigint & 15) << 8 | get_byte(bytes, 7)::bigint) & 4095) << 48 + ) - 122192928000000000 + ) / 10000::double precision + ; +END +$$ LANGUAGE plpgsql + IMMUTABLE PARALLEL SAFE + RETURNS NULL ON NULL INPUT; diff --git a/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbEntityDataSubscriptionService.java b/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbEntityDataSubscriptionService.java index a076129631..a86c5c730d 100644 --- a/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbEntityDataSubscriptionService.java +++ b/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbEntityDataSubscriptionService.java @@ -15,10 +15,14 @@ */ package org.thingsboard.server.service.subscription; +import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.MoreExecutors; import lombok.extern.slf4j.Slf4j; +import org.checkerframework.checker.nullness.qual.Nullable; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Lazy; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; @@ -33,6 +37,8 @@ import org.thingsboard.server.common.data.kv.TsKvEntry; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.query.EntityData; import org.thingsboard.server.common.data.query.EntityDataQuery; +import org.thingsboard.server.common.data.query.EntityKey; +import org.thingsboard.server.common.data.query.EntityKeyType; import org.thingsboard.server.common.data.query.TsValue; import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.TbCallback; @@ -53,6 +59,7 @@ import org.thingsboard.server.service.telemetry.cmd.v2.EntityDataUpdate; import org.thingsboard.server.service.telemetry.cmd.v2.EntityHistoryCmd; import org.thingsboard.server.service.telemetry.cmd.v2.LatestValueCmd; import org.thingsboard.server.service.telemetry.cmd.v2.TimeSeriesCmd; +import org.thingsboard.server.service.telemetry.sub.SubscriptionErrorCode; import org.thingsboard.server.service.telemetry.sub.SubscriptionUpdate; import javax.annotation.PostConstruct; @@ -60,6 +67,7 @@ import javax.annotation.PreDestroy; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -67,7 +75,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.function.Function; import java.util.stream.Collectors; @Slf4j @@ -101,11 +108,16 @@ public class DefaultTbEntityDataSubscriptionService implements TbEntityDataSubsc @Autowired private TimeseriesService tsService; + @Value("${database.ts.type}") + private String databaseTsType; + private ExecutorService wsCallBackExecutor; + private boolean tsInSqlDB; @PostConstruct public void initExecutor() { wsCallBackExecutor = Executors.newSingleThreadExecutor(ThingsBoardThreadFactory.forName("ws-entity-sub-callback")); + tsInSqlDB = databaseTsType.equalsIgnoreCase("sql") || databaseTsType.equalsIgnoreCase("timescale"); } @PreDestroy @@ -156,7 +168,70 @@ public class DefaultTbEntityDataSubscriptionService implements TbEntityDataSubsc } private void handleLatestCmd(TelemetryWebSocketSessionRef session, int cmdId, EntityDataQuery query, LatestValueCmd latestCmd) { + TenantId tenantId = session.getSecurityCtx().getTenantId(); + CustomerId customerId = session.getSecurityCtx().getCustomerId(); + //Step 1. Update existing query with the contents of LatestValueCmd + latestCmd.getKeys().forEach(key -> { + if (!query.getLatestValues().contains(key)) { + query.getLatestValues().add(key); + } + }); + + //Step 2. Fetch the initial data + PageData data = entityService.findEntityDataByQuery(tenantId, customerId, query); + + //Step 3. Fetch the latest values for telemetry keys (in case they are not copied from NoSQL to SQL DB in hybrid mode. + if (!tsInSqlDB) { + List allTsKeys = latestCmd.getKeys().stream() + .filter(key -> key.getType().equals(EntityKeyType.TIME_SERIES)) + .map(EntityKey::getKey).collect(Collectors.toList()); + + Map>> missingTelemetryFurutes = new HashMap<>(); + for (EntityData entityData : data.getData()) { + Map> latestEntityData = entityData.getLatest(); + Map tsEntityData = latestEntityData.get(EntityKeyType.TIME_SERIES); + Set missingTsKeys = new LinkedHashSet<>(allTsKeys); + if (tsEntityData != null) { + missingTsKeys.removeAll(tsEntityData.keySet()); + } else { + tsEntityData = new HashMap<>(); + latestEntityData.put(EntityKeyType.TIME_SERIES, tsEntityData); + } + + ListenableFuture> missingTsData = tsService.findLatest(tenantId, entityData.getEntityId(), missingTsKeys); + missingTelemetryFurutes.put(entityData, Futures.transform(missingTsData, this::toTsValue, MoreExecutors.directExecutor())); + } + Futures.addCallback(Futures.allAsList(missingTelemetryFurutes.values()), new FutureCallback>>() { + @Override + public void onSuccess(@Nullable List> result) { + missingTelemetryFurutes.forEach((key, value) -> { + try { + key.getLatest().get(EntityKeyType.TIME_SERIES).putAll(value.get()); + } catch (InterruptedException | ExecutionException e) { + log.warn("[{}][{}] Failed to lookup latest telemetry: {}:{}", session.getSessionId(), cmdId, key.getEntityId(), allTsKeys, e); + } + }); + EntityDataUpdate update = new EntityDataUpdate(cmdId, data, null); + wsService.sendWsMsg(session.getSessionId(), update); + //TODO: create context for this (session, cmdId) that contains query, latestCmd and update. Subscribe + periodic updates. + } + + @Override + public void onFailure(Throwable t) { + log.warn("[{}][{}] Failed to process websocket command: {}:{}", session.getSessionId(), cmdId, query, latestCmd, t); + wsService.sendWsMsg(session.getSessionId(), + new EntityDataUpdate(cmdId, SubscriptionErrorCode.INTERNAL_ERROR.getCode(), "Failed to process websocket command!")); + } + }, wsCallBackExecutor); + } else { + EntityDataUpdate update = new EntityDataUpdate(cmdId, data, null); + wsService.sendWsMsg(session.getSessionId(), update); + //TODO: create context for this (session, cmdId) that contains query, latestCmd and update. Subscribe + periodic updates. + } + } + private Map toTsValue(List data) { + return data.stream().collect(Collectors.toMap(TsKvEntry::getKey, value -> new TsValue(value.getTs(), value.getValueAsString()))); } private void handleHistoryCmd(TelemetryWebSocketSessionRef session, int cmdId, EntityDataQuery query, EntityHistoryCmd historyCmd) { @@ -181,6 +256,8 @@ public class DefaultTbEntityDataSubscriptionService implements TbEntityDataSubsc keyData.forEach((k, v) -> entityData.getTimeseries().put(k, v.toArray(new TsValue[v.size()]))); } catch (InterruptedException | ExecutionException e) { log.warn("[{}][{}][{}] Failed to fetch historical data", session.getSessionId(), cmdId, entityData.getEntityId(), e); + wsService.sendWsMsg(session.getSessionId(), + new EntityDataUpdate(cmdId, SubscriptionErrorCode.INTERNAL_ERROR.getCode(), "Failed to fetch historical data!")); } }); EntityDataUpdate update = new EntityDataUpdate(cmdId, data, null); diff --git a/application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/EntityDataUpdate.java b/application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/EntityDataUpdate.java index a87f2aa6a7..3bd51405f8 100644 --- a/application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/EntityDataUpdate.java +++ b/application/src/main/java/org/thingsboard/server/service/telemetry/cmd/v2/EntityDataUpdate.java @@ -15,18 +15,30 @@ */ package org.thingsboard.server.service.telemetry.cmd.v2; +import lombok.AllArgsConstructor; import lombok.Data; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.query.EntityData; +import org.thingsboard.server.service.telemetry.sub.SubscriptionErrorCode; import java.util.List; @Data +@AllArgsConstructor public class EntityDataUpdate { private final int cmdId; private final PageData data; private final List update; - private int errorCode; - private String errorMsg; + private final int errorCode; + private final String errorMsg; + + public EntityDataUpdate(int cmdId, PageData data, List update) { + this(cmdId, data, update, SubscriptionErrorCode.NO_ERROR.getCode(), null); + } + + public EntityDataUpdate(int cmdId, int errorCode, String errorMsg) { + this(cmdId, null, null, errorCode, errorMsg); + } + } diff --git a/application/src/main/java/org/thingsboard/server/service/ttl/timeseries/PsqlTimeseriesCleanUpService.java b/application/src/main/java/org/thingsboard/server/service/ttl/timeseries/PsqlTimeseriesCleanUpService.java index cd403ee3b8..d6b08195b2 100644 --- a/application/src/main/java/org/thingsboard/server/service/ttl/timeseries/PsqlTimeseriesCleanUpService.java +++ b/application/src/main/java/org/thingsboard/server/service/ttl/timeseries/PsqlTimeseriesCleanUpService.java @@ -35,7 +35,7 @@ public class PsqlTimeseriesCleanUpService extends AbstractTimeseriesCleanUpServi protected void doCleanUp(Connection connection) { long totalPartitionsRemoved = executeQuery(connection, "call drop_partitions_by_max_ttl('" + partitionType + "'," + systemTtl + ", 0);"); log.info("Total partitions removed by TTL: [{}]", totalPartitionsRemoved); - long totalEntitiesTelemetryRemoved = executeQuery(connection, "call cleanup_timeseries_by_ttl('" + ModelConstants.NULL_UUID_STR + "'," + systemTtl + ", 0);"); + long totalEntitiesTelemetryRemoved = executeQuery(connection, "call cleanup_timeseries_by_ttl('" + ModelConstants.NULL_UUID + "'," + systemTtl + ", 0);"); log.info("Total telemetry removed stats by TTL for entities: [{}]", totalEntitiesTelemetryRemoved); } } \ No newline at end of file diff --git a/application/src/main/java/org/thingsboard/server/service/ttl/timeseries/TimescaleTimeseriesCleanUpService.java b/application/src/main/java/org/thingsboard/server/service/ttl/timeseries/TimescaleTimeseriesCleanUpService.java index f5898b9b20..7070ef5dc3 100644 --- a/application/src/main/java/org/thingsboard/server/service/ttl/timeseries/TimescaleTimeseriesCleanUpService.java +++ b/application/src/main/java/org/thingsboard/server/service/ttl/timeseries/TimescaleTimeseriesCleanUpService.java @@ -29,7 +29,7 @@ public class TimescaleTimeseriesCleanUpService extends AbstractTimeseriesCleanUp @Override protected void doCleanUp(Connection connection) { - long totalEntitiesTelemetryRemoved = executeQuery(connection, "call cleanup_timeseries_by_ttl('" + ModelConstants.NULL_UUID_STR + "'," + systemTtl + ", 0);"); + long totalEntitiesTelemetryRemoved = executeQuery(connection, "call cleanup_timeseries_by_ttl('" + ModelConstants.NULL_UUID + "'," + systemTtl + ", 0);"); log.info("Total telemetry removed stats by TTL for entities: [{}]", totalEntitiesTelemetryRemoved); } } \ No newline at end of file diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseWebsocketApiTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseWebsocketApiTest.java index 94dba3108e..41d9ed278a 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseWebsocketApiTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseWebsocketApiTest.java @@ -18,6 +18,7 @@ package org.thingsboard.server.controller; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.thingsboard.server.common.data.Device; @@ -32,6 +33,8 @@ import org.thingsboard.server.common.data.query.DeviceTypeFilter; import org.thingsboard.server.common.data.query.EntityData; import org.thingsboard.server.common.data.query.EntityDataPageLink; import org.thingsboard.server.common.data.query.EntityDataQuery; +import org.thingsboard.server.common.data.query.EntityKey; +import org.thingsboard.server.common.data.query.EntityKeyType; import org.thingsboard.server.common.data.query.TsValue; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.dao.timeseries.TimeseriesService; @@ -39,6 +42,7 @@ import org.thingsboard.server.service.telemetry.cmd.TelemetryPluginCmdsWrapper; import org.thingsboard.server.service.telemetry.cmd.v2.EntityDataCmd; import org.thingsboard.server.service.telemetry.cmd.v2.EntityDataUpdate; import org.thingsboard.server.service.telemetry.cmd.v2.EntityHistoryCmd; +import org.thingsboard.server.service.telemetry.cmd.v2.LatestValueCmd; import java.util.Arrays; import java.util.Collections; @@ -142,4 +146,58 @@ public class BaseWebsocketApiTest extends AbstractWebsocketTest { Assert.assertEquals(new TsValue(dataPoint3.getTs(), dataPoint3.getValueAsString()), tsArray[2]); } + @Test + @Ignore + public void testEntityDataLatestWsCmd() throws Exception { + Device device = new Device(); + device.setName("Device"); + device.setType("default"); + device.setLabel("testLabel" + (int) (Math.random() * 1000)); + device = doPost("/api/device", device, Device.class); + + long now = System.currentTimeMillis(); + + DeviceTypeFilter dtf = new DeviceTypeFilter(); + dtf.setDeviceNameFilter("D"); + dtf.setDeviceType("default"); + EntityDataQuery edq = new EntityDataQuery(dtf, new EntityDataPageLink(1, 0, null, null), Collections.emptyList(), Collections.emptyList(), Collections.emptyList()); + + LatestValueCmd latestCmd = new LatestValueCmd(); + latestCmd.setKeys(Collections.singletonList(new EntityKey(EntityKeyType.TIME_SERIES, "temperature"))); + EntityDataCmd cmd = new EntityDataCmd(1, edq, null, latestCmd, null); + + TelemetryPluginCmdsWrapper wrapper = new TelemetryPluginCmdsWrapper(); + wrapper.setEntityDataCmds(Collections.singletonList(cmd)); + + wsClient.send(mapper.writeValueAsString(wrapper)); + String msg = wsClient.waitForReply(); + EntityDataUpdate update = mapper.readValue(msg, EntityDataUpdate.class); + Assert.assertEquals(1, update.getCmdId()); + PageData pageData = update.getData(); + Assert.assertNotNull(pageData); + Assert.assertEquals(1, pageData.getData().size()); + Assert.assertEquals(device.getId(), pageData.getData().get(0).getEntityId()); + Assert.assertNull(pageData.getData().get(0).getLatest().get(EntityKeyType.TIME_SERIES).get("temperature")); + + TsKvEntry dataPoint1 = new BasicTsKvEntry(now - TimeUnit.MINUTES.toMillis(1), new LongDataEntry("temperature", 42L)); + tsService.save(device.getTenantId(), device.getId(), Arrays.asList(dataPoint1), 0).get(); + + cmd = new EntityDataCmd(2, edq, null, latestCmd, null); + + wrapper = new TelemetryPluginCmdsWrapper(); + wrapper.setEntityDataCmds(Collections.singletonList(cmd)); + + wsClient.send(mapper.writeValueAsString(wrapper)); + msg = wsClient.waitForReply(); + update = mapper.readValue(msg, EntityDataUpdate.class); + Assert.assertEquals(2, update.getCmdId()); + pageData = update.getData(); + Assert.assertNotNull(pageData); + Assert.assertEquals(1, pageData.getData().size()); + Assert.assertEquals(device.getId(), pageData.getData().get(0).getEntityId()); + Assert.assertNotNull(pageData.getData().get(0).getLatest().get(EntityKeyType.TIME_SERIES)); + TsValue tsValue = pageData.getData().get(0).getLatest().get(EntityKeyType.TIME_SERIES).get("temperature"); + Assert.assertEquals(new TsValue(dataPoint1.getTs(), dataPoint1.getValueAsString()), tsValue); + } + } diff --git a/application/src/test/java/org/thingsboard/server/controller/sql/WebsocketApiSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/sql/WebsocketApiSqlTest.java index 8e7751bbb6..ba2a393c69 100644 --- a/application/src/test/java/org/thingsboard/server/controller/sql/WebsocketApiSqlTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/sql/WebsocketApiSqlTest.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.controller.sql; -import org.thingsboard.server.controller.BaseEntityQueryControllerTest; import org.thingsboard.server.controller.BaseWebsocketApiTest; import org.thingsboard.server.dao.service.DaoSqlTest; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/page/TimePageLink.java b/common/data/src/main/java/org/thingsboard/server/common/data/page/TimePageLink.java index 8f88ecbc7c..96c231f525 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/page/TimePageLink.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/page/TimePageLink.java @@ -15,16 +15,8 @@ */ package org.thingsboard.server.common.data.page; -import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; -import lombok.Getter; -import lombok.ToString; - -import java.io.Serializable; -import java.util.Arrays; -import java.util.UUID; @Data public class TimePageLink extends PageLink { diff --git a/common/data/src/test/java/org/thingsboard/server/common/data/UUIDConverterTest.java b/common/data/src/test/java/org/thingsboard/server/common/data/UUIDConverterTest.java index 35666ddf1f..b2ff5f9010 100644 --- a/common/data/src/test/java/org/thingsboard/server/common/data/UUIDConverterTest.java +++ b/common/data/src/test/java/org/thingsboard/server/common/data/UUIDConverterTest.java @@ -21,8 +21,11 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.runners.MockitoJUnitRunner; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Random; import java.util.UUID; +import java.util.stream.Collectors; /** * Created by ashvayka on 14.07.17. @@ -37,6 +40,18 @@ public class UUIDConverterTest { Assert.assertEquals("1d8eebc58e0a7d796690800200c9a66", result); } + + @Test + public void basicUuid() { + System.out.println(UUIDConverter.fromString("1e746126eaaefa6a91992ebcb67fe33")); + } + + @Test + public void basicUuidConversion() { + UUID original = UUID.fromString("3dd11790-abf2-11ea-b151-83a091b9d4cc"); + Assert.assertEquals(Uuids.unixTimestamp(original), 1591886749577L); + } + @Test public void basicStringToUUIDTest() { UUID result = UUIDConverter.fromString("1d8eebc58e0a7d796690800200c9a66"); diff --git a/dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java b/dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java index 25abeb239a..b3de720be8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java +++ b/dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java @@ -27,7 +27,13 @@ import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.SortOrder; import org.thingsboard.server.dao.model.ToData; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; public abstract class DaoUtil { @@ -77,9 +83,6 @@ public abstract class DaoUtil { if (columnMap.containsKey(property)) { property = columnMap.get(property); } - if (property.equals("createdTime")) { - property = "id"; - } return Sort.by(Sort.Direction.fromString(sortOrder.getDirection().name()), property); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDao.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDao.java index 04c5a77067..a7eaa3f6d5 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmDao.java @@ -24,7 +24,6 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.dao.Dao; -import java.util.List; import java.util.UUID; /** diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java index 49926ad5c1..6ca6b986f4 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java @@ -29,12 +29,12 @@ import org.springframework.util.StringUtils; import org.thingsboard.common.util.ThingsBoardThreadFactory; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.alarm.Alarm; -import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmQuery; import org.thingsboard.server.common.data.alarm.AlarmSearchStatus; import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.alarm.AlarmStatus; +import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; diff --git a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java index 551af3df23..c308ebe322 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java @@ -28,7 +28,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; -import org.thingsboard.server.common.data.BaseData; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.HasName; import org.thingsboard.server.common.data.audit.ActionStatus; @@ -38,7 +37,6 @@ import org.thingsboard.server.common.data.id.AuditLogId; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.common.data.id.UUIDBased; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.data.page.PageData; diff --git a/dao/src/main/java/org/thingsboard/server/dao/audit/DummyAuditLogServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/audit/DummyAuditLogServiceImpl.java index 4800abb874..a3863ed012 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/audit/DummyAuditLogServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/audit/DummyAuditLogServiceImpl.java @@ -18,14 +18,12 @@ package org.thingsboard.server.dao.audit; import com.google.common.util.concurrent.ListenableFuture; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; -import org.thingsboard.server.common.data.BaseData; import org.thingsboard.server.common.data.HasName; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.audit.AuditLog; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.common.data.id.UUIDBased; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.TimePageLink; diff --git a/dao/src/main/java/org/thingsboard/server/dao/component/BaseComponentDescriptorService.java b/dao/src/main/java/org/thingsboard/server/dao/component/BaseComponentDescriptorService.java index ea1526038c..4acd766c58 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/component/BaseComponentDescriptorService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/component/BaseComponentDescriptorService.java @@ -37,7 +37,6 @@ import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.service.DataValidator; import org.thingsboard.server.dao.service.Validator; -import java.util.List; import java.util.Optional; /** diff --git a/dao/src/main/java/org/thingsboard/server/dao/component/ComponentDescriptorDao.java b/dao/src/main/java/org/thingsboard/server/dao/component/ComponentDescriptorDao.java index fdd296c0c8..7c7a56c204 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/component/ComponentDescriptorDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/component/ComponentDescriptorDao.java @@ -24,7 +24,6 @@ import org.thingsboard.server.common.data.plugin.ComponentScope; import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.dao.Dao; -import java.util.List; import java.util.Optional; /** diff --git a/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerDao.java b/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerDao.java index d074cea31f..11fa5cb7cd 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerDao.java @@ -21,7 +21,6 @@ import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.dao.Dao; -import java.util.List; import java.util.Optional; import java.util.UUID; diff --git a/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java index 661613ca73..14d591e7e8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java @@ -42,7 +42,6 @@ import org.thingsboard.server.dao.tenant.TenantDao; import org.thingsboard.server.dao.user.UserService; import java.io.IOException; -import java.util.List; import java.util.Optional; import static org.thingsboard.server.dao.service.Validator.validateId; diff --git a/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardInfoDao.java b/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardInfoDao.java index f0b5969a8e..a7a5934aef 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardInfoDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardInfoDao.java @@ -15,14 +15,11 @@ */ package org.thingsboard.server.dao.dashboard; -import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.DashboardInfo; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; -import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.dao.Dao; -import java.util.List; import java.util.UUID; /** diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java index 0084fa9213..6f7fa11462 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java @@ -29,7 +29,12 @@ import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Caching; import org.springframework.stereotype.Service; -import org.thingsboard.server.common.data.*; +import org.thingsboard.server.common.data.Customer; +import org.thingsboard.server.common.data.EntitySubtype; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.EntityView; +import org.thingsboard.server.common.data.EntityViewInfo; +import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/BaseEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/BaseEntity.java index b5bda06a47..c7f9a9b86b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/BaseEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/BaseEntity.java @@ -23,4 +23,8 @@ public interface BaseEntity extends ToData { void setUuid(UUID id); + long getCreatedTime(); + + void setCreatedTime(long createdTime); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/BaseSqlEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/BaseSqlEntity.java index 44fd70f977..3d1fd53679 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/BaseSqlEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/BaseSqlEntity.java @@ -16,7 +16,6 @@ package org.thingsboard.server.dao.model; import lombok.Data; -import org.thingsboard.server.common.data.UUIDConverter; import javax.persistence.Column; import javax.persistence.Id; @@ -31,28 +30,30 @@ import java.util.UUID; public abstract class BaseSqlEntity implements BaseEntity { @Id - @Column(name = ModelConstants.ID_PROPERTY) - protected String id; + @Column(name = ModelConstants.ID_PROPERTY, columnDefinition = "uuid") + protected UUID id; + + @Column(name = ModelConstants.CREATED_TIME_PROPERTY) + protected long createdTime; @Override public UUID getUuid() { - if (id == null) { - return null; - } - return UUIDConverter.fromString(id); + return id; } @Override public void setUuid(UUID id) { - this.id = UUIDConverter.fromTimeUUID(id); + this.id = id; } - protected UUID toUUID(String src){ - return UUIDConverter.fromString(src); + @Override + public long getCreatedTime() { + return createdTime; } - protected String toString(UUID timeUUID){ - return UUIDConverter.fromTimeUUID(timeUUID); + public void setCreatedTime(long createdTime) { + if (createdTime > 0) { + this.createdTime = createdTime; + } } - } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java index f52e450d8b..0f36382d22 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java @@ -17,7 +17,6 @@ package org.thingsboard.server.dao.model; import com.datastax.oss.driver.api.core.uuid.Uuids; import org.apache.commons.lang3.ArrayUtils; -import org.thingsboard.server.common.data.UUIDConverter; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.kv.Aggregation; @@ -29,7 +28,6 @@ public class ModelConstants { } public static final UUID NULL_UUID = Uuids.startOf(0); - public static final String NULL_UUID_STR = UUIDConverter.fromTimeUUID(NULL_UUID); public static final TenantId SYSTEM_TENANT = new TenantId(ModelConstants.NULL_UUID); // this is the difference between midnight October 15, 1582 UTC and midnight January 1, 1970 UTC as 100 nanosecond units @@ -39,6 +37,7 @@ public class ModelConstants { * Generic constants. */ public static final String ID_PROPERTY = "id"; + public static final String CREATED_TIME_PROPERTY = "created_time"; public static final String USER_ID_PROPERTY = "user_id"; public static final String TENANT_ID_PROPERTY = "tenant_id"; public static final String CUSTOMER_ID_PROPERTY = "customer_id"; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmEntity.java index 8ebaf17c9e..546863ce75 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmEntity.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.model.sql; -import com.datastax.oss.driver.api.core.uuid.Uuids; import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; import lombok.EqualsAndHashCode; @@ -24,11 +23,10 @@ import org.hibernate.annotations.TypeDef; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.UUIDConverter; import org.thingsboard.server.common.data.alarm.Alarm; -import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.alarm.AlarmStatus; +import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.BaseEntity; @@ -42,6 +40,7 @@ import javax.persistence.Enumerated; import javax.persistence.MappedSuperclass; import java.util.Arrays; import java.util.Collections; +import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.ALARM_ACK_TS_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.ALARM_CLEAR_TS_PROPERTY; @@ -63,10 +62,10 @@ import static org.thingsboard.server.dao.model.ModelConstants.ALARM_TYPE_PROPERT public abstract class AbstractAlarmEntity extends BaseSqlEntity implements BaseEntity { @Column(name = ALARM_TENANT_ID_PROPERTY) - private String tenantId; + private UUID tenantId; @Column(name = ALARM_ORIGINATOR_ID_PROPERTY) - private String originatorId; + private UUID originatorId; @Column(name = ALARM_ORIGINATOR_TYPE_PROPERTY) private EntityType originatorType; @@ -110,13 +109,14 @@ public abstract class AbstractAlarmEntity extends BaseSqlEntity public AbstractAlarmEntity(Alarm alarm) { if (alarm.getId() != null) { - this.setUuid(alarm.getId().getId()); + this.setUuid(alarm.getUuidId()); } + this.setCreatedTime(alarm.getCreatedTime()); if (alarm.getTenantId() != null) { - this.tenantId = UUIDConverter.fromTimeUUID(alarm.getTenantId().getId()); + this.tenantId = alarm.getTenantId().getId(); } this.type = alarm.getType(); - this.originatorId = UUIDConverter.fromTimeUUID(alarm.getOriginator().getId()); + this.originatorId = alarm.getOriginator().getId(); this.originatorType = alarm.getOriginator().getEntityType(); this.type = alarm.getType(); this.severity = alarm.getSeverity(); @@ -153,12 +153,12 @@ public abstract class AbstractAlarmEntity extends BaseSqlEntity } protected Alarm toAlarm() { - Alarm alarm = new Alarm(new AlarmId(UUIDConverter.fromString(id))); - alarm.setCreatedTime(Uuids.unixTimestamp(UUIDConverter.fromString(id))); + Alarm alarm = new Alarm(new AlarmId(id)); + alarm.setCreatedTime(createdTime); if (tenantId != null) { - alarm.setTenantId(new TenantId(UUIDConverter.fromString(tenantId))); + alarm.setTenantId(new TenantId(tenantId)); } - alarm.setOriginator(EntityIdFactory.getByTypeAndUuid(originatorType, UUIDConverter.fromString(originatorId))); + alarm.setOriginator(EntityIdFactory.getByTypeAndUuid(originatorType, originatorId)); alarm.setType(type); alarm.setSeverity(severity); alarm.setStatus(status); diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAssetEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAssetEntity.java index 367864db6b..3e9c636e3b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAssetEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAssetEntity.java @@ -15,13 +15,11 @@ */ package org.thingsboard.server.dao.model.sql; -import com.datastax.oss.driver.api.core.uuid.Uuids; import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; import lombok.EqualsAndHashCode; import org.hibernate.annotations.Type; import org.hibernate.annotations.TypeDef; -import org.thingsboard.server.common.data.UUIDConverter; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.CustomerId; @@ -33,6 +31,7 @@ import org.thingsboard.server.dao.util.mapping.JsonStringType; import javax.persistence.Column; import javax.persistence.MappedSuperclass; +import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.ASSET_CUSTOMER_ID_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.ASSET_LABEL_PROPERTY; @@ -48,10 +47,10 @@ import static org.thingsboard.server.dao.model.ModelConstants.SEARCH_TEXT_PROPER public abstract class AbstractAssetEntity extends BaseSqlEntity implements SearchTextEntity { @Column(name = ASSET_TENANT_ID_PROPERTY) - private String tenantId; + private UUID tenantId; @Column(name = ASSET_CUSTOMER_ID_PROPERTY) - private String customerId; + private UUID customerId; @Column(name = ASSET_NAME_PROPERTY) private String name; @@ -77,11 +76,12 @@ public abstract class AbstractAssetEntity extends BaseSqlEntity if (asset.getId() != null) { this.setUuid(asset.getId().getId()); } + this.setCreatedTime(asset.getCreatedTime()); if (asset.getTenantId() != null) { - this.tenantId = UUIDConverter.fromTimeUUID(asset.getTenantId().getId()); + this.tenantId = asset.getTenantId().getId(); } if (asset.getCustomerId() != null) { - this.customerId = UUIDConverter.fromTimeUUID(asset.getCustomerId().getId()); + this.customerId = asset.getCustomerId().getId(); } this.name = asset.getName(); this.type = asset.getType(); @@ -91,6 +91,7 @@ public abstract class AbstractAssetEntity extends BaseSqlEntity public AbstractAssetEntity(AssetEntity assetEntity) { this.setId(assetEntity.getId()); + this.setCreatedTime(assetEntity.getCreatedTime()); this.tenantId = assetEntity.getTenantId(); this.customerId = assetEntity.getCustomerId(); this.type = assetEntity.getType(); @@ -115,13 +116,13 @@ public abstract class AbstractAssetEntity extends BaseSqlEntity } protected Asset toAsset() { - Asset asset = new Asset(new AssetId(UUIDConverter.fromString(id))); - asset.setCreatedTime(Uuids.unixTimestamp(UUIDConverter.fromString(id))); + Asset asset = new Asset(new AssetId(id)); + asset.setCreatedTime(createdTime); if (tenantId != null) { - asset.setTenantId(new TenantId(UUIDConverter.fromString(tenantId))); + asset.setTenantId(new TenantId(tenantId)); } if (customerId != null) { - asset.setCustomerId(new CustomerId(UUIDConverter.fromString(customerId))); + asset.setCustomerId(new CustomerId(customerId)); } asset.setName(name); asset.setType(type); diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractDeviceEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractDeviceEntity.java index 6b4d8d8ba5..7dc7414e87 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractDeviceEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractDeviceEntity.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.model.sql; -import com.datastax.oss.driver.api.core.uuid.Uuids; import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; import lombok.EqualsAndHashCode; @@ -32,6 +31,7 @@ import org.thingsboard.server.dao.util.mapping.JsonStringType; import javax.persistence.Column; import javax.persistence.MappedSuperclass; +import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) @@ -39,11 +39,11 @@ import javax.persistence.MappedSuperclass; @MappedSuperclass public abstract class AbstractDeviceEntity extends BaseSqlEntity implements SearchTextEntity { - @Column(name = ModelConstants.DEVICE_TENANT_ID_PROPERTY) - private String tenantId; + @Column(name = ModelConstants.DEVICE_TENANT_ID_PROPERTY, columnDefinition = "uuid") + private UUID tenantId; - @Column(name = ModelConstants.DEVICE_CUSTOMER_ID_PROPERTY) - private String customerId; + @Column(name = ModelConstants.DEVICE_CUSTOMER_ID_PROPERTY, columnDefinition = "uuid") + private UUID customerId; @Column(name = ModelConstants.DEVICE_TYPE_PROPERTY) private String type; @@ -67,13 +67,14 @@ public abstract class AbstractDeviceEntity extends BaseSqlEnti public AbstractDeviceEntity(Device device) { if (device.getId() != null) { - this.setUuid(device.getId().getId()); + this.setUuid(device.getUuidId()); } + this.setCreatedTime(device.getCreatedTime()); if (device.getTenantId() != null) { - this.tenantId = toString(device.getTenantId().getId()); + this.tenantId = device.getTenantId().getId(); } if (device.getCustomerId() != null) { - this.customerId = toString(device.getCustomerId().getId()); + this.customerId = device.getCustomerId().getId(); } this.name = device.getName(); this.type = device.getType(); @@ -83,6 +84,7 @@ public abstract class AbstractDeviceEntity extends BaseSqlEnti public AbstractDeviceEntity(DeviceEntity deviceEntity) { this.setId(deviceEntity.getId()); + this.setCreatedTime(deviceEntity.getCreatedTime()); this.tenantId = deviceEntity.getTenantId(); this.customerId = deviceEntity.getCustomerId(); this.type = deviceEntity.getType(); @@ -104,12 +106,12 @@ public abstract class AbstractDeviceEntity extends BaseSqlEnti protected Device toDevice() { Device device = new Device(new DeviceId(getUuid())); - device.setCreatedTime(Uuids.unixTimestamp(getUuid())); + device.setCreatedTime(createdTime); if (tenantId != null) { - device.setTenantId(new TenantId(toUUID(tenantId))); + device.setTenantId(new TenantId(tenantId)); } if (customerId != null) { - device.setCustomerId(new CustomerId(toUUID(customerId))); + device.setCustomerId(new CustomerId(customerId)); } device.setName(name); device.setType(type); diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractEntityViewEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractEntityViewEntity.java index 649078cd47..5ecbb6758e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractEntityViewEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractEntityViewEntity.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.model.sql; -import com.datastax.oss.driver.api.core.uuid.Uuids; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Data; @@ -35,7 +34,10 @@ import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; import org.thingsboard.server.dao.util.mapping.JsonStringType; -import javax.persistence.*; +import javax.persistence.Column; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.MappedSuperclass; import java.io.IOException; import java.util.UUID; @@ -53,17 +55,17 @@ import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_TYPE_PROPER public abstract class AbstractEntityViewEntity extends BaseSqlEntity implements SearchTextEntity { @Column(name = ModelConstants.ENTITY_VIEW_ENTITY_ID_PROPERTY) - private String entityId; + private UUID entityId; @Enumerated(EnumType.STRING) @Column(name = ENTITY_TYPE_PROPERTY) private EntityType entityType; @Column(name = ModelConstants.ENTITY_VIEW_TENANT_ID_PROPERTY) - private String tenantId; + private UUID tenantId; @Column(name = ModelConstants.ENTITY_VIEW_CUSTOMER_ID_PROPERTY) - private String customerId; + private UUID customerId; @Column(name = ModelConstants.DEVICE_TYPE_PROPERTY) private String type; @@ -97,15 +99,16 @@ public abstract class AbstractEntityViewEntity extends Bas if (entityView.getId() != null) { this.setUuid(entityView.getId().getId()); } + this.setCreatedTime(entityView.getCreatedTime()); if (entityView.getEntityId() != null) { - this.entityId = toString(entityView.getEntityId().getId()); + this.entityId = entityView.getEntityId().getId(); this.entityType = entityView.getEntityId().getEntityType(); } if (entityView.getTenantId() != null) { - this.tenantId = toString(entityView.getTenantId().getId()); + this.tenantId = entityView.getTenantId().getId(); } if (entityView.getCustomerId() != null) { - this.customerId = toString(entityView.getCustomerId().getId()); + this.customerId = entityView.getCustomerId().getId(); } this.type = entityView.getType(); this.name = entityView.getName(); @@ -122,6 +125,7 @@ public abstract class AbstractEntityViewEntity extends Bas public AbstractEntityViewEntity(EntityViewEntity entityViewEntity) { this.setId(entityViewEntity.getId()); + this.setCreatedTime(entityViewEntity.getCreatedTime()); this.entityId = entityViewEntity.getEntityId(); this.entityType = entityViewEntity.getEntityType(); this.tenantId = entityViewEntity.getTenantId(); @@ -147,16 +151,16 @@ public abstract class AbstractEntityViewEntity extends Bas protected EntityView toEntityView() { EntityView entityView = new EntityView(new EntityViewId(getUuid())); - entityView.setCreatedTime(Uuids.unixTimestamp(getUuid())); + entityView.setCreatedTime(createdTime); if (entityId != null) { - entityView.setEntityId(EntityIdFactory.getByTypeAndId(entityType.name(), toUUID(entityId).toString())); + entityView.setEntityId(EntityIdFactory.getByTypeAndUuid(entityType.name(), entityId)); } if (tenantId != null) { - entityView.setTenantId(new TenantId(toUUID(tenantId))); + entityView.setTenantId(new TenantId(tenantId)); } if (customerId != null) { - entityView.setCustomerId(new CustomerId(toUUID(customerId))); + entityView.setCustomerId(new CustomerId(customerId)); } entityView.setType(type); entityView.setName(name); diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AdminSettingsEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AdminSettingsEntity.java index 909c959bf5..7bd303dfa1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AdminSettingsEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AdminSettingsEntity.java @@ -15,14 +15,12 @@ */ package org.thingsboard.server.dao.model.sql; -import com.datastax.oss.driver.api.core.uuid.Uuids; import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; import lombok.EqualsAndHashCode; import org.hibernate.annotations.Type; import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.AdminSettings; -import org.thingsboard.server.common.data.UUIDConverter; import org.thingsboard.server.common.data.id.AdminSettingsId; import org.thingsboard.server.dao.model.BaseEntity; import org.thingsboard.server.dao.model.BaseSqlEntity; @@ -58,14 +56,15 @@ public final class AdminSettingsEntity extends BaseSqlEntity impl if (adminSettings.getId() != null) { this.setUuid(adminSettings.getId().getId()); } + this.setCreatedTime(adminSettings.getCreatedTime()); this.key = adminSettings.getKey(); this.jsonValue = adminSettings.getJsonValue(); } @Override public AdminSettings toData() { - AdminSettings adminSettings = new AdminSettings(new AdminSettingsId(UUIDConverter.fromString(id))); - adminSettings.setCreatedTime(Uuids.unixTimestamp(UUIDConverter.fromString(id))); + AdminSettings adminSettings = new AdminSettings(new AdminSettingsId(id)); + adminSettings.setCreatedTime(createdTime); adminSettings.setKey(key); adminSettings.setJsonValue(jsonValue); return adminSettings; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AttributeKvCompositeKey.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AttributeKvCompositeKey.java index 31a667de71..a13685ea3c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AttributeKvCompositeKey.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AttributeKvCompositeKey.java @@ -25,6 +25,7 @@ import javax.persistence.Embeddable; import javax.persistence.EnumType; import javax.persistence.Enumerated; import java.io.Serializable; +import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.ATTRIBUTE_KEY_COLUMN; import static org.thingsboard.server.dao.model.ModelConstants.ATTRIBUTE_TYPE_COLUMN; @@ -39,8 +40,8 @@ public class AttributeKvCompositeKey implements Serializable { @Enumerated(EnumType.STRING) @Column(name = ENTITY_TYPE_COLUMN) private EntityType entityType; - @Column(name = ENTITY_ID_COLUMN) - private String entityId; + @Column(name = ENTITY_ID_COLUMN, columnDefinition = "uuid") + private UUID entityId; @Column(name = ATTRIBUTE_TYPE_COLUMN) private String attributeType; @Column(name = ATTRIBUTE_KEY_COLUMN) diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AuditLogEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AuditLogEntity.java index 520fd8b41d..99c526c611 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AuditLogEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AuditLogEntity.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.model.sql; -import com.datastax.oss.driver.api.core.uuid.Uuids; import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; import lombok.EqualsAndHashCode; @@ -40,6 +39,7 @@ import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.Table; +import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.AUDIT_LOG_ACTION_DATA_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.AUDIT_LOG_ACTION_FAILURE_DETAILS_PROPERTY; @@ -61,23 +61,23 @@ import static org.thingsboard.server.dao.model.ModelConstants.AUDIT_LOG_USER_NAM public class AuditLogEntity extends BaseSqlEntity implements BaseEntity { @Column(name = AUDIT_LOG_TENANT_ID_PROPERTY) - private String tenantId; + private UUID tenantId; @Column(name = AUDIT_LOG_CUSTOMER_ID_PROPERTY) - private String customerId; + private UUID customerId; @Enumerated(EnumType.STRING) @Column(name = AUDIT_LOG_ENTITY_TYPE_PROPERTY) private EntityType entityType; @Column(name = AUDIT_LOG_ENTITY_ID_PROPERTY) - private String entityId; + private UUID entityId; @Column(name = AUDIT_LOG_ENTITY_NAME_PROPERTY) private String entityName; @Column(name = AUDIT_LOG_USER_ID_PROPERTY) - private String userId; + private UUID userId; @Column(name = AUDIT_LOG_USER_NAME_PROPERTY) private String userName; @@ -105,18 +105,19 @@ public class AuditLogEntity extends BaseSqlEntity implements BaseEntit if (auditLog.getId() != null) { this.setUuid(auditLog.getId().getId()); } + this.setCreatedTime(auditLog.getCreatedTime()); if (auditLog.getTenantId() != null) { - this.tenantId = toString(auditLog.getTenantId().getId()); + this.tenantId = auditLog.getTenantId().getId(); } if (auditLog.getCustomerId() != null) { - this.customerId = toString(auditLog.getCustomerId().getId()); + this.customerId = auditLog.getCustomerId().getId(); } if (auditLog.getEntityId() != null) { - this.entityId = toString(auditLog.getEntityId().getId()); + this.entityId = auditLog.getEntityId().getId(); this.entityType = auditLog.getEntityId().getEntityType(); } if (auditLog.getUserId() != null) { - this.userId = toString(auditLog.getUserId().getId()); + this.userId = auditLog.getUserId().getId(); } this.entityName = auditLog.getEntityName(); this.userName = auditLog.getUserName(); @@ -129,18 +130,18 @@ public class AuditLogEntity extends BaseSqlEntity implements BaseEntit @Override public AuditLog toData() { AuditLog auditLog = new AuditLog(new AuditLogId(this.getUuid())); - auditLog.setCreatedTime(Uuids.unixTimestamp(this.getUuid())); + auditLog.setCreatedTime(createdTime); if (tenantId != null) { - auditLog.setTenantId(new TenantId(toUUID(tenantId))); + auditLog.setTenantId(new TenantId(tenantId)); } if (customerId != null) { - auditLog.setCustomerId(new CustomerId(toUUID(customerId))); + auditLog.setCustomerId(new CustomerId(customerId)); } if (entityId != null) { - auditLog.setEntityId(EntityIdFactory.getByTypeAndId(entityType.name(), toUUID(entityId).toString())); + auditLog.setEntityId(EntityIdFactory.getByTypeAndUuid(entityType.name(), entityId)); } if (userId != null) { - auditLog.setUserId(new UserId(toUUID(userId))); + auditLog.setUserId(new UserId(userId)); } auditLog.setEntityName(this.entityName); auditLog.setUserName(this.userName); diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/ComponentDescriptorEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/ComponentDescriptorEntity.java index d5b287fe9b..381610a82c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/ComponentDescriptorEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/ComponentDescriptorEntity.java @@ -73,6 +73,7 @@ public class ComponentDescriptorEntity extends BaseSqlEntity implements SearchTextEntity { @Column(name = ModelConstants.CUSTOMER_TENANT_ID_PROPERTY) - private String tenantId; + private UUID tenantId; @Column(name = ModelConstants.CUSTOMER_TITLE_PROPERTY) private String title; @@ -86,7 +85,8 @@ public final class CustomerEntity extends BaseSqlEntity implements Sea if (customer.getId() != null) { this.setUuid(customer.getId().getId()); } - this.tenantId = UUIDConverter.fromTimeUUID(customer.getTenantId().getId()); + this.setCreatedTime(customer.getCreatedTime()); + this.tenantId = customer.getTenantId().getId(); this.title = customer.getTitle(); this.country = customer.getCountry(); this.state = customer.getState(); @@ -112,8 +112,8 @@ public final class CustomerEntity extends BaseSqlEntity implements Sea @Override public Customer toData() { Customer customer = new Customer(new CustomerId(this.getUuid())); - customer.setCreatedTime(Uuids.unixTimestamp(this.getUuid())); - customer.setTenantId(new TenantId(UUIDConverter.fromString(tenantId))); + customer.setCreatedTime(createdTime); + customer.setTenantId(new TenantId(tenantId)); customer.setTitle(title); customer.setCountry(country); customer.setState(state); @@ -126,4 +126,5 @@ public final class CustomerEntity extends BaseSqlEntity implements Sea customer.setAdditionalInfo(additionalInfo); return customer; } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardEntity.java index 622f03cbad..41eb90a5d1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardEntity.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.model.sql; -import com.datastax.oss.driver.api.core.uuid.Uuids; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonNode; @@ -40,6 +39,7 @@ import javax.persistence.Entity; import javax.persistence.Table; import java.io.IOException; import java.util.HashSet; +import java.util.UUID; @Data @Slf4j @@ -54,7 +54,7 @@ public final class DashboardEntity extends BaseSqlEntity implements S objectMapper.getTypeFactory().constructCollectionType(HashSet.class, ShortCustomerInfo.class); @Column(name = ModelConstants.DASHBOARD_TENANT_ID_PROPERTY) - private String tenantId; + private UUID tenantId; @Column(name = ModelConstants.DASHBOARD_TITLE_PROPERTY) private String title; @@ -77,8 +77,9 @@ public final class DashboardEntity extends BaseSqlEntity implements S if (dashboard.getId() != null) { this.setUuid(dashboard.getId().getId()); } + this.setCreatedTime(dashboard.getCreatedTime()); if (dashboard.getTenantId() != null) { - this.tenantId = toString(dashboard.getTenantId().getId()); + this.tenantId = dashboard.getTenantId().getId(); } this.title = dashboard.getTitle(); if (dashboard.getAssignedCustomers() != null) { @@ -104,9 +105,9 @@ public final class DashboardEntity extends BaseSqlEntity implements S @Override public Dashboard toData() { Dashboard dashboard = new Dashboard(new DashboardId(this.getUuid())); - dashboard.setCreatedTime(Uuids.unixTimestamp(this.getUuid())); + dashboard.setCreatedTime(this.getCreatedTime()); if (tenantId != null) { - dashboard.setTenantId(new TenantId(toUUID(tenantId))); + dashboard.setTenantId(new TenantId(tenantId)); } dashboard.setTitle(title); if (!StringUtils.isEmpty(assignedCustomers)) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardInfoEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardInfoEntity.java index 7e5aabd328..d0e7721142 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardInfoEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardInfoEntity.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.model.sql; -import com.datastax.oss.driver.api.core.uuid.Uuids; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; @@ -36,6 +35,7 @@ import javax.persistence.Entity; import javax.persistence.Table; import java.io.IOException; import java.util.HashSet; +import java.util.UUID; @Data @Slf4j @@ -49,7 +49,7 @@ public class DashboardInfoEntity extends BaseSqlEntity implements objectMapper.getTypeFactory().constructCollectionType(HashSet.class, ShortCustomerInfo.class); @Column(name = ModelConstants.DASHBOARD_TENANT_ID_PROPERTY) - private String tenantId; + private UUID tenantId; @Column(name = ModelConstants.DASHBOARD_TITLE_PROPERTY) private String title; @@ -68,8 +68,9 @@ public class DashboardInfoEntity extends BaseSqlEntity implements if (dashboardInfo.getId() != null) { this.setUuid(dashboardInfo.getId().getId()); } + this.setCreatedTime(dashboardInfo.getCreatedTime()); if (dashboardInfo.getTenantId() != null) { - this.tenantId = toString(dashboardInfo.getTenantId().getId()); + this.tenantId = dashboardInfo.getTenantId().getId(); } this.title = dashboardInfo.getTitle(); if (dashboardInfo.getAssignedCustomers() != null) { @@ -98,9 +99,9 @@ public class DashboardInfoEntity extends BaseSqlEntity implements @Override public DashboardInfo toData() { DashboardInfo dashboardInfo = new DashboardInfo(new DashboardId(this.getUuid())); - dashboardInfo.setCreatedTime(Uuids.unixTimestamp(this.getUuid())); + dashboardInfo.setCreatedTime(createdTime); if (tenantId != null) { - dashboardInfo.setTenantId(new TenantId(toUUID(tenantId))); + dashboardInfo.setTenantId(new TenantId(tenantId)); } dashboardInfo.setTitle(title); if (!StringUtils.isEmpty(assignedCustomers)) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceCredentialsEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceCredentialsEntity.java index c9fbce0f8b..ab438add62 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceCredentialsEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceCredentialsEntity.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.model.sql; -import com.datastax.oss.driver.api.core.uuid.Uuids; import lombok.Data; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.id.DeviceCredentialsId; @@ -31,6 +30,7 @@ import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.Table; +import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) @@ -39,7 +39,7 @@ import javax.persistence.Table; public final class DeviceCredentialsEntity extends BaseSqlEntity implements BaseEntity { @Column(name = ModelConstants.DEVICE_CREDENTIALS_DEVICE_ID_PROPERTY) - private String deviceId; + private UUID deviceId; @Enumerated(EnumType.STRING) @Column(name = ModelConstants.DEVICE_CREDENTIALS_CREDENTIALS_TYPE_PROPERTY) @@ -59,8 +59,9 @@ public final class DeviceCredentialsEntity extends BaseSqlEntity implements BaseEntity { +public class EventEntity extends BaseSqlEntity implements BaseEntity { @Column(name = EVENT_TENANT_ID_PROPERTY) - private String tenantId; + private UUID tenantId; @Enumerated(EnumType.STRING) @Column(name = EVENT_ENTITY_TYPE_PROPERTY) private EntityType entityType; @Column(name = EVENT_ENTITY_ID_PROPERTY) - private String entityId; + private UUID entityId; @Column(name = EVENT_TYPE_PROPERTY) private String eventType; @@ -87,12 +85,13 @@ public class EventEntity extends BaseSqlEntity implements BaseEntity implements BaseEntity { @Id - @Column(name = RELATION_FROM_ID_PROPERTY) - private String fromId; + @Column(name = RELATION_FROM_ID_PROPERTY, columnDefinition = "uuid") + private UUID fromId; @Id @Column(name = RELATION_FROM_TYPE_PROPERTY) private String fromType; @Id - @Column(name = RELATION_TO_ID_PROPERTY) - private String toId; + @Column(name = RELATION_TO_ID_PROPERTY, columnDefinition = "uuid") + private UUID toId; @Id @Column(name = RELATION_TO_TYPE_PROPERTY) @@ -82,11 +82,11 @@ public final class RelationEntity implements ToData { public RelationEntity(EntityRelation relation) { if (relation.getTo() != null) { - this.toId = UUIDConverter.fromTimeUUID(relation.getTo().getId()); + this.toId = relation.getTo().getId(); this.toType = relation.getTo().getEntityType().name(); } if (relation.getFrom() != null) { - this.fromId = UUIDConverter.fromTimeUUID(relation.getFrom().getId()); + this.fromId = relation.getFrom().getId(); this.fromType = relation.getFrom().getEntityType().name(); } this.relationType = relation.getType(); @@ -98,10 +98,10 @@ public final class RelationEntity implements ToData { public EntityRelation toData() { EntityRelation relation = new EntityRelation(); if (toId != null && toType != null) { - relation.setTo(EntityIdFactory.getByTypeAndUuid(toType, UUIDConverter.fromString(toId))); + relation.setTo(EntityIdFactory.getByTypeAndUuid(toType, toId)); } if (fromId != null && fromType != null) { - relation.setFrom(EntityIdFactory.getByTypeAndUuid(fromType, UUIDConverter.fromString(fromId))); + relation.setFrom(EntityIdFactory.getByTypeAndUuid(fromType, fromId)); } relation.setType(relationType); relation.setTypeGroup(RelationTypeGroup.valueOf(relationTypeGroup)); diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleChainEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleChainEntity.java index cc3016c9c7..bad6017314 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleChainEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleChainEntity.java @@ -15,13 +15,11 @@ */ package org.thingsboard.server.dao.model.sql; -import com.datastax.oss.driver.api.core.uuid.Uuids; import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; import lombok.EqualsAndHashCode; import org.hibernate.annotations.Type; import org.hibernate.annotations.TypeDef; -import org.thingsboard.server.common.data.UUIDConverter; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleNodeId; import org.thingsboard.server.common.data.id.TenantId; @@ -35,6 +33,7 @@ import org.thingsboard.server.dao.util.mapping.JsonStringType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; +import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) @@ -44,7 +43,7 @@ import javax.persistence.Table; public class RuleChainEntity extends BaseSqlEntity implements SearchTextEntity { @Column(name = ModelConstants.RULE_CHAIN_TENANT_ID_PROPERTY) - private String tenantId; + private UUID tenantId; @Column(name = ModelConstants.RULE_CHAIN_NAME_PROPERTY) private String name; @@ -53,7 +52,7 @@ public class RuleChainEntity extends BaseSqlEntity implements SearchT private String searchText; @Column(name = ModelConstants.RULE_CHAIN_FIRST_RULE_NODE_ID_PROPERTY) - private String firstRuleNodeId; + private UUID firstRuleNodeId; @Column(name = ModelConstants.RULE_CHAIN_ROOT_PROPERTY) private boolean root; @@ -76,11 +75,12 @@ public class RuleChainEntity extends BaseSqlEntity implements SearchT if (ruleChain.getId() != null) { this.setUuid(ruleChain.getUuidId()); } - this.tenantId = toString(DaoUtil.getId(ruleChain.getTenantId())); + this.setCreatedTime(ruleChain.getCreatedTime()); + this.tenantId = DaoUtil.getId(ruleChain.getTenantId()); this.name = ruleChain.getName(); this.searchText = ruleChain.getName(); if (ruleChain.getFirstRuleNodeId() != null) { - this.firstRuleNodeId = UUIDConverter.fromTimeUUID(ruleChain.getFirstRuleNodeId().getId()); + this.firstRuleNodeId = ruleChain.getFirstRuleNodeId().getId(); } this.root = ruleChain.isRoot(); this.debugMode = ruleChain.isDebugMode(); @@ -101,11 +101,11 @@ public class RuleChainEntity extends BaseSqlEntity implements SearchT @Override public RuleChain toData() { RuleChain ruleChain = new RuleChain(new RuleChainId(this.getUuid())); - ruleChain.setCreatedTime(Uuids.unixTimestamp(this.getUuid())); - ruleChain.setTenantId(new TenantId(toUUID(tenantId))); + ruleChain.setCreatedTime(createdTime); + ruleChain.setTenantId(new TenantId(tenantId)); ruleChain.setName(name); if (firstRuleNodeId != null) { - ruleChain.setFirstRuleNodeId(new RuleNodeId(UUIDConverter.fromString(firstRuleNodeId))); + ruleChain.setFirstRuleNodeId(new RuleNodeId(firstRuleNodeId)); } ruleChain.setRoot(root); ruleChain.setDebugMode(debugMode); diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleNodeEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleNodeEntity.java index a12861f475..c9a72c405d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleNodeEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleNodeEntity.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.model.sql; -import com.datastax.oss.driver.api.core.uuid.Uuids; import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; import lombok.EqualsAndHashCode; @@ -33,6 +32,7 @@ import org.thingsboard.server.dao.util.mapping.JsonStringType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; +import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) @@ -42,7 +42,7 @@ import javax.persistence.Table; public class RuleNodeEntity extends BaseSqlEntity implements SearchTextEntity { @Column(name = ModelConstants.RULE_NODE_CHAIN_ID_PROPERTY) - private String ruleChainId; + private UUID ruleChainId; @Column(name = ModelConstants.RULE_NODE_TYPE_PROPERTY) private String type; @@ -71,8 +71,9 @@ public class RuleNodeEntity extends BaseSqlEntity implements SearchTex if (ruleNode.getId() != null) { this.setUuid(ruleNode.getUuidId()); } + this.setCreatedTime(ruleNode.getCreatedTime()); if (ruleNode.getRuleChainId() != null) { - this.ruleChainId = toString(DaoUtil.getId(ruleNode.getRuleChainId())); + this.ruleChainId = DaoUtil.getId(ruleNode.getRuleChainId()); } this.type = ruleNode.getType(); this.name = ruleNode.getName(); @@ -95,9 +96,9 @@ public class RuleNodeEntity extends BaseSqlEntity implements SearchTex @Override public RuleNode toData() { RuleNode ruleNode = new RuleNode(new RuleNodeId(this.getUuid())); - ruleNode.setCreatedTime(Uuids.unixTimestamp(this.getUuid())); + ruleNode.setCreatedTime(createdTime); if (ruleChainId != null) { - ruleNode.setRuleChainId(new RuleChainId(toUUID(ruleChainId))); + ruleNode.setRuleChainId(new RuleChainId(ruleChainId)); } ruleNode.setType(type); ruleNode.setName(name); diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java index 51de38f68b..7cb48081bb 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.model.sql; -import com.datastax.oss.driver.api.core.uuid.Uuids; import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; import lombok.EqualsAndHashCode; @@ -90,6 +89,7 @@ public final class TenantEntity extends BaseSqlEntity implements SearchT if (tenant.getId() != null) { this.setUuid(tenant.getId().getId()); } + this.setCreatedTime(tenant.getCreatedTime()); this.title = tenant.getTitle(); this.region = tenant.getRegion(); this.country = tenant.getCountry(); @@ -122,7 +122,7 @@ public final class TenantEntity extends BaseSqlEntity implements SearchT @Override public Tenant toData() { Tenant tenant = new Tenant(new TenantId(this.getUuid())); - tenant.setCreatedTime(Uuids.unixTimestamp(this.getUuid())); + tenant.setCreatedTime(createdTime); tenant.setTitle(title); tenant.setRegion(region); tenant.setCountry(country); diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserCredentialsEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserCredentialsEntity.java index ed6cd3f8a7..3e30471391 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserCredentialsEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserCredentialsEntity.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.model.sql; -import com.datastax.oss.driver.api.core.uuid.Uuids; import lombok.Data; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.id.UserCredentialsId; @@ -28,6 +27,7 @@ import org.thingsboard.server.dao.model.ModelConstants; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; +import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) @@ -36,7 +36,7 @@ import javax.persistence.Table; public final class UserCredentialsEntity extends BaseSqlEntity implements BaseEntity { @Column(name = ModelConstants.USER_CREDENTIALS_USER_ID_PROPERTY, unique = true) - private String userId; + private UUID userId; @Column(name = ModelConstants.USER_CREDENTIALS_ENABLED_PROPERTY) private boolean enabled; @@ -58,8 +58,9 @@ public final class UserCredentialsEntity extends BaseSqlEntity if (userCredentials.getId() != null) { this.setUuid(userCredentials.getId().getId()); } + this.setCreatedTime(userCredentials.getCreatedTime()); if (userCredentials.getUserId() != null) { - this.userId = toString(userCredentials.getUserId().getId()); + this.userId = userCredentials.getUserId().getId(); } this.enabled = userCredentials.isEnabled(); this.password = userCredentials.getPassword(); @@ -70,9 +71,9 @@ public final class UserCredentialsEntity extends BaseSqlEntity @Override public UserCredentials toData() { UserCredentials userCredentials = new UserCredentials(new UserCredentialsId(this.getUuid())); - userCredentials.setCreatedTime(Uuids.unixTimestamp(this.getUuid())); + userCredentials.setCreatedTime(createdTime); if (userId != null) { - userCredentials.setUserId(new UserId(toUUID(userId))); + userCredentials.setUserId(new UserId(userId)); } userCredentials.setEnabled(enabled); userCredentials.setPassword(password); diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserEntity.java index 1637c334ba..5715588278 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserEntity.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.model.sql; -import com.datastax.oss.driver.api.core.uuid.Uuids; import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; import lombok.EqualsAndHashCode; @@ -36,9 +35,7 @@ import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.Table; - -import static org.thingsboard.server.common.data.UUIDConverter.fromString; -import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID; +import java.util.UUID; /** * Created by Valerii Sosliuk on 4/21/2017. @@ -51,10 +48,10 @@ import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID; public class UserEntity extends BaseSqlEntity implements SearchTextEntity { @Column(name = ModelConstants.USER_TENANT_ID_PROPERTY) - private String tenantId; + private UUID tenantId; @Column(name = ModelConstants.USER_CUSTOMER_ID_PROPERTY) - private String customerId; + private UUID customerId; @Enumerated(EnumType.STRING) @Column(name = ModelConstants.USER_AUTHORITY_PROPERTY) @@ -83,12 +80,13 @@ public class UserEntity extends BaseSqlEntity implements SearchTextEntity< if (user.getId() != null) { this.setUuid(user.getId().getId()); } + this.setCreatedTime(user.getCreatedTime()); this.authority = user.getAuthority(); if (user.getTenantId() != null) { - this.tenantId = fromTimeUUID(user.getTenantId().getId()); + this.tenantId = user.getTenantId().getId(); } if (user.getCustomerId() != null) { - this.customerId = fromTimeUUID(user.getCustomerId().getId()); + this.customerId = user.getCustomerId().getId(); } this.email = user.getEmail(); this.firstName = user.getFirstName(); @@ -109,13 +107,13 @@ public class UserEntity extends BaseSqlEntity implements SearchTextEntity< @Override public User toData() { User user = new User(new UserId(this.getUuid())); - user.setCreatedTime(Uuids.unixTimestamp(this.getUuid())); + user.setCreatedTime(createdTime); user.setAuthority(authority); if (tenantId != null) { - user.setTenantId(new TenantId(fromString(tenantId))); + user.setTenantId(new TenantId(tenantId)); } if (customerId != null) { - user.setCustomerId(new CustomerId(fromString(customerId))); + user.setCustomerId(new CustomerId(customerId)); } user.setEmail(email); user.setFirstName(firstName); diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java index 01854a4e11..d0b875968e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.model.sql; -import com.datastax.oss.driver.api.core.uuid.Uuids; import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; import lombok.EqualsAndHashCode; @@ -32,6 +31,7 @@ import org.thingsboard.server.dao.util.mapping.JsonStringType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; +import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) @@ -41,7 +41,7 @@ import javax.persistence.Table; public final class WidgetTypeEntity extends BaseSqlEntity implements BaseEntity { @Column(name = ModelConstants.WIDGET_TYPE_TENANT_ID_PROPERTY) - private String tenantId; + private UUID tenantId; @Column(name = ModelConstants.WIDGET_TYPE_BUNDLE_ALIAS_PROPERTY) private String bundleAlias; @@ -64,8 +64,9 @@ public final class WidgetTypeEntity extends BaseSqlEntity implement if (widgetType.getId() != null) { this.setUuid(widgetType.getId().getId()); } + this.setCreatedTime(widgetType.getCreatedTime()); if (widgetType.getTenantId() != null) { - this.tenantId = toString(widgetType.getTenantId().getId()); + this.tenantId = widgetType.getTenantId().getId(); } this.bundleAlias = widgetType.getBundleAlias(); this.alias = widgetType.getAlias(); @@ -76,9 +77,9 @@ public final class WidgetTypeEntity extends BaseSqlEntity implement @Override public WidgetType toData() { WidgetType widgetType = new WidgetType(new WidgetTypeId(this.getUuid())); - widgetType.setCreatedTime(Uuids.unixTimestamp(this.getUuid())); + widgetType.setCreatedTime(createdTime); if (tenantId != null) { - widgetType.setTenantId(new TenantId(toUUID(tenantId))); + widgetType.setTenantId(new TenantId(tenantId)); } widgetType.setBundleAlias(bundleAlias); widgetType.setAlias(alias); diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetsBundleEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetsBundleEntity.java index 4fee25d82f..e2d2855b2a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetsBundleEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetsBundleEntity.java @@ -16,10 +16,8 @@ package org.thingsboard.server.dao.model.sql; -import com.datastax.oss.driver.api.core.uuid.Uuids; import lombok.Data; import lombok.EqualsAndHashCode; -import org.thingsboard.server.common.data.UUIDConverter; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.WidgetsBundleId; import org.thingsboard.server.common.data.widget.WidgetsBundle; @@ -30,6 +28,7 @@ import org.thingsboard.server.dao.model.SearchTextEntity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; +import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) @@ -38,7 +37,7 @@ import javax.persistence.Table; public final class WidgetsBundleEntity extends BaseSqlEntity implements SearchTextEntity { @Column(name = ModelConstants.WIDGETS_BUNDLE_TENANT_ID_PROPERTY) - private String tenantId; + private UUID tenantId; @Column(name = ModelConstants.WIDGETS_BUNDLE_ALIAS_PROPERTY) private String alias; @@ -57,8 +56,9 @@ public final class WidgetsBundleEntity extends BaseSqlEntity impl if (widgetsBundle.getId() != null) { this.setUuid(widgetsBundle.getId().getId()); } + this.setCreatedTime(widgetsBundle.getCreatedTime()); if (widgetsBundle.getTenantId() != null) { - this.tenantId = UUIDConverter.fromTimeUUID(widgetsBundle.getTenantId().getId()); + this.tenantId = widgetsBundle.getTenantId().getId(); } this.alias = widgetsBundle.getAlias(); this.title = widgetsBundle.getTitle(); @@ -76,10 +76,10 @@ public final class WidgetsBundleEntity extends BaseSqlEntity impl @Override public WidgetsBundle toData() { - WidgetsBundle widgetsBundle = new WidgetsBundle(new WidgetsBundleId(UUIDConverter.fromString(id))); - widgetsBundle.setCreatedTime(Uuids.unixTimestamp(UUIDConverter.fromString(id))); + WidgetsBundle widgetsBundle = new WidgetsBundle(new WidgetsBundleId(id)); + widgetsBundle.setCreatedTime(createdTime); if (tenantId != null) { - widgetsBundle.setTenantId(new TenantId(UUIDConverter.fromString(tenantId))); + widgetsBundle.setTenantId(new TenantId(tenantId)); } widgetsBundle.setAlias(alias); widgetsBundle.setTitle(title); diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestCompositeKey.java b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestCompositeKey.java index 69c9c26a9b..77f2fa29d6 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestCompositeKey.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestCompositeKey.java @@ -18,7 +18,6 @@ package org.thingsboard.server.dao.model.sqlts.latest; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import org.thingsboard.server.common.data.EntityType; import javax.persistence.Transient; import java.io.Serializable; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestEntity.java index e7de4afa67..7894e0e4b0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestEntity.java @@ -19,11 +19,9 @@ import lombok.Data; import org.thingsboard.server.dao.model.sql.AbstractTsKvEntity; import org.thingsboard.server.dao.sqlts.latest.SearchTsKvLatestRepository; -import javax.persistence.Column; import javax.persistence.ColumnResult; import javax.persistence.ConstructorResult; import javax.persistence.Entity; -import javax.persistence.Id; import javax.persistence.IdClass; import javax.persistence.NamedNativeQueries; import javax.persistence.NamedNativeQuery; @@ -32,8 +30,6 @@ import javax.persistence.SqlResultSetMappings; import javax.persistence.Table; import java.util.UUID; -import static org.thingsboard.server.dao.model.ModelConstants.KEY_COLUMN; - @Data @Entity @Table(name = "ts_kv_latest") diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/ts/TsKvEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/ts/TsKvEntity.java index 3a14d0c957..ab1df90b39 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/ts/TsKvEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/ts/TsKvEntity.java @@ -18,14 +18,10 @@ package org.thingsboard.server.dao.model.sqlts.ts; import lombok.Data; import org.thingsboard.server.dao.model.sql.AbstractTsKvEntity; -import javax.persistence.Column; import javax.persistence.Entity; -import javax.persistence.Id; import javax.persistence.IdClass; import javax.persistence.Table; -import static org.thingsboard.server.dao.model.ModelConstants.KEY_COLUMN; - @Data @Entity @Table(name = "ts_kv") diff --git a/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraAbstractAsyncDao.java b/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraAbstractAsyncDao.java index 639ddf0877..76ed6d2cc6 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraAbstractAsyncDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraAbstractAsyncDao.java @@ -15,10 +15,7 @@ */ package org.thingsboard.server.dao.nosql; -import com.datastax.oss.driver.api.core.cql.AsyncResultSet; -import com.datastax.oss.driver.api.core.cql.Row; import com.google.common.base.Function; -import com.google.common.collect.Lists; import com.google.common.util.concurrent.AsyncFunction; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; @@ -27,11 +24,8 @@ import org.thingsboard.common.util.ThingsBoardThreadFactory; import javax.annotation.Nullable; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; -import java.util.ArrayList; -import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.stream.Collectors; /** * Created by ashvayka on 21.02.17. diff --git a/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraBufferedRateExecutor.java b/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraBufferedRateExecutor.java index 5832acac53..f37fd5f8ec 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraBufferedRateExecutor.java +++ b/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraBufferedRateExecutor.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.nosql; -import com.datastax.oss.driver.api.core.cql.AsyncResultSet; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; import lombok.extern.slf4j.Slf4j; diff --git a/dao/src/main/java/org/thingsboard/server/dao/relation/RelationDao.java b/dao/src/main/java/org/thingsboard/server/dao/relation/RelationDao.java index 4337f04354..e67590d677 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/relation/RelationDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/relation/RelationDao.java @@ -59,6 +59,4 @@ public interface RelationDao { ListenableFuture deleteOutboundRelationsAsync(TenantId tenantId, EntityId entity); - ListenableFuture> findRelations(TenantId tenantId, EntityId from, String relationType, RelationTypeGroup typeGroup, EntityType toType, TimePageLink pageLink); - } diff --git a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java index 09746fdd74..f3ac74596f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java @@ -48,7 +48,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; -import java.util.stream.Collectors; /** * Created by igor on 3/12/18. diff --git a/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainDao.java b/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainDao.java index 07b9e59670..c3214425fe 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainDao.java @@ -20,7 +20,6 @@ import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.dao.Dao; -import java.util.List; import java.util.UUID; /** diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/PaginatedRemover.java b/dao/src/main/java/org/thingsboard/server/dao/service/PaginatedRemover.java index e78f5a58aa..1d4eedf1f6 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/PaginatedRemover.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/PaginatedRemover.java @@ -20,9 +20,6 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; -import java.util.List; -import java.util.UUID; - public abstract class PaginatedRemover> { private static final int DEFAULT_LIMIT = 100; diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/TimePaginatedRemover.java b/dao/src/main/java/org/thingsboard/server/dao/service/TimePaginatedRemover.java index e2ea5be619..43716fda25 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/TimePaginatedRemover.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/TimePaginatedRemover.java @@ -20,9 +20,6 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.TimePageLink; -import java.util.List; -import java.util.UUID; - public abstract class TimePaginatedRemover> { private static final int DEFAULT_LIMIT = 100; diff --git a/dao/src/main/java/org/thingsboard/server/dao/settings/AdminSettingsServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/settings/AdminSettingsServiceImpl.java index 6c7495cc19..3d53064ff1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/settings/AdminSettingsServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/settings/AdminSettingsServiceImpl.java @@ -20,7 +20,6 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.AdminSettings; -import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.id.AdminSettingsId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.exception.DataValidationException; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java index aef060cd89..a7608f9861 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java @@ -30,8 +30,6 @@ import java.util.List; import java.util.Optional; import java.util.UUID; -import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID; - /** * @author Valerii Sosliuk */ @@ -42,9 +40,10 @@ public abstract class JpaAbstractDao, D> protected abstract Class getEntityClass(); - protected abstract CrudRepository getCrudRepository(); + protected abstract CrudRepository getCrudRepository(); - protected void setSearchText(E entity) {} + protected void setSearchText(E entity) { + } @Override @Transactional @@ -59,7 +58,9 @@ public abstract class JpaAbstractDao, D> setSearchText(entity); log.debug("Saving entity {}", entity); if (entity.getUuid() == null) { - entity.setUuid(Uuids.timeBased()); + UUID uuid = Uuids.timeBased(); + entity.setUuid(uuid); + entity.setCreatedTime(Uuids.unixTimestamp(uuid)); } entity = getCrudRepository().save(entity); return DaoUtil.getData(entity); @@ -68,23 +69,22 @@ public abstract class JpaAbstractDao, D> @Override public D findById(TenantId tenantId, UUID key) { log.debug("Get entity by key {}", key); - Optional entity = getCrudRepository().findById(fromTimeUUID(key)); + Optional entity = getCrudRepository().findById(key); return DaoUtil.getData(entity); } @Override public ListenableFuture findByIdAsync(TenantId tenantId, UUID key) { log.debug("Get entity by key async {}", key); - return service.submit(() -> DaoUtil.getData(getCrudRepository().findById(fromTimeUUID(key)))); + return service.submit(() -> DaoUtil.getData(getCrudRepository().findById(key))); } @Override @Transactional public boolean removeById(TenantId tenantId, UUID id) { - String key = fromTimeUUID(id); - getCrudRepository().deleteById(key); - log.debug("Remove request: {}", key); - return !getCrudRepository().existsById(key); + getCrudRepository().deleteById(id); + log.debug("Remove request: {}", id); + return !getCrudRepository().existsById(id); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractSearchTimeDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractSearchTimeDao.java index 5aabc88f75..485a069674 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractSearchTimeDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractSearchTimeDao.java @@ -34,6 +34,7 @@ import java.util.UUID; */ public abstract class JpaAbstractSearchTimeDao, D> extends JpaAbstractDao { + //TODO 3.1: refactoring to createdTime column public static Specification getTimeSearchPageSpec(TimePageLink pageLink, String idColumn) { return new Specification() { @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java index 78230332b4..f393cac046 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java @@ -20,21 +20,21 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; -import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.dao.model.sql.AlarmEntity; import org.thingsboard.server.dao.model.sql.AlarmInfoEntity; import org.thingsboard.server.dao.util.SqlDao; import java.util.List; +import java.util.UUID; /** * Created by Valerii Sosliuk on 5/21/2017. */ @SqlDao -public interface AlarmRepository extends CrudRepository { +public interface AlarmRepository extends CrudRepository { @Query("SELECT a FROM AlarmEntity a WHERE a.originatorId = :originatorId AND a.type = :alarmType ORDER BY a.startTs DESC") - List findLatestByOriginatorAndType(@Param("originatorId") String originatorId, + List findLatestByOriginatorAndType(@Param("originatorId") UUID originatorId, @Param("alarmType") String alarmType, Pageable pageable); @@ -46,9 +46,8 @@ public interface AlarmRepository extends CrudRepository { "AND re.relationType = :relationType " + "AND re.fromId = :affectedEntityId " + "AND re.fromType = :affectedEntityType " + - "AND (:startId IS NULL OR a.id >= :startId) " + - "AND (:endId IS NULL OR a.id <= :endId) " + - "AND (:idOffset IS NULL OR a.id < :idOffset) " + + "AND (:startTime IS NULL OR a.createdTime >= :startTime) " + + "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + "AND (LOWER(a.type) LIKE LOWER(CONCAT(:searchText, '%'))" + "OR LOWER(a.severity) LIKE LOWER(CONCAT(:searchText, '%'))" + "OR LOWER(a.status) LIKE LOWER(CONCAT(:searchText, '%')))", @@ -60,19 +59,17 @@ public interface AlarmRepository extends CrudRepository { "AND re.relationType = :relationType " + "AND re.fromId = :affectedEntityId " + "AND re.fromType = :affectedEntityType " + - "AND (:startId IS NULL OR a.id >= :startId) " + - "AND (:endId IS NULL OR a.id <= :endId) " + - "AND (:idOffset IS NULL OR a.id < :idOffset) " + + "AND (:startTime IS NULL OR a.createdTime >= :startTime) " + + "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + "AND (LOWER(a.type) LIKE LOWER(CONCAT(:searchText, '%'))" + "OR LOWER(a.severity) LIKE LOWER(CONCAT(:searchText, '%'))" + "OR LOWER(a.status) LIKE LOWER(CONCAT(:searchText, '%')))") - Page findAlarms(@Param("tenantId") String tenantId, - @Param("affectedEntityId") String affectedEntityId, + Page findAlarms(@Param("tenantId") UUID tenantId, + @Param("affectedEntityId") UUID affectedEntityId, @Param("affectedEntityType") String affectedEntityType, @Param("relationType") String relationType, - @Param("startId") String startId, - @Param("endId") String endId, - @Param("idOffset") String idOffset, + @Param("startTime") Long startTime, + @Param("endTime") Long endTime, @Param("searchText") String searchText, Pageable pageable); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java index 832e59345f..72f07b2085 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java @@ -41,7 +41,6 @@ import java.util.List; import java.util.Objects; import java.util.UUID; -import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID; import static org.thingsboard.server.dao.DaoUtil.endTimeToId; import static org.thingsboard.server.dao.DaoUtil.startTimeToId; @@ -65,7 +64,7 @@ public class JpaAlarmDao extends JpaAbstractDao implements A } @Override - protected CrudRepository getCrudRepository() { + protected CrudRepository getCrudRepository() { return alarmRepository; } @@ -78,7 +77,7 @@ public class JpaAlarmDao extends JpaAbstractDao implements A public ListenableFuture findLatestByOriginatorAndType(TenantId tenantId, EntityId originator, String type) { return service.submit(() -> { List latest = alarmRepository.findLatestByOriginatorAndType( - UUIDConverter.fromTimeUUID(originator.getId()), + originator.getId(), type, PageRequest.of(0, 1)); return latest.isEmpty() ? null : DaoUtil.getData(latest.get(0)); @@ -106,13 +105,12 @@ public class JpaAlarmDao extends JpaAbstractDao implements A return DaoUtil.toPageData( alarmRepository.findAlarms( - fromTimeUUID(tenantId.getId()), - fromTimeUUID(affectedEntity.getId()), + tenantId.getId(), + affectedEntity.getId(), affectedEntity.getEntityType().name(), relationType, - startTimeToId(query.getPageLink().getStartTime()), - endTimeToId(query.getPageLink().getEndTime()), - query.getIdOffset() != null ? UUIDConverter.fromTimeUUID(query.getIdOffset()) : null, + query.getPageLink().getStartTime(), + query.getPageLink().getEndTime(), Objects.toString(query.getPageLink().getTextSearch(), ""), DaoUtil.toPageable(query.getPageLink()) ) diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetRepository.java index bfbe407a97..6d87d75366 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetRepository.java @@ -18,7 +18,6 @@ package org.thingsboard.server.dao.sql.asset; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.query.Param; import org.thingsboard.server.dao.model.sql.AssetEntity; @@ -26,22 +25,23 @@ import org.thingsboard.server.dao.model.sql.AssetInfoEntity; import org.thingsboard.server.dao.util.SqlDao; import java.util.List; +import java.util.UUID; /** * Created by Valerii Sosliuk on 5/21/2017. */ @SqlDao -public interface AssetRepository extends PagingAndSortingRepository { +public interface AssetRepository extends PagingAndSortingRepository { @Query("SELECT new org.thingsboard.server.dao.model.sql.AssetInfoEntity(a, c.title, c.additionalInfo) " + "FROM AssetEntity a " + "LEFT JOIN CustomerEntity c on c.id = a.customerId " + "WHERE a.id = :assetId") - AssetInfoEntity findAssetInfoById(@Param("assetId") String assetId); + AssetInfoEntity findAssetInfoById(@Param("assetId") UUID assetId); @Query("SELECT a FROM AssetEntity a WHERE a.tenantId = :tenantId " + "AND LOWER(a.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))") - Page findByTenantId(@Param("tenantId") String tenantId, + Page findByTenantId(@Param("tenantId") UUID tenantId, @Param("textSearch") String textSearch, Pageable pageable); @@ -50,15 +50,15 @@ public interface AssetRepository extends PagingAndSortingRepository findAssetInfosByTenantId(@Param("tenantId") String tenantId, + Page findAssetInfosByTenantId(@Param("tenantId") UUID tenantId, @Param("textSearch") String textSearch, Pageable pageable); @Query("SELECT a FROM AssetEntity a WHERE a.tenantId = :tenantId " + "AND a.customerId = :customerId " + "AND LOWER(a.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))") - Page findByTenantIdAndCustomerId(@Param("tenantId") String tenantId, - @Param("customerId") String customerId, + Page findByTenantIdAndCustomerId(@Param("tenantId") UUID tenantId, + @Param("customerId") UUID customerId, @Param("textSearch") String textSearch, Pageable pageable); @@ -68,21 +68,21 @@ public interface AssetRepository extends PagingAndSortingRepository findAssetInfosByTenantIdAndCustomerId(@Param("tenantId") String tenantId, - @Param("customerId") String customerId, + Page findAssetInfosByTenantIdAndCustomerId(@Param("tenantId") UUID tenantId, + @Param("customerId") UUID customerId, @Param("searchText") String searchText, Pageable pageable); - List findByTenantIdAndIdIn(String tenantId, List assetIds); + List findByTenantIdAndIdIn(UUID tenantId, List assetIds); - List findByTenantIdAndCustomerIdAndIdIn(String tenantId, String customerId, List assetIds); + List findByTenantIdAndCustomerIdAndIdIn(UUID tenantId, UUID customerId, List assetIds); - AssetEntity findByTenantIdAndName(String tenantId, String name); + AssetEntity findByTenantIdAndName(UUID tenantId, String name); @Query("SELECT a FROM AssetEntity a WHERE a.tenantId = :tenantId " + "AND a.type = :type " + "AND LOWER(a.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))") - Page findByTenantIdAndType(@Param("tenantId") String tenantId, + Page findByTenantIdAndType(@Param("tenantId") UUID tenantId, @Param("type") String type, @Param("textSearch") String textSearch, Pageable pageable); @@ -93,7 +93,7 @@ public interface AssetRepository extends PagingAndSortingRepository findAssetInfosByTenantIdAndType(@Param("tenantId") String tenantId, + Page findAssetInfosByTenantIdAndType(@Param("tenantId") UUID tenantId, @Param("type") String type, @Param("textSearch") String textSearch, Pageable pageable); @@ -102,8 +102,8 @@ public interface AssetRepository extends PagingAndSortingRepository findByTenantIdAndCustomerIdAndType(@Param("tenantId") String tenantId, - @Param("customerId") String customerId, + Page findByTenantIdAndCustomerIdAndType(@Param("tenantId") UUID tenantId, + @Param("customerId") UUID customerId, @Param("type") String type, @Param("textSearch") String textSearch, Pageable pageable); @@ -115,13 +115,13 @@ public interface AssetRepository extends PagingAndSortingRepository findAssetInfosByTenantIdAndCustomerIdAndType(@Param("tenantId") String tenantId, - @Param("customerId") String customerId, + Page findAssetInfosByTenantIdAndCustomerIdAndType(@Param("tenantId") UUID tenantId, + @Param("customerId") UUID customerId, @Param("type") String type, @Param("textSearch") String textSearch, Pageable pageable); @Query("SELECT DISTINCT a.type FROM AssetEntity a WHERE a.tenantId = :tenantId") - List findTenantAssetTypes(@Param("tenantId") String tenantId); + List findTenantAssetTypes(@Param("tenantId") UUID tenantId); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetDao.java index b7dede224a..e836aa1ef2 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetDao.java @@ -17,7 +17,6 @@ package org.thingsboard.server.dao.sql.asset; import com.google.common.util.concurrent.ListenableFuture; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.PageRequest; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.EntitySubtype; @@ -41,9 +40,6 @@ import java.util.Objects; import java.util.Optional; import java.util.UUID; -import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID; -import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUIDs; - /** * Created by Valerii Sosliuk on 5/19/2017. */ @@ -60,20 +56,20 @@ public class JpaAssetDao extends JpaAbstractSearchTextDao im } @Override - protected CrudRepository getCrudRepository() { + protected CrudRepository getCrudRepository() { return assetRepository; } @Override public AssetInfo findAssetInfoById(TenantId tenantId, UUID assetId) { - return DaoUtil.getData(assetRepository.findAssetInfoById(fromTimeUUID(assetId))); + return DaoUtil.getData(assetRepository.findAssetInfoById(assetId)); } @Override public PageData findAssetsByTenantId(UUID tenantId, PageLink pageLink) { return DaoUtil.toPageData(assetRepository .findByTenantId( - fromTimeUUID(tenantId), + tenantId, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink))); } @@ -82,7 +78,7 @@ public class JpaAssetDao extends JpaAbstractSearchTextDao im public PageData findAssetInfosByTenantId(UUID tenantId, PageLink pageLink) { return DaoUtil.toPageData( assetRepository.findAssetInfosByTenantId( - fromTimeUUID(tenantId), + tenantId, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink, AssetInfoEntity.assetInfoColumnMap))); } @@ -90,15 +86,15 @@ public class JpaAssetDao extends JpaAbstractSearchTextDao im @Override public ListenableFuture> findAssetsByTenantIdAndIdsAsync(UUID tenantId, List assetIds) { return service.submit(() -> - DaoUtil.convertDataList(assetRepository.findByTenantIdAndIdIn(fromTimeUUID(tenantId), fromTimeUUIDs(assetIds)))); + DaoUtil.convertDataList(assetRepository.findByTenantIdAndIdIn(tenantId, assetIds))); } @Override public PageData findAssetsByTenantIdAndCustomerId(UUID tenantId, UUID customerId, PageLink pageLink) { return DaoUtil.toPageData(assetRepository .findByTenantIdAndCustomerId( - fromTimeUUID(tenantId), - fromTimeUUID(customerId), + tenantId, + customerId, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink))); } @@ -107,8 +103,8 @@ public class JpaAssetDao extends JpaAbstractSearchTextDao im public PageData findAssetInfosByTenantIdAndCustomerId(UUID tenantId, UUID customerId, PageLink pageLink) { return DaoUtil.toPageData( assetRepository.findAssetInfosByTenantIdAndCustomerId( - fromTimeUUID(tenantId), - fromTimeUUID(customerId), + tenantId, + customerId, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink, AssetInfoEntity.assetInfoColumnMap))); } @@ -116,12 +112,12 @@ public class JpaAssetDao extends JpaAbstractSearchTextDao im @Override public ListenableFuture> findAssetsByTenantIdAndCustomerIdAndIdsAsync(UUID tenantId, UUID customerId, List assetIds) { return service.submit(() -> - DaoUtil.convertDataList(assetRepository.findByTenantIdAndCustomerIdAndIdIn(fromTimeUUID(tenantId), fromTimeUUID(customerId), fromTimeUUIDs(assetIds)))); + DaoUtil.convertDataList(assetRepository.findByTenantIdAndCustomerIdAndIdIn(tenantId, customerId, assetIds))); } @Override public Optional findAssetsByTenantIdAndName(UUID tenantId, String name) { - Asset asset = DaoUtil.getData(assetRepository.findByTenantIdAndName(fromTimeUUID(tenantId), name)); + Asset asset = DaoUtil.getData(assetRepository.findByTenantIdAndName(tenantId, name)); return Optional.ofNullable(asset); } @@ -129,7 +125,7 @@ public class JpaAssetDao extends JpaAbstractSearchTextDao im public PageData findAssetsByTenantIdAndType(UUID tenantId, String type, PageLink pageLink) { return DaoUtil.toPageData(assetRepository .findByTenantIdAndType( - fromTimeUUID(tenantId), + tenantId, type, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink))); @@ -139,7 +135,7 @@ public class JpaAssetDao extends JpaAbstractSearchTextDao im public PageData findAssetInfosByTenantIdAndType(UUID tenantId, String type, PageLink pageLink) { return DaoUtil.toPageData( assetRepository.findAssetInfosByTenantIdAndType( - fromTimeUUID(tenantId), + tenantId, type, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink, AssetInfoEntity.assetInfoColumnMap))); @@ -149,8 +145,8 @@ public class JpaAssetDao extends JpaAbstractSearchTextDao im public PageData findAssetsByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, PageLink pageLink) { return DaoUtil.toPageData(assetRepository .findByTenantIdAndCustomerIdAndType( - fromTimeUUID(tenantId), - fromTimeUUID(customerId), + tenantId, + customerId, type, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink))); @@ -160,8 +156,8 @@ public class JpaAssetDao extends JpaAbstractSearchTextDao im public PageData findAssetInfosByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, PageLink pageLink) { return DaoUtil.toPageData( assetRepository.findAssetInfosByTenantIdAndCustomerIdAndType( - fromTimeUUID(tenantId), - fromTimeUUID(customerId), + tenantId, + customerId, type, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink, AssetInfoEntity.assetInfoColumnMap))); @@ -169,7 +165,7 @@ public class JpaAssetDao extends JpaAbstractSearchTextDao im @Override public ListenableFuture> findTenantAssetTypesAsync(UUID tenantId) { - return service.submit(() -> convertTenantAssetTypesToDto(tenantId, assetRepository.findTenantAssetTypes(fromTimeUUID(tenantId)))); + return service.submit(() -> convertTenantAssetTypesToDto(tenantId, assetRepository.findTenantAssetTypes(tenantId))); } private List convertTenantAssetTypesToDto(UUID tenantId, List types) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/AttributeKvInsertRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/AttributeKvInsertRepository.java index f667587c73..70500d38a0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/AttributeKvInsertRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/AttributeKvInsertRepository.java @@ -29,6 +29,7 @@ import org.thingsboard.server.dao.util.SqlDao; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.sql.SQLType; import java.sql.Types; import java.util.ArrayList; import java.util.List; @@ -92,7 +93,7 @@ public abstract class AttributeKvInsertRepository { ps.setLong(6, kvEntity.getLastUpdateTs()); ps.setString(7, kvEntity.getId().getEntityType().name()); - ps.setString(8, kvEntity.getId().getEntityId()); + ps.setObject(8, kvEntity.getId().getEntityId()); ps.setString(9, kvEntity.getId().getAttributeType()); ps.setString(10, kvEntity.getId().getAttributeKey()); } @@ -122,7 +123,7 @@ public abstract class AttributeKvInsertRepository { public void setValues(PreparedStatement ps, int i) throws SQLException { AttributeKvEntity kvEntity = insertEntities.get(i); ps.setString(1, kvEntity.getId().getEntityType().name()); - ps.setString(2, kvEntity.getId().getEntityId()); + ps.setObject(2, kvEntity.getId().getEntityId()); ps.setString(3, kvEntity.getId().getAttributeType()); ps.setString(4, kvEntity.getId().getAttributeKey()); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/AttributeKvRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/AttributeKvRepository.java index 0bd667b790..1114fe5e66 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/AttributeKvRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/AttributeKvRepository.java @@ -26,6 +26,7 @@ import org.thingsboard.server.dao.model.sql.AttributeKvEntity; import org.thingsboard.server.dao.util.SqlDao; import java.util.List; +import java.util.UUID; @SqlDao public interface AttributeKvRepository extends CrudRepository { @@ -34,7 +35,7 @@ public interface AttributeKvRepository extends CrudRepository findAllByEntityTypeAndEntityIdAndAttributeType(@Param("entityType") EntityType entityType, - @Param("entityId") String entityId, + @Param("entityId") UUID entityId, @Param("attributeType") String attributeType); @Transactional @@ -44,7 +45,7 @@ public interface AttributeKvRepository extends CrudRepository { jdbcTemplate.update(INSERT_OR_UPDATE, ps -> { ps.setString(1, entity.getId().getEntityType().name()); - ps.setString(2, entity.getId().getEntityId()); + ps.setObject(2, entity.getId().getEntityId()); ps.setString(3, entity.getId().getAttributeType()); ps.setString(4, entity.getId().getAttributeKey()); ps.setString(5, entity.getStrValue()); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/JpaAttributeDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/JpaAttributeDao.java index c14e2dd7d0..bf6ac47424 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/JpaAttributeDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/JpaAttributeDao.java @@ -22,7 +22,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import org.thingsboard.server.common.data.UUIDConverter; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.kv.AttributeKvEntry; @@ -43,8 +42,6 @@ import java.util.List; import java.util.Optional; import java.util.stream.Collectors; -import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID; - @Component @Slf4j @SqlDao @@ -115,14 +112,14 @@ public class JpaAttributeDao extends JpaAbstractDaoListeningExecutorService impl DaoUtil.convertDataList(Lists.newArrayList( attributeKvRepository.findAllByEntityTypeAndEntityIdAndAttributeType( entityId.getEntityType(), - UUIDConverter.fromTimeUUID(entityId.getId()), + entityId.getId(), attributeType)))); } @Override public ListenableFuture save(TenantId tenantId, EntityId entityId, String attributeType, AttributeKvEntry attribute) { AttributeKvEntity entity = new AttributeKvEntity(); - entity.setId(new AttributeKvCompositeKey(entityId.getEntityType(), fromTimeUUID(entityId.getId()), attributeType, attribute.getKey())); + entity.setId(new AttributeKvCompositeKey(entityId.getEntityType(), entityId.getId(), attributeType, attribute.getKey())); entity.setLastUpdateTs(attribute.getLastUpdateTs()); entity.setStrValue(attribute.getStrValue().orElse(null)); entity.setDoubleValue(attribute.getDoubleValue().orElse(null)); @@ -140,7 +137,7 @@ public class JpaAttributeDao extends JpaAbstractDaoListeningExecutorService impl public ListenableFuture> removeAll(TenantId tenantId, EntityId entityId, String attributeType, List keys) { return service.submit(() -> { keys.forEach(key -> - attributeKvRepository.delete(entityId.getEntityType(), UUIDConverter.fromTimeUUID(entityId.getId()), attributeType, key) + attributeKvRepository.delete(entityId.getEntityType(), entityId.getId(), attributeType, key) ); return null; }); @@ -149,7 +146,7 @@ public class JpaAttributeDao extends JpaAbstractDaoListeningExecutorService impl private AttributeKvCompositeKey getAttributeKvCompositeKey(EntityId entityId, String attributeType, String attributeKey) { return new AttributeKvCompositeKey( entityId.getEntityType(), - fromTimeUUID(entityId.getId()), + entityId.getId(), attributeType, attributeKey); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/audit/AuditLogRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/audit/AuditLogRepository.java index 19a88ae831..379b198caa 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/audit/AuditLogRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/audit/AuditLogRepository.java @@ -25,8 +25,9 @@ import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.dao.model.sql.AuditLogEntity; import java.util.List; +import java.util.UUID; -public interface AuditLogRepository extends PagingAndSortingRepository { +public interface AuditLogRepository extends PagingAndSortingRepository { @Query("SELECT a FROM AuditLogEntity a WHERE " + "a.tenantId = :tenantId " + @@ -40,7 +41,7 @@ public interface AuditLogRepository extends PagingAndSortingRepository findByTenantId( - @Param("tenantId") String tenantId, + @Param("tenantId") UUID tenantId, @Param("textSearch") String textSearch, @Param("startId") String startId, @Param("endId") String endId, @@ -58,9 +59,9 @@ public interface AuditLogRepository extends PagingAndSortingRepository findAuditLogsByTenantIdAndEntityId(@Param("tenantId") String tenantId, + Page findAuditLogsByTenantIdAndEntityId(@Param("tenantId") UUID tenantId, @Param("entityType") EntityType entityType, - @Param("entityId") String entityId, + @Param("entityId") UUID entityId, @Param("textSearch") String textSearch, @Param("startId") String startId, @Param("endId") String endId, @@ -79,8 +80,8 @@ public interface AuditLogRepository extends PagingAndSortingRepository findAuditLogsByTenantIdAndCustomerId(@Param("tenantId") String tenantId, - @Param("customerId") String customerId, + Page findAuditLogsByTenantIdAndCustomerId(@Param("tenantId") UUID tenantId, + @Param("customerId") UUID customerId, @Param("textSearch") String textSearch, @Param("startId") String startId, @Param("endId") String endId, @@ -98,8 +99,8 @@ public interface AuditLogRepository extends PagingAndSortingRepository findAuditLogsByTenantIdAndUserId(@Param("tenantId") String tenantId, - @Param("userId") String userId, + Page findAuditLogsByTenantIdAndUserId(@Param("tenantId") UUID tenantId, + @Param("userId") UUID userId, @Param("textSearch") String textSearch, @Param("startId") String startId, @Param("endId") String endId, diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/audit/JpaAuditLogDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/audit/JpaAuditLogDao.java index 38abc36940..f4d9cf283a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/audit/JpaAuditLogDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/audit/JpaAuditLogDao.java @@ -36,7 +36,6 @@ import java.util.List; import java.util.Objects; import java.util.UUID; -import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID; import static org.thingsboard.server.dao.DaoUtil.endTimeToId; import static org.thingsboard.server.dao.DaoUtil.startTimeToId; @@ -53,7 +52,7 @@ public class JpaAuditLogDao extends JpaAbstractDao imp } @Override - protected CrudRepository getCrudRepository() { + protected CrudRepository getCrudRepository() { return auditLogRepository; } @@ -70,9 +69,9 @@ public class JpaAuditLogDao extends JpaAbstractDao imp return DaoUtil.toPageData( auditLogRepository .findAuditLogsByTenantIdAndEntityId( - fromTimeUUID(tenantId), + tenantId, entityId.getEntityType(), - fromTimeUUID(entityId.getId()), + entityId.getId(), Objects.toString(pageLink.getTextSearch(), ""), startTimeToId(pageLink.getStartTime()), endTimeToId(pageLink.getEndTime()), @@ -85,8 +84,8 @@ public class JpaAuditLogDao extends JpaAbstractDao imp return DaoUtil.toPageData( auditLogRepository .findAuditLogsByTenantIdAndCustomerId( - fromTimeUUID(tenantId), - fromTimeUUID(customerId.getId()), + tenantId, + customerId.getId(), Objects.toString(pageLink.getTextSearch(), ""), startTimeToId(pageLink.getStartTime()), endTimeToId(pageLink.getEndTime()), @@ -99,8 +98,8 @@ public class JpaAuditLogDao extends JpaAbstractDao imp return DaoUtil.toPageData( auditLogRepository .findAuditLogsByTenantIdAndUserId( - fromTimeUUID(tenantId), - fromTimeUUID(userId.getId()), + tenantId, + userId.getId(), Objects.toString(pageLink.getTextSearch(), ""), startTimeToId(pageLink.getStartTime()), endTimeToId(pageLink.getEndTime()), @@ -112,7 +111,7 @@ public class JpaAuditLogDao extends JpaAbstractDao imp public PageData findAuditLogsByTenantId(UUID tenantId, List actionTypes, TimePageLink pageLink) { return DaoUtil.toPageData( auditLogRepository.findByTenantId( - fromTimeUUID(tenantId), + tenantId, Objects.toString(pageLink.getTextSearch(), ""), startTimeToId(pageLink.getStartTime()), endTimeToId(pageLink.getEndTime()), diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/component/AbstractComponentDescriptorInsertRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/component/AbstractComponentDescriptorInsertRepository.java index d8272e3a57..5ea12ca85c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/component/AbstractComponentDescriptorInsertRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/component/AbstractComponentDescriptorInsertRepository.java @@ -23,7 +23,6 @@ import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionDefinition; -import org.thingsboard.server.common.data.UUIDConverter; import org.thingsboard.server.dao.model.sql.ComponentDescriptorEntity; import javax.persistence.EntityManager; @@ -69,7 +68,8 @@ public abstract class AbstractComponentDescriptorInsertRepository implements Com protected Query getQuery(ComponentDescriptorEntity entity, String query) { return entityManager.createNativeQuery(query, ComponentDescriptorEntity.class) - .setParameter("id", UUIDConverter.fromTimeUUID(entity.getUuid())) + .setParameter("id", entity.getUuid()) + .setParameter("created_time", entity.getCreatedTime()) .setParameter("actions", entity.getActions()) .setParameter("clazz", entity.getClazz()) .setParameter("configuration_descriptor", entity.getConfigurationDescriptor().toString()) diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/component/ComponentDescriptorRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/component/ComponentDescriptorRepository.java index 74554ab98b..83c2ad1e23 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/component/ComponentDescriptorRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/component/ComponentDescriptorRepository.java @@ -18,7 +18,6 @@ package org.thingsboard.server.dao.sql.component; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.query.Param; import org.thingsboard.server.common.data.plugin.ComponentScope; @@ -26,13 +25,13 @@ import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.dao.model.sql.ComponentDescriptorEntity; import org.thingsboard.server.dao.util.SqlDao; -import java.util.List; +import java.util.UUID; /** * Created by Valerii Sosliuk on 5/6/2017. */ @SqlDao -public interface ComponentDescriptorRepository extends PagingAndSortingRepository { +public interface ComponentDescriptorRepository extends PagingAndSortingRepository { ComponentDescriptorEntity findByClazz(String clazz); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/component/HsqlComponentDescriptorInsertRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/component/HsqlComponentDescriptorInsertRepository.java index c33dd4f5e1..2608a6eed1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/component/HsqlComponentDescriptorInsertRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/component/HsqlComponentDescriptorInsertRepository.java @@ -16,7 +16,6 @@ package org.thingsboard.server.dao.sql.component; import org.springframework.stereotype.Repository; -import org.thingsboard.server.common.data.UUIDConverter; import org.thingsboard.server.dao.model.sql.ComponentDescriptorEntity; import org.thingsboard.server.dao.util.HsqlDao; import org.thingsboard.server.dao.util.SqlDao; @@ -40,11 +39,11 @@ public class HsqlComponentDescriptorInsertRepository extends AbstractComponentDe @Override protected ComponentDescriptorEntity doProcessSaveOrUpdate(ComponentDescriptorEntity entity, String query) { getQuery(entity, query).executeUpdate(); - return entityManager.find(ComponentDescriptorEntity.class, UUIDConverter.fromTimeUUID(entity.getUuid())); + return entityManager.find(ComponentDescriptorEntity.class, entity.getUuid()); } private static String getInsertString(String conflictStatement) { - return "MERGE INTO component_descriptor USING (VALUES :id, :actions, :clazz, :configuration_descriptor, :name, :scope, :search_text, :type) I (id, actions, clazz, configuration_descriptor, name, scope, search_text, type) ON " + conflictStatement + " WHEN MATCHED THEN UPDATE SET component_descriptor.id = I.id, component_descriptor.actions = I.actions, component_descriptor.clazz = I.clazz, component_descriptor.configuration_descriptor = I.configuration_descriptor, component_descriptor.name = I.name, component_descriptor.scope = I.scope, component_descriptor.search_text = I.search_text, component_descriptor.type = I.type" + - " WHEN NOT MATCHED THEN INSERT (id, actions, clazz, configuration_descriptor, name, scope, search_text, type) VALUES (I.id, I.actions, I.clazz, I.configuration_descriptor, I.name, I.scope, I.search_text, I.type)"; + return "MERGE INTO component_descriptor USING (VALUES :id, :created_time, :actions, :clazz, :configuration_descriptor, :name, :scope, :search_text, :type) I (id, craeted_time, actions, clazz, configuration_descriptor, name, scope, search_text, type) ON " + conflictStatement + " WHEN MATCHED THEN UPDATE SET component_descriptor.id = I.id, component_descriptor.actions = I.actions, component_descriptor.clazz = I.clazz, component_descriptor.configuration_descriptor = I.configuration_descriptor, component_descriptor.name = I.name, component_descriptor.scope = I.scope, component_descriptor.search_text = I.search_text, component_descriptor.type = I.type" + + " WHEN NOT MATCHED THEN INSERT (id, created_time, actions, clazz, configuration_descriptor, name, scope, search_text, type) VALUES (I.id, I.created_time, I.actions, I.clazz, I.configuration_descriptor, I.name, I.scope, I.search_text, I.type)"; } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/component/JpaBaseComponentDescriptorDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/component/JpaBaseComponentDescriptorDao.java index 35c63ed816..dae2ab4341 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/component/JpaBaseComponentDescriptorDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/component/JpaBaseComponentDescriptorDao.java @@ -5,7 +5,7 @@ * 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 + * 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, @@ -20,7 +20,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; -import org.thingsboard.server.common.data.UUIDConverter; import org.thingsboard.server.common.data.id.ComponentDescriptorId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; @@ -36,6 +35,7 @@ import org.thingsboard.server.dao.util.SqlDao; import java.util.Objects; import java.util.Optional; +import java.util.UUID; /** * Created by Valerii Sosliuk on 5/6/2017. @@ -57,16 +57,18 @@ public class JpaBaseComponentDescriptorDao extends JpaAbstractSearchTextDao getCrudRepository() { + protected CrudRepository getCrudRepository() { return componentDescriptorRepository; } @Override public Optional saveIfNotExist(TenantId tenantId, ComponentDescriptor component) { if (component.getId() == null) { - component.setId(new ComponentDescriptorId(Uuids.timeBased())); + UUID uuid = Uuids.timeBased(); + component.setId(new ComponentDescriptorId(uuid)); + component.setCreatedTime(Uuids.unixTimestamp(uuid)); } - if (!componentDescriptorRepository.existsById(UUIDConverter.fromTimeUUID(component.getId().getId()))) { + if (!componentDescriptorRepository.existsById(component.getId().getId())) { ComponentDescriptorEntity componentDescriptorEntity = new ComponentDescriptorEntity(component); ComponentDescriptorEntity savedEntity = componentDescriptorInsertRepository.saveOrUpdate(componentDescriptorEntity); return Optional.of(savedEntity.toData()); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/component/PsqlComponentDescriptorInsertRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/component/PsqlComponentDescriptorInsertRepository.java index 97808398f7..dfe63ec69a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/component/PsqlComponentDescriptorInsertRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/component/PsqlComponentDescriptorInsertRepository.java @@ -19,7 +19,6 @@ import org.springframework.stereotype.Repository; import org.thingsboard.server.dao.model.sql.ComponentDescriptorEntity; import org.thingsboard.server.dao.util.PsqlDao; import org.thingsboard.server.dao.util.SqlDao; -import org.thingsboard.server.dao.util.SqlTsDao; @SqlDao @PsqlDao @@ -49,10 +48,10 @@ public class PsqlComponentDescriptorInsertRepository extends AbstractComponentDe } private static String getInsertOrUpdateStatement(String conflictKeyStatement, String updateKeyStatement) { - return "INSERT INTO component_descriptor (id, actions, clazz, configuration_descriptor, name, scope, search_text, type) VALUES (:id, :actions, :clazz, :configuration_descriptor, :name, :scope, :search_text, :type) ON CONFLICT " + conflictKeyStatement + " DO UPDATE SET " + updateKeyStatement + " returning *"; + return "INSERT INTO component_descriptor (id, created_time, actions, clazz, configuration_descriptor, name, scope, search_text, type) VALUES (:id, :created_time, :actions, :clazz, :configuration_descriptor, :name, :scope, :search_text, :type) ON CONFLICT " + conflictKeyStatement + " DO UPDATE SET " + updateKeyStatement + " returning *"; } private static String getUpdateStatement(String id) { - return "actions = :actions, " + id + ", configuration_descriptor = :configuration_descriptor, name = :name, scope = :scope, search_text = :search_text, type = :type"; + return "actions = :actions, " + id + ",created_time = :created_time, configuration_descriptor = :configuration_descriptor, name = :name, scope = :scope, search_text = :search_text, type = :type"; } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/customer/CustomerRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/customer/CustomerRepository.java index 8b40fe1122..66977419fe 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/customer/CustomerRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/customer/CustomerRepository.java @@ -18,26 +18,25 @@ package org.thingsboard.server.dao.sql.customer; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.query.Param; import org.thingsboard.server.dao.model.sql.CustomerEntity; import org.thingsboard.server.dao.util.SqlDao; -import java.util.List; +import java.util.UUID; /** * Created by Valerii Sosliuk on 5/6/2017. */ @SqlDao -public interface CustomerRepository extends PagingAndSortingRepository { +public interface CustomerRepository extends PagingAndSortingRepository { @Query("SELECT c FROM CustomerEntity c WHERE c.tenantId = :tenantId " + "AND LOWER(c.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))") - Page findByTenantId(@Param("tenantId") String tenantId, + Page findByTenantId(@Param("tenantId") UUID tenantId, @Param("textSearch") String textSearch, Pageable pageable); - CustomerEntity findByTenantIdAndTitle(String tenantId, String title); + CustomerEntity findByTenantIdAndTitle(UUID tenantId, String title); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/customer/JpaCustomerDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/customer/JpaCustomerDao.java index b908eb4be2..a3b585c596 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/customer/JpaCustomerDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/customer/JpaCustomerDao.java @@ -19,7 +19,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.Customer; -import org.thingsboard.server.common.data.UUIDConverter; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.dao.DaoUtil; @@ -48,21 +47,21 @@ public class JpaCustomerDao extends JpaAbstractSearchTextDao getCrudRepository() { + protected CrudRepository getCrudRepository() { return customerRepository; } @Override public PageData findCustomersByTenantId(UUID tenantId, PageLink pageLink) { return DaoUtil.toPageData(customerRepository.findByTenantId( - UUIDConverter.fromTimeUUID(tenantId), + tenantId, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink))); } @Override public Optional findCustomersByTenantIdAndTitle(UUID tenantId, String title) { - Customer customer = DaoUtil.getData(customerRepository.findByTenantIdAndTitle(UUIDConverter.fromTimeUUID(tenantId), title)); + Customer customer = DaoUtil.getData(customerRepository.findByTenantIdAndTitle(tenantId, title)); return Optional.ofNullable(customer); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/DashboardInfoRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/DashboardInfoRepository.java index 32afcfd3a7..f2e21f06c5 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/DashboardInfoRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/DashboardInfoRepository.java @@ -18,23 +18,22 @@ package org.thingsboard.server.dao.sql.dashboard; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.query.Param; import org.thingsboard.server.dao.model.sql.DashboardInfoEntity; import org.thingsboard.server.dao.util.SqlDao; -import java.util.List; +import java.util.UUID; /** * Created by Valerii Sosliuk on 5/6/2017. */ @SqlDao -public interface DashboardInfoRepository extends PagingAndSortingRepository { +public interface DashboardInfoRepository extends PagingAndSortingRepository { @Query("SELECT di FROM DashboardInfoEntity di WHERE di.tenantId = :tenantId " + "AND LOWER(di.searchText) LIKE LOWER(CONCAT(:searchText, '%'))") - Page findByTenantId(@Param("tenantId") String tenantId, + Page findByTenantId(@Param("tenantId") UUID tenantId, @Param("searchText") String searchText, Pageable pageable); @@ -42,8 +41,8 @@ public interface DashboardInfoRepository extends PagingAndSortingRepository findByTenantIdAndCustomerId(@Param("tenantId") String tenantId, - @Param("customerId") String customerId, + Page findByTenantIdAndCustomerId(@Param("tenantId") UUID tenantId, + @Param("customerId") UUID customerId, @Param("searchText") String searchText, Pageable pageable); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/DashboardRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/DashboardRepository.java index bcb8e774cd..76b8723f2a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/DashboardRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/DashboardRepository.java @@ -19,9 +19,11 @@ import org.springframework.data.repository.CrudRepository; import org.thingsboard.server.dao.model.sql.DashboardEntity; import org.thingsboard.server.dao.util.SqlDao; +import java.util.UUID; + /** * Created by Valerii Sosliuk on 5/6/2017. */ @SqlDao -public interface DashboardRepository extends CrudRepository { +public interface DashboardRepository extends CrudRepository { } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardDao.java index bdee891c10..017cf2e328 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardDao.java @@ -24,6 +24,8 @@ import org.thingsboard.server.dao.model.sql.DashboardEntity; import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; import org.thingsboard.server.dao.util.SqlDao; +import java.util.UUID; + /** * Created by Valerii Sosliuk on 5/6/2017. */ @@ -40,7 +42,7 @@ public class JpaDashboardDao extends JpaAbstractSearchTextDao getCrudRepository() { + protected CrudRepository getCrudRepository() { return dashboardRepository; } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardInfoDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardInfoDao.java index 7b0e6a8882..ac8fb2aabc 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardInfoDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardInfoDao.java @@ -20,7 +20,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.DashboardInfo; -import org.thingsboard.server.common.data.UUIDConverter; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.dao.DaoUtil; @@ -61,7 +60,7 @@ public class JpaDashboardInfoDao extends JpaAbstractSearchTextDao findDashboardsByTenantId(UUID tenantId, PageLink pageLink) { return DaoUtil.toPageData(dashboardInfoRepository .findByTenantId( - UUIDConverter.fromTimeUUID(tenantId), + tenantId, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink))); } @@ -70,8 +69,8 @@ public class JpaDashboardInfoDao extends JpaAbstractSearchTextDao findDashboardsByTenantIdAndCustomerId(UUID tenantId, UUID customerId, PageLink pageLink) { return DaoUtil.toPageData(dashboardInfoRepository .findByTenantIdAndCustomerId( - UUIDConverter.fromTimeUUID(tenantId), - UUIDConverter.fromTimeUUID(customerId), + tenantId, + customerId, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink))); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceCredentialsRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceCredentialsRepository.java index c3a6a162ba..8995a33b3a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceCredentialsRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceCredentialsRepository.java @@ -19,13 +19,15 @@ import org.springframework.data.repository.CrudRepository; import org.thingsboard.server.dao.model.sql.DeviceCredentialsEntity; import org.thingsboard.server.dao.util.SqlDao; +import java.util.UUID; + /** * Created by Valerii Sosliuk on 5/6/2017. */ @SqlDao -public interface DeviceCredentialsRepository extends CrudRepository { +public interface DeviceCredentialsRepository extends CrudRepository { - DeviceCredentialsEntity findByDeviceId(String deviceId); + DeviceCredentialsEntity findByDeviceId(UUID deviceId); DeviceCredentialsEntity findByCredentialsId(String credentialsId); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java index 084eb20731..d198333ef0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java @@ -25,24 +25,25 @@ import org.thingsboard.server.dao.model.sql.DeviceInfoEntity; import org.thingsboard.server.dao.util.SqlDao; import java.util.List; +import java.util.UUID; /** * Created by Valerii Sosliuk on 5/6/2017. */ @SqlDao -public interface DeviceRepository extends PagingAndSortingRepository { +public interface DeviceRepository extends PagingAndSortingRepository { @Query("SELECT new org.thingsboard.server.dao.model.sql.DeviceInfoEntity(d, c.title, c.additionalInfo) " + "FROM DeviceEntity d " + "LEFT JOIN CustomerEntity c on c.id = d.customerId " + "WHERE d.id = :deviceId") - DeviceInfoEntity findDeviceInfoById(@Param("deviceId") String deviceId); + DeviceInfoEntity findDeviceInfoById(@Param("deviceId") UUID deviceId); @Query("SELECT d FROM DeviceEntity d WHERE d.tenantId = :tenantId " + "AND d.customerId = :customerId " + "AND LOWER(d.searchText) LIKE LOWER(CONCAT(:searchText, '%'))") - Page findByTenantIdAndCustomerId(@Param("tenantId") String tenantId, - @Param("customerId") String customerId, + Page findByTenantIdAndCustomerId(@Param("tenantId") UUID tenantId, + @Param("customerId") UUID customerId, @Param("searchText") String searchText, Pageable pageable); @@ -52,18 +53,18 @@ public interface DeviceRepository extends PagingAndSortingRepository findDeviceInfosByTenantIdAndCustomerId(@Param("tenantId") String tenantId, - @Param("customerId") String customerId, + Page findDeviceInfosByTenantIdAndCustomerId(@Param("tenantId") UUID tenantId, + @Param("customerId") UUID customerId, @Param("searchText") String searchText, Pageable pageable); @Query("SELECT d FROM DeviceEntity d WHERE d.tenantId = :tenantId") - Page findByTenantId(@Param("tenantId") String tenantId, + Page findByTenantId(@Param("tenantId") UUID tenantId, Pageable pageable); @Query("SELECT d FROM DeviceEntity d WHERE d.tenantId = :tenantId " + "AND LOWER(d.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))") - Page findByTenantId(@Param("tenantId") String tenantId, + Page findByTenantId(@Param("tenantId") UUID tenantId, @Param("textSearch") String textSearch, Pageable pageable); @@ -72,14 +73,14 @@ public interface DeviceRepository extends PagingAndSortingRepository findDeviceInfosByTenantId(@Param("tenantId") String tenantId, + Page findDeviceInfosByTenantId(@Param("tenantId") UUID tenantId, @Param("textSearch") String textSearch, Pageable pageable); @Query("SELECT d FROM DeviceEntity d WHERE d.tenantId = :tenantId " + "AND d.type = :type " + "AND LOWER(d.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))") - Page findByTenantIdAndType(@Param("tenantId") String tenantId, + Page findByTenantIdAndType(@Param("tenantId") UUID tenantId, @Param("type") String type, @Param("textSearch") String textSearch, Pageable pageable); @@ -90,7 +91,7 @@ public interface DeviceRepository extends PagingAndSortingRepository findDeviceInfosByTenantIdAndType(@Param("tenantId") String tenantId, + Page findDeviceInfosByTenantIdAndType(@Param("tenantId") UUID tenantId, @Param("type") String type, @Param("textSearch") String textSearch, Pageable pageable); @@ -99,8 +100,8 @@ public interface DeviceRepository extends PagingAndSortingRepository findByTenantIdAndCustomerIdAndType(@Param("tenantId") String tenantId, - @Param("customerId") String customerId, + Page findByTenantIdAndCustomerIdAndType(@Param("tenantId") UUID tenantId, + @Param("customerId") UUID customerId, @Param("type") String type, @Param("textSearch") String textSearch, Pageable pageable); @@ -112,18 +113,18 @@ public interface DeviceRepository extends PagingAndSortingRepository findDeviceInfosByTenantIdAndCustomerIdAndType(@Param("tenantId") String tenantId, - @Param("customerId") String customerId, + Page findDeviceInfosByTenantIdAndCustomerIdAndType(@Param("tenantId") UUID tenantId, + @Param("customerId") UUID customerId, @Param("type") String type, @Param("textSearch") String textSearch, Pageable pageable); @Query("SELECT DISTINCT d.type FROM DeviceEntity d WHERE d.tenantId = :tenantId") - List findTenantDeviceTypes(@Param("tenantId") String tenantId); + List findTenantDeviceTypes(@Param("tenantId") UUID tenantId); - DeviceEntity findByTenantIdAndName(String tenantId, String name); + DeviceEntity findByTenantIdAndName(UUID tenantId, String name); - List findDevicesByTenantIdAndCustomerIdAndIdIn(String tenantId, String customerId, List deviceIds); + List findDevicesByTenantIdAndCustomerIdAndIdIn(UUID tenantId, UUID customerId, List deviceIds); - List findDevicesByTenantIdAndIdIn(String tenantId, List deviceIds); + List findDevicesByTenantIdAndIdIn(UUID tenantId, List deviceIds); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceCredentialsDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceCredentialsDao.java index f88f578e9e..12a38d2642 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceCredentialsDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceCredentialsDao.java @@ -18,7 +18,6 @@ package org.thingsboard.server.dao.sql.device; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; -import org.thingsboard.server.common.data.UUIDConverter; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.dao.DaoUtil; @@ -45,13 +44,13 @@ public class JpaDeviceCredentialsDao extends JpaAbstractDao getCrudRepository() { + protected CrudRepository getCrudRepository() { return deviceCredentialsRepository; } @Override public DeviceCredentials findByDeviceId(TenantId tenantId, UUID deviceId) { - return DaoUtil.getData(deviceCredentialsRepository.findByDeviceId(UUIDConverter.fromTimeUUID(deviceId))); + return DaoUtil.getData(deviceCredentialsRepository.findByDeviceId(deviceId)); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java index 177bf68bf6..4942df5fa1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java @@ -24,7 +24,6 @@ import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceInfo; import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.UUIDConverter; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; @@ -42,9 +41,6 @@ import java.util.Objects; import java.util.Optional; import java.util.UUID; -import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID; -import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUIDs; - /** * Created by Valerii Sosliuk on 5/6/2017. */ @@ -61,13 +57,13 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao } @Override - protected CrudRepository getCrudRepository() { + protected CrudRepository getCrudRepository() { return deviceRepository; } @Override public DeviceInfo findDeviceInfoById(TenantId tenantId, UUID deviceId) { - return DaoUtil.getData(deviceRepository.findDeviceInfoById(fromTimeUUID(deviceId))); + return DaoUtil.getData(deviceRepository.findDeviceInfoById(deviceId)); } @Override @@ -75,12 +71,12 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao if (StringUtils.isEmpty(pageLink.getTextSearch())) { return DaoUtil.toPageData( deviceRepository.findByTenantId( - fromTimeUUID(tenantId), + tenantId, DaoUtil.toPageable(pageLink))); } else { return DaoUtil.toPageData( deviceRepository.findByTenantId( - fromTimeUUID(tenantId), + tenantId, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink))); } @@ -90,22 +86,22 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao public PageData findDeviceInfosByTenantId(UUID tenantId, PageLink pageLink) { return DaoUtil.toPageData( deviceRepository.findDeviceInfosByTenantId( - fromTimeUUID(tenantId), + tenantId, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink, DeviceInfoEntity.deviceInfoColumnMap))); } @Override public ListenableFuture> findDevicesByTenantIdAndIdsAsync(UUID tenantId, List deviceIds) { - return service.submit(() -> DaoUtil.convertDataList(deviceRepository.findDevicesByTenantIdAndIdIn(UUIDConverter.fromTimeUUID(tenantId), fromTimeUUIDs(deviceIds)))); + return service.submit(() -> DaoUtil.convertDataList(deviceRepository.findDevicesByTenantIdAndIdIn(tenantId, deviceIds))); } @Override public PageData findDevicesByTenantIdAndCustomerId(UUID tenantId, UUID customerId, PageLink pageLink) { return DaoUtil.toPageData( deviceRepository.findByTenantIdAndCustomerId( - fromTimeUUID(tenantId), - fromTimeUUID(customerId), + tenantId, + customerId, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink))); } @@ -114,8 +110,8 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao public PageData findDeviceInfosByTenantIdAndCustomerId(UUID tenantId, UUID customerId, PageLink pageLink) { return DaoUtil.toPageData( deviceRepository.findDeviceInfosByTenantIdAndCustomerId( - fromTimeUUID(tenantId), - fromTimeUUID(customerId), + tenantId, + customerId, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink, DeviceInfoEntity.deviceInfoColumnMap))); } @@ -123,12 +119,12 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao @Override public ListenableFuture> findDevicesByTenantIdCustomerIdAndIdsAsync(UUID tenantId, UUID customerId, List deviceIds) { return service.submit(() -> DaoUtil.convertDataList( - deviceRepository.findDevicesByTenantIdAndCustomerIdAndIdIn(fromTimeUUID(tenantId), fromTimeUUID(customerId), fromTimeUUIDs(deviceIds)))); + deviceRepository.findDevicesByTenantIdAndCustomerIdAndIdIn(tenantId, customerId, deviceIds))); } @Override public Optional findDeviceByTenantIdAndName(UUID tenantId, String name) { - Device device = DaoUtil.getData(deviceRepository.findByTenantIdAndName(fromTimeUUID(tenantId), name)); + Device device = DaoUtil.getData(deviceRepository.findByTenantIdAndName(tenantId, name)); return Optional.ofNullable(device); } @@ -136,7 +132,7 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao public PageData findDevicesByTenantIdAndType(UUID tenantId, String type, PageLink pageLink) { return DaoUtil.toPageData( deviceRepository.findByTenantIdAndType( - fromTimeUUID(tenantId), + tenantId, type, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink))); @@ -146,7 +142,7 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao public PageData findDeviceInfosByTenantIdAndType(UUID tenantId, String type, PageLink pageLink) { return DaoUtil.toPageData( deviceRepository.findDeviceInfosByTenantIdAndType( - fromTimeUUID(tenantId), + tenantId, type, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink, DeviceInfoEntity.deviceInfoColumnMap))); @@ -156,8 +152,8 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao public PageData findDevicesByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, PageLink pageLink) { return DaoUtil.toPageData( deviceRepository.findByTenantIdAndCustomerIdAndType( - fromTimeUUID(tenantId), - fromTimeUUID(customerId), + tenantId, + customerId, type, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink))); @@ -167,8 +163,8 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao public PageData findDeviceInfosByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, PageLink pageLink) { return DaoUtil.toPageData( deviceRepository.findDeviceInfosByTenantIdAndCustomerIdAndType( - fromTimeUUID(tenantId), - fromTimeUUID(customerId), + tenantId, + customerId, type, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink, DeviceInfoEntity.deviceInfoColumnMap))); @@ -176,7 +172,7 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao @Override public ListenableFuture> findTenantDeviceTypesAsync(UUID tenantId) { - return service.submit(() -> convertTenantDeviceTypesToDto(tenantId, deviceRepository.findTenantDeviceTypes(fromTimeUUID(tenantId)))); + return service.submit(() -> convertTenantDeviceTypesToDto(tenantId, deviceRepository.findTenantDeviceTypes(tenantId))); } private List convertTenantDeviceTypesToDto(UUID tenantId, List types) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/EntityViewRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/EntityViewRepository.java index 794c11a032..d119648d76 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/EntityViewRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/EntityViewRepository.java @@ -18,7 +18,6 @@ package org.thingsboard.server.dao.sql.entityview; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.query.Param; import org.thingsboard.server.dao.model.sql.EntityViewEntity; @@ -26,22 +25,23 @@ import org.thingsboard.server.dao.model.sql.EntityViewInfoEntity; import org.thingsboard.server.dao.util.SqlDao; import java.util.List; +import java.util.UUID; /** * Created by Victor Basanets on 8/31/2017. */ @SqlDao -public interface EntityViewRepository extends PagingAndSortingRepository { +public interface EntityViewRepository extends PagingAndSortingRepository { @Query("SELECT new org.thingsboard.server.dao.model.sql.EntityViewInfoEntity(e, c.title, c.additionalInfo) " + "FROM EntityViewEntity e " + "LEFT JOIN CustomerEntity c on c.id = e.customerId " + "WHERE e.id = :entityViewId") - EntityViewInfoEntity findEntityViewInfoById(@Param("entityViewId") String entityViewId); + EntityViewInfoEntity findEntityViewInfoById(@Param("entityViewId") UUID entityViewId); @Query("SELECT e FROM EntityViewEntity e WHERE e.tenantId = :tenantId " + "AND LOWER(e.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))") - Page findByTenantId(@Param("tenantId") String tenantId, + Page findByTenantId(@Param("tenantId") UUID tenantId, @Param("textSearch") String textSearch, Pageable pageable); @@ -50,14 +50,14 @@ public interface EntityViewRepository extends PagingAndSortingRepository findEntityViewInfosByTenantId(@Param("tenantId") String tenantId, + Page findEntityViewInfosByTenantId(@Param("tenantId") UUID tenantId, @Param("textSearch") String textSearch, Pageable pageable); @Query("SELECT e FROM EntityViewEntity e WHERE e.tenantId = :tenantId " + "AND e.type = :type " + "AND LOWER(e.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))") - Page findByTenantIdAndType(@Param("tenantId") String tenantId, + Page findByTenantIdAndType(@Param("tenantId") UUID tenantId, @Param("type") String type, @Param("textSearch") String textSearch, Pageable pageable); @@ -68,7 +68,7 @@ public interface EntityViewRepository extends PagingAndSortingRepository findEntityViewInfosByTenantIdAndType(@Param("tenantId") String tenantId, + Page findEntityViewInfosByTenantIdAndType(@Param("tenantId") UUID tenantId, @Param("type") String type, @Param("textSearch") String textSearch, Pageable pageable); @@ -76,8 +76,8 @@ public interface EntityViewRepository extends PagingAndSortingRepository findByTenantIdAndCustomerId(@Param("tenantId") String tenantId, - @Param("customerId") String customerId, + Page findByTenantIdAndCustomerId(@Param("tenantId") UUID tenantId, + @Param("customerId") UUID customerId, @Param("searchText") String searchText, Pageable pageable); @@ -87,8 +87,8 @@ public interface EntityViewRepository extends PagingAndSortingRepository findEntityViewInfosByTenantIdAndCustomerId(@Param("tenantId") String tenantId, - @Param("customerId") String customerId, + Page findEntityViewInfosByTenantIdAndCustomerId(@Param("tenantId") UUID tenantId, + @Param("customerId") UUID customerId, @Param("searchText") String searchText, Pageable pageable); @@ -96,8 +96,8 @@ public interface EntityViewRepository extends PagingAndSortingRepository findByTenantIdAndCustomerIdAndType(@Param("tenantId") String tenantId, - @Param("customerId") String customerId, + Page findByTenantIdAndCustomerIdAndType(@Param("tenantId") UUID tenantId, + @Param("customerId") UUID customerId, @Param("type") String type, @Param("searchText") String searchText, Pageable pageable); @@ -109,16 +109,16 @@ public interface EntityViewRepository extends PagingAndSortingRepository findEntityViewInfosByTenantIdAndCustomerIdAndType(@Param("tenantId") String tenantId, - @Param("customerId") String customerId, + Page findEntityViewInfosByTenantIdAndCustomerIdAndType(@Param("tenantId") UUID tenantId, + @Param("customerId") UUID customerId, @Param("type") String type, @Param("textSearch") String textSearch, Pageable pageable); - EntityViewEntity findByTenantIdAndName(String tenantId, String name); + EntityViewEntity findByTenantIdAndName(UUID tenantId, String name); - List findAllByTenantIdAndEntityId(String tenantId, String entityId); + List findAllByTenantIdAndEntityId(UUID tenantId, UUID entityId); @Query("SELECT DISTINCT ev.type FROM EntityViewEntity ev WHERE ev.tenantId = :tenantId") - List findTenantEntityViewTypes(@Param("tenantId") String tenantId); + List findTenantEntityViewTypes(@Param("tenantId") UUID tenantId); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java index 2720def286..556d8dab5e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java @@ -19,7 +19,10 @@ import com.google.common.util.concurrent.ListenableFuture; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; -import org.thingsboard.server.common.data.*; +import org.thingsboard.server.common.data.EntitySubtype; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.EntityView; +import org.thingsboard.server.common.data.EntityViewInfo; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; @@ -37,8 +40,6 @@ import java.util.Objects; import java.util.Optional; import java.util.UUID; -import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID; - /** * Created by Victor Basanets on 8/31/2017. */ @@ -56,20 +57,20 @@ public class JpaEntityViewDao extends JpaAbstractSearchTextDao getCrudRepository() { + protected CrudRepository getCrudRepository() { return entityViewRepository; } @Override public EntityViewInfo findEntityViewInfoById(TenantId tenantId, UUID entityViewId) { - return DaoUtil.getData(entityViewRepository.findEntityViewInfoById(fromTimeUUID(entityViewId))); + return DaoUtil.getData(entityViewRepository.findEntityViewInfoById(entityViewId)); } @Override public PageData findEntityViewsByTenantId(UUID tenantId, PageLink pageLink) { return DaoUtil.toPageData( entityViewRepository.findByTenantId( - fromTimeUUID(tenantId), + tenantId, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink))); } @@ -78,7 +79,7 @@ public class JpaEntityViewDao extends JpaAbstractSearchTextDao findEntityViewInfosByTenantId(UUID tenantId, PageLink pageLink) { return DaoUtil.toPageData( entityViewRepository.findEntityViewInfosByTenantId( - fromTimeUUID(tenantId), + tenantId, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink, EntityViewInfoEntity.entityViewInfoColumnMap))); } @@ -87,7 +88,7 @@ public class JpaEntityViewDao extends JpaAbstractSearchTextDao findEntityViewsByTenantIdAndType(UUID tenantId, String type, PageLink pageLink) { return DaoUtil.toPageData( entityViewRepository.findByTenantIdAndType( - fromTimeUUID(tenantId), + tenantId, type, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink))); @@ -97,7 +98,7 @@ public class JpaEntityViewDao extends JpaAbstractSearchTextDao findEntityViewInfosByTenantIdAndType(UUID tenantId, String type, PageLink pageLink) { return DaoUtil.toPageData( entityViewRepository.findEntityViewInfosByTenantIdAndType( - fromTimeUUID(tenantId), + tenantId, type, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink, EntityViewInfoEntity.entityViewInfoColumnMap))); @@ -106,7 +107,7 @@ public class JpaEntityViewDao extends JpaAbstractSearchTextDao findEntityViewByTenantIdAndName(UUID tenantId, String name) { return Optional.ofNullable( - DaoUtil.getData(entityViewRepository.findByTenantIdAndName(fromTimeUUID(tenantId), name))); + DaoUtil.getData(entityViewRepository.findByTenantIdAndName(tenantId, name))); } @Override @@ -115,8 +116,8 @@ public class JpaEntityViewDao extends JpaAbstractSearchTextDao findEntityViewInfosByTenantIdAndCustomerId(UUID tenantId, UUID customerId, PageLink pageLink) { return DaoUtil.toPageData( entityViewRepository.findEntityViewInfosByTenantIdAndCustomerId( - fromTimeUUID(tenantId), - fromTimeUUID(customerId), + tenantId, + customerId, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink, EntityViewInfoEntity.entityViewInfoColumnMap))); } @@ -136,8 +137,8 @@ public class JpaEntityViewDao extends JpaAbstractSearchTextDao findEntityViewsByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, PageLink pageLink) { return DaoUtil.toPageData( entityViewRepository.findByTenantIdAndCustomerIdAndType( - fromTimeUUID(tenantId), - fromTimeUUID(customerId), + tenantId, + customerId, type, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink) @@ -148,8 +149,8 @@ public class JpaEntityViewDao extends JpaAbstractSearchTextDao findEntityViewInfosByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, PageLink pageLink) { return DaoUtil.toPageData( entityViewRepository.findEntityViewInfosByTenantIdAndCustomerIdAndType( - fromTimeUUID(tenantId), - fromTimeUUID(customerId), + tenantId, + customerId, type, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink, EntityViewInfoEntity.entityViewInfoColumnMap))); @@ -158,12 +159,12 @@ public class JpaEntityViewDao extends JpaAbstractSearchTextDao> findEntityViewsByTenantIdAndEntityIdAsync(UUID tenantId, UUID entityId) { return service.submit(() -> DaoUtil.convertDataList( - entityViewRepository.findAllByTenantIdAndEntityId(UUIDConverter.fromTimeUUID(tenantId), UUIDConverter.fromTimeUUID(entityId)))); + entityViewRepository.findAllByTenantIdAndEntityId(tenantId, entityId))); } @Override public ListenableFuture> findTenantEntityViewTypesAsync(UUID tenantId) { - return service.submit(() -> convertTenantEntityViewTypesToDto(tenantId, entityViewRepository.findTenantEntityViewTypes(fromTimeUUID(tenantId)))); + return service.submit(() -> convertTenantEntityViewTypesToDto(tenantId, entityViewRepository.findTenantEntityViewTypes(tenantId))); } private List convertTenantEntityViewTypesToDto(UUID tenantId, List types) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/AbstractEventInsertRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/AbstractEventInsertRepository.java index 8a341e0f81..81f931fc58 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/event/AbstractEventInsertRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/AbstractEventInsertRepository.java @@ -23,7 +23,6 @@ import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionDefinition; -import org.thingsboard.server.common.data.UUIDConverter; import org.thingsboard.server.dao.model.sql.EventEntity; import javax.persistence.EntityManager; @@ -69,7 +68,8 @@ public abstract class AbstractEventInsertRepository implements EventInsertReposi protected Query getQuery(EventEntity entity, String query) { return entityManager.createNativeQuery(query, EventEntity.class) - .setParameter("id", UUIDConverter.fromTimeUUID(entity.getUuid())) + .setParameter("id", entity.getUuid()) + .setParameter("created_time", entity.getCreatedTime()) .setParameter("body", entity.getBody().toString()) .setParameter("entity_id", entity.getEntityId()) .setParameter("entity_type", entity.getEntityType().name()) diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventRepository.java index 6b2160e625..6a09a70ebc 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventRepository.java @@ -25,60 +25,61 @@ import org.thingsboard.server.dao.model.sql.EventEntity; import org.thingsboard.server.dao.util.SqlDao; import java.util.List; +import java.util.UUID; /** * Created by Valerii Sosliuk on 5/3/2017. */ @SqlDao -public interface EventRepository extends PagingAndSortingRepository { +public interface EventRepository extends PagingAndSortingRepository { - EventEntity findByTenantIdAndEntityTypeAndEntityIdAndEventTypeAndEventUid(String tenantId, + EventEntity findByTenantIdAndEntityTypeAndEntityIdAndEventTypeAndEventUid(UUID tenantId, EntityType entityType, - String entityId, + UUID entityId, String eventType, String eventUid); - EventEntity findByTenantIdAndEntityTypeAndEntityId(String tenantId, + EventEntity findByTenantIdAndEntityTypeAndEntityId(UUID tenantId, EntityType entityType, - String entityId); + UUID entityId); @Query("SELECT e FROM EventEntity e WHERE e.tenantId = :tenantId AND e.entityType = :entityType " + "AND e.entityId = :entityId AND e.eventType = :eventType ORDER BY e.eventType DESC, e.id DESC") List findLatestByTenantIdAndEntityTypeAndEntityIdAndEventType( - @Param("tenantId") String tenantId, + @Param("tenantId") UUID tenantId, @Param("entityType") EntityType entityType, - @Param("entityId") String entityId, + @Param("entityId") UUID entityId, @Param("eventType") String eventType, Pageable pageable); @Query("SELECT e FROM EventEntity e WHERE " + "e.tenantId = :tenantId " + "AND e.entityType = :entityType AND e.entityId = :entityId " + - "AND (:startId IS NULL OR e.id >= :startId) " + - "AND (:endId IS NULL OR e.id <= :endId) " + + "AND (:startTime IS NULL OR e.createdTime >= :startTime) " + + "AND (:endTime IS NULL OR e.createdTime <= :endTime) " + "AND LOWER(e.eventType) LIKE LOWER(CONCAT(:textSearch, '%'))" ) - Page findEventsByTenantIdAndEntityId(@Param("tenantId") String tenantId, + Page findEventsByTenantIdAndEntityId(@Param("tenantId") UUID tenantId, @Param("entityType") EntityType entityType, - @Param("entityId") String entityId, + @Param("entityId") UUID entityId, @Param("textSearch") String textSearch, - @Param("startId") String startId, - @Param("endId") String endId, + @Param("startTime") Long startTime, + @Param("endTime") Long endTime, Pageable pageable); @Query("SELECT e FROM EventEntity e WHERE " + "e.tenantId = :tenantId " + "AND e.entityType = :entityType AND e.entityId = :entityId " + "AND e.eventType = :eventType " + - "AND (:startId IS NULL OR e.id >= :startId) " + - "AND (:endId IS NULL OR e.id <= :endId)" + "AND (:startTime IS NULL OR e.createdTime >= :startTime) " + + "AND (:endTime IS NULL OR e.createdTime <= :endTime)" ) - Page findEventsByTenantIdAndEntityIdAndEventType(@Param("tenantId") String tenantId, + Page findEventsByTenantIdAndEntityIdAndEventType(@Param("tenantId") UUID tenantId, @Param("entityType") EntityType entityType, - @Param("entityId") String entityId, + @Param("entityId") UUID entityId, @Param("eventType") String eventType, - @Param("startId") String startId, - @Param("endId") String endId, + @Param("startTime") Long startTime, + @Param("endTime") Long endTime, Pageable pageable); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/HsqlEventInsertRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/HsqlEventInsertRepository.java index f5a00fe7f7..1122499721 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/event/HsqlEventInsertRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/HsqlEventInsertRepository.java @@ -16,11 +16,12 @@ package org.thingsboard.server.dao.sql.event; import org.springframework.stereotype.Repository; -import org.thingsboard.server.common.data.UUIDConverter; import org.thingsboard.server.dao.model.sql.EventEntity; import org.thingsboard.server.dao.util.HsqlDao; import org.thingsboard.server.dao.util.SqlDao; +import javax.persistence.Query; + @SqlDao @HsqlDao @Repository @@ -40,11 +41,25 @@ public class HsqlEventInsertRepository extends AbstractEventInsertRepository { @Override protected EventEntity doProcessSaveOrUpdate(EventEntity entity, String query) { getQuery(entity, query).executeUpdate(); - return entityManager.find(EventEntity.class, UUIDConverter.fromTimeUUID(entity.getUuid())); + return entityManager.find(EventEntity.class, entity.getUuid()); + } + + protected Query getQuery(EventEntity entity, String query) { + return entityManager.createNativeQuery(query, EventEntity.class) + .setParameter("id", entity.getUuid().toString()) + .setParameter("created_time", entity.getCreatedTime()) + .setParameter("body", entity.getBody().toString()) + .setParameter("entity_id", entity.getEntityId().toString()) + .setParameter("entity_type", entity.getEntityType().name()) + .setParameter("event_type", entity.getEventType()) + .setParameter("event_uid", entity.getEventUid()) + .setParameter("tenant_id", entity.getTenantId().toString()) + .setParameter("ts", entity.getTs()); } private static String getInsertString(String conflictStatement) { - return "MERGE INTO event USING (VALUES :id, :body, :entity_id, :entity_type, :event_type, :event_uid, :tenant_id, :ts) I (id, body, entity_id, entity_type, event_type, event_uid, tenant_id, ts) ON " + conflictStatement + " WHEN MATCHED THEN UPDATE SET event.id = I.id, event.body = I.body, event.entity_id = I.entity_id, event.entity_type = I.entity_type, event.event_type = I.event_type, event.event_uid = I.event_uid, event.tenant_id = I.tenant_id, event.ts = I.ts" + - " WHEN NOT MATCHED THEN INSERT (id, body, entity_id, entity_type, event_type, event_uid, tenant_id, ts) VALUES (I.id, I.body, I.entity_id, I.entity_type, I.event_type, I.event_uid, I.tenant_id, I.ts)"; + return "MERGE INTO event USING (VALUES UUID(:id), :created_time, :body, UUID(:entity_id), :entity_type, :event_type, :event_uid, UUID(:tenant_id), :ts) I (id, created_time, body, entity_id, entity_type, event_type, event_uid, tenant_id, ts) ON " + conflictStatement + + " WHEN MATCHED THEN UPDATE SET event.id = I.id, event.created_time = I.created_time, event.body = I.body, event.entity_id = I.entity_id, event.entity_type = I.entity_type, event.event_type = I.event_type, event.event_uid = I.event_uid, event.tenant_id = I.tenant_id, event.ts = I.ts" + + " WHEN NOT MATCHED THEN INSERT (id, created_time, body, entity_id, entity_type, event_type, event_uid, tenant_id, ts) VALUES (I.id, I.created_time, I.body, I.entity_id, I.entity_type, I.event_type, I.event_uid, I.tenant_id, I.ts)"; } } \ No newline at end of file diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java index d2b4fdec8a..c130aac87d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java @@ -38,9 +38,12 @@ import org.thingsboard.server.dao.sql.JpaAbstractSearchTimeDao; import org.thingsboard.server.dao.util.SqlDao; import javax.persistence.criteria.Predicate; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; -import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID; import static org.thingsboard.server.dao.DaoUtil.endTimeToId; import static org.thingsboard.server.dao.DaoUtil.startTimeToId; import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; @@ -67,7 +70,7 @@ public class JpaBaseEventDao extends JpaAbstractSearchTimeDao getCrudRepository() { + protected CrudRepository getCrudRepository() { return eventRepository; } @@ -75,7 +78,16 @@ public class JpaBaseEventDao extends JpaAbstractSearchTimeDao saveAsync(Event event) { log.debug("Save event [{}] ", event); if (event.getId() == null) { - event.setId(new EventId(Uuids.timeBased())); + UUID timeBased = Uuids.timeBased(); + event.setId(new EventId(timeBased)); + event.setCreatedTime(Uuids.unixTimestamp(timeBased)); + } else if (event.getCreatedTime() == 0L) { + UUID eventId = event.getId().getId(); + if (eventId.version() == 1) { + event.setCreatedTime(Uuids.unixTimestamp(eventId)); + } else { + event.setCreatedTime(System.currentTimeMillis()); + } } if (StringUtils.isEmpty(event.getUid())) { event.setUid(event.getId().toString()); @@ -103,7 +124,7 @@ public class JpaBaseEventDao extends JpaAbstractSearchTimeDao findLatestEvents(UUID tenantId, EntityId entityId, String eventType, int limit) { List latest = eventRepository.findLatestByTenantIdAndEntityTypeAndEntityIdAndEventType( - UUIDConverter.fromTimeUUID(tenantId), + tenantId, entityId.getEntityType(), - UUIDConverter.fromTimeUUID(entityId.getId()), + entityId.getId(), eventType, PageRequest.of(0, limit)); return DaoUtil.convertDataList(latest); @@ -149,7 +170,7 @@ public class JpaBaseEventDao extends JpaAbstractSearchTimeDao { List predicates = new ArrayList<>(); if (tenantId != null) { - Predicate tenantIdPredicate = criteriaBuilder.equal(root.get("tenantId"), UUIDConverter.fromTimeUUID(tenantId)); + Predicate tenantIdPredicate = criteriaBuilder.equal(root.get("tenantId"), tenantId); predicates.add(tenantIdPredicate); } if (entityId != null) { Predicate entityTypePredicate = criteriaBuilder.equal(root.get("entityType"), entityId.getEntityType()); predicates.add(entityTypePredicate); - Predicate entityIdPredicate = criteriaBuilder.equal(root.get("entityId"), UUIDConverter.fromTimeUUID(entityId.getId())); + Predicate entityIdPredicate = criteriaBuilder.equal(root.get("entityId"), entityId.getId()); predicates.add(entityIdPredicate); } if (eventType != null) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/PsqlEventInsertRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/PsqlEventInsertRepository.java index 937262241a..e0e3e728ea 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/event/PsqlEventInsertRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/PsqlEventInsertRepository.java @@ -28,10 +28,10 @@ import org.thingsboard.server.dao.util.SqlDao; public class PsqlEventInsertRepository extends AbstractEventInsertRepository { private static final String P_KEY_CONFLICT_STATEMENT = "(id)"; - private static final String UNQ_KEY_CONFLICT_STATEMENT = "(tenant_id, entity_type, entity_id, event_type, event_uid)"; + private static final String UNQ_KEY_CONFLICT_STATEMENT = "(tenant_id, created_time, entity_type, entity_id, event_type, event_uid)"; private static final String UPDATE_P_KEY_STATEMENT = "id = :id"; - private static final String UPDATE_UNQ_KEY_STATEMENT = "tenant_id = :tenant_id, entity_type = :entity_type, entity_id = :entity_id, event_type = :event_type, event_uid = :event_uid"; + private static final String UPDATE_UNQ_KEY_STATEMENT = "created_time = :created_time, tenant_id = :tenant_id, entity_type = :entity_type, entity_id = :entity_id, event_type = :event_type, event_uid = :event_uid"; private static final String INSERT_OR_UPDATE_ON_P_KEY_CONFLICT = getInsertOrUpdateString(P_KEY_CONFLICT_STATEMENT, UPDATE_UNQ_KEY_STATEMENT); private static final String INSERT_OR_UPDATE_ON_UNQ_KEY_CONFLICT = getInsertOrUpdateString(UNQ_KEY_CONFLICT_STATEMENT, UPDATE_P_KEY_STATEMENT); @@ -48,6 +48,8 @@ public class PsqlEventInsertRepository extends AbstractEventInsertRepository { } private static String getInsertOrUpdateString(String eventKeyStatement, String updateKeyStatement) { - return "INSERT INTO event (id, body, entity_id, entity_type, event_type, event_uid, tenant_id, ts) VALUES (:id, :body, :entity_id, :entity_type, :event_type, :event_uid, :tenant_id, :ts) ON CONFLICT " + eventKeyStatement + " DO UPDATE SET body = :body, ts = :ts," + updateKeyStatement + " returning *"; + return "INSERT INTO event (id, created_time, body, entity_id, entity_type, event_type, event_uid, tenant_id, ts) " + + "VALUES (:id, :created_time, :body, :entity_id, :entity_type, :event_type, :event_uid, :tenant_id, :ts) " + + "ON CONFLICT " + eventKeyStatement + " DO UPDATE SET body = :body, ts = :ts," + updateKeyStatement + " returning *"; } } \ No newline at end of file diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java index a88e65e37c..79fbd90700 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java @@ -19,8 +19,6 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Repository; import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.UUIDConverter; -import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; @@ -205,14 +203,14 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { case RELATIONS_QUERY: case DEVICE_SEARCH_QUERY: case ASSET_SEARCH_QUERY: - return String.format("e.tenant_id='%s' and e.customer_id='%s'", UUIDConverter.fromTimeUUID(tenantId.getId()), UUIDConverter.fromTimeUUID(customerId.getId())); + return String.format("e.tenant_id='%s' and e.customer_id='%s'", tenantId.getId(), customerId.getId()); default: if (entityType == EntityType.TENANT) { - return String.format("e.id='%s'", UUIDConverter.fromTimeUUID(tenantId.getId())); + return String.format("e.id='%s'", tenantId.getId()); } else if (entityType == EntityType.CUSTOMER) { - return String.format("e.tenant_id='%s' and e.id='%s'", UUIDConverter.fromTimeUUID(tenantId.getId()), UUIDConverter.fromTimeUUID(customerId.getId())); + return String.format("e.tenant_id='%s' and e.id='%s'", tenantId.getId(), customerId.getId()); } else { - return String.format("e.tenant_id='%s' and e.customer_id='%s'", UUIDConverter.fromTimeUUID(tenantId.getId()), UUIDConverter.fromTimeUUID(customerId.getId())); + return String.format("e.tenant_id='%s' and e.customer_id='%s'", tenantId.getId(), customerId.getId()); } } } @@ -256,13 +254,14 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { private String entitySearchQuery(EntitySearchQueryFilter entityFilter, EntityType entityType, List types) { EntityId rootId = entityFilter.getRootEntity(); //TODO: fetch last level only. + //TODO: fetch distinct records. String lvlFilter = getLvlFilter(entityFilter.getMaxLevel()); String selectFields = "SELECT tenant_id, customer_id, id, type, name, label FROM " + entityType.name() + " WHERE id in ( SELECT entity_id"; String from = getQueryTemplate(entityFilter.getDirection()); String whereFilter = " WHERE " + " re.relation_type = '" + entityFilter.getRelationType() + "'" + " AND re.to_type = '" + entityType.name() + "'"; - from = String.format(from, UUIDConverter.fromTimeUUID(rootId.getId()), rootId.getEntityType().name(), lvlFilter, whereFilter); + from = String.format(from, rootId.getId(), rootId.getEntityType().name(), lvlFilter, whereFilter); String query = "( " + selectFields + from + ")"; if (types != null && !types.isEmpty()) { query += " and type in (" + types.stream().map(type -> "'" + type + "'").collect(Collectors.joining(", ")) + ")"; @@ -305,7 +304,7 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { } else { whereFilter = new StringBuilder(); } - from = String.format(from, UUIDConverter.fromTimeUUID(rootId.getId()), rootId.getEntityType().name(), lvlFilter, whereFilter); + from = String.format(from, rootId.getId(), rootId.getEntityType().name(), lvlFilter, whereFilter); return "( " + selectFields + from + ")"; } @@ -344,7 +343,7 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { private String getSelectCustomerId() { return "CASE" + " WHEN entity.entity_type = 'TENANT'" + - " THEN '" + UUIDConverter.fromTimeUUID(TenantId.NULL_UUID) + "'" + + " THEN UUID('" + TenantId.NULL_UUID + "')" + " WHEN entity.entity_type = 'CUSTOMER' THEN entity_id" + " WHEN entity.entity_type = 'USER'" + " THEN (select customer_id from tb_user where id = entity_id)" + @@ -442,12 +441,12 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { } private String singleEntityQuery(SingleEntityFilter filter) { - return String.format("e.id='%s'", UUIDConverter.fromTimeUUID(filter.getSingleEntity().getId())); + return String.format("e.id='%s'", filter.getSingleEntity().getId()); } private String entityListQuery(EntityListFilter filter) { return String.format("e.id in (%s)", - filter.getEntityList().stream().map(UUID::fromString).map(UUIDConverter::fromTimeUUID) + filter.getEntityList().stream().map(UUID::fromString) .map(s -> String.format("'%s'", s)).collect(Collectors.joining(","))); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityDataAdapter.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityDataAdapter.java index fa98f3313f..d06f6475b7 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityDataAdapter.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityDataAdapter.java @@ -26,9 +26,11 @@ import org.thingsboard.server.common.data.query.EntityKey; import org.thingsboard.server.common.data.query.EntityKeyType; import org.thingsboard.server.common.data.query.TsValue; +import java.nio.ByteBuffer; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import java.util.stream.Collectors; public class EntityDataAdapter { @@ -49,9 +51,10 @@ public class EntityDataAdapter { } private static EntityData toEntityData(Object[] row, List selectionMapping) { - String id = (String)row[0]; + ByteBuffer bb = ByteBuffer.wrap((byte[])row[0]); + UUID id = new UUID(bb.getLong(), bb.getLong()); EntityType entityType = EntityType.valueOf((String)row[1]); - EntityId entityId = EntityIdFactory.getByTypeAndUuid(entityType, UUIDConverter.fromString(id)); + EntityId entityId = EntityIdFactory.getByTypeAndUuid(entityType, id); Map> latest = new HashMap<>(); Map timeseries = new HashMap<>(); EntityData entityData = new EntityData(entityId, latest, timeseries); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java index a71b6e8d85..a77c1e2a9e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java @@ -94,7 +94,7 @@ public class EntityKeyMapping { String column = entityFieldColumnMap.get(entityKey.getKey()); return String.format("e.%s as %s", column, getValueAlias()); } else if (entityKey.getType().equals(EntityKeyType.TIME_SERIES)) { - return buildTimeseriesSelection(); + return buildTimeSeriesSelection(); } else { return buildAttributeSelection(); } @@ -119,8 +119,8 @@ public class EntityKeyMapping { } String join = hasFilter() ? "left join" : "left outer join"; if (entityKey.getType().equals(EntityKeyType.TIME_SERIES)) { - // TODO: - throw new RuntimeException("Not implemented!"); + return String.format("%s ts_kv_latest %s ON %s.entity_id=to_uuid(entities.id) AND %s.key = (select key_id from ts_kv_dictionary where key = '%s')", + join, alias, alias, alias, entityKey.getKey()); } else { String query = String.format("%s attribute_kv %s ON %s.entity_id=entities.id AND %s.entity_type=%s AND %s.attribute_key='%s'", join, alias, alias, alias, entityTypeStr, alias, entityKey.getKey()); @@ -249,11 +249,17 @@ public class EntityKeyMapping { return String.join(", ", attrValSelection, attrTsSelection); } - private String buildTimeseriesSelection() { - // TODO: + private String buildTimeSeriesSelection() { String attrValAlias = getValueAlias(); String attrTsAlias = getTsAlias(); - return String.format("(select '') as %s, (select 1) as %s", attrValAlias, attrTsAlias); + String attrValSelection = + String.format("(coalesce(cast(%s.bool_v as varchar), '') || " + + "coalesce(%s.str_v, '') || " + + "coalesce(cast(%s.long_v as varchar), '') || " + + "coalesce(cast(%s.dbl_v as varchar), '') || " + + "coalesce(cast(%s.json_v as varchar), '')) as %s", alias, alias, alias, alias, alias, attrValAlias); + String attrTsSelection = String.format("%s.ts as %s", alias, attrTsAlias); + return String.join(", ", attrValSelection, attrTsSelection); } private String buildKeyQuery(String alias, KeyFilter keyFilter) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/relation/HsqlRelationInsertRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/relation/HsqlRelationInsertRepository.java index 8438999302..fc262945e1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/relation/HsqlRelationInsertRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/relation/HsqlRelationInsertRepository.java @@ -22,6 +22,8 @@ import org.thingsboard.server.dao.model.sql.RelationEntity; import org.thingsboard.server.dao.util.HsqlDao; import org.thingsboard.server.dao.util.SqlDao; +import javax.persistence.Query; + @HsqlDao @SqlDao @Repository @@ -30,9 +32,25 @@ public class HsqlRelationInsertRepository extends AbstractRelationInsertReposito private static final String INSERT_ON_CONFLICT_DO_UPDATE = "MERGE INTO relation USING (VALUES :fromId, :fromType, :toId, :toType, :relationTypeGroup, :relationType, :additionalInfo) R " + "(from_id, from_type, to_id, to_type, relation_type_group, relation_type, additional_info) " + - "ON (relation.from_id = R.from_id AND relation.from_type = R.from_type AND relation.relation_type_group = R.relation_type_group AND relation.relation_type = R.relation_type AND relation.to_id = R.to_id AND relation.to_type = R.to_type) " + + "ON (relation.from_id = UUID(R.from_id) AND relation.from_type = R.from_type AND relation.relation_type_group = R.relation_type_group AND relation.relation_type = R.relation_type AND relation.to_id = UUID(R.to_id) AND relation.to_type = R.to_type) " + "WHEN MATCHED THEN UPDATE SET relation.additional_info = R.additional_info " + - "WHEN NOT MATCHED THEN INSERT (from_id, from_type, to_id, to_type, relation_type_group, relation_type, additional_info) VALUES (R.from_id, R.from_type, R.to_id, R.to_type, R.relation_type_group, R.relation_type, R.additional_info)"; + "WHEN NOT MATCHED THEN INSERT (from_id, from_type, to_id, to_type, relation_type_group, relation_type, additional_info) VALUES (UUID(R.from_id), R.from_type, UUID(R.to_id), R.to_type, R.relation_type_group, R.relation_type, R.additional_info)"; + + protected Query getQuery(RelationEntity entity, String query) { + Query nativeQuery = entityManager.createNativeQuery(query, RelationEntity.class); + if (entity.getAdditionalInfo() == null) { + nativeQuery.setParameter("additionalInfo", null); + } else { + nativeQuery.setParameter("additionalInfo", entity.getAdditionalInfo().toString()); + } + return nativeQuery + .setParameter("fromId", entity.getFromId().toString()) + .setParameter("fromType", entity.getFromType()) + .setParameter("toId", entity.getToId().toString()) + .setParameter("toType", entity.getToType()) + .setParameter("relationTypeGroup", entity.getRelationTypeGroup()) + .setParameter("relationType", entity.getRelationType()); + } @Override public RelationEntity saveOrUpdate(RelationEntity entity) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/relation/JpaRelationDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/relation/JpaRelationDao.java index a1bdf9a496..306f2c91a9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/relation/JpaRelationDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/relation/JpaRelationDao.java @@ -44,8 +44,6 @@ import javax.persistence.criteria.Predicate; import java.util.ArrayList; import java.util.List; -import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID; - /** * Created by Valerii Sosliuk on 5/29/2017. */ @@ -64,7 +62,7 @@ public class JpaRelationDao extends JpaAbstractDaoListeningExecutorService imple public ListenableFuture> findAllByFrom(TenantId tenantId, EntityId from, RelationTypeGroup typeGroup) { return service.submit(() -> DaoUtil.convertDataList( relationRepository.findAllByFromIdAndFromTypeAndRelationTypeGroup( - UUIDConverter.fromTimeUUID(from.getId()), + from.getId(), from.getEntityType().name(), typeGroup.name()))); } @@ -73,7 +71,7 @@ public class JpaRelationDao extends JpaAbstractDaoListeningExecutorService imple public ListenableFuture> findAllByFromAndType(TenantId tenantId, EntityId from, String relationType, RelationTypeGroup typeGroup) { return service.submit(() -> DaoUtil.convertDataList( relationRepository.findAllByFromIdAndFromTypeAndRelationTypeAndRelationTypeGroup( - UUIDConverter.fromTimeUUID(from.getId()), + from.getId(), from.getEntityType().name(), relationType, typeGroup.name()))); @@ -83,7 +81,7 @@ public class JpaRelationDao extends JpaAbstractDaoListeningExecutorService imple public ListenableFuture> findAllByTo(TenantId tenantId, EntityId to, RelationTypeGroup typeGroup) { return service.submit(() -> DaoUtil.convertDataList( relationRepository.findAllByToIdAndToTypeAndRelationTypeGroup( - UUIDConverter.fromTimeUUID(to.getId()), + to.getId(), to.getEntityType().name(), typeGroup.name()))); } @@ -92,7 +90,7 @@ public class JpaRelationDao extends JpaAbstractDaoListeningExecutorService imple public ListenableFuture> findAllByToAndType(TenantId tenantId, EntityId to, String relationType, RelationTypeGroup typeGroup) { return service.submit(() -> DaoUtil.convertDataList( relationRepository.findAllByToIdAndToTypeAndRelationTypeAndRelationTypeGroup( - UUIDConverter.fromTimeUUID(to.getId()), + to.getId(), to.getEntityType().name(), relationType, typeGroup.name()))); @@ -111,9 +109,9 @@ public class JpaRelationDao extends JpaAbstractDaoListeningExecutorService imple } private RelationCompositeKey getRelationCompositeKey(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) { - return new RelationCompositeKey(fromTimeUUID(from.getId()), + return new RelationCompositeKey(from.getId(), from.getEntityType().name(), - fromTimeUUID(to.getId()), + to.getId(), to.getEntityType().name(), relationType, typeGroup.name()); @@ -166,10 +164,10 @@ public class JpaRelationDao extends JpaAbstractDaoListeningExecutorService imple @Override public boolean deleteOutboundRelations(TenantId tenantId, EntityId entity) { boolean relationExistsBeforeDelete = relationRepository - .findAllByFromIdAndFromType(UUIDConverter.fromTimeUUID(entity.getId()), entity.getEntityType().name()) + .findAllByFromIdAndFromType(entity.getId(), entity.getEntityType().name()) .size() > 0; if (relationExistsBeforeDelete) { - relationRepository.deleteByFromIdAndFromType(UUIDConverter.fromTimeUUID(entity.getId()), entity.getEntityType().name()); + relationRepository.deleteByFromIdAndFromType(entity.getId(), entity.getEntityType().name()); } return relationExistsBeforeDelete; } @@ -179,33 +177,20 @@ public class JpaRelationDao extends JpaAbstractDaoListeningExecutorService imple return service.submit( () -> { boolean relationExistsBeforeDelete = relationRepository - .findAllByFromIdAndFromType(UUIDConverter.fromTimeUUID(entity.getId()), entity.getEntityType().name()) + .findAllByFromIdAndFromType(entity.getId(), entity.getEntityType().name()) .size() > 0; if (relationExistsBeforeDelete) { - relationRepository.deleteByFromIdAndFromType(UUIDConverter.fromTimeUUID(entity.getId()), entity.getEntityType().name()); + relationRepository.deleteByFromIdAndFromType(entity.getId(), entity.getEntityType().name()); } return relationExistsBeforeDelete; }); } - @Override - public ListenableFuture> findRelations(TenantId tenantId, EntityId from, String relationType, RelationTypeGroup typeGroup, EntityType childType, TimePageLink pageLink) { - Specification timeSearchSpec = JpaAbstractSearchTimeDao.getTimeSearchPageSpec(pageLink, "toId"); - Specification fieldsSpec = getEntityFieldsSpec(from, relationType, typeGroup, childType); - Sort.Direction sortDirection = Sort.Direction.DESC; - if (pageLink.getSortOrder() != null) { - sortDirection = pageLink.getSortOrder().getDirection() == SortOrder.Direction.ASC ? Sort.Direction.ASC : Sort.Direction.DESC; - } - Pageable pageable = PageRequest.of(pageLink.getPage(), pageLink.getPageSize(), sortDirection, "toId"); - return service.submit(() -> - DaoUtil.toPageData(relationRepository.findAll(Specification.where(timeSearchSpec).and(fieldsSpec), pageable))); - } - private Specification getEntityFieldsSpec(EntityId from, String relationType, RelationTypeGroup typeGroup, EntityType childType) { return (root, criteriaQuery, criteriaBuilder) -> { List predicates = new ArrayList<>(); if (from != null) { - Predicate fromIdPredicate = criteriaBuilder.equal(root.get("fromId"), UUIDConverter.fromTimeUUID(from.getId())); + Predicate fromIdPredicate = criteriaBuilder.equal(root.get("fromId"), from.getId()); predicates.add(fromIdPredicate); Predicate fromEntityTypePredicate = criteriaBuilder.equal(root.get("fromType"), from.getEntityType().name()); predicates.add(fromEntityTypePredicate); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/relation/RelationRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/relation/RelationRepository.java index 8eee388176..95c67e0b9f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/relation/RelationRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/relation/RelationRepository.java @@ -23,30 +23,31 @@ import org.thingsboard.server.dao.model.sql.RelationEntity; import org.thingsboard.server.dao.util.SqlDao; import java.util.List; +import java.util.UUID; @SqlDao public interface RelationRepository extends CrudRepository, JpaSpecificationExecutor { - List findAllByFromIdAndFromTypeAndRelationTypeGroup(String fromId, + List findAllByFromIdAndFromTypeAndRelationTypeGroup(UUID fromId, String fromType, String relationTypeGroup); - List findAllByFromIdAndFromTypeAndRelationTypeAndRelationTypeGroup(String fromId, + List findAllByFromIdAndFromTypeAndRelationTypeAndRelationTypeGroup(UUID fromId, String fromType, String relationType, String relationTypeGroup); - List findAllByToIdAndToTypeAndRelationTypeGroup(String toId, + List findAllByToIdAndToTypeAndRelationTypeGroup(UUID toId, String toType, String relationTypeGroup); - List findAllByToIdAndToTypeAndRelationTypeAndRelationTypeGroup(String toId, + List findAllByToIdAndToTypeAndRelationTypeAndRelationTypeGroup(UUID toId, String toType, String relationType, String relationTypeGroup); - List findAllByFromIdAndFromType(String fromId, + List findAllByFromIdAndFromType(UUID fromId, String fromType); @Transactional @@ -56,5 +57,5 @@ public interface RelationRepository void deleteById(RelationCompositeKey id); @Transactional - void deleteByFromIdAndFromType(String fromId, String fromType); + void deleteByFromIdAndFromType(UUID fromId, String fromType); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaRuleChainDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaRuleChainDao.java index d2dbe725cd..63e2889bc5 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaRuleChainDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaRuleChainDao.java @@ -17,10 +17,8 @@ package org.thingsboard.server.dao.sql.rule; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.PageRequest; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; -import org.thingsboard.server.common.data.UUIDConverter; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.rule.RuleChain; @@ -30,12 +28,9 @@ import org.thingsboard.server.dao.rule.RuleChainDao; import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; import org.thingsboard.server.dao.util.SqlDao; -import java.util.List; import java.util.Objects; import java.util.UUID; -import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID_STR; - @Slf4j @Component @SqlDao @@ -58,7 +53,7 @@ public class JpaRuleChainDao extends JpaAbstractSearchTextDao findRuleChainsByTenantId(UUID tenantId, PageLink pageLink) { return DaoUtil.toPageData(ruleChainRepository .findByTenantId( - UUIDConverter.fromTimeUUID(tenantId), + tenantId, Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink))); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/rule/RuleChainRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/RuleChainRepository.java index d29acd1751..24b795cae4 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/rule/RuleChainRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/RuleChainRepository.java @@ -18,20 +18,19 @@ package org.thingsboard.server.dao.sql.rule; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.query.Param; import org.thingsboard.server.dao.model.sql.RuleChainEntity; import org.thingsboard.server.dao.util.SqlDao; -import java.util.List; +import java.util.UUID; @SqlDao -public interface RuleChainRepository extends PagingAndSortingRepository { +public interface RuleChainRepository extends PagingAndSortingRepository { @Query("SELECT rc FROM RuleChainEntity rc WHERE rc.tenantId = :tenantId " + "AND LOWER(rc.searchText) LIKE LOWER(CONCAT(:searchText, '%'))") - Page findByTenantId(@Param("tenantId") String tenantId, + Page findByTenantId(@Param("tenantId") UUID tenantId, @Param("searchText") String searchText, Pageable pageable); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/settings/AdminSettingsRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/settings/AdminSettingsRepository.java index 799e71a9b5..b1871fe785 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/settings/AdminSettingsRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/settings/AdminSettingsRepository.java @@ -18,10 +18,12 @@ package org.thingsboard.server.dao.sql.settings; import org.springframework.data.repository.CrudRepository; import org.thingsboard.server.dao.model.sql.AdminSettingsEntity; +import java.util.UUID; + /** * Created by Valerii Sosliuk on 5/6/2017. */ -public interface AdminSettingsRepository extends CrudRepository { +public interface AdminSettingsRepository extends CrudRepository { AdminSettingsEntity findByKey(String key); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/settings/JpaAdminSettingsDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/settings/JpaAdminSettingsDao.java index ab4c34781a..ad56b5754c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/settings/JpaAdminSettingsDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/settings/JpaAdminSettingsDao.java @@ -27,6 +27,8 @@ import org.thingsboard.server.dao.settings.AdminSettingsDao; import org.thingsboard.server.dao.sql.JpaAbstractDao; import org.thingsboard.server.dao.util.SqlDao; +import java.util.UUID; + @Component @Slf4j @SqlDao @@ -41,7 +43,7 @@ public class JpaAdminSettingsDao extends JpaAbstractDao getCrudRepository() { + protected CrudRepository getCrudRepository() { return adminSettingsRepository; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDao.java index e701a0e212..2c1dcb7516 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDao.java @@ -29,6 +29,7 @@ import org.thingsboard.server.dao.tenant.TenantDao; import org.thingsboard.server.dao.util.SqlDao; import java.util.Objects; +import java.util.UUID; /** @@ -47,7 +48,7 @@ public class JpaTenantDao extends JpaAbstractSearchTextDao } @Override - protected CrudRepository getCrudRepository() { + protected CrudRepository getCrudRepository() { return tenantRepository; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/TenantRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/TenantRepository.java index 7a3796e579..04471d2e26 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/TenantRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/TenantRepository.java @@ -18,19 +18,18 @@ package org.thingsboard.server.dao.sql.tenant; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.query.Param; import org.thingsboard.server.dao.model.sql.TenantEntity; import org.thingsboard.server.dao.util.SqlDao; -import java.util.List; +import java.util.UUID; /** * Created by Valerii Sosliuk on 4/30/2017. */ @SqlDao -public interface TenantRepository extends PagingAndSortingRepository { +public interface TenantRepository extends PagingAndSortingRepository { @Query("SELECT t FROM TenantEntity t WHERE t.region = :region " + "AND LOWER(t.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))") diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserCredentialsDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserCredentialsDao.java index dfa57d87cf..5c732bafd8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserCredentialsDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserCredentialsDao.java @@ -18,7 +18,6 @@ package org.thingsboard.server.dao.sql.user; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; -import org.thingsboard.server.common.data.UUIDConverter; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.security.UserCredentials; import org.thingsboard.server.dao.DaoUtil; @@ -45,13 +44,13 @@ public class JpaUserCredentialsDao extends JpaAbstractDao getCrudRepository() { + protected CrudRepository getCrudRepository() { return userCredentialsRepository; } @Override public UserCredentials findByUserId(TenantId tenantId, UUID userId) { - return DaoUtil.getData(userCredentialsRepository.findByUserId(UUIDConverter.fromTimeUUID(userId))); + return DaoUtil.getData(userCredentialsRepository.findByUserId(userId)); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java index 5bf7b0db31..5108332bd6 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java @@ -32,8 +32,7 @@ import org.thingsboard.server.dao.util.SqlDao; import java.util.Objects; import java.util.UUID; -import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID; -import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID_STR; +import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; /** * @author Valerii Sosliuk @@ -51,7 +50,7 @@ public class JpaUserDao extends JpaAbstractSearchTextDao imple } @Override - protected CrudRepository getCrudRepository() { + protected CrudRepository getCrudRepository() { return userRepository; } @@ -65,8 +64,8 @@ public class JpaUserDao extends JpaAbstractSearchTextDao imple return DaoUtil.toPageData( userRepository .findUsersByAuthority( - fromTimeUUID(tenantId), - NULL_UUID_STR, + tenantId, + NULL_UUID, Objects.toString(pageLink.getTextSearch(), ""), Authority.TENANT_ADMIN, DaoUtil.toPageable(pageLink))); @@ -77,8 +76,8 @@ public class JpaUserDao extends JpaAbstractSearchTextDao imple return DaoUtil.toPageData( userRepository .findUsersByAuthority( - fromTimeUUID(tenantId), - fromTimeUUID(customerId), + tenantId, + customerId, Objects.toString(pageLink.getTextSearch(), ""), Authority.CUSTOMER_USER, DaoUtil.toPageable(pageLink))); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserCredentialsRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserCredentialsRepository.java index bcb5faaef4..57e954f796 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserCredentialsRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserCredentialsRepository.java @@ -19,13 +19,15 @@ import org.springframework.data.repository.CrudRepository; import org.thingsboard.server.dao.model.sql.UserCredentialsEntity; import org.thingsboard.server.dao.util.SqlDao; +import java.util.UUID; + /** * Created by Valerii Sosliuk on 4/22/2017. */ @SqlDao -public interface UserCredentialsRepository extends CrudRepository { +public interface UserCredentialsRepository extends CrudRepository { - UserCredentialsEntity findByUserId(String userId); + UserCredentialsEntity findByUserId(UUID userId); UserCredentialsEntity findByActivateToken(String activateToken); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java index ea50ef45bf..265748c6b8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java @@ -18,28 +18,27 @@ package org.thingsboard.server.dao.sql.user; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.query.Param; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.dao.model.sql.UserEntity; import org.thingsboard.server.dao.util.SqlDao; -import java.util.List; +import java.util.UUID; /** * @author Valerii Sosliuk */ @SqlDao -public interface UserRepository extends PagingAndSortingRepository { +public interface UserRepository extends PagingAndSortingRepository { UserEntity findByEmail(String email); @Query("SELECT u FROM UserEntity u WHERE u.tenantId = :tenantId " + "AND u.customerId = :customerId AND u.authority = :authority " + "AND LOWER(u.searchText) LIKE LOWER(CONCAT(:searchText, '%'))") - Page findUsersByAuthority(@Param("tenantId") String tenantId, - @Param("customerId") String customerId, + Page findUsersByAuthority(@Param("tenantId") UUID tenantId, + @Param("customerId") UUID customerId, @Param("searchText") String searchText, @Param("authority") Authority authority, Pageable pageable); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java index ad141bc11c..4be5e5f514 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java @@ -18,7 +18,6 @@ package org.thingsboard.server.dao.sql.widget; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; -import org.thingsboard.server.common.data.UUIDConverter; import org.thingsboard.server.common.data.widget.WidgetType; import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.model.sql.WidgetTypeEntity; @@ -45,17 +44,17 @@ public class JpaWidgetTypeDao extends JpaAbstractDao getCrudRepository() { + protected CrudRepository getCrudRepository() { return widgetTypeRepository; } @Override public List findWidgetTypesByTenantIdAndBundleAlias(UUID tenantId, String bundleAlias) { - return DaoUtil.convertDataList(widgetTypeRepository.findByTenantIdAndBundleAlias(UUIDConverter.fromTimeUUID(tenantId), bundleAlias)); + return DaoUtil.convertDataList(widgetTypeRepository.findByTenantIdAndBundleAlias(tenantId, bundleAlias)); } @Override public WidgetType findByTenantIdBundleAliasAndAlias(UUID tenantId, String bundleAlias, String alias) { - return DaoUtil.getData(widgetTypeRepository.findByTenantIdAndBundleAliasAndAlias(UUIDConverter.fromTimeUUID(tenantId), bundleAlias, alias)); + return DaoUtil.getData(widgetTypeRepository.findByTenantIdAndBundleAliasAndAlias(tenantId, bundleAlias, alias)); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java index 6f7490277a..8e84f95627 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java @@ -18,7 +18,6 @@ package org.thingsboard.server.dao.sql.widget; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; -import org.thingsboard.server.common.data.UUIDConverter; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; @@ -32,7 +31,7 @@ import org.thingsboard.server.dao.widget.WidgetsBundleDao; import java.util.Objects; import java.util.UUID; -import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID_STR; +import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; /** * Created by Valerii Sosliuk on 4/23/2017. @@ -50,13 +49,13 @@ public class JpaWidgetsBundleDao extends JpaAbstractSearchTextDao getCrudRepository() { + protected CrudRepository getCrudRepository() { return widgetsBundleRepository; } @Override public WidgetsBundle findWidgetsBundleByTenantIdAndAlias(UUID tenantId, String alias) { - return DaoUtil.getData(widgetsBundleRepository.findWidgetsBundleByTenantIdAndAlias(UUIDConverter.fromTimeUUID(tenantId), alias)); + return DaoUtil.getData(widgetsBundleRepository.findWidgetsBundleByTenantIdAndAlias(tenantId, alias)); } @Override @@ -64,7 +63,7 @@ public class JpaWidgetsBundleDao extends JpaAbstractSearchTextDao { +public interface WidgetTypeRepository extends CrudRepository { - List findByTenantIdAndBundleAlias(String tenantId, String bundleAlias); + List findByTenantIdAndBundleAlias(UUID tenantId, String bundleAlias); - WidgetTypeEntity findByTenantIdAndBundleAliasAndAlias(String tenantId, String bundleAlias, String alias); + WidgetTypeEntity findByTenantIdAndBundleAliasAndAlias(UUID tenantId, String bundleAlias, String alias); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java index c01ac80f64..f442a9739e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java @@ -18,38 +18,37 @@ package org.thingsboard.server.dao.sql.widget; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.query.Param; import org.thingsboard.server.dao.model.sql.WidgetsBundleEntity; import org.thingsboard.server.dao.util.SqlDao; -import java.util.List; +import java.util.UUID; /** * Created by Valerii Sosliuk on 4/23/2017. */ @SqlDao -public interface WidgetsBundleRepository extends PagingAndSortingRepository { +public interface WidgetsBundleRepository extends PagingAndSortingRepository { - WidgetsBundleEntity findWidgetsBundleByTenantIdAndAlias(String tenantId, String alias); + WidgetsBundleEntity findWidgetsBundleByTenantIdAndAlias(UUID tenantId, String alias); @Query("SELECT wb FROM WidgetsBundleEntity wb WHERE wb.tenantId = :systemTenantId " + "AND LOWER(wb.searchText) LIKE LOWER(CONCAT(:searchText, '%'))") - Page findSystemWidgetsBundles(@Param("systemTenantId") String systemTenantId, + Page findSystemWidgetsBundles(@Param("systemTenantId") UUID systemTenantId, @Param("searchText") String searchText, Pageable pageable); @Query("SELECT wb FROM WidgetsBundleEntity wb WHERE wb.tenantId = :tenantId " + "AND LOWER(wb.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))") - Page findTenantWidgetsBundlesByTenantId(@Param("tenantId") String tenantId, + Page findTenantWidgetsBundlesByTenantId(@Param("tenantId") UUID tenantId, @Param("textSearch") String textSearch, Pageable pageable); @Query("SELECT wb FROM WidgetsBundleEntity wb WHERE wb.tenantId IN (:tenantId, :nullTenantId) " + "AND LOWER(wb.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))") - Page findAllTenantWidgetsBundlesByTenantId(@Param("tenantId") String tenantId, - @Param("nullTenantId") String nullTenantId, + Page findAllTenantWidgetsBundlesByTenantId(@Param("tenantId") UUID tenantId, + @Param("nullTenantId") UUID nullTenantId, @Param("textSearch") String textSearch, Pageable pageable); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantDao.java b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantDao.java index 60fb93bae4..d850694135 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantDao.java @@ -21,8 +21,6 @@ import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.dao.Dao; -import java.util.List; - public interface TenantDao extends Dao { /** diff --git a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java index 33407db373..b63e4f7846 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java @@ -21,7 +21,6 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.Tenant; -import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; @@ -40,8 +39,6 @@ import org.thingsboard.server.dao.service.Validator; import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.dao.widget.WidgetsBundleService; -import java.util.List; - import static org.thingsboard.server.dao.service.Validator.validateId; @Service diff --git a/dao/src/main/java/org/thingsboard/server/dao/timeseries/AggregatePartitionsFunction.java b/dao/src/main/java/org/thingsboard/server/dao/timeseries/AggregatePartitionsFunction.java index 41945526fe..43b221d315 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/timeseries/AggregatePartitionsFunction.java +++ b/dao/src/main/java/org/thingsboard/server/dao/timeseries/AggregatePartitionsFunction.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.timeseries; -import com.datastax.oss.driver.api.core.cql.AsyncResultSet; import com.datastax.oss.driver.api.core.cql.Row; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; diff --git a/dao/src/main/java/org/thingsboard/server/dao/user/UserDao.java b/dao/src/main/java/org/thingsboard/server/dao/user/UserDao.java index 1ab1037613..d212034ce7 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/user/UserDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/user/UserDao.java @@ -21,7 +21,6 @@ import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.dao.Dao; -import java.util.List; import java.util.UUID; public interface UserDao extends Dao { diff --git a/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java index 1c69e222fb..19d993b82c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java @@ -46,7 +46,6 @@ import org.thingsboard.server.dao.service.PaginatedRemover; import org.thingsboard.server.dao.tenant.TenantDao; import java.util.HashMap; -import java.util.List; import java.util.Map; import static org.thingsboard.server.dao.service.Validator.validateId; diff --git a/dao/src/main/java/org/thingsboard/server/dao/util/AbstractBufferedRateExecutor.java b/dao/src/main/java/org/thingsboard/server/dao/util/AbstractBufferedRateExecutor.java index 77f38952bc..b840586a67 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/util/AbstractBufferedRateExecutor.java +++ b/dao/src/main/java/org/thingsboard/server/dao/util/AbstractBufferedRateExecutor.java @@ -35,7 +35,15 @@ import org.thingsboard.server.dao.nosql.CassandraStatementTask; import javax.annotation.Nullable; import java.util.UUID; -import java.util.concurrent.*; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Matcher; diff --git a/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleDao.java b/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleDao.java index 1cc24a990c..9a43c8cd08 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleDao.java @@ -21,7 +21,6 @@ import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.widget.WidgetsBundle; import org.thingsboard.server.dao.Dao; -import java.util.List; import java.util.UUID; /** diff --git a/dao/src/main/resources/sql/schema-entities-hsql.sql b/dao/src/main/resources/sql/schema-entities-hsql.sql index 697e34930a..1a1f5b02ed 100644 --- a/dao/src/main/resources/sql/schema-entities-hsql.sql +++ b/dao/src/main/resources/sql/schema-entities-hsql.sql @@ -16,48 +16,52 @@ CREATE TABLE IF NOT EXISTS admin_settings ( - id varchar(31) NOT NULL CONSTRAINT admin_settings_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT admin_settings_pkey PRIMARY KEY, + created_time bigint NOT NULL, json_value varchar, key varchar(255) ); CREATE TABLE IF NOT EXISTS alarm ( - id varchar(31) NOT NULL CONSTRAINT alarm_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT alarm_pkey PRIMARY KEY, + created_time bigint NOT NULL, ack_ts bigint, clear_ts bigint, additional_info varchar, end_ts bigint, - originator_id varchar(31), + originator_id uuid, originator_type integer, propagate boolean, severity varchar(255), start_ts bigint, status varchar(255), - tenant_id varchar(31), + tenant_id uuid, propagate_relation_types varchar, type varchar(255) ); CREATE TABLE IF NOT EXISTS asset ( - id varchar(31) NOT NULL CONSTRAINT asset_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT asset_pkey PRIMARY KEY, + created_time bigint NOT NULL, additional_info varchar, - customer_id varchar(31), + customer_id uuid, name varchar(255), label varchar(255), search_text varchar(255), - tenant_id varchar(31), + tenant_id uuid, type varchar(255), CONSTRAINT asset_name_unq_key UNIQUE (tenant_id, name) ); CREATE TABLE IF NOT EXISTS audit_log ( - id varchar(31) NOT NULL CONSTRAINT audit_log_pkey PRIMARY KEY, - tenant_id varchar(31), - customer_id varchar(31), - entity_id varchar(31), + id uuid NOT NULL CONSTRAINT audit_log_pkey PRIMARY KEY, + created_time bigint NOT NULL, + tenant_id uuid, + customer_id uuid, + entity_id uuid, entity_type varchar(255), entity_name varchar(255), - user_id varchar(31), + user_id uuid, user_name varchar(255), action_type varchar(255), action_data varchar(1000000), @@ -67,7 +71,7 @@ CREATE TABLE IF NOT EXISTS audit_log ( CREATE TABLE IF NOT EXISTS attribute_kv ( entity_type varchar(255), - entity_id varchar(31), + entity_id uuid, attribute_type varchar(255), attribute_key varchar(255), bool_v boolean, @@ -80,7 +84,8 @@ CREATE TABLE IF NOT EXISTS attribute_kv ( ); CREATE TABLE IF NOT EXISTS component_descriptor ( - id varchar(31) NOT NULL CONSTRAINT component_descriptor_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT component_descriptor_pkey PRIMARY KEY, + created_time bigint NOT NULL, actions varchar(255), clazz varchar UNIQUE, configuration_descriptor varchar, @@ -91,7 +96,8 @@ CREATE TABLE IF NOT EXISTS component_descriptor ( ); CREATE TABLE IF NOT EXISTS customer ( - id varchar(31) NOT NULL CONSTRAINT customer_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT customer_pkey PRIMARY KEY, + created_time bigint NOT NULL, additional_info varchar, address varchar, address2 varchar, @@ -101,57 +107,61 @@ CREATE TABLE IF NOT EXISTS customer ( phone varchar(255), search_text varchar(255), state varchar(255), - tenant_id varchar(31), + tenant_id uuid, title varchar(255), zip varchar(255) ); CREATE TABLE IF NOT EXISTS dashboard ( - id varchar(31) NOT NULL CONSTRAINT dashboard_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT dashboard_pkey PRIMARY KEY, + created_time bigint NOT NULL, configuration varchar(10000000), assigned_customers varchar(1000000), search_text varchar(255), - tenant_id varchar(31), + tenant_id uuid, title varchar(255) ); CREATE TABLE IF NOT EXISTS device ( - id varchar(31) NOT NULL CONSTRAINT device_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT device_pkey PRIMARY KEY, + created_time bigint NOT NULL, additional_info varchar, - customer_id varchar(31), + customer_id uuid, type varchar(255), name varchar(255), label varchar(255), search_text varchar(255), - tenant_id varchar(31), + tenant_id uuid, CONSTRAINT device_name_unq_key UNIQUE (tenant_id, name) ); CREATE TABLE IF NOT EXISTS device_credentials ( - id varchar(31) NOT NULL CONSTRAINT device_credentials_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT device_credentials_pkey PRIMARY KEY, + created_time bigint NOT NULL, credentials_id varchar, credentials_type varchar(255), credentials_value varchar, - device_id varchar(31), + device_id uuid, CONSTRAINT device_credentials_id_unq_key UNIQUE (credentials_id) ); CREATE TABLE IF NOT EXISTS event ( - id varchar(31) NOT NULL CONSTRAINT event_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT event_pkey PRIMARY KEY, + created_time bigint NOT NULL, body varchar(10000000), - entity_id varchar(31), + entity_id uuid, entity_type varchar(255), event_type varchar(255), event_uid varchar(255), - tenant_id varchar(31), + tenant_id uuid, ts bigint NOT NULL, CONSTRAINT event_unq_key UNIQUE (tenant_id, entity_type, entity_id, event_type, event_uid) ); CREATE TABLE IF NOT EXISTS relation ( - from_id varchar(31), + from_id uuid, from_type varchar(255), - to_id varchar(31), + to_id uuid, to_type varchar(255), relation_type_group varchar(255), relation_type varchar(255), @@ -160,19 +170,21 @@ CREATE TABLE IF NOT EXISTS relation ( ); CREATE TABLE IF NOT EXISTS tb_user ( - id varchar(31) NOT NULL CONSTRAINT tb_user_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT tb_user_pkey PRIMARY KEY, + created_time bigint NOT NULL, additional_info varchar, authority varchar(255), - customer_id varchar(31), + customer_id uuid, email varchar(255) UNIQUE, first_name varchar(255), last_name varchar(255), search_text varchar(255), - tenant_id varchar(31) + tenant_id uuid ); CREATE TABLE IF NOT EXISTS tenant ( - id varchar(31) NOT NULL CONSTRAINT tenant_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT tenant_pkey PRIMARY KEY, + created_time bigint NOT NULL, additional_info varchar, address varchar, address2 varchar, @@ -190,46 +202,51 @@ CREATE TABLE IF NOT EXISTS tenant ( ); CREATE TABLE IF NOT EXISTS user_credentials ( - id varchar(31) NOT NULL CONSTRAINT user_credentials_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT user_credentials_pkey PRIMARY KEY, + created_time bigint NOT NULL, activate_token varchar(255) UNIQUE, enabled boolean, password varchar(255), reset_token varchar(255) UNIQUE, - user_id varchar(31) UNIQUE + user_id uuid UNIQUE ); CREATE TABLE IF NOT EXISTS widget_type ( - id varchar(31) NOT NULL CONSTRAINT widget_type_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT widget_type_pkey PRIMARY KEY, + created_time bigint NOT NULL, alias varchar(255), bundle_alias varchar(255), descriptor varchar(1000000), name varchar(255), - tenant_id varchar(31) + tenant_id uuid ); CREATE TABLE IF NOT EXISTS widgets_bundle ( - id varchar(31) NOT NULL CONSTRAINT widgets_bundle_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT widgets_bundle_pkey PRIMARY KEY, + created_time bigint NOT NULL, alias varchar(255), search_text varchar(255), - tenant_id varchar(31), + tenant_id uuid, title varchar(255) ); CREATE TABLE IF NOT EXISTS rule_chain ( - id varchar(31) NOT NULL CONSTRAINT rule_chain_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT rule_chain_pkey PRIMARY KEY, + created_time bigint NOT NULL, additional_info varchar, configuration varchar(10000000), name varchar(255), - first_rule_node_id varchar(31), + first_rule_node_id uuid, root boolean, debug_mode boolean, search_text varchar(255), - tenant_id varchar(31) + tenant_id uuid ); CREATE TABLE IF NOT EXISTS rule_node ( - id varchar(31) NOT NULL CONSTRAINT rule_node_pkey PRIMARY KEY, - rule_chain_id varchar(31), + id uuid NOT NULL CONSTRAINT rule_node_pkey PRIMARY KEY, + created_time bigint NOT NULL, + rule_chain_id uuid, additional_info varchar, configuration varchar(10000000), type varchar(255), @@ -239,11 +256,12 @@ CREATE TABLE IF NOT EXISTS rule_node ( ); CREATE TABLE IF NOT EXISTS entity_view ( - id varchar(31) NOT NULL CONSTRAINT entity_view_pkey PRIMARY KEY, - entity_id varchar(31), + id uuid NOT NULL CONSTRAINT entity_view_pkey PRIMARY KEY, + created_time bigint NOT NULL, + entity_id uuid, entity_type varchar(255), - tenant_id varchar(31), - customer_id varchar(31), + tenant_id uuid, + customer_id uuid, type varchar(255), name varchar(255), keys varchar(10000000), diff --git a/dao/src/main/resources/sql/schema-entities.sql b/dao/src/main/resources/sql/schema-entities.sql index 931856e1df..6a995365ef 100644 --- a/dao/src/main/resources/sql/schema-entities.sql +++ b/dao/src/main/resources/sql/schema-entities.sql @@ -16,48 +16,52 @@ CREATE TABLE IF NOT EXISTS admin_settings ( - id varchar(31) NOT NULL CONSTRAINT admin_settings_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT admin_settings_pkey PRIMARY KEY, + created_time bigint NOT NULL, json_value varchar, key varchar(255) ); CREATE TABLE IF NOT EXISTS alarm ( - id varchar(31) NOT NULL CONSTRAINT alarm_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT alarm_pkey PRIMARY KEY, + created_time bigint NOT NULL, ack_ts bigint, clear_ts bigint, additional_info varchar, end_ts bigint, - originator_id varchar(31), + originator_id uuid, originator_type integer, propagate boolean, severity varchar(255), start_ts bigint, status varchar(255), - tenant_id varchar(31), + tenant_id uuid, propagate_relation_types varchar, type varchar(255) ); CREATE TABLE IF NOT EXISTS asset ( - id varchar(31) NOT NULL CONSTRAINT asset_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT asset_pkey PRIMARY KEY, + created_time bigint NOT NULL, additional_info varchar, - customer_id varchar(31), + customer_id uuid, name varchar(255), label varchar(255), search_text varchar(255), - tenant_id varchar(31), + tenant_id uuid, type varchar(255), CONSTRAINT asset_name_unq_key UNIQUE (tenant_id, name) ); CREATE TABLE IF NOT EXISTS audit_log ( - id varchar(31) NOT NULL CONSTRAINT audit_log_pkey PRIMARY KEY, - tenant_id varchar(31), - customer_id varchar(31), - entity_id varchar(31), + id uuid NOT NULL CONSTRAINT audit_log_pkey PRIMARY KEY, + created_time bigint NOT NULL, + tenant_id uuid, + customer_id uuid, + entity_id uuid, entity_type varchar(255), entity_name varchar(255), - user_id varchar(31), + user_id uuid, user_name varchar(255), action_type varchar(255), action_data varchar(1000000), @@ -67,7 +71,7 @@ CREATE TABLE IF NOT EXISTS audit_log ( CREATE TABLE IF NOT EXISTS attribute_kv ( entity_type varchar(255), - entity_id varchar(31), + entity_id uuid, attribute_type varchar(255), attribute_key varchar(255), bool_v boolean, @@ -80,7 +84,8 @@ CREATE TABLE IF NOT EXISTS attribute_kv ( ); CREATE TABLE IF NOT EXISTS component_descriptor ( - id varchar(31) NOT NULL CONSTRAINT component_descriptor_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT component_descriptor_pkey PRIMARY KEY, + created_time bigint NOT NULL, actions varchar(255), clazz varchar UNIQUE, configuration_descriptor varchar, @@ -91,7 +96,8 @@ CREATE TABLE IF NOT EXISTS component_descriptor ( ); CREATE TABLE IF NOT EXISTS customer ( - id varchar(31) NOT NULL CONSTRAINT customer_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT customer_pkey PRIMARY KEY, + created_time bigint NOT NULL, additional_info varchar, address varchar, address2 varchar, @@ -101,78 +107,90 @@ CREATE TABLE IF NOT EXISTS customer ( phone varchar(255), search_text varchar(255), state varchar(255), - tenant_id varchar(31), + tenant_id uuid, title varchar(255), zip varchar(255) ); CREATE TABLE IF NOT EXISTS dashboard ( - id varchar(31) NOT NULL CONSTRAINT dashboard_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT dashboard_pkey PRIMARY KEY, + created_time bigint NOT NULL, configuration varchar(10000000), assigned_customers varchar(1000000), search_text varchar(255), - tenant_id varchar(31), + tenant_id uuid, title varchar(255) ); CREATE TABLE IF NOT EXISTS device ( - id varchar(31) NOT NULL CONSTRAINT device_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT device_pkey PRIMARY KEY, + created_time bigint NOT NULL, additional_info varchar, - customer_id varchar(31), + customer_id uuid, type varchar(255), name varchar(255), label varchar(255), search_text varchar(255), - tenant_id varchar(31), + tenant_id uuid, CONSTRAINT device_name_unq_key UNIQUE (tenant_id, name) ); CREATE TABLE IF NOT EXISTS device_credentials ( - id varchar(31) NOT NULL CONSTRAINT device_credentials_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT device_credentials_pkey PRIMARY KEY, + created_time bigint NOT NULL, credentials_id varchar, credentials_type varchar(255), credentials_value varchar, - device_id varchar(31), + device_id uuid, CONSTRAINT device_credentials_id_unq_key UNIQUE (credentials_id) ); CREATE TABLE IF NOT EXISTS event ( - id varchar(31) NOT NULL CONSTRAINT event_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT event_pkey PRIMARY KEY, + created_time bigint NOT NULL, body varchar(10000000), - entity_id varchar(31), + entity_id uuid, entity_type varchar(255), event_type varchar(255), event_uid varchar(255), - tenant_id varchar(31), + tenant_id uuid, ts bigint NOT NULL, CONSTRAINT event_unq_key UNIQUE (tenant_id, entity_type, entity_id, event_type, event_uid) ); CREATE TABLE IF NOT EXISTS relation ( - from_id varchar(31), + from_id uuid, from_type varchar(255), - to_id varchar(31), + to_id uuid, to_type varchar(255), relation_type_group varchar(255), relation_type varchar(255), additional_info varchar, CONSTRAINT relation_pkey PRIMARY KEY (from_id, from_type, relation_type_group, relation_type, to_id, to_type) -); +) PARTITION BY LIST (relation_type_group); + +CREATE TABLE other_relations PARTITION OF relation DEFAULT; +CREATE TABLE common_relations PARTITION OF relation FOR VALUES IN ('COMMON'); +CREATE TABLE alarm_relations PARTITION OF relation FOR VALUES IN ('ALARM'); +CREATE TABLE dashboard_relations PARTITION OF relation FOR VALUES IN ('DASHBOARD'); +CREATE TABLE rule_relations PARTITION OF relation FOR VALUES IN ('RULE_CHAIN', 'RULE_NODE'); CREATE TABLE IF NOT EXISTS tb_user ( - id varchar(31) NOT NULL CONSTRAINT tb_user_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT tb_user_pkey PRIMARY KEY, + created_time bigint NOT NULL, additional_info varchar, authority varchar(255), - customer_id varchar(31), + customer_id uuid, email varchar(255) UNIQUE, first_name varchar(255), last_name varchar(255), search_text varchar(255), - tenant_id varchar(31) + tenant_id uuid ); CREATE TABLE IF NOT EXISTS tenant ( - id varchar(31) NOT NULL CONSTRAINT tenant_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT tenant_pkey PRIMARY KEY, + created_time bigint NOT NULL, additional_info varchar, address varchar, address2 varchar, @@ -190,46 +208,51 @@ CREATE TABLE IF NOT EXISTS tenant ( ); CREATE TABLE IF NOT EXISTS user_credentials ( - id varchar(31) NOT NULL CONSTRAINT user_credentials_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT user_credentials_pkey PRIMARY KEY, + created_time bigint NOT NULL, activate_token varchar(255) UNIQUE, enabled boolean, password varchar(255), reset_token varchar(255) UNIQUE, - user_id varchar(31) UNIQUE + user_id uuid UNIQUE ); CREATE TABLE IF NOT EXISTS widget_type ( - id varchar(31) NOT NULL CONSTRAINT widget_type_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT widget_type_pkey PRIMARY KEY, + created_time bigint NOT NULL, alias varchar(255), bundle_alias varchar(255), descriptor varchar(1000000), name varchar(255), - tenant_id varchar(31) + tenant_id uuid ); CREATE TABLE IF NOT EXISTS widgets_bundle ( - id varchar(31) NOT NULL CONSTRAINT widgets_bundle_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT widgets_bundle_pkey PRIMARY KEY, + created_time bigint NOT NULL, alias varchar(255), search_text varchar(255), - tenant_id varchar(31), + tenant_id uuid, title varchar(255) ); CREATE TABLE IF NOT EXISTS rule_chain ( - id varchar(31) NOT NULL CONSTRAINT rule_chain_pkey PRIMARY KEY, + id uuid NOT NULL CONSTRAINT rule_chain_pkey PRIMARY KEY, + created_time bigint NOT NULL, additional_info varchar, configuration varchar(10000000), name varchar(255), - first_rule_node_id varchar(31), + first_rule_node_id uuid, root boolean, debug_mode boolean, search_text varchar(255), - tenant_id varchar(31) + tenant_id uuid ); CREATE TABLE IF NOT EXISTS rule_node ( - id varchar(31) NOT NULL CONSTRAINT rule_node_pkey PRIMARY KEY, - rule_chain_id varchar(31), + id uuid NOT NULL CONSTRAINT rule_node_pkey PRIMARY KEY, + created_time bigint NOT NULL, + rule_chain_id uuid, additional_info varchar, configuration varchar(10000000), type varchar(255), @@ -239,11 +262,12 @@ CREATE TABLE IF NOT EXISTS rule_node ( ); CREATE TABLE IF NOT EXISTS entity_view ( - id varchar(31) NOT NULL CONSTRAINT entity_view_pkey PRIMARY KEY, - entity_id varchar(31), + id uuid NOT NULL CONSTRAINT entity_view_pkey PRIMARY KEY, + created_time bigint NOT NULL, + entity_id uuid, entity_type varchar(255), - tenant_id varchar(31), - customer_id varchar(31), + tenant_id uuid, + customer_id uuid, type varchar(255), name varchar(255), keys varchar(10000000), diff --git a/dao/src/main/resources/sql/schema-timescale.sql b/dao/src/main/resources/sql/schema-timescale.sql index 926f9ee1a6..b8e62196a6 100644 --- a/dao/src/main/resources/sql/schema-timescale.sql +++ b/dao/src/main/resources/sql/schema-timescale.sql @@ -62,37 +62,37 @@ BEGIN END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION delete_device_records_from_ts_kv(tenant_id varchar, customer_id varchar, ttl bigint, +CREATE OR REPLACE FUNCTION delete_device_records_from_ts_kv(tenant_id uuid, customer_id uuid, ttl bigint, OUT deleted bigint) AS $$ BEGIN EXECUTE format( - 'WITH deleted AS (DELETE FROM ts_kv WHERE entity_id IN (SELECT to_uuid(device.id) as entity_id FROM device WHERE tenant_id = %L and customer_id = %L) AND ts < %L::bigint RETURNING *) SELECT count(*) FROM deleted', + 'WITH deleted AS (DELETE FROM ts_kv WHERE entity_id IN (SELECT device.id as entity_id FROM device WHERE tenant_id = %L and customer_id = %L) AND ts < %L::bigint RETURNING *) SELECT count(*) FROM deleted', tenant_id, customer_id, ttl) into deleted; END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION delete_asset_records_from_ts_kv(tenant_id varchar, customer_id varchar, ttl bigint, +CREATE OR REPLACE FUNCTION delete_asset_records_from_ts_kv(tenant_id uuid, customer_id uuid, ttl bigint, OUT deleted bigint) AS $$ BEGIN EXECUTE format( - 'WITH deleted AS (DELETE FROM ts_kv WHERE entity_id IN (SELECT to_uuid(asset.id) as entity_id FROM asset WHERE tenant_id = %L and customer_id = %L) AND ts < %L::bigint RETURNING *) SELECT count(*) FROM deleted', + 'WITH deleted AS (DELETE FROM ts_kv WHERE entity_id IN (SELECT asset.id as entity_id FROM asset WHERE tenant_id = %L and customer_id = %L) AND ts < %L::bigint RETURNING *) SELECT count(*) FROM deleted', tenant_id, customer_id, ttl) into deleted; END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION delete_customer_records_from_ts_kv(tenant_id varchar, customer_id varchar, ttl bigint, +CREATE OR REPLACE FUNCTION delete_customer_records_from_ts_kv(tenant_id uuid, customer_id uuid, ttl bigint, OUT deleted bigint) AS $$ BEGIN EXECUTE format( - 'WITH deleted AS (DELETE FROM ts_kv WHERE entity_id IN (SELECT to_uuid(customer.id) as entity_id FROM customer WHERE tenant_id = %L and id = %L) AND ts < %L::bigint RETURNING *) SELECT count(*) FROM deleted', + 'WITH deleted AS (DELETE FROM ts_kv WHERE entity_id IN (SELECT customer.id as entity_id FROM customer WHERE tenant_id = %L and id = %L) AND ts < %L::bigint RETURNING *) SELECT count(*) FROM deleted', tenant_id, customer_id, ttl) into deleted; END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE PROCEDURE cleanup_timeseries_by_ttl(IN null_uuid varchar(31), +CREATE OR REPLACE PROCEDURE cleanup_timeseries_by_ttl(IN null_uuid uuid, IN system_ttl bigint, INOUT deleted bigint) LANGUAGE plpgsql AS $$ diff --git a/dao/src/main/resources/sql/schema-ts-hsql.sql b/dao/src/main/resources/sql/schema-ts-hsql.sql index eb053a7a84..ce4e4d4275 100644 --- a/dao/src/main/resources/sql/schema-ts-hsql.sql +++ b/dao/src/main/resources/sql/schema-ts-hsql.sql @@ -45,3 +45,8 @@ CREATE TABLE IF NOT EXISTS ts_kv_dictionary ( key_id int GENERATED BY DEFAULT AS IDENTITY(start with 0 increment by 1) UNIQUE, CONSTRAINT ts_key_id_pkey PRIMARY KEY (key) ); + +CREATE FUNCTION to_uuid(IN entity_id varchar) + RETURNS UUID + RETURN UUID(substring(entity_id, 8, 8) || '-' || substring(entity_id, 4, 4) || '-1' || substring(entity_id, 1, 3) || + '-' || substring(entity_id, 16, 4) || '-' || substring(entity_id, 20, 12)); diff --git a/dao/src/main/resources/sql/schema-ts-psql.sql b/dao/src/main/resources/sql/schema-ts-psql.sql index 28420a8957..0b5cab6ebb 100644 --- a/dao/src/main/resources/sql/schema-ts-psql.sql +++ b/dao/src/main/resources/sql/schema-ts-psql.sql @@ -171,37 +171,37 @@ BEGIN END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION delete_device_records_from_ts_kv(tenant_id varchar, customer_id varchar, ttl bigint, +CREATE OR REPLACE FUNCTION delete_device_records_from_ts_kv(tenant_id uuid, customer_id uuid, ttl bigint, OUT deleted bigint) AS $$ BEGIN EXECUTE format( - 'WITH deleted AS (DELETE FROM ts_kv WHERE entity_id IN (SELECT to_uuid(device.id) as entity_id FROM device WHERE tenant_id = %L and customer_id = %L) AND ts < %L::bigint RETURNING *) SELECT count(*) FROM deleted', + 'WITH deleted AS (DELETE FROM ts_kv WHERE entity_id IN (SELECT device.id as entity_id FROM device WHERE tenant_id = %L and customer_id = %L) AND ts < %L::bigint RETURNING *) SELECT count(*) FROM deleted', tenant_id, customer_id, ttl) into deleted; END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION delete_asset_records_from_ts_kv(tenant_id varchar, customer_id varchar, ttl bigint, +CREATE OR REPLACE FUNCTION delete_asset_records_from_ts_kv(tenant_id uuid, customer_id uuid, ttl bigint, OUT deleted bigint) AS $$ BEGIN EXECUTE format( - 'WITH deleted AS (DELETE FROM ts_kv WHERE entity_id IN (SELECT to_uuid(asset.id) as entity_id FROM asset WHERE tenant_id = %L and customer_id = %L) AND ts < %L::bigint RETURNING *) SELECT count(*) FROM deleted', + 'WITH deleted AS (DELETE FROM ts_kv WHERE entity_id IN (SELECT asset.id as entity_id FROM asset WHERE tenant_id = %L and customer_id = %L) AND ts < %L::bigint RETURNING *) SELECT count(*) FROM deleted', tenant_id, customer_id, ttl) into deleted; END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION delete_customer_records_from_ts_kv(tenant_id varchar, customer_id varchar, ttl bigint, +CREATE OR REPLACE FUNCTION delete_customer_records_from_ts_kv(tenant_id uuid, customer_id uuid, ttl bigint, OUT deleted bigint) AS $$ BEGIN EXECUTE format( - 'WITH deleted AS (DELETE FROM ts_kv WHERE entity_id IN (SELECT to_uuid(customer.id) as entity_id FROM customer WHERE tenant_id = %L and id = %L) AND ts < %L::bigint RETURNING *) SELECT count(*) FROM deleted', + 'WITH deleted AS (DELETE FROM ts_kv WHERE entity_id IN (SELECT customer.id as entity_id FROM customer WHERE tenant_id = %L and id = %L) AND ts < %L::bigint RETURNING *) SELECT count(*) FROM deleted', tenant_id, customer_id, ttl) into deleted; END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE PROCEDURE cleanup_timeseries_by_ttl(IN null_uuid varchar(31), +CREATE OR REPLACE PROCEDURE cleanup_timeseries_by_ttl(IN null_uuid uuid, IN system_ttl bigint, INOUT deleted bigint) LANGUAGE plpgsql AS $$ diff --git a/dao/src/test/java/org/thingsboard/server/dao/SqlDaoServiceTestSuite.java b/dao/src/test/java/org/thingsboard/server/dao/SqlDaoServiceTestSuite.java index 32fd45c188..a9239a6588 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/SqlDaoServiceTestSuite.java +++ b/dao/src/test/java/org/thingsboard/server/dao/SqlDaoServiceTestSuite.java @@ -24,24 +24,30 @@ import java.util.Arrays; @RunWith(ClasspathSuite.class) @ClassnameFilters({ - "org.thingsboard.server.dao.service.*ServiceSqlTest" + "org.thingsboard.server.dao.service.sql.EntityServiceSqlTest" }) public class SqlDaoServiceTestSuite { - @ClassRule - public static CustomSqlUnit sqlUnit = new CustomSqlUnit( - Arrays.asList("sql/schema-ts-hsql.sql", "sql/schema-entities-hsql.sql", "sql/schema-entities-idx.sql", "sql/system-data.sql", "sql/system-test.sql"), - "sql/hsql/drop-all-tables.sql", - "sql-test.properties" - ); - // @ClassRule // public static CustomSqlUnit sqlUnit = new CustomSqlUnit( -// Arrays.asList("sql/schema-ts-psql.sql", "sql/schema-entities.sql", "sql/schema-entities-idx.sql", "sql/system-data.sql", "sql/system-test.sql"), -// "sql/psql/drop-all-tables.sql", +// Arrays.asList("sql/schema-ts-hsql.sql", "sql/schema-entities-hsql.sql", "sql/schema-entities-idx.sql" +// , "sql/system-data.sql" +// , "sql/system-test.sql" +// ), +// "sql/hsql/drop-all-tables.sql", // "sql-test.properties" // ); + @ClassRule + public static CustomSqlUnit sqlUnit = new CustomSqlUnit( + Arrays.asList("sql/schema-ts-psql.sql" + , "sql/schema-entities.sql", "sql/schema-entities-idx.sql" + , "sql/system-data.sql", "sql/system-test.sql" + ), + "sql/psql/drop-all-tables.sql", + "sql-test.properties" + ); + // @ClassRule // public static CustomSqlUnit sqlUnit = new CustomSqlUnit( // Arrays.asList("sql/schema-timescale.sql", "sql/schema-entities.sql", "sql/schema-entities-idx.sql", "sql/system-data.sql", "sql/system-test.sql"), diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceTest.java index 21158d1582..8691986005 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceTest.java @@ -299,6 +299,7 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { loadedEntities.addAll(data.getData()); } Assert.assertEquals(25, loadedEntities.size()); + loadedEntities.forEach(entity -> Assert.assertTrue(devices.stream().map(Device::getId).collect(Collectors.toSet()).contains(entity.getEntityId()))); List loadedTemperatures = loadedEntities.stream().map(entityData -> entityData.getLatest().get(EntityKeyType.ATTRIBUTE).get("temperature").getValue()).collect(Collectors.toList()); List deviceTemperatures = temperatures.stream().map(aLong -> Long.toString(aLong)).collect(Collectors.toList()); diff --git a/dao/src/test/resources/sql-test.properties b/dao/src/test/resources/sql-test.properties index 781e0ee01e..1807a89b55 100644 --- a/dao/src/test/resources/sql-test.properties +++ b/dao/src/test/resources/sql-test.properties @@ -4,17 +4,17 @@ sql.ts_inserts_executor_type=fixed sql.ts_inserts_fixed_thread_pool_size=200 sql.ts_key_value_partitioning=MONTHS -spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true -spring.jpa.properties.hibernate.order_by.default_null_ordering=last -spring.jpa.show-sql=false -spring.jpa.hibernate.ddl-auto=validate -spring.jpa.database-platform=org.hibernate.dialect.HSQLDialect - -spring.datasource.username=sa -spring.datasource.password= -spring.datasource.url=jdbc:hsqldb:file:/tmp/testDb;sql.enforce_size=false -spring.datasource.driverClassName=org.hsqldb.jdbc.JDBCDriver -spring.datasource.hikari.maximumPoolSize = 50 +#spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true +#spring.jpa.properties.hibernate.order_by.default_null_ordering=last +#spring.jpa.show-sql=false +#spring.jpa.hibernate.ddl-auto=validate +#spring.jpa.database-platform=org.hibernate.dialect.HSQLDialect +# +#spring.datasource.username=sa +#spring.datasource.password= +#spring.datasource.url=jdbc:hsqldb:file:/tmp/testDb;sql.enforce_size=false +#spring.datasource.driverClassName=org.hsqldb.jdbc.JDBCDriver +#spring.datasource.hikari.maximumPoolSize = 50 service.type=monolith @@ -26,16 +26,16 @@ service.type=monolith #sql.ts_inserts_fixed_thread_pool_size=200 #sql.ts_key_value_partitioning=MONTHS # -#spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true -#spring.jpa.show-sql=false -#spring.jpa.hibernate.ddl-auto=none -#spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect -# -#spring.datasource.username=postgres -#spring.datasource.password=postgres -#spring.datasource.url=jdbc:postgresql://localhost:5432/sqltest -#spring.datasource.driverClassName=org.postgresql.Driver -#spring.datasource.hikari.maximumPoolSize = 50 +spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true +spring.jpa.show-sql=false +spring.jpa.hibernate.ddl-auto=none +spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect + +spring.datasource.username=postgres +spring.datasource.password=postgres +spring.datasource.url=jdbc:postgresql://localhost:5432/sqltest +spring.datasource.driverClassName=org.postgresql.Driver +spring.datasource.hikari.maximumPoolSize = 50 queue.core.pack-processing-timeout=3000 queue.rule-engine.pack-processing-timeout=3000 diff --git a/dao/src/test/resources/sql/hsql/drop-all-tables.sql b/dao/src/test/resources/sql/hsql/drop-all-tables.sql index 1bdc1a7ece..d99a6d5e0f 100644 --- a/dao/src/test/resources/sql/hsql/drop-all-tables.sql +++ b/dao/src/test/resources/sql/hsql/drop-all-tables.sql @@ -20,3 +20,4 @@ DROP TABLE IF EXISTS widgets_bundle; DROP TABLE IF EXISTS rule_node; DROP TABLE IF EXISTS rule_chain; DROP TABLE IF EXISTS entity_view; +DROP FUNCTION IF EXISTS to_uuid; diff --git a/dao/src/test/resources/sql/system-data.sql b/dao/src/test/resources/sql/system-data.sql index f261eb2c04..339d6e94ba 100644 --- a/dao/src/test/resources/sql/system-data.sql +++ b/dao/src/test/resources/sql/system-data.sql @@ -17,22 +17,22 @@ /** SYSTEM **/ /** System admin **/ -INSERT INTO tb_user ( id, tenant_id, customer_id, email, search_text, authority ) -VALUES ( '1e746125a797660a91992ebcb67fe33', '1b21dd2138140008080808080808080', '1b21dd2138140008080808080808080', 'sysadmin@thingsboard.org', +INSERT INTO tb_user ( id, created_time, tenant_id, customer_id, email, search_text, authority ) +VALUES ( '5a797660-4612-11e7-a919-92ebcb67fe33', 1592576748000, '13814000-1dd2-11b2-8080-808080808080', '13814000-1dd2-11b2-8080-808080808080', 'sysadmin@thingsboard.org', 'sysadmin@thingsboard.org', 'SYS_ADMIN' ); -INSERT INTO user_credentials ( id, user_id, enabled, password ) -VALUES ( '1e7461261441950a91992ebcb67fe33', '1e746125a797660a91992ebcb67fe33', true, +INSERT INTO user_credentials ( id, created_time, user_id, enabled, password ) +VALUES ( '61441950-4612-11e7-a919-92ebcb67fe33', 1592576748000, '5a797660-4612-11e7-a919-92ebcb67fe33', true, '$2a$10$5JTB8/hxWc9WAy62nCGSxeefl3KWmipA9nFpVdDa0/xfIseeBB4Bu' ); /** System settings **/ -INSERT INTO admin_settings ( id, key, json_value ) -VALUES ( '1e746126a2266e4a91992ebcb67fe33', 'general', '{ +INSERT INTO admin_settings ( id, created_time, key, json_value ) +VALUES ( '6a2266e4-4612-11e7-a919-92ebcb67fe33', 1592576748000, 'general', '{ "baseUrl": "http://localhost:8080" }' ); -INSERT INTO admin_settings ( id, key, json_value ) -VALUES ( '1e746126eaaefa6a91992ebcb67fe33', 'mail', '{ +INSERT INTO admin_settings ( id, created_time, key, json_value ) +VALUES ( '6eaaefa6-4612-11e7-a919-92ebcb67fe33', 1592576748000, 'mail', '{ "mailFrom": "Thingsboard ", "smtpProtocol": "smtp", "smtpHost": "localhost", From f09f3e5fe73668d93810554650250dcfa479d4d2 Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Mon, 22 Jun 2020 15:35:11 +0300 Subject: [PATCH 2/3] UUID refactoring --- ...qlComponentDescriptorInsertRepository.java | 24 ++- .../JpaBaseComponentDescriptorDao.java | 2 +- .../query/DefaultEntityQueryRepository.java | 152 ++++++++++-------- .../dao/sql/query/EntityDataAdapter.java | 19 ++- .../dao/sql/query/EntityKeyMapping.java | 101 +++++++----- .../dao/sql/query/EntityQueryContext.java | 122 ++++++++++++++ .../server/dao/SqlDaoServiceTestSuite.java | 30 ++-- .../dao/service/BaseEntityServiceTest.java | 1 + dao/src/test/resources/sql-test.properties | 42 ++--- 9 files changed, 337 insertions(+), 156 deletions(-) create mode 100644 dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityQueryContext.java diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/component/HsqlComponentDescriptorInsertRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/component/HsqlComponentDescriptorInsertRepository.java index 2608a6eed1..7477da2f74 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/component/HsqlComponentDescriptorInsertRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/component/HsqlComponentDescriptorInsertRepository.java @@ -20,12 +20,14 @@ import org.thingsboard.server.dao.model.sql.ComponentDescriptorEntity; import org.thingsboard.server.dao.util.HsqlDao; import org.thingsboard.server.dao.util.SqlDao; +import javax.persistence.Query; + @SqlDao @HsqlDao @Repository public class HsqlComponentDescriptorInsertRepository extends AbstractComponentDescriptorInsertRepository { - private static final String P_KEY_CONFLICT_STATEMENT = "(component_descriptor.id=I.id)"; + private static final String P_KEY_CONFLICT_STATEMENT = "(component_descriptor.id=UUID(I.id))"; private static final String UNQ_KEY_CONFLICT_STATEMENT = "(component_descriptor.clazz=I.clazz)"; private static final String INSERT_OR_UPDATE_ON_P_KEY_CONFLICT = getInsertString(P_KEY_CONFLICT_STATEMENT); @@ -36,6 +38,20 @@ public class HsqlComponentDescriptorInsertRepository extends AbstractComponentDe return saveAndGet(entity, INSERT_OR_UPDATE_ON_P_KEY_CONFLICT, INSERT_OR_UPDATE_ON_UNQ_KEY_CONFLICT); } + @Override + protected Query getQuery(ComponentDescriptorEntity entity, String query) { + return entityManager.createNativeQuery(query, ComponentDescriptorEntity.class) + .setParameter("id", entity.getUuid().toString()) + .setParameter("created_time", entity.getCreatedTime()) + .setParameter("actions", entity.getActions()) + .setParameter("clazz", entity.getClazz()) + .setParameter("configuration_descriptor", entity.getConfigurationDescriptor().toString()) + .setParameter("name", entity.getName()) + .setParameter("scope", entity.getScope().name()) + .setParameter("search_text", entity.getSearchText()) + .setParameter("type", entity.getType().name()); + } + @Override protected ComponentDescriptorEntity doProcessSaveOrUpdate(ComponentDescriptorEntity entity, String query) { getQuery(entity, query).executeUpdate(); @@ -43,7 +59,9 @@ public class HsqlComponentDescriptorInsertRepository extends AbstractComponentDe } private static String getInsertString(String conflictStatement) { - return "MERGE INTO component_descriptor USING (VALUES :id, :created_time, :actions, :clazz, :configuration_descriptor, :name, :scope, :search_text, :type) I (id, craeted_time, actions, clazz, configuration_descriptor, name, scope, search_text, type) ON " + conflictStatement + " WHEN MATCHED THEN UPDATE SET component_descriptor.id = I.id, component_descriptor.actions = I.actions, component_descriptor.clazz = I.clazz, component_descriptor.configuration_descriptor = I.configuration_descriptor, component_descriptor.name = I.name, component_descriptor.scope = I.scope, component_descriptor.search_text = I.search_text, component_descriptor.type = I.type" + - " WHEN NOT MATCHED THEN INSERT (id, created_time, actions, clazz, configuration_descriptor, name, scope, search_text, type) VALUES (I.id, I.created_time, I.actions, I.clazz, I.configuration_descriptor, I.name, I.scope, I.search_text, I.type)"; + return "MERGE INTO component_descriptor USING (VALUES :id, :created_time, :actions, :clazz, :configuration_descriptor, :name, :scope, :search_text, :type) I (id, created_time, actions, clazz, configuration_descriptor, name, scope, search_text, type) ON " + + conflictStatement + + " WHEN MATCHED THEN UPDATE SET component_descriptor.id = UUID(I.id), component_descriptor.actions = I.actions, component_descriptor.clazz = I.clazz, component_descriptor.configuration_descriptor = I.configuration_descriptor, component_descriptor.name = I.name, component_descriptor.scope = I.scope, component_descriptor.search_text = I.search_text, component_descriptor.type = I.type" + + " WHEN NOT MATCHED THEN INSERT (id, created_time, actions, clazz, configuration_descriptor, name, scope, search_text, type) VALUES (UUID(I.id), I.created_time, I.actions, I.clazz, I.configuration_descriptor, I.name, I.scope, I.search_text, I.type)"; } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/component/JpaBaseComponentDescriptorDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/component/JpaBaseComponentDescriptorDao.java index dae2ab4341..c128eda12f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/component/JpaBaseComponentDescriptorDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/component/JpaBaseComponentDescriptorDao.java @@ -5,7 +5,7 @@ * 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 + * 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, diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java index 79fbd90700..8342b83c0f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java @@ -17,6 +17,8 @@ package org.thingsboard.server.dao.sql.query; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.id.CustomerId; @@ -44,8 +46,6 @@ import org.thingsboard.server.common.data.relation.EntitySearchDirection; import org.thingsboard.server.common.data.relation.EntityTypeFilter; import org.thingsboard.server.dao.util.SqlDao; -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; import java.math.BigInteger; import java.util.Collections; import java.util.HashMap; @@ -75,7 +75,7 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { public static final String HIERARCHICAL_QUERY_TEMPLATE = " FROM (WITH RECURSIVE related_entities(from_id, from_type, to_id, to_type, relation_type, lvl) AS (" + " SELECT from_id, from_type, to_id, to_type, relation_type, 1 as lvl" + " FROM relation" + - " WHERE $in_id = '%s' and $in_type = '%s' and relation_type_group = 'COMMON'" + + " WHERE $in_id = :relation_root_id and $in_type = :relation_root_type and relation_type_group = 'COMMON'" + " UNION ALL" + " SELECT r.from_id, r.from_type, r.to_id, r.to_type, r.relation_type, lvl + 1" + " FROM relation r" + @@ -88,21 +88,23 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { public static final String HIERARCHICAL_TO_QUERY_TEMPLATE = HIERARCHICAL_QUERY_TEMPLATE.replace("$in", "to").replace("$out", "from"); public static final String HIERARCHICAL_FROM_QUERY_TEMPLATE = HIERARCHICAL_QUERY_TEMPLATE.replace("$in", "from").replace("$out", "to"); - @PersistenceContext - private EntityManager entityManager; + @Autowired + protected NamedParameterJdbcTemplate jdbcTemplate; @Override public long countEntitiesByQuery(TenantId tenantId, CustomerId customerId, EntityCountQuery query) { EntityType entityType = resolveEntityType(query.getEntityFilter()); - String countQuery = String.format("select count(e.id) from %s e where %s", - getEntityTableQuery(query.getEntityFilter(), entityType), this.buildEntityWhere(tenantId, customerId, query.getEntityFilter(), - Collections.emptyList(), entityType)); - return ((BigInteger) entityManager.createNativeQuery(countQuery) - .getSingleResult()).longValue(); + EntityQueryContext ctx = new EntityQueryContext(); + ctx.append("select count(e.id) from "); + ctx.append(addEntityTableQuery(ctx, query.getEntityFilter(), entityType)); + ctx.append(" e where "); + ctx.append(buildEntityWhere(ctx, tenantId, customerId, query.getEntityFilter(), Collections.emptyList(), entityType)); + return jdbcTemplate.queryForObject(ctx.getQuery(), ctx, Long.class); } @Override public PageData findEntityDataByQuery(TenantId tenantId, CustomerId customerId, EntityDataQuery query) { + EntityQueryContext ctx = new EntityQueryContext(); EntityType entityType = resolveEntityType(query.getEntityFilter()); EntityDataPageLink pageLink = query.getPageLink(); @@ -126,9 +128,9 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { .collect(Collectors.toList()); - String entityWhereClause = this.buildEntityWhere(tenantId, customerId, query.getEntityFilter(), entityFieldsFiltersMapping, entityType); - String latestJoins = EntityKeyMapping.buildLatestJoins(query.getEntityFilter(), entityType, allLatestMappings); - String whereClause = this.buildWhere(selectionMapping, latestFiltersMapping, pageLink.getTextSearch()); + String entityWhereClause = this.buildEntityWhere(ctx, tenantId, customerId, query.getEntityFilter(), entityFieldsFiltersMapping, entityType); + String latestJoins = EntityKeyMapping.buildLatestJoins(ctx, query.getEntityFilter(), entityType, allLatestMappings); + String whereClause = this.buildWhere(ctx, selectionMapping, latestFiltersMapping, pageLink.getTextSearch()); String entityFieldsSelection = EntityKeyMapping.buildSelections(entityFieldsSelectionMapping); String entityTypeStr; if (query.getEntityFilter().getType().equals(EntityFilterType.RELATIONS_QUERY)) { @@ -137,9 +139,9 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { entityTypeStr = "'" + entityType.name() + "'"; } if (!StringUtils.isEmpty(entityFieldsSelection)) { - entityFieldsSelection = String.format("e.id, %s, %s", entityTypeStr, entityFieldsSelection); + entityFieldsSelection = String.format("e.id id, %s entity_type, %s", entityTypeStr, entityFieldsSelection); } else { - entityFieldsSelection = String.format("e.id, %s", entityTypeStr); + entityFieldsSelection = String.format("e.id id, %s entity_type", entityTypeStr); } String latestSelection = EntityKeyMapping.buildSelections(latestSelectionMapping); String topSelection = "entities.*"; @@ -150,13 +152,13 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { String fromClause = String.format("from (select %s from (select %s from %s e where %s) entities %s %s) result", topSelection, entityFieldsSelection, - getEntityTableQuery(query.getEntityFilter(), entityType), + addEntityTableQuery(ctx, query.getEntityFilter(), entityType), entityWhereClause, latestJoins, whereClause); - int totalElements = ((BigInteger) entityManager.createNativeQuery(String.format("select count(*) %s", fromClause)) - .getSingleResult()).intValue(); + + int totalElements = jdbcTemplate.queryForObject(String.format("select count(*) %s", fromClause), ctx, Integer.class); String dataQuery = String.format("select * %s", fromClause); @@ -177,17 +179,18 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { if (pageLink.getPageSize() > 0) { dataQuery = String.format("%s limit %s offset %s", dataQuery, pageLink.getPageSize(), startIndex); } - List rows = entityManager.createNativeQuery(dataQuery).getResultList(); + List> rows = jdbcTemplate.queryForList(dataQuery, ctx); return EntityDataAdapter.createEntityData(pageLink, selectionMapping, rows, totalElements); } - private String buildEntityWhere(TenantId tenantId, + private String buildEntityWhere(EntityQueryContext ctx, + TenantId tenantId, CustomerId customerId, EntityFilter entityFilter, List entityFieldsFilters, EntityType entityType) { - String permissionQuery = this.buildPermissionQuery(entityFilter, tenantId, customerId, entityType); - String entityFilterQuery = this.buildEntityFilterQuery(entityFilter); + String permissionQuery = this.buildPermissionQuery(ctx, entityFilter, tenantId, customerId, entityType); + String entityFilterQuery = this.buildEntityFilterQuery(ctx, entityFilter); String result = permissionQuery; if (!entityFilterQuery.isEmpty()) { result += " and " + entityFilterQuery; @@ -198,35 +201,42 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { return result; } - private String buildPermissionQuery(EntityFilter entityFilter, TenantId tenantId, CustomerId customerId, EntityType entityType) { + private String buildPermissionQuery(EntityQueryContext ctx, EntityFilter entityFilter, TenantId tenantId, CustomerId customerId, EntityType entityType) { switch (entityFilter.getType()) { case RELATIONS_QUERY: case DEVICE_SEARCH_QUERY: case ASSET_SEARCH_QUERY: - return String.format("e.tenant_id='%s' and e.customer_id='%s'", tenantId.getId(), customerId.getId()); + ctx.addUuidParameter("permissions_tenant_id", tenantId.getId()); + ctx.addUuidParameter("permissions_customer_id", customerId.getId()); + return "e.tenant_id=:permissions_tenant_id and e.customer_id=:permissions_customer_id"; default: if (entityType == EntityType.TENANT) { - return String.format("e.id='%s'", tenantId.getId()); + ctx.addUuidParameter("permissions_tenant_id", tenantId.getId()); + return "e.id=:permissions_tenant_id"; } else if (entityType == EntityType.CUSTOMER) { - return String.format("e.tenant_id='%s' and e.id='%s'", tenantId.getId(), customerId.getId()); + ctx.addUuidParameter("permissions_tenant_id", tenantId.getId()); + ctx.addUuidParameter("permissions_customer_id", customerId.getId()); + return "e.tenant_id=:permissions_tenant_id and e.id=:permissions_customer_id"; } else { - return String.format("e.tenant_id='%s' and e.customer_id='%s'", tenantId.getId(), customerId.getId()); + ctx.addUuidParameter("permissions_tenant_id", tenantId.getId()); + ctx.addUuidParameter("permissions_customer_id", customerId.getId()); + return "e.tenant_id=:permissions_tenant_id and e.customer_id=:permissions_customer_id"; } } } - private String buildEntityFilterQuery(EntityFilter entityFilter) { + private String buildEntityFilterQuery(EntityQueryContext ctx, EntityFilter entityFilter) { switch (entityFilter.getType()) { case SINGLE_ENTITY: - return this.singleEntityQuery((SingleEntityFilter) entityFilter); + return this.singleEntityQuery(ctx, (SingleEntityFilter) entityFilter); case ENTITY_LIST: - return this.entityListQuery((EntityListFilter) entityFilter); + return this.entityListQuery(ctx, (EntityListFilter) entityFilter); case ENTITY_NAME: - return this.entityNameQuery((EntityNameFilter) entityFilter); + return this.entityNameQuery(ctx, (EntityNameFilter) entityFilter); case ASSET_TYPE: case DEVICE_TYPE: case ENTITY_VIEW_TYPE: - return this.typeQuery(entityFilter); + return this.typeQuery(ctx, entityFilter); case RELATIONS_QUERY: case DEVICE_SEARCH_QUERY: case ASSET_SEARCH_QUERY: @@ -236,53 +246,60 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { } } - private String getEntityTableQuery(EntityFilter entityFilter, EntityType entityType) { + private String addEntityTableQuery(EntityQueryContext ctx, EntityFilter entityFilter, EntityType entityType) { switch (entityFilter.getType()) { case RELATIONS_QUERY: - return relationQuery((RelationsQueryFilter) entityFilter); + return relationQuery(ctx, (RelationsQueryFilter) entityFilter); case DEVICE_SEARCH_QUERY: DeviceSearchQueryFilter deviceQuery = (DeviceSearchQueryFilter) entityFilter; - return entitySearchQuery(deviceQuery, EntityType.DEVICE, deviceQuery.getDeviceTypes()); + return entitySearchQuery(ctx, deviceQuery, EntityType.DEVICE, deviceQuery.getDeviceTypes()); case ASSET_SEARCH_QUERY: AssetSearchQueryFilter assetQuery = (AssetSearchQueryFilter) entityFilter; - return entitySearchQuery(assetQuery, EntityType.ASSET, assetQuery.getAssetTypes()); + return entitySearchQuery(ctx, assetQuery, EntityType.ASSET, assetQuery.getAssetTypes()); default: return entityTableMap.get(entityType); } } - private String entitySearchQuery(EntitySearchQueryFilter entityFilter, EntityType entityType, List types) { + private String entitySearchQuery(EntityQueryContext ctx, EntitySearchQueryFilter entityFilter, EntityType entityType, List types) { EntityId rootId = entityFilter.getRootEntity(); //TODO: fetch last level only. //TODO: fetch distinct records. String lvlFilter = getLvlFilter(entityFilter.getMaxLevel()); String selectFields = "SELECT tenant_id, customer_id, id, type, name, label FROM " + entityType.name() + " WHERE id in ( SELECT entity_id"; String from = getQueryTemplate(entityFilter.getDirection()); + String whereFilter = " WHERE re.relation_type = :where_relation_type AND re.to_type = :where_entity_type"; - String whereFilter = " WHERE " + " re.relation_type = '" + entityFilter.getRelationType() + "'" + - " AND re.to_type = '" + entityType.name() + "'"; - from = String.format(from, rootId.getId(), rootId.getEntityType().name(), lvlFilter, whereFilter); + from = String.format(from, lvlFilter, whereFilter); String query = "( " + selectFields + from + ")"; if (types != null && !types.isEmpty()) { - query += " and type in (" + types.stream().map(type -> "'" + type + "'").collect(Collectors.joining(", ")) + ")"; + query += " and type in (:relation_sub_types)"; + ctx.addStringListParameter("relation_sub_types", types); } query += " )"; + ctx.addUuidParameter("relation_root_id", rootId.getId()); + ctx.addStringParameter("relation_root_type", rootId.getEntityType().name()); + ctx.addStringParameter("where_relation_type", entityFilter.getRelationType()); + ctx.addStringParameter("where_entity_type", entityType.name()); return query; } - private String relationQuery(RelationsQueryFilter entityFilter) { + private String relationQuery(EntityQueryContext ctx, RelationsQueryFilter entityFilter) { EntityId rootId = entityFilter.getRootEntity(); String lvlFilter = getLvlFilter(entityFilter.getMaxLevel()); String selectFields = getSelectTenantId() + ", " + getSelectCustomerId() + ", " + " entity.entity_id as id," + getSelectType() + ", " + getSelectName() + ", " + getSelectLabel() + ", entity.entity_type as entity_type"; String from = getQueryTemplate(entityFilter.getDirection()); + ctx.addUuidParameter("relation_root_id", rootId.getId()); + ctx.addStringParameter("relation_root_type", rootId.getEntityType().name()); StringBuilder whereFilter; if (entityFilter.getFilters() != null && !entityFilter.getFilters().isEmpty()) { whereFilter = new StringBuilder(" WHERE "); boolean first = true; boolean single = entityFilter.getFilters().size() == 1; + int entityTypeFilterIdx = 0; for (EntityTypeFilter etf : entityFilter.getFilters()) { if (first) { first = false; @@ -290,21 +307,23 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { whereFilter.append(" AND "); } String relationType = etf.getRelationType(); - String entityTypes = etf.getEntityTypes().stream().map(type -> "'" + type + "'").collect(Collectors.joining(", ")); if (!single) { whereFilter.append(" ("); } - whereFilter.append(" re.relation_type = '").append(relationType).append("' and re.") + whereFilter.append(" re.relation_type = :where_relation_type").append(entityTypeFilterIdx).append(" and re.") .append(entityFilter.getDirection().equals(EntitySearchDirection.FROM) ? "to" : "from") - .append("_type in (").append(entityTypes).append(")"); + .append("_type in (:where_entity_types").append(entityTypeFilterIdx).append(")"); if (!single) { whereFilter.append(" )"); } + ctx.addStringParameter("where_relation_type" + entityTypeFilterIdx, relationType); + ctx.addStringListParameter("where_entity_types" + entityTypeFilterIdx, etf.getEntityTypes().stream().map(EntityType::name).collect(Collectors.toList())); + entityTypeFilterIdx++; } } else { whereFilter = new StringBuilder(); } - from = String.format(from, rootId.getId(), rootId.getEntityType().name(), lvlFilter, whereFilter); + from = String.format(from, lvlFilter, whereFilter); return "( " + selectFields + from + ")"; } @@ -410,10 +429,9 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { " END as label"; } - private String buildWhere - (List selectionMapping, List latestFiltersMapping, String searchText) { - String latestFilters = EntityKeyMapping.buildQuery(latestFiltersMapping); - String textSearchQuery = this.buildTextSearchQuery(selectionMapping, searchText); + private String buildWhere(EntityQueryContext ctx, List selectionMapping, List latestFiltersMapping, String searchText) { + String latestFilters = EntityKeyMapping.buildQuery(ctx, latestFiltersMapping); + String textSearchQuery = this.buildTextSearchQuery(ctx, selectionMapping, searchText); String query; if (!StringUtils.isEmpty(latestFilters) && !StringUtils.isEmpty(textSearchQuery)) { query = String.join(" AND ", latestFilters, textSearchQuery); @@ -429,32 +447,38 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { } } - private String buildTextSearchQuery(List selectionMapping, String searchText) { + private String buildTextSearchQuery(EntityQueryContext ctx, List selectionMapping, String searchText) { if (!StringUtils.isEmpty(searchText) && !selectionMapping.isEmpty()) { String lowerSearchText = searchText.toLowerCase() + "%"; - List searchPredicates = selectionMapping.stream().map(mapping -> String.format("LOWER(%s) LIKE '%s'", - mapping.getValueAlias(), lowerSearchText)).collect(Collectors.toList()); + List searchPredicates = selectionMapping.stream().map(mapping -> { + String paramName = mapping.getValueAlias() + "_lowerSearchText"; + ctx.addStringParameter(paramName, lowerSearchText); + return String.format("LOWER(%s) LIKE :%s", mapping.getValueAlias(), paramName); + } + ).collect(Collectors.toList()); return String.format("(%s)", String.join(" or ", searchPredicates)); } else { return null; } + } - private String singleEntityQuery(SingleEntityFilter filter) { - return String.format("e.id='%s'", filter.getSingleEntity().getId()); + private String singleEntityQuery(EntityQueryContext ctx, SingleEntityFilter filter) { + ctx.addUuidParameter("entity_filter_single_entity_id", filter.getSingleEntity().getId()); + return "e.id=:entity_filter_single_entity_id"; } - private String entityListQuery(EntityListFilter filter) { - return String.format("e.id in (%s)", - filter.getEntityList().stream().map(UUID::fromString) - .map(s -> String.format("'%s'", s)).collect(Collectors.joining(","))); + private String entityListQuery(EntityQueryContext ctx, EntityListFilter filter) { + ctx.addUuidListParameter("entity_filter_entity_ids", filter.getEntityList().stream().map(UUID::fromString).collect(Collectors.toList())); + return "e.id in (:entity_filter_entity_ids)"; } - private String entityNameQuery(EntityNameFilter filter) { - return String.format("lower(e.search_text) like lower(concat(%s, '%%'))", filter.getEntityNameFilter()); + private String entityNameQuery(EntityQueryContext ctx, EntityNameFilter filter) { + ctx.addStringParameter("entity_filter_name_filter", filter.getEntityNameFilter()); + return "lower(e.search_text) like lower(concat(:entity_filter_name_filter, '%%'))"; } - private String typeQuery(EntityFilter filter) { + private String typeQuery(EntityQueryContext ctx, EntityFilter filter) { String type; String name; switch (filter.getType()) { @@ -473,7 +497,9 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { default: throw new RuntimeException("Not supported!"); } - return String.format("e.type = '%s' and lower(e.search_text) like lower(concat('%s', '%%'))", type, name); + ctx.addStringParameter("entity_filter_type_query_type", type); + ctx.addStringParameter("entity_filter_type_query_name", name); + return "e.type = :entity_filter_type_query_type and lower(e.search_text) like lower(concat(:entity_filter_type_query_name, '%%'))"; } private EntityType resolveEntityType(EntityFilter entityFilter) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityDataAdapter.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityDataAdapter.java index d06f6475b7..9277a3bdcd 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityDataAdapter.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityDataAdapter.java @@ -37,31 +37,30 @@ public class EntityDataAdapter { public static PageData createEntityData(EntityDataPageLink pageLink, List selectionMapping, - List rows, + List> rows, int totalElements) { - int totalPages = pageLink.getPageSize() > 0 ? (int)Math.ceil((float)totalElements / pageLink.getPageSize()) : 1; + int totalPages = pageLink.getPageSize() > 0 ? (int) Math.ceil((float) totalElements / pageLink.getPageSize()) : 1; int startIndex = pageLink.getPageSize() * pageLink.getPage(); boolean hasNext = pageLink.getPageSize() > 0 && totalElements > startIndex + rows.size(); List entitiesData = convertListToEntityData(rows, selectionMapping); return new PageData<>(entitiesData, totalPages, totalElements, hasNext); } - private static List convertListToEntityData(List result, List selectionMapping) { + private static List convertListToEntityData(List> result, List selectionMapping) { return result.stream().map(row -> toEntityData(row, selectionMapping)).collect(Collectors.toList()); } - private static EntityData toEntityData(Object[] row, List selectionMapping) { - ByteBuffer bb = ByteBuffer.wrap((byte[])row[0]); - UUID id = new UUID(bb.getLong(), bb.getLong()); - EntityType entityType = EntityType.valueOf((String)row[1]); + private static EntityData toEntityData(Map row, List selectionMapping) { + UUID id = (UUID)row.get("id"); + EntityType entityType = EntityType.valueOf((String) row.get("entity_type")); EntityId entityId = EntityIdFactory.getByTypeAndUuid(entityType, id); Map> latest = new HashMap<>(); Map timeseries = new HashMap<>(); EntityData entityData = new EntityData(entityId, latest, timeseries); - for (EntityKeyMapping mapping: selectionMapping) { + for (EntityKeyMapping mapping : selectionMapping) { if (!mapping.isIgnore()) { EntityKey entityKey = mapping.getEntityKey(); - Object value = row[mapping.getIndex()]; + Object value = row.get(mapping.getValueAlias()); String strValue; long ts; if (entityKey.getType().equals(EntityKeyType.ENTITY_FIELD)) { @@ -69,7 +68,7 @@ public class EntityDataAdapter { ts = System.currentTimeMillis(); } else { strValue = convertValue(value); - Object tsObject = row[mapping.getIndex() + 1]; + Object tsObject = row.get(mapping.getTsAlias()); ts = tsObject != null ? Long.parseLong(tsObject.toString()) : 0; } TsValue tsValue = new TsValue(ts, strValue); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java index a77c1e2a9e..08eb668ce0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java @@ -72,6 +72,7 @@ public class EntityKeyMapping { private boolean ignore = false; private List keyFilters; private EntityKey entityKey; + private int paramIdx = 0; public boolean hasFilter() { return keyFilters != null && !keyFilters.isEmpty(); @@ -100,17 +101,17 @@ public class EntityKeyMapping { } } - public Stream toQueries() { + public Stream toQueries(EntityQueryContext ctx) { if (hasFilter()) { String keyAlias = entityKey.getType().equals(EntityKeyType.ENTITY_FIELD) ? "e" : alias; return keyFilters.stream().map(keyFilter -> - this.buildKeyQuery(keyAlias, keyFilter)); + this.buildKeyQuery(ctx, keyAlias, keyFilter)); } else { return null; } } - public String toLatestJoin(EntityFilter entityFilter, EntityType entityType) { + public String toLatestJoin(EntityQueryContext ctx, EntityFilter entityFilter, EntityType entityType) { String entityTypeStr; if (entityFilter.getType().equals(EntityFilterType.RELATIONS_QUERY)) { entityTypeStr = "entities.entity_type"; @@ -118,12 +119,13 @@ public class EntityKeyMapping { entityTypeStr = "'" + entityType.name() + "'"; } String join = hasFilter() ? "left join" : "left outer join"; + ctx.addStringParameter(alias + "_key_id", entityKey.getKey()); if (entityKey.getType().equals(EntityKeyType.TIME_SERIES)) { - return String.format("%s ts_kv_latest %s ON %s.entity_id=to_uuid(entities.id) AND %s.key = (select key_id from ts_kv_dictionary where key = '%s')", - join, alias, alias, alias, entityKey.getKey()); + return String.format("%s ts_kv_latest %s ON %s.entity_id=to_uuid(entities.id) AND %s.key = (select key_id from ts_kv_dictionary where key = :%s_key_id)", + join, alias, alias, alias, alias); } else { - String query = String.format("%s attribute_kv %s ON %s.entity_id=entities.id AND %s.entity_type=%s AND %s.attribute_key='%s'", - join, alias, alias, alias, entityTypeStr, alias, entityKey.getKey()); + String query = String.format("%s attribute_kv %s ON %s.entity_id=entities.id AND %s.entity_type=%s AND %s.attribute_key=:%s_key_id", + join, alias, alias, alias, entityTypeStr, alias, alias); if (!entityKey.getType().equals(EntityKeyType.ATTRIBUTE)) { String scope; if (entityKey.getType().equals(EntityKeyType.CLIENT_ATTRIBUTE)) { @@ -144,13 +146,13 @@ public class EntityKeyMapping { Collectors.joining(", ")); } - public static String buildLatestJoins(EntityFilter entityFilter, EntityType entityType, List latestMappings) { - return latestMappings.stream().map(mapping -> mapping.toLatestJoin(entityFilter, entityType)).collect( + public static String buildLatestJoins(EntityQueryContext ctx, EntityFilter entityFilter, EntityType entityType, List latestMappings) { + return latestMappings.stream().map(mapping -> mapping.toLatestJoin(ctx, entityFilter, entityType)).collect( Collectors.joining(" ")); } - public static String buildQuery(List mappings) { - return mappings.stream().flatMap(EntityKeyMapping::toQueries).collect( + public static String buildQuery(EntityQueryContext ctx, List mappings) { + return mappings.stream().flatMap(mapping -> mapping.toQueries(ctx)).collect( Collectors.joining(" AND ")); } @@ -262,33 +264,33 @@ public class EntityKeyMapping { return String.join(", ", attrValSelection, attrTsSelection); } - private String buildKeyQuery(String alias, KeyFilter keyFilter) { - return this.buildPredicateQuery(alias, keyFilter.getKey(), keyFilter.getPredicate()); + private String buildKeyQuery(EntityQueryContext ctx, String alias, KeyFilter keyFilter) { + return this.buildPredicateQuery(ctx, alias, keyFilter.getKey(), keyFilter.getPredicate()); } - private String buildPredicateQuery(String alias, EntityKey key, KeyFilterPredicate predicate) { + private String buildPredicateQuery(EntityQueryContext ctx, String alias, EntityKey key, KeyFilterPredicate predicate) { if (predicate.getType().equals(FilterPredicateType.COMPLEX)) { - return this.buildComplexPredicateQuery(alias, key, (ComplexFilterPredicate) predicate); + return this.buildComplexPredicateQuery(ctx, alias, key, (ComplexFilterPredicate) predicate); } else { - return this.buildSimplePredicateQuery(alias, key, predicate); + return this.buildSimplePredicateQuery(ctx, alias, key, predicate); } } - private String buildComplexPredicateQuery(String alias, EntityKey key, ComplexFilterPredicate predicate) { + private String buildComplexPredicateQuery(EntityQueryContext ctx, String alias, EntityKey key, ComplexFilterPredicate predicate) { return predicate.getPredicates().stream() - .map(keyFilterPredicate -> this.buildPredicateQuery(alias, key, keyFilterPredicate)).collect(Collectors.joining( + .map(keyFilterPredicate -> this.buildPredicateQuery(ctx, alias, key, keyFilterPredicate)).collect(Collectors.joining( " " + predicate.getOperation().name() + " " )); } - private String buildSimplePredicateQuery(String alias, EntityKey key, KeyFilterPredicate predicate) { + private String buildSimplePredicateQuery(EntityQueryContext ctx, String alias, EntityKey key, KeyFilterPredicate predicate) { if (predicate.getType().equals(FilterPredicateType.NUMERIC)) { if (key.getType().equals(EntityKeyType.ENTITY_FIELD)) { String column = entityFieldColumnMap.get(key.getKey()); - return this.buildNumericPredicateQuery(alias + "." + column, (NumericFilterPredicate) predicate); + return this.buildNumericPredicateQuery(ctx, alias + "." + column, (NumericFilterPredicate) predicate); } else { - String longQuery = this.buildNumericPredicateQuery(alias + ".long_v", (NumericFilterPredicate) predicate); - String doubleQuery = this.buildNumericPredicateQuery(alias + ".dbl_v", (NumericFilterPredicate) predicate); + String longQuery = this.buildNumericPredicateQuery(ctx, alias + ".long_v", (NumericFilterPredicate) predicate); + String doubleQuery = this.buildNumericPredicateQuery(ctx, alias + ".dbl_v", (NumericFilterPredicate) predicate); return String.format("(%s or %s)", longQuery, doubleQuery); } } else { @@ -300,15 +302,16 @@ public class EntityKeyMapping { } String field = alias + "." + column; if (predicate.getType().equals(FilterPredicateType.STRING)) { - return this.buildStringPredicateQuery(field, (StringFilterPredicate) predicate); + return this.buildStringPredicateQuery(ctx, field, (StringFilterPredicate) predicate); } else { - return this.buildBooleanPredicateQuery(field, (BooleanFilterPredicate) predicate); + return this.buildBooleanPredicateQuery(ctx, field, (BooleanFilterPredicate) predicate); } } } - private String buildStringPredicateQuery(String field, StringFilterPredicate stringFilterPredicate) { + private String buildStringPredicateQuery(EntityQueryContext ctx, String field, StringFilterPredicate stringFilterPredicate) { String operationField = field; + String paramName = getNextParameterName(field); String value = stringFilterPredicate.getValue(); String stringOperationQuery = ""; if (stringFilterPredicate.isIgnoreCase()) { @@ -317,65 +320,77 @@ public class EntityKeyMapping { } switch (stringFilterPredicate.getOperation()) { case EQUAL: - stringOperationQuery = String.format("%s = '%s'", operationField, value); + stringOperationQuery = String.format("%s = :%s", operationField, paramName); break; case NOT_EQUAL: - stringOperationQuery = String.format("%s != '%s'", operationField, value); + stringOperationQuery = String.format("%s != :%s", operationField, paramName); break; case STARTS_WITH: - stringOperationQuery = String.format("%s like '%s%%'", operationField, value); + value += "%"; + stringOperationQuery = String.format("%s like :%s", operationField, paramName); break; case ENDS_WITH: - stringOperationQuery = String.format("%s like '%%%s'", operationField, value); + value = "%" + value; + stringOperationQuery = String.format("%s like :%s", operationField, paramName); break; case CONTAINS: - stringOperationQuery = String.format("%s like '%%%s%%'", operationField, value); + value = "%" + value + "%"; + stringOperationQuery = String.format("%s like :%s", operationField, paramName); break; case NOT_CONTAINS: - stringOperationQuery = String.format("%s not like '%%%s%%'", operationField, value); + value = "%" + value + "%"; + stringOperationQuery = String.format("%s not like :%s", operationField, paramName); break; } + ctx.addStringParameter(paramName, value); return String.format("(%s is not null and %s)", field, stringOperationQuery); } - private String buildNumericPredicateQuery(String field, NumericFilterPredicate numericFilterPredicate) { - double value = numericFilterPredicate.getValue(); + private String buildNumericPredicateQuery(EntityQueryContext ctx, String field, NumericFilterPredicate numericFilterPredicate) { + String paramName = getNextParameterName(field); + ctx.addDoubleParameter(paramName, numericFilterPredicate.getValue()); String numericOperationQuery = ""; switch (numericFilterPredicate.getOperation()) { case EQUAL: - numericOperationQuery = String.format("%s = %s", field, value); + numericOperationQuery = String.format("%s = :%s", field, paramName); break; case NOT_EQUAL: - numericOperationQuery = String.format("%s != '%s'", field, value); + numericOperationQuery = String.format("%s != :%s", field, paramName); break; case GREATER: - numericOperationQuery = String.format("%s > %s", field, value); + numericOperationQuery = String.format("%s > :%s", field, paramName); break; case GREATER_OR_EQUAL: - numericOperationQuery = String.format("%s >= %s", field, value); + numericOperationQuery = String.format("%s >= :%s", field, paramName); break; case LESS: - numericOperationQuery = String.format("%s < %s", field, value); + numericOperationQuery = String.format("%s < :%s", field, paramName); break; case LESS_OR_EQUAL: - numericOperationQuery = String.format("%s <= %s", field, value); + numericOperationQuery = String.format("%s <= :%s", field, paramName); break; } return String.format("(%s is not null and %s)", field, numericOperationQuery); } - private String buildBooleanPredicateQuery(String field, + private String buildBooleanPredicateQuery(EntityQueryContext ctx, String field, BooleanFilterPredicate booleanFilterPredicate) { - boolean value = booleanFilterPredicate.isValue(); + String paramName = getNextParameterName(field); + ctx.addBooleanParameter(paramName, booleanFilterPredicate.isValue()); String booleanOperationQuery = ""; switch (booleanFilterPredicate.getOperation()) { case EQUAL: - booleanOperationQuery = String.format("%s = %s", field, value); + booleanOperationQuery = String.format("%s = :%s", field, paramName); break; case NOT_EQUAL: - booleanOperationQuery = String.format("%s != %s", field, value); + booleanOperationQuery = String.format("%s != :%s", field, paramName); break; } return String.format("(%s is not null and %s)", field, booleanOperationQuery); } + + private String getNextParameterName(String field) { + paramIdx++; + return field.replace(".", "_") + "_" + paramIdx; + } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityQueryContext.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityQueryContext.java new file mode 100644 index 0000000000..9aa433c300 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityQueryContext.java @@ -0,0 +1,122 @@ +/** + * Copyright © 2016-2020 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.sql.query; + +import org.hibernate.type.PostgresUUIDType; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; + +import java.sql.Types; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class EntityQueryContext implements SqlParameterSource { + private static final PostgresUUIDType UUID_TYPE = new PostgresUUIDType(); + + private final StringBuilder query; + private final Map params; + + public EntityQueryContext() { + query = new StringBuilder(); + params = new HashMap<>(); + } + + void addParameter(String name, Object value, int type, String typeName) { + Parameter existing = params.put(name, new Parameter(value, type, typeName)); + if (existing != null) { + throw new RuntimeException("Parameter with name: " + name + " was already registered!"); + } + } + + public void append(String s) { + query.append(s); + } + + @Override + public boolean hasValue(String paramName) { + return params.containsKey(paramName); + } + + @Override + public Object getValue(String paramName) throws IllegalArgumentException { + return checkParameter(paramName).value; + } + + @Override + public int getSqlType(String paramName) { + return checkParameter(paramName).type; + } + + private Parameter checkParameter(String paramName) { + Parameter param = params.get(paramName); + if (param == null) { + throw new RuntimeException("Parameter with name: " + paramName + " is not set!"); + } + return param; + } + + @Override + public String getTypeName(String paramName) { + return params.get(paramName).name; + } + + @Override + public String[] getParameterNames() { + return params.keySet().toArray(new String[]{}); + } + + public void addUuidParameter(String name, UUID value) { + addParameter(name, value, UUID_TYPE.sqlType(), UUID_TYPE.getName()); + } + + public void addStringParameter(String name, String value) { + addParameter(name, value, Types.VARCHAR, "VARCHAR"); + } + + public void addDoubleParameter(String name, double value) { + addParameter(name, value, Types.DOUBLE, "DOUBLE"); + } + + public void addStringListParameter(String name, List value) { + addParameter(name, value, Types.VARCHAR, "VARCHAR"); + } + + public void addBooleanParameter(String name, boolean value) { + addParameter(name, value, Types.BOOLEAN, "BOOLEAN"); + } + + public void addUuidListParameter(String name, List value) { + addParameter(name, value, UUID_TYPE.sqlType(), UUID_TYPE.getName()); + } + + public String getQuery() { + return query.toString(); + } + + + public static class Parameter { + private final Object value; + private final int type; + private final String name; + + public Parameter(Object value, int type, String name) { + this.value = value; + this.type = type; + this.name = name; + } + } +} diff --git a/dao/src/test/java/org/thingsboard/server/dao/SqlDaoServiceTestSuite.java b/dao/src/test/java/org/thingsboard/server/dao/SqlDaoServiceTestSuite.java index a9239a6588..a6ef3935b0 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/SqlDaoServiceTestSuite.java +++ b/dao/src/test/java/org/thingsboard/server/dao/SqlDaoServiceTestSuite.java @@ -24,30 +24,30 @@ import java.util.Arrays; @RunWith(ClasspathSuite.class) @ClassnameFilters({ - "org.thingsboard.server.dao.service.sql.EntityServiceSqlTest" + "org.thingsboard.server.dao.service.sql.*SqlTest" }) public class SqlDaoServiceTestSuite { -// @ClassRule -// public static CustomSqlUnit sqlUnit = new CustomSqlUnit( -// Arrays.asList("sql/schema-ts-hsql.sql", "sql/schema-entities-hsql.sql", "sql/schema-entities-idx.sql" -// , "sql/system-data.sql" -// , "sql/system-test.sql" -// ), -// "sql/hsql/drop-all-tables.sql", -// "sql-test.properties" -// ); - @ClassRule public static CustomSqlUnit sqlUnit = new CustomSqlUnit( - Arrays.asList("sql/schema-ts-psql.sql" - , "sql/schema-entities.sql", "sql/schema-entities-idx.sql" - , "sql/system-data.sql", "sql/system-test.sql" + Arrays.asList("sql/schema-ts-hsql.sql", "sql/schema-entities-hsql.sql", "sql/schema-entities-idx.sql" + , "sql/system-data.sql" + , "sql/system-test.sql" ), - "sql/psql/drop-all-tables.sql", + "sql/hsql/drop-all-tables.sql", "sql-test.properties" ); +// @ClassRule +// public static CustomSqlUnit sqlUnit = new CustomSqlUnit( +// Arrays.asList("sql/schema-ts-psql.sql" +// , "sql/schema-entities.sql", "sql/schema-entities-idx.sql" +// , "sql/system-data.sql", "sql/system-test.sql" +// ), +// "sql/psql/drop-all-tables.sql", +// "sql-test.properties" +// ); + // @ClassRule // public static CustomSqlUnit sqlUnit = new CustomSqlUnit( // Arrays.asList("sql/schema-timescale.sql", "sql/schema-entities.sql", "sql/schema-entities-idx.sql", "sql/system-data.sql", "sql/system-test.sql"), diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceTest.java index 8691986005..1e3d334e22 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceTest.java @@ -20,6 +20,7 @@ import com.google.common.util.concurrent.ListenableFuture; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.thingsboard.server.common.data.DataConstants; diff --git a/dao/src/test/resources/sql-test.properties b/dao/src/test/resources/sql-test.properties index 1807a89b55..b353bcc048 100644 --- a/dao/src/test/resources/sql-test.properties +++ b/dao/src/test/resources/sql-test.properties @@ -3,18 +3,18 @@ database.ts.type=sql sql.ts_inserts_executor_type=fixed sql.ts_inserts_fixed_thread_pool_size=200 sql.ts_key_value_partitioning=MONTHS - -#spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true -#spring.jpa.properties.hibernate.order_by.default_null_ordering=last -#spring.jpa.show-sql=false -#spring.jpa.hibernate.ddl-auto=validate -#spring.jpa.database-platform=org.hibernate.dialect.HSQLDialect # -#spring.datasource.username=sa -#spring.datasource.password= -#spring.datasource.url=jdbc:hsqldb:file:/tmp/testDb;sql.enforce_size=false -#spring.datasource.driverClassName=org.hsqldb.jdbc.JDBCDriver -#spring.datasource.hikari.maximumPoolSize = 50 +spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true +spring.jpa.properties.hibernate.order_by.default_null_ordering=last +spring.jpa.show-sql=false +spring.jpa.hibernate.ddl-auto=validate +spring.jpa.database-platform=org.hibernate.dialect.HSQLDialect + +spring.datasource.username=sa +spring.datasource.password= +spring.datasource.url=jdbc:hsqldb:file:/tmp/testDb;sql.enforce_size=false +spring.datasource.driverClassName=org.hsqldb.jdbc.JDBCDriver +spring.datasource.hikari.maximumPoolSize = 50 service.type=monolith @@ -26,16 +26,16 @@ service.type=monolith #sql.ts_inserts_fixed_thread_pool_size=200 #sql.ts_key_value_partitioning=MONTHS # -spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true -spring.jpa.show-sql=false -spring.jpa.hibernate.ddl-auto=none -spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect - -spring.datasource.username=postgres -spring.datasource.password=postgres -spring.datasource.url=jdbc:postgresql://localhost:5432/sqltest -spring.datasource.driverClassName=org.postgresql.Driver -spring.datasource.hikari.maximumPoolSize = 50 +#spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true +#spring.jpa.show-sql=false +#spring.jpa.hibernate.ddl-auto=none +#spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect +# +#spring.datasource.username=postgres +#spring.datasource.password=postgres +#spring.datasource.url=jdbc:postgresql://localhost:5432/sqltest +#spring.datasource.driverClassName=org.postgresql.Driver +#spring.datasource.hikari.maximumPoolSize = 50 queue.core.pack-processing-timeout=3000 queue.rule-engine.pack-processing-timeout=3000 From f37ebb66aa39283a16fd80fae3bdb015292bfd8f Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Mon, 22 Jun 2020 18:55:15 +0300 Subject: [PATCH 3/3] UI: Entities data query --- .../json/system/widget_bundles/cards.json | 32 +- .../query/DefaultEntityQueryRepository.java | 2 +- .../dao/sql/query/EntityKeyMapping.java | 1 + ui-ngx/src/app/core/api/alias-controller.ts | 54 ++- .../app/core/api/entity-data-subscription.ts | 361 ++++++++++-------- .../src/app/core/api/entity-data.service.ts | 91 +++-- ui-ngx/src/app/core/api/widget-api.models.ts | 13 +- .../src/app/core/api/widget-subscription.ts | 215 ++++++----- ui-ngx/src/app/core/http/entity.service.ts | 87 +++-- .../core/ws/telemetry-websocket.service.ts | 11 + .../lib/entities-table-widget.component.html | 2 +- .../lib/entities-table-widget.component.ts | 156 ++++++-- .../widget/lib/table-widget.models.ts | 58 +++ .../widget/widget-component.service.ts | 7 + .../components/widget/widget.component.ts | 9 +- .../app/shared/models/query/query.models.ts | 31 +- .../models/telemetry/telemetry.models.ts | 11 +- ui-ngx/src/app/shared/models/widget.models.ts | 2 + 18 files changed, 730 insertions(+), 413 deletions(-) diff --git a/application/src/main/data/json/system/widget_bundles/cards.json b/application/src/main/data/json/system/widget_bundles/cards.json index 1c96d7168e..8f115009d0 100644 --- a/application/src/main/data/json/system/widget_bundles/cards.json +++ b/application/src/main/data/json/system/widget_bundles/cards.json @@ -21,22 +21,6 @@ "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Attributes card\"}" } }, - { - "alias": "entities_table", - "name": "Entities table", - "descriptor": { - "type": "latest", - "sizeX": 7.5, - "sizeY": 6.5, - "resources": [], - "templateHtml": "\n", - "templateCss": "", - "controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.entitiesTableWidget.onDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n dataKeysOptional: true\n };\n}\n\nself.actionSources = function() {\n return {\n 'actionCellButton': {\n name: 'widget-action.action-cell-button',\n multiple: true\n },\n 'rowClick': {\n name: 'widget-action.row-click',\n multiple: false\n },\n 'rowDoubleClick': {\n name: 'widget-action.row-double-click',\n multiple: false\n }\n };\n}\n\nself.onDestroy = function() {\n}\n", - "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"entitiesTitle\": {\n \"title\": \"Entities table title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"enableSearch\": {\n \"title\": \"Enable entities search\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"enableSelectColumnDisplay\": {\n \"title\": \"Enable select columns to display\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"displayEntityName\": {\n \"title\": \"Display entity name column\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"entityNameColumnTitle\": {\n \"title\": \"Entity name column title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"displayEntityLabel\": {\n \"title\": \"Display entity label column\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"entityLabelColumnTitle\": {\n \"title\": \"Entity label column title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"displayEntityType\": {\n \"title\": \"Display entity type column\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"displayPagination\": {\n \"title\": \"Display pagination\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"defaultPageSize\": {\n \"title\": \"Default page size\",\n \"type\": \"number\",\n \"default\": 10\n },\n \"defaultSortOrder\": {\n \"title\": \"Default sort order\",\n \"type\": \"string\",\n \"default\": \"entityName\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"entitiesTitle\",\n \"enableSearch\",\n \"enableSelectColumnDisplay\",\n \"displayEntityName\",\n \"entityNameColumnTitle\",\n \"displayEntityLabel\",\n \"entityLabelColumnTitle\",\n \"displayEntityType\",\n \"displayPagination\",\n \"defaultPageSize\",\n \"defaultSortOrder\"\n ]\n}", - "dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {\n \"columnWidth\": {\n \"title\": \"Column width (px or %)\",\n \"type\": \"string\",\n \"default\": \"0px\"\n },\n \"useCellStyleFunction\": {\n \"title\": \"Use cell style function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellStyleFunction\": {\n \"title\": \"Cell style function: f(value)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"useCellContentFunction\": {\n \"title\": \"Use cell content function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellContentFunction\": {\n \"title\": \"Cell content function: f(value, entity, ctx)\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"columnWidth\",\n \"useCellStyleFunction\",\n {\n \"key\": \"cellStyleFunction\",\n \"type\": \"javascript\"\n },\n \"useCellContentFunction\",\n {\n \"key\": \"cellContentFunction\",\n \"type\": \"javascript\"\n }\n ]\n}", - "defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{\"enableSelection\":true,\"enableSearch\":true,\"displayDetails\":true,\"displayPagination\":true,\"defaultPageSize\":10,\"defaultSortOrder\":\"entityName\",\"displayEntityName\":true,\"displayEntityType\":true},\"title\":\"Entities table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"datasources\":[{\"type\":\"function\",\"name\":\"Simulated\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Sin\",\"color\":\"#2196f3\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.472295003170325,\"funcBody\":\"return Math.round(1000*Math.sin(time/5000));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Cos\",\"color\":\"#4caf50\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.8926244886945558,\"funcBody\":\"return Math.round(1000*Math.cos(time/5000));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#f44336\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.6401141393938932,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}]}" - } - }, { "alias": "html_card", "name": "HTML Card", @@ -132,6 +116,22 @@ "dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {},\n \"required\": []\n },\n \"form\": []\n}", "defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{\"nodeRelationQueryFunction\":\"/**\\n\\n// Function should return relations query object for current node used to fetch entity children.\\n// Function can return 'default' string value. In this case default relations query will be used.\\n\\n// The following example code will construct simple relations query that will fetch relations of type 'Contains'\\n// from the current entity.\\n\\nvar entity = nodeCtx.entity;\\nvar query = {\\n parameters: {\\n rootId: entity.id.id,\\n rootType: entity.id.entityType,\\n direction: types.entitySearchDirection.from,\\n relationTypeGroup: \\\"COMMON\\\",\\n maxLevel: 1\\n },\\n filters: [{\\n relationType: \\\"Contains\\\",\\n entityTypes: []\\n }]\\n};\\nreturn query;\\n\\n**/\\n\",\"nodeHasChildrenFunction\":\"/**\\n\\n// Function should return boolean value indicating whether current node has children (whether it can be expanded).\\n\\n// The following example code will restrict entities hierarchy expansion up to third level.\\n\\nreturn nodeCtx.level <= 2;\\n\\n// The next example code will restrict entities expansion according to the value of example 'nodeHasChildren' attribute.\\n\\nvar data = nodeCtx.data;\\nif (data.hasOwnProperty('nodeHasChildren') && data['nodeHasChildren'] !== null) {\\n return data['nodeHasChildren'] === 'true';\\n} else {\\n return true;\\n}\\n \\n**/\\n \",\"nodeTextFunction\":\"/**\\n\\n// Function should return text (can be HTML code) for the current node.\\n\\n// The following example code will generate node text consisting of entity name and temperature if temperature value is present in entity attributes/timeseries.\\n\\nvar data = nodeCtx.data;\\nvar entity = nodeCtx.entity;\\nvar text = entity.name;\\nif (data.hasOwnProperty('temperature') && data['temperature'] !== null) {\\n text += \\\" \\\"+ data['temperature'] +\\\" °C\\\";\\n}\\nreturn text;\\n\\n**/\",\"nodeIconFunction\":\"/** \\n\\n// Function should return node icon info object.\\n// Resulting object should contain either 'materialIcon' or 'iconUrl' property. \\n// Where:\\n - 'materialIcon' - name of the material icon to be used from the Material Icons Library (https://material.io/tools/icons);\\n - 'iconUrl' - url of the external image to be used as node icon.\\n// Function can return 'default' string value. In this case default icons according to entity type will be used.\\n\\n// The following example code shows how to use external image for devices which name starts with 'Test' and use \\n// default icons for the rest of entities.\\n\\nvar entity = nodeCtx.entity;\\nif (entity.id.entityType === 'DEVICE' && entity.name.startsWith('Test')) {\\n return {iconUrl: 'https://avatars1.githubusercontent.com/u/14793288?v=4&s=117'};\\n} else {\\n return 'default';\\n}\\n \\n**/\",\"nodeDisabledFunction\":\"/**\\n\\n// Function should return boolean value indicating whether current node should be disabled (not selectable).\\n\\n// The following example code will disable current node according to the value of example 'nodeDisabled' attribute.\\n\\nvar data = nodeCtx.data;\\nif (data.hasOwnProperty('nodeDisabled') && data['nodeDisabled'] !== null) {\\n return data['nodeDisabled'] === 'true';\\n} else {\\n return false;\\n}\\n \\n**/\\n\",\"nodesSortFunction\":\"/**\\n\\n// This function is used to sort nodes of the same level. Function should compare two nodes and return \\n// integer value: \\n// - less than 0 - sort nodeCtx1 to an index lower than nodeCtx2\\n// - 0 - leave nodeCtx1 and nodeCtx2 unchanged with respect to each other\\n// - greater than 0 - sort nodeCtx2 to an index lower than nodeCtx1\\n\\n// The following example code will sort entities first by entity type in alphabetical order then\\n// by entity name in alphabetical order.\\n\\nvar result = nodeCtx1.entity.id.entityType.localeCompare(nodeCtx2.entity.id.entityType);\\nif (result === 0) {\\n result = nodeCtx1.entity.name.localeCompare(nodeCtx2.entity.name);\\n}\\nreturn result;\\n \\n**/\",\"nodeOpenedFunction\":\"/**\\n\\n// Function should return boolean value indicating whether current node should be opened (expanded) when it first loaded.\\n\\n// The following example code will open by default nodes up to third level.\\n\\nreturn nodeCtx.level <= 2;\\n\\n**/\\n \"},\"title\":\"Entities hierarchy\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"datasources\":[{\"type\":\"function\",\"name\":\"Simulated\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Sin\",\"color\":\"#2196f3\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.472295003170325,\"funcBody\":\"return Math.round(1000*Math.sin(time/5000));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Cos\",\"color\":\"#4caf50\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.8926244886945558,\"funcBody\":\"return Math.round(1000*Math.cos(time/5000));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#f44336\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.6401141393938932,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"widgetStyle\":{},\"actions\":{}}" } + }, + { + "alias": "entities_table", + "name": "Entities table", + "descriptor": { + "type": "latest", + "sizeX": 7.5, + "sizeY": 6.5, + "resources": [], + "templateHtml": "\n", + "templateCss": "", + "controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.entitiesTableWidget.onDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n hasDataPageLink: true,\n dataKeysOptional: true\n };\n}\n\nself.actionSources = function() {\n return {\n 'actionCellButton': {\n name: 'widget-action.action-cell-button',\n multiple: true\n },\n 'rowClick': {\n name: 'widget-action.row-click',\n multiple: false\n },\n 'rowDoubleClick': {\n name: 'widget-action.row-double-click',\n multiple: false\n }\n };\n}\n\nself.onDestroy = function() {\n}\n", + "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"entitiesTitle\": {\n \"title\": \"Entities table title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"enableSearch\": {\n \"title\": \"Enable entities search\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"enableSelectColumnDisplay\": {\n \"title\": \"Enable select columns to display\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"displayEntityName\": {\n \"title\": \"Display entity name column\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"entityNameColumnTitle\": {\n \"title\": \"Entity name column title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"displayEntityLabel\": {\n \"title\": \"Display entity label column\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"entityLabelColumnTitle\": {\n \"title\": \"Entity label column title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"displayEntityType\": {\n \"title\": \"Display entity type column\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"displayPagination\": {\n \"title\": \"Display pagination\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"defaultPageSize\": {\n \"title\": \"Default page size\",\n \"type\": \"number\",\n \"default\": 10\n },\n \"defaultSortOrder\": {\n \"title\": \"Default sort order\",\n \"type\": \"string\",\n \"default\": \"entityName\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"entitiesTitle\",\n \"enableSearch\",\n \"enableSelectColumnDisplay\",\n \"displayEntityName\",\n \"entityNameColumnTitle\",\n \"displayEntityLabel\",\n \"entityLabelColumnTitle\",\n \"displayEntityType\",\n \"displayPagination\",\n \"defaultPageSize\",\n \"defaultSortOrder\"\n ]\n}", + "dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {\n \"columnWidth\": {\n \"title\": \"Column width (px or %)\",\n \"type\": \"string\",\n \"default\": \"0px\"\n },\n \"useCellStyleFunction\": {\n \"title\": \"Use cell style function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellStyleFunction\": {\n \"title\": \"Cell style function: f(value)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"useCellContentFunction\": {\n \"title\": \"Use cell content function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellContentFunction\": {\n \"title\": \"Cell content function: f(value, entity, ctx)\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"columnWidth\",\n \"useCellStyleFunction\",\n {\n \"key\": \"cellStyleFunction\",\n \"type\": \"javascript\"\n },\n \"useCellContentFunction\",\n {\n \"key\": \"cellContentFunction\",\n \"type\": \"javascript\"\n }\n ]\n}", + "defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{\"enableSelection\":true,\"enableSearch\":true,\"displayDetails\":true,\"displayPagination\":true,\"defaultPageSize\":10,\"defaultSortOrder\":\"entityName\",\"displayEntityName\":true,\"displayEntityType\":true},\"title\":\"Entities table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"datasources\":[{\"type\":\"function\",\"name\":\"Simulated\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Sin\",\"color\":\"#2196f3\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.472295003170325,\"funcBody\":\"return Math.round(1000*Math.sin(time/5000));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Cos\",\"color\":\"#4caf50\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.8926244886945558,\"funcBody\":\"return Math.round(1000*Math.cos(time/5000));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#f44336\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.6401141393938932,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}]}" + } } ] } \ No newline at end of file diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java index a88e65e37c..8ffe29a450 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java @@ -452,7 +452,7 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { } private String entityNameQuery(EntityNameFilter filter) { - return String.format("lower(e.search_text) like lower(concat(%s, '%%'))", filter.getEntityNameFilter()); + return String.format("lower(e.search_text) like lower(concat('%s', '%%'))", filter.getEntityNameFilter()); } private String typeQuery(EntityFilter filter) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java index a71b6e8d85..19fa447e88 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java @@ -48,6 +48,7 @@ public class EntityKeyMapping { static { entityFieldColumnMap.put("createdTime", "id"); + entityFieldColumnMap.put("entityType", "entity_type"); entityFieldColumnMap.put("name", "name"); entityFieldColumnMap.put("type", "type"); entityFieldColumnMap.put("label", "label"); diff --git a/ui-ngx/src/app/core/api/alias-controller.ts b/ui-ngx/src/app/core/api/alias-controller.ts index e0afe96c42..f0beea751e 100644 --- a/ui-ngx/src/app/core/api/alias-controller.ts +++ b/ui-ngx/src/app/core/api/alias-controller.ts @@ -22,8 +22,8 @@ import { EntityService } from '@core/http/entity.service'; import { UtilsService } from '@core/services/utils.service'; import { AliasFilterType, EntityAliases } from '@shared/models/alias.models'; import { EntityInfo } from '@shared/models/entity.models'; -import { map } from 'rxjs/operators'; -import { defaultEntityDataPageLink } from '@shared/models/query/query.models'; +import { map, mergeMap } from 'rxjs/operators'; +import { createDefaultEntityDataPageLink, defaultEntityDataPageLink } from '@shared/models/query/query.models'; export class AliasController implements IAliasController { @@ -169,7 +169,24 @@ export class AliasController implements IAliasController { } } - private resolveDatasource(datasource: Datasource, isSingle?: boolean): Observable> { + resolveSingleEntityInfo(aliasId: string): Observable { + return this.getAliasInfo(aliasId).pipe( + mergeMap((aliasInfo) => { + if (aliasInfo.resolveMultiple) { + if (aliasInfo.entityFilter) { + return this.entityService.findSingleEntityInfoByEntityFilter(aliasInfo.entityFilter, + {ignoreLoading: true, ignoreErrors: true}); + } else { + return of(null); + } + } else { + return of(aliasInfo.currentEntity); + } + }) + ); + } + + private resolveDatasource(datasource: Datasource, isSingle?: boolean): Observable { if (datasource.type === DatasourceType.entity) { if (datasource.entityAliasId) { return this.getAliasInfo(datasource.entityAliasId).pipe( @@ -200,14 +217,14 @@ export class AliasController implements IAliasController { datasources.push(newDatasource); } return datasources;*/ - return [newDatasource]; + return newDatasource; } else { if (aliasInfo.stateEntity) { newDatasource = deepClone(datasource); newDatasource.unresolvedStateEntity = true; - return [newDatasource]; + return newDatasource; } else { - return []; + return null; // throw new Error('Unable to resolve datasource.'); } } @@ -232,13 +249,13 @@ export class AliasController implements IAliasController { entityType: entity.entityType } }; - return [datasource]; + return datasource; } else { if (aliasInfo.stateEntity) { datasource.unresolvedStateEntity = true; - return [datasource]; + return datasource; } else { - return []; + return null; // throw new Error('Unable to resolve datasource.'); } } @@ -248,10 +265,10 @@ export class AliasController implements IAliasController { } else { datasource.aliasName = datasource.entityName; datasource.name = datasource.entityName; - return of([datasource]); + return of(datasource); } } else { - return of([datasource]); + return of(datasource); } } @@ -354,18 +371,14 @@ export class AliasController implements IAliasController { ); } - resolveDatasources(datasources: Array): Observable> { - const newDatasources = deepClone(datasources); - const observables = new Array>>(); + resolveDatasources(datasources: Array, singleEntity?: boolean): Observable> { + const newDatasources = deepClone(singleEntity ? [datasources[0]] : datasources); + const observables = new Array>(); newDatasources.forEach((datasource) => { observables.push(this.resolveDatasource(datasource)); }); return forkJoin(observables).pipe( - map((arrayOfDatasources) => { - const result = new Array(); - arrayOfDatasources.forEach((datasourcesArray) => { - result.push(...datasourcesArray); - }); + map((result) => { let functionIndex = 0; result.forEach((datasource) => { if (datasource.type === DatasourceType.function) { @@ -386,6 +399,9 @@ export class AliasController implements IAliasController { datasource.name = 'Unresolved'; datasource.entityName = 'Unresolved'; } else if (datasource.type === DatasourceType.entity) { + if (singleEntity) { + datasource.pageLink = createDefaultEntityDataPageLink(1); + } if (!datasource.pageLink) { datasource.pageLink = deepClone(defaultEntityDataPageLink); } diff --git a/ui-ngx/src/app/core/api/entity-data-subscription.ts b/ui-ngx/src/app/core/api/entity-data-subscription.ts index d700672d53..591a5436d4 100644 --- a/ui-ngx/src/app/core/api/entity-data-subscription.ts +++ b/ui-ngx/src/app/core/api/entity-data-subscription.ts @@ -35,19 +35,21 @@ import { TelemetrySubscriber } from '@shared/models/telemetry/telemetry.models'; import { UtilsService } from '@core/services/utils.service'; -import { EntityDataListener } from '@core/api/entity-data.service'; +import { EntityDataListener, EntityDataLoadResult } from '@core/api/entity-data.service'; import { deepClone, isDefinedAndNotNull, isObject, objectHashCode } from '@core/utils'; import { PageData } from '@shared/models/page/page-data'; import { DataAggregator } from '@core/api/data-aggregator'; import { NULL_UUID } from '@shared/models/id/has-uuid'; import { EntityType } from '@shared/models/entity-type.models'; import Timeout = NodeJS.Timeout; +import { Observable, of, ReplaySubject, Subject } from 'rxjs'; export interface EntityDataSubscriptionOptions { datasourceType: DatasourceType; dataKeys: Array; type: widgetType; entityFilter?: EntityFilter; + isLatestDataSubscription?: boolean; pageLink?: EntityDataPageLink; keyFilters?: Array; subscriptionTimewindow?: SubscriptionTimewindow; @@ -59,21 +61,19 @@ declare type DataUpdatedCb = (data: DataSetHolder, dataIndex: number, dataKeyInd export class EntityDataSubscription { - private listeners: Array = []; private datasourceType: DatasourceType = this.entityDataSubscriptionOptions.datasourceType; - - private history = this.entityDataSubscriptionOptions.subscriptionTimewindow && - isObject(this.entityDataSubscriptionOptions.subscriptionTimewindow.fixedWindow); - - private realtime = this.entityDataSubscriptionOptions.subscriptionTimewindow && - isDefinedAndNotNull(this.entityDataSubscriptionOptions.subscriptionTimewindow.realtimeWindowMs); + private history: boolean; + private realtime: boolean; private subscriber: TelemetrySubscriber; + private dataCommand: EntityDataCmd; + private subsCommand: EntityDataCmd; private attrFields: Array; private tsFields: Array; private latestValues: Array; + private entityDataResolveSubject: Subject; private pageData: PageData; private subsTw: SubscriptionTimewindow; private dataAggregators: Array; @@ -87,7 +87,11 @@ export class EntityDataSubscription { private tickElapsed = 0; private timer: Timeout; - constructor(private entityDataSubscriptionOptions: EntityDataSubscriptionOptions, + private dataResolved = false; + private started = false; + + constructor(public entityDataSubscriptionOptions: EntityDataSubscriptionOptions, + private listener: EntityDataListener, private telemetryService: TelemetryService, private utils: UtilsService) { this.initializeSubscription(); @@ -126,50 +130,6 @@ export class EntityDataSubscription { } dataKey.key = key; } - if (this.datasourceType === DatasourceType.function) { - this.frequency = 1000; - if (this.entityDataSubscriptionOptions.type === widgetType.timeseries) { - this.frequency = Math.min(this.entityDataSubscriptionOptions.subscriptionTimewindow.aggregation.interval, 5000); - } - } - } - - public addListener(listener: EntityDataListener) { - this.listeners.push(listener); - } - - public hasListeners(): boolean { - return this.listeners.length > 0; - } - - public removeListener(listener: EntityDataListener) { - this.listeners.splice(this.listeners.indexOf(listener), 1); - } - - public syncListener(listener: EntityDataListener) { - if (this.pageData) { - let key: string; - let dataKey: SubscriptionDataKey; - const data: Array> = []; - for (let dataIndex = 0; dataIndex < this.pageData.data.length; dataIndex++) { - data[dataIndex] = []; - for (key of Object.keys(this.dataKeys)) { - if (this.datasourceType === DatasourceType.entity || this.entityDataSubscriptionOptions.type === widgetType.timeseries) { - const dataKeysList = this.dataKeys[key] as Array; - for (let i = 0; i < dataKeysList.length; i++) { - dataKey = dataKeysList[i]; - const datasourceKey = `${key}_${i}`; - data[dataIndex][dataKey.index] = this.datasourceData[dataIndex][datasourceKey]; - } - } else { - dataKey = this.dataKeys[key] as SubscriptionDataKey; - data[dataIndex][dataKey.index] = this.datasourceData[dataIndex][key]; - } - } - } - listener.dataLoaded(this.pageData, data, listener.configDatasourceIndex); - } - this.listeners.push(listener); } public unsubscribe() { @@ -192,19 +152,30 @@ export class EntityDataSubscription { this.pageData = null; } - public start() { - this.subsTw = this.entityDataSubscriptionOptions.subscriptionTimewindow; + public subscribe(): Observable { + if (!this.entityDataSubscriptionOptions.isLatestDataSubscription) { + this.entityDataResolveSubject = new ReplaySubject(1); + } else { + this.started = true; + this.dataResolved = true; + } if (this.datasourceType === DatasourceType.entity) { const entityFields: Array = this.entityDataSubscriptionOptions.dataKeys.filter(dataKey => dataKey.type === DataKeyType.entityField).map( - dataKey => ({ type: EntityKeyType.ENTITY_FIELD, key: dataKey.name }) - ); + dataKey => ({ type: EntityKeyType.ENTITY_FIELD, key: dataKey.name }) + ); if (!entityFields.find(key => key.key === 'name')) { entityFields.push({ type: EntityKeyType.ENTITY_FIELD, key: 'name' }); } + if (!entityFields.find(key => key.key === 'label')) { + entityFields.push({ + type: EntityKeyType.ENTITY_FIELD, + key: 'label' + }); + } this.attrFields = this.entityDataSubscriptionOptions.dataKeys.filter(dataKey => dataKey.type === DataKeyType.attribute).map( dataKey => ({ type: EntityKeyType.ATTRIBUTE, key: dataKey.name }) @@ -217,9 +188,9 @@ export class EntityDataSubscription { this.latestValues = this.attrFields.concat(this.tsFields); this.subscriber = new TelemetrySubscriber(this.telemetryService); - const command = new EntityDataCmd(); + this.dataCommand = new EntityDataCmd(); - command.query = { + this.dataCommand.query = { entityFilter: this.entityDataSubscriptionOptions.entityFilter, pageLink: this.entityDataSubscriptionOptions.pageLink, keyFilters: this.entityDataSubscriptionOptions.keyFilters, @@ -227,72 +198,17 @@ export class EntityDataSubscription { latestValues: this.latestValues }; - if (this.entityDataSubscriptionOptions.type === widgetType.timeseries) { - if (this.tsFields.length > 0) { - if (this.history) { - command.historyCmd = { - keys: this.tsFields.map(key => key.key), - startTs: this.subsTw.fixedWindow.startTimeMs, - endTs: this.subsTw.fixedWindow.endTimeMs, - interval: this.subsTw.aggregation.interval, - limit: this.subsTw.aggregation.limit, - agg: this.subsTw.aggregation.type + if (this.entityDataSubscriptionOptions.isLatestDataSubscription) { + if (this.entityDataSubscriptionOptions.type === widgetType.latest) { + if (this.latestValues.length > 0) { + this.dataCommand.latestCmd = { + keys: this.latestValues }; - if (this.subsTw.aggregation.stateData) { - command.historyCmd.startTs -= YEAR; - } - } else { - command.tsCmd = { - keys: this.tsFields.map(key => key.key), - startTs: this.subsTw.startTs, - timeWindow: this.subsTw.aggregation.timeWindow, - interval: this.subsTw.aggregation.interval, - limit: this.subsTw.aggregation.limit, - agg: this.subsTw.aggregation.type - } - if (this.subsTw.aggregation.stateData) { - command.historyCmd = { - keys: this.tsFields.map(key => key.key), - startTs: this.subsTw.startTs - YEAR, - endTs: this.subsTw.startTs, - interval: this.subsTw.aggregation.interval, - limit: this.subsTw.aggregation.limit, - agg: this.subsTw.aggregation.type - }; - } - this.subscriber.reconnect$.subscribe(() => { - let newSubsTw: SubscriptionTimewindow = null; - this.listeners.forEach((listener) => { - if (!newSubsTw) { - newSubsTw = listener.updateRealtimeSubscription(); - } else { - listener.setRealtimeSubscription(newSubsTw); - } - }); - this.subsTw = newSubsTw; - command.tsCmd.startTs = this.subsTw.startTs; - command.tsCmd.timeWindow = this.subsTw.aggregation.timeWindow; - command.tsCmd.interval = this.subsTw.aggregation.interval; - command.tsCmd.limit = this.subsTw.aggregation.limit; - command.tsCmd.agg = this.subsTw.aggregation.type; - if (this.subsTw.aggregation.stateData) { - command.historyCmd.startTs = this.subsTw.startTs - YEAR; - command.historyCmd.endTs = this.subsTw.startTs; - command.historyCmd.interval = this.subsTw.aggregation.interval; - command.historyCmd.limit = this.subsTw.aggregation.limit; - command.historyCmd.agg = this.subsTw.aggregation.type; - } - }); } } - } else if (this.entityDataSubscriptionOptions.type === widgetType.latest) { - if (this.latestValues.length > 0) { - command.latestCmd = { - keys: this.latestValues.map(key => key.key) - }; - } } - this.subscriber.subscriptionCommands.push(command); + + this.subscriber.subscriptionCommands.push(this.dataCommand); this.subscriber.entityData$.subscribe( (entityDataUpdate) => { @@ -304,6 +220,30 @@ export class EntityDataSubscription { } ); + this.subscriber.reconnect$.subscribe(() => { + const newSubsTw: SubscriptionTimewindow = this.listener.updateRealtimeSubscription(); + this.listener.setRealtimeSubscription(newSubsTw); + this.subsTw = newSubsTw; + if (this.started && !this.entityDataSubscriptionOptions.isLatestDataSubscription) { + this.subsCommand.tsCmd.startTs = this.subsTw.startTs; + this.subsCommand.tsCmd.timeWindow = this.subsTw.aggregation.timeWindow; + this.subsCommand.tsCmd.interval = this.subsTw.aggregation.interval; + this.subsCommand.tsCmd.limit = this.subsTw.aggregation.limit; + this.subsCommand.tsCmd.agg = this.subsTw.aggregation.type; + if (this.subsTw.aggregation.stateData) { + this.subsCommand.historyCmd.startTs = this.subsTw.startTs - YEAR; + this.subsCommand.historyCmd.endTs = this.subsTw.startTs; + this.subsCommand.historyCmd.interval = this.subsTw.aggregation.interval; + this.subsCommand.historyCmd.limit = this.subsTw.aggregation.limit; + this.subsCommand.historyCmd.agg = this.subsTw.aggregation.type; + } + this.subsCommand.query = this.dataCommand.query; + this.subscriber.subscriptionCommands = [this.subsCommand]; + } else { + this.subscriber.subscriptionCommands = [this.dataCommand]; + } + }); + this.subscriber.subscribe(); } else if (this.datasourceType === DatasourceType.function) { const entityData: EntityData = { @@ -325,29 +265,46 @@ export class EntityDataSubscription { totalPages: 1 }; this.onPageData(pageData); - this.tickScheduledTime = this.utils.currentPerfTime(); - if (this.history) { - this.onTick(true); - } else { - this.timer = setTimeout(this.onTick.bind(this, true), 0); + if (this.entityDataSubscriptionOptions.isLatestDataSubscription) { + if (this.entityDataSubscriptionOptions.type === widgetType.latest) { + this.frequency = 1000; + this.timer = setTimeout(this.onTick.bind(this, true), 0); + } } } + if (this.entityDataSubscriptionOptions.isLatestDataSubscription) { + return of(null); + } else { + return this.entityDataResolveSubject.asObservable(); + } } - private onPageData(pageData: PageData) { + public start() { + if (this.entityDataSubscriptionOptions.isLatestDataSubscription) { + return; + } + this.subsTw = this.entityDataSubscriptionOptions.subscriptionTimewindow; + this.history = this.entityDataSubscriptionOptions.subscriptionTimewindow && + isObject(this.entityDataSubscriptionOptions.subscriptionTimewindow.fixedWindow); + this.realtime = this.entityDataSubscriptionOptions.subscriptionTimewindow && + isDefinedAndNotNull(this.entityDataSubscriptionOptions.subscriptionTimewindow.realtimeWindowMs); + + if (this.timer) { + clearTimeout(this.timer); + this.timer = null; + } + if (this.dataAggregators) { this.dataAggregators.forEach((aggregator) => { aggregator.destroy(); }) - this.dataAggregators = null; } - this.datasourceData = []; this.dataAggregators = []; - this.entityIdToDataIndex = {}; - let tsKeyNames; + this.resetData(); + if (this.entityDataSubscriptionOptions.type === widgetType.timeseries) { + let tsKeyNames = []; if (this.datasourceType === DatasourceType.function) { - tsKeyNames = []; for (const key of Object.keys(this.dataKeys)) { const dataKeysList = this.dataKeys[key] as Array; dataKeysList.forEach((subscriptionDataKey) => { @@ -357,20 +314,85 @@ export class EntityDataSubscription { } else { tsKeyNames = this.tsFields ? this.tsFields.map(field => field.key) : []; } - } - for (let dataIndex = 0; dataIndex < pageData.data.length; dataIndex++) { - const entityData = pageData.data[dataIndex]; - this.entityIdToDataIndex[entityData.entityId.id] = dataIndex; - this.datasourceData[dataIndex] = {}; - if (this.entityDataSubscriptionOptions.type === widgetType.timeseries) { + for (let dataIndex = 0; dataIndex < this.pageData.data.length; dataIndex++) { if (this.datasourceType === DatasourceType.function) { this.dataAggregators[dataIndex] = this.createRealtimeDataAggregator(this.subsTw, tsKeyNames, - DataKeyType.function, dataIndex, this.notifyListeners.bind(this)); + DataKeyType.function, dataIndex, this.notifyListener.bind(this)); } else if (!this.history && tsKeyNames.length) { this.dataAggregators[dataIndex] = this.createRealtimeDataAggregator(this.subsTw, tsKeyNames, - DataKeyType.timeseries, dataIndex, this.notifyListeners.bind(this)); + DataKeyType.timeseries, dataIndex, this.notifyListener.bind(this)); } } + } + if (this.datasourceType === DatasourceType.entity) { + this.subsCommand = new EntityDataCmd(); + this.subsCommand.cmdId = this.dataCommand.cmdId; + if (this.entityDataSubscriptionOptions.type === widgetType.timeseries) { + if (this.tsFields.length > 0) { + if (this.history) { + this.subsCommand.historyCmd = { + keys: this.tsFields.map(key => key.key), + startTs: this.subsTw.fixedWindow.startTimeMs, + endTs: this.subsTw.fixedWindow.endTimeMs, + interval: this.subsTw.aggregation.interval, + limit: this.subsTw.aggregation.limit, + agg: this.subsTw.aggregation.type + }; + if (this.subsTw.aggregation.stateData) { + this.subsCommand.historyCmd.startTs -= YEAR; + } + } else { + this.subsCommand.tsCmd = { + keys: this.tsFields.map(key => key.key), + startTs: this.subsTw.startTs, + timeWindow: this.subsTw.aggregation.timeWindow, + interval: this.subsTw.aggregation.interval, + limit: this.subsTw.aggregation.limit, + agg: this.subsTw.aggregation.type + } + if (this.subsTw.aggregation.stateData) { + this.subsCommand.historyCmd = { + keys: this.tsFields.map(key => key.key), + startTs: this.subsTw.startTs - YEAR, + endTs: this.subsTw.startTs, + interval: this.subsTw.aggregation.interval, + limit: this.subsTw.aggregation.limit, + agg: this.subsTw.aggregation.type + }; + } + } + } + } else if (this.entityDataSubscriptionOptions.type === widgetType.latest) { + if (this.latestValues.length > 0) { + this.subsCommand.latestCmd = { + keys: this.latestValues + }; + } + } + this.subscriber.subscriptionCommands = [this.subsCommand]; + this.subscriber.update(); + } else if (this.datasourceType === DatasourceType.function) { + this.frequency = 1000; + if (this.entityDataSubscriptionOptions.type === widgetType.timeseries) { + this.frequency = Math.min(this.entityDataSubscriptionOptions.subscriptionTimewindow.aggregation.interval, 5000); + } + this.tickScheduledTime = this.utils.currentPerfTime(); + if (this.history) { + this.onTick(true); + } else { + this.timer = setTimeout(this.onTick.bind(this, true), 0); + } + } + this.started = true; + } + + private resetData() { + this.datasourceData = []; + this.entityIdToDataIndex = {}; + for (let dataIndex = 0; dataIndex < this.pageData.data.length; dataIndex++) { + const entityData = this.pageData.data[dataIndex]; + this.entityIdToDataIndex[entityData.entityId.id] = dataIndex; + this.datasourceData[dataIndex] = {}; for (const key of Object.keys(this.dataKeys)) { const dataKey = this.dataKeys[key]; if (this.datasourceType === DatasourceType.entity || this.entityDataSubscriptionOptions.type === widgetType.timeseries) { @@ -388,7 +410,23 @@ export class EntityDataSubscription { } } this.datasourceOrigData = deepClone(this.datasourceData); + if (this.entityDataSubscriptionOptions.type === widgetType.timeseries) { + for (const key of Object.keys(this.dataKeys)) { + const dataKeyList = this.dataKeys[key] as Array; + dataKeyList.forEach((dataKey) => { + delete dataKey.lastUpdateTime; + }); + } + } else if (this.entityDataSubscriptionOptions.type === widgetType.latest) { + for (const key of Object.keys(this.dataKeys)) { + delete (this.dataKeys[key] as SubscriptionDataKey).lastUpdateTime; + } + } + } + private onPageData(pageData: PageData) { + this.pageData = pageData; + this.resetData(); const data: Array> = []; for (let dataIndex = 0; dataIndex < pageData.data.length; dataIndex++) { const entityData = pageData.data[dataIndex]; @@ -401,28 +439,33 @@ export class EntityDataSubscription { } ); } - - this.pageData = pageData; - - this.listeners.forEach((listener) => { - listener.dataLoaded(pageData, data, - listener.configDatasourceIndex); - }); + if (!this.dataResolved) { + this.dataResolved = true; + this.entityDataResolveSubject.next( + { + pageData, + data, + datasourceIndex: this.listener.configDatasourceIndex + } + ); + this.entityDataResolveSubject.complete(); + } else { + this.listener.dataLoaded(pageData, data, + this.listener.configDatasourceIndex); + } } private onDataUpdate(update: Array) { for (const entityData of update) { const dataIndex = this.entityIdToDataIndex[entityData.entityId.id]; - this.processEntityData(entityData, dataIndex, true, this.notifyListeners.bind(this)); + this.processEntityData(entityData, dataIndex, true, this.notifyListener.bind(this)); } } - private notifyListeners(data: DataSetHolder, dataIndex: number, dataKeyIndex: number, detectChanges: boolean) { - this.listeners.forEach((listener) => { - listener.dataUpdated(data, - listener.configDatasourceIndex, + private notifyListener(data: DataSetHolder, dataIndex: number, dataKeyIndex: number, detectChanges: boolean) { + this.listener.dataUpdated(data, + this.listener.configDatasourceIndex, dataIndex, dataKeyIndex, detectChanges); - }); } private processEntityData(entityData: EntityData, dataIndex: number, aggregate: boolean, @@ -596,14 +639,10 @@ export class EntityDataSubscription { const value = dataKey.func(time, prevSeries[1]); const series: [number, any] = [time, value]; this.datasourceData[0][dataKey.key].data = [series]; - this.listeners.forEach( - (listener) => { - listener.dataUpdated(this.datasourceData[0][dataKey.key], - listener.configDatasourceIndex, - 0, - dataKey.index, detectChanges); - } - ); + this.listener.dataUpdated(this.datasourceData[0][dataKey.key], + this.listener.configDatasourceIndex, + 0, + dataKey.index, detectChanges); } private onTick(detectChanges: boolean) { diff --git a/ui-ngx/src/app/core/api/entity-data.service.ts b/ui-ngx/src/app/core/api/entity-data.service.ts index b17e5f7b82..cddc9bcba0 100644 --- a/ui-ngx/src/app/core/api/entity-data.service.ts +++ b/ui-ngx/src/app/core/api/entity-data.service.ts @@ -24,17 +24,24 @@ import { UtilsService } from '@core/services/utils.service'; import { SubscriptionDataKey } from '@core/api/datasource-subcription'; import { deepClone, objectHashCode } from '@core/utils'; import { EntityDataSubscription, EntityDataSubscriptionOptions } from '@core/api/entity-data-subscription'; +import { Observable, of } from 'rxjs'; export interface EntityDataListener { subscriptionType: widgetType; - subscriptionTimewindow: SubscriptionTimewindow; + subscriptionTimewindow?: SubscriptionTimewindow; configDatasource: Datasource; configDatasourceIndex: number; dataLoaded: (pageData: PageData, data: Array>, datasourceIndex: number) => void; dataUpdated: (data: DataSetHolder, datasourceIndex: number, dataIndex: number, dataKeyIndex: number, detectChanges: boolean) => void; - updateRealtimeSubscription: () => SubscriptionTimewindow; - setRealtimeSubscription: (subscriptionTimewindow: SubscriptionTimewindow) => void; - entityDataSubscriptionKey?: number; + updateRealtimeSubscription?: () => SubscriptionTimewindow; + setRealtimeSubscription?: (subscriptionTimewindow: SubscriptionTimewindow) => void; + subscription?: EntityDataSubscription; +} + +export interface EntityDataLoadResult { + pageData: PageData; + data: Array>; + datasourceIndex: number; } @Injectable({ @@ -42,16 +49,48 @@ export interface EntityDataListener { }) export class EntityDataService { - private subscriptions: {[entityDataSubscriptionKey: string]: EntityDataSubscription} = {}; - constructor(private telemetryService: TelemetryWebsocketService, private utils: UtilsService) {} - public subscribeToEntityData(listener: EntityDataListener) { + public prepareSubscription(listener: EntityDataListener): Observable { const datasource = listener.configDatasource; if (datasource.type === DatasourceType.entity && (!datasource.entityFilter || !datasource.pageLink)) { + return of(null); + } + listener.subscription = this.createSubscription(listener, + datasource.pageLink, datasource.keyFilters, + false); + return listener.subscription.subscribe(); + } + + public startSubscription(listener: EntityDataListener) { + if (listener.subscriptionType === widgetType.timeseries) { + listener.subscription.entityDataSubscriptionOptions.subscriptionTimewindow = deepClone(listener.subscriptionTimewindow); + } + listener.subscription.start(); + } + + public subscribeForLatestData(listener: EntityDataListener, + pageLink: EntityDataPageLink, + keyFilters: KeyFilter[]) { + const datasource = listener.configDatasource; + if (datasource.type === DatasourceType.entity && (!datasource.entityFilter || !pageLink)) { return; } + listener.subscription = this.createSubscription(listener, + pageLink, keyFilters, true); + listener.subscription.subscribe(); + } + + public stopSubscription(listener: EntityDataListener) { + listener.subscription.unsubscribe(); + } + + private createSubscription(listener: EntityDataListener, + pageLink: EntityDataPageLink, + keyFilters: KeyFilter[], + isLatestDataSubscription: boolean): EntityDataSubscription { + const datasource = listener.configDatasource; const subscriptionDataKeys: Array = []; datasource.dataKeys.forEach((dataKey) => { const subscriptionDataKey: SubscriptionDataKey = { @@ -62,47 +101,19 @@ export class EntityDataService { }; subscriptionDataKeys.push(subscriptionDataKey); }); - const entityDataSubscriptionOptions: EntityDataSubscriptionOptions = { datasourceType: datasource.type, dataKeys: subscriptionDataKeys, type: listener.subscriptionType }; - - if (listener.subscriptionType === widgetType.timeseries) { - entityDataSubscriptionOptions.subscriptionTimewindow = deepClone(listener.subscriptionTimewindow); - } if (entityDataSubscriptionOptions.datasourceType === DatasourceType.entity) { entityDataSubscriptionOptions.entityFilter = datasource.entityFilter; - entityDataSubscriptionOptions.pageLink = datasource.pageLink; - entityDataSubscriptionOptions.keyFilters = datasource.keyFilters; - } - listener.entityDataSubscriptionKey = objectHashCode(entityDataSubscriptionOptions); - let subscription: EntityDataSubscription; - if (this.subscriptions[listener.entityDataSubscriptionKey]) { - subscription = this.subscriptions[listener.entityDataSubscriptionKey]; - subscription.syncListener(listener); - } else { - subscription = new EntityDataSubscription(entityDataSubscriptionOptions, - this.telemetryService, this.utils); - this.subscriptions[listener.entityDataSubscriptionKey] = subscription; - subscription.addListener(listener); - subscription.start(); - } - } - - public unsubscribeFromDatasource(listener: EntityDataListener) { - if (listener.entityDataSubscriptionKey) { - const subscription = this.subscriptions[listener.entityDataSubscriptionKey]; - if (subscription) { - subscription.removeListener(listener); - if (!subscription.hasListeners()) { - subscription.unsubscribe(); - delete this.subscriptions[listener.entityDataSubscriptionKey]; - } - } - listener.entityDataSubscriptionKey = null; + entityDataSubscriptionOptions.pageLink = pageLink; + entityDataSubscriptionOptions.keyFilters = keyFilters; } + entityDataSubscriptionOptions.isLatestDataSubscription = isLatestDataSubscription; + return new EntityDataSubscription(entityDataSubscriptionOptions, + listener, this.telemetryService, this.utils); } } diff --git a/ui-ngx/src/app/core/api/widget-api.models.ts b/ui-ngx/src/app/core/api/widget-api.models.ts index 5ab06505b7..c6a39e726b 100644 --- a/ui-ngx/src/app/core/api/widget-api.models.ts +++ b/ui-ngx/src/app/core/api/widget-api.models.ts @@ -98,7 +98,8 @@ export interface IAliasController { getAliasInfo(aliasId: string): Observable; getEntityAliasId(aliasName: string): string; getInstantAliasInfo(aliasId: string): AliasInfo; - resolveDatasources(datasources: Array): Observable>; + resolveSingleEntityInfo(aliasId: string): Observable; + resolveDatasources(datasources: Array, singleEntity?: boolean): Observable>; resolveAlarmSource(alarmSource: Datasource): Observable; getEntityAliases(): EntityAliases; updateCurrentAliasEntity(aliasId: string, currentEntity: EntityInfo); @@ -202,8 +203,8 @@ export interface WidgetSubscriptionOptions { alarmsMaxCountLoad?: number; alarmsFetchSize?: number; datasources?: Array; - keyFilters?: Array; - pageLink?: EntityDataPageLink; + hasDataPageLink?: boolean; + singleEntity?: boolean; targetDeviceAliasIds?: Array; targetDeviceIds?: Array; useDashboardTimewindow?: boolean; @@ -264,7 +265,7 @@ export interface IWidgetSubscription { onAliasesChanged(aliasIds: Array): boolean; - onDashboardTimewindowChanged(dashboardTimewindow: Timewindow): boolean; + onDashboardTimewindowChanged(dashboardTimewindow: Timewindow): void; updateDataVisibility(index: number): void; @@ -278,6 +279,10 @@ export interface IWidgetSubscription { subscribe(): void; + subscribeForLatestData(datasourceIndex: number, + pageLink: EntityDataPageLink, + keyFilters: KeyFilter[]): void; + isDataResolved(): boolean; destroy(): void; diff --git a/ui-ngx/src/app/core/api/widget-subscription.ts b/ui-ngx/src/app/core/api/widget-subscription.ts index 924f161d8f..e4cfee4f3e 100644 --- a/ui-ngx/src/app/core/api/widget-subscription.ts +++ b/ui-ngx/src/app/core/api/widget-subscription.ts @@ -22,7 +22,6 @@ import { WidgetSubscriptionOptions } from '@core/api/widget-api.models'; import { - DataKey, DataSet, DataSetHolder, Datasource, @@ -43,20 +42,18 @@ import { toHistoryTimewindow, WidgetTimewindow } from '@app/shared/models/time/time.models'; -import { Observable, ReplaySubject, Subject, throwError } from 'rxjs'; +import { forkJoin, Observable, of, ReplaySubject, Subject, throwError } from 'rxjs'; import { CancelAnimationFrame } from '@core/services/raf.service'; import { EntityType } from '@shared/models/entity-type.models'; import { AlarmInfo, AlarmSearchStatus } from '@shared/models/alarm.models'; import { createLabelFromDatasource, deepClone, isDefined, isEqual } from '@core/utils'; import { AlarmSourceListener } from '@core/http/alarm.service'; -import { DatasourceListener } from '@core/api/datasource.service'; import { EntityId } from '@app/shared/models/id/entity-id'; -import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; -import { entityFields } from '@shared/models/entity.models'; import * as moment_ from 'moment'; import { PageData } from '@shared/models/page/page-data'; import { EntityDataListener } from '@core/api/entity-data.service'; -import { EntityData, EntityDataPageLink, EntityKeyType } from '@shared/models/query/query.models'; +import { EntityData, EntityDataPageLink, EntityKeyType, KeyFilter } from '@shared/models/query/query.models'; +import { map } from 'rxjs/operators'; const moment = moment_; @@ -73,12 +70,14 @@ export class WidgetSubscription implements IWidgetSubscription { subscriptionTimewindow: SubscriptionTimewindow; useDashboardTimewindow: boolean; + hasDataPageLink: boolean; + singleEntity: boolean; + datasourcePages: PageData[]; dataPages: PageData>[]; entityDataListeners: Array; configuredDatasources: Array; - initDataSubscriptionSubject: Subject; data: Array; datasources: Array; // datasourceListeners: Array; @@ -211,6 +210,8 @@ export class WidgetSubscription implements IWidgetSubscription { // this.datasources = this.ctx.utils.validateDatasources(options.datasources); this.configuredDatasources = this.ctx.utils.validateDatasources(options.datasources); this.entityDataListeners = []; + this.hasDataPageLink = options.hasDataPageLink; + this.singleEntity = options.singleEntity; // this.datasourceListeners = []; this.datasourcePages = []; this.datasources = []; @@ -271,11 +272,11 @@ export class WidgetSubscription implements IWidgetSubscription { const initRpcSubject = new ReplaySubject(); if (this.targetDeviceAliasIds && this.targetDeviceAliasIds.length > 0) { this.targetDeviceAliasId = this.targetDeviceAliasIds[0]; - this.ctx.aliasController.getAliasInfo(this.targetDeviceAliasId).subscribe( - (aliasInfo) => { - if (aliasInfo.currentEntity && aliasInfo.currentEntity.entityType === EntityType.DEVICE) { - this.targetDeviceId = aliasInfo.currentEntity.id; - this.targetDeviceName = aliasInfo.currentEntity.name; + this.ctx.aliasController.resolveSingleEntityInfo(this.targetDeviceAliasId).subscribe( + (entityInfo) => { + if (entityInfo && entityInfo.entityType === EntityType.DEVICE) { + this.targetDeviceId = entityInfo.id; + this.targetDeviceName = entityInfo.name; if (this.targetDeviceId) { this.rpcEnabled = true; } else { @@ -348,34 +349,72 @@ export class WidgetSubscription implements IWidgetSubscription { } private initDataSubscription(): Observable { - this.initDataSubscriptionSubject = new ReplaySubject(1); + const initDataSubscriptionSubject = new ReplaySubject(1); this.loadStDiff().subscribe(() => { if (!this.ctx.aliasController) { this.hasResolvedData = true; - // this.configureData(); - // initDataSubscriptionSubject.next(); - // initDataSubscriptionSubject.complete(); - this.subscribe(); + this.prepareDataSubscriptions().subscribe( + () => { + initDataSubscriptionSubject.next(); + initDataSubscriptionSubject.complete(); + } + ); } else { - this.ctx.aliasController.resolveDatasources(this.configuredDatasources).subscribe( + this.ctx.aliasController.resolveDatasources(this.configuredDatasources, this.singleEntity).subscribe( (datasources) => { this.configuredDatasources = datasources; - /* if (datasources && datasources.length) { - this.hasResolvedData = true; - }*/ - this.subscribe(); - // this.configureData(); - // initDataSubscriptionSubject.next(); - // initDataSubscriptionSubject.complete(); + this.prepareDataSubscriptions().subscribe( + () => { + initDataSubscriptionSubject.next(); + initDataSubscriptionSubject.complete(); + } + ); }, (err) => { this.notifyDataLoaded(); - this.initDataSubscriptionSubject.error(err); + initDataSubscriptionSubject.error(err); } ); } }); - return this.initDataSubscriptionSubject.asObservable(); + return initDataSubscriptionSubject.asObservable(); + } + + private prepareDataSubscriptions(): Observable { + if (this.hasDataPageLink) { + this.hasResolvedData = true; + return of(null); + } + const resolveResultObservables = this.configuredDatasources.map((datasource, index) => { + const listener: EntityDataListener = { + subscriptionType: this.type, + configDatasource: datasource, + configDatasourceIndex: index, + dataLoaded: (pageData, data1, datasourceIndex) => { + this.dataLoaded(pageData, data1, datasourceIndex, true) + }, + dataUpdated: this.dataUpdated.bind(this), + updateRealtimeSubscription: () => { + this.subscriptionTimewindow = this.updateRealtimeSubscription(); + return this.subscriptionTimewindow; + }, + setRealtimeSubscription: (subscriptionTimewindow) => { + this.updateRealtimeSubscription(deepClone(subscriptionTimewindow)); + } + }; + this.entityDataListeners.push(listener); + return this.ctx.entityDataService.prepareSubscription(listener); + }); + return forkJoin(resolveResultObservables).pipe( + map((resolveResults) => { + resolveResults.forEach((resolveResult) => { + this.dataLoaded(resolveResult.pageData, resolveResult.data, resolveResult.datasourceIndex, false); + }); + this.configureLoadedData(); + this.hasResolvedData = true; + this.notifyDataLoaded(); + }) + ); } /* private initDataSubscriptionOld(): Observable { @@ -592,13 +631,12 @@ export class WidgetSubscription implements IWidgetSubscription { }); } - onDashboardTimewindowChanged(newDashboardTimewindow: Timewindow): boolean { + onDashboardTimewindowChanged(newDashboardTimewindow: Timewindow) { if (this.type === widgetType.timeseries || this.type === widgetType.alarm) { if (this.useDashboardTimewindow) { if (!isEqual(this.timeWindowConfig, newDashboardTimewindow) && newDashboardTimewindow) { - // this.timeWindowConfig = deepClone(newDashboardTimewindow); - // this.update(); - // TODO: + this.timeWindowConfig = deepClone(newDashboardTimewindow); + this.update(); return true; } } @@ -785,8 +823,12 @@ export class WidgetSubscription implements IWidgetSubscription { } update() { - this.unsubscribe(); - this.subscribe(); + if (this.type === widgetType.rpc || this.type === widgetType.alarm) { + this.unsubscribe(); + this.subscribe(); + } else { + this.dataSubscribe(); + } } subscribe(): void { @@ -802,6 +844,29 @@ export class WidgetSubscription implements IWidgetSubscription { } } + subscribeForLatestData(datasourceIndex: number, + pageLink: EntityDataPageLink, + keyFilters: KeyFilter[]): void { + let entityDataListener = this.entityDataListeners[datasourceIndex]; + if (entityDataListener) { + this.ctx.entityDataService.stopSubscription(entityDataListener); + } + const datasource = this.configuredDatasources[datasourceIndex]; + if (datasource) { + entityDataListener = { + subscriptionType: this.type, + configDatasource: datasource, + configDatasourceIndex: datasourceIndex, + dataLoaded: (pageData, data1, datasourceIndex1) => { + this.dataLoaded(pageData, data1, datasourceIndex1, true) + }, + dataUpdated: this.dataUpdated.bind(this) + }; + this.entityDataListeners[datasourceIndex] = entityDataListener; + this.ctx.entityDataService.subscribeForLatestData(entityDataListener, pageLink, keyFilters); + } + } + private doSubscribe() { if (this.type === widgetType.rpc) { return; @@ -809,6 +874,12 @@ export class WidgetSubscription implements IWidgetSubscription { if (this.type === widgetType.alarm) { this.alarmsSubscribe(); } else { + this.dataSubscribe(); + } + } + + private dataSubscribe() { + if (!this.hasDataPageLink) { this.notifyDataLoading(); if (this.type === widgetType.timeseries && this.timeWindowConfig) { this.updateRealtimeSubscription(); @@ -819,62 +890,10 @@ export class WidgetSubscription implements IWidgetSubscription { this.onDataUpdated(); } } - // let index = 0; const forceUpdate = !this.datasources.length; - this.configuredDatasources.forEach((datasource, index) => { - const listener: EntityDataListener = { - subscriptionType: this.type, - subscriptionTimewindow: this.subscriptionTimewindow, - configDatasource: datasource, - configDatasourceIndex: index, - dataLoaded: this.dataLoaded.bind(this), - dataUpdated: this.dataUpdated.bind(this), - updateRealtimeSubscription: () => { - this.subscriptionTimewindow = this.updateRealtimeSubscription(); - return this.subscriptionTimewindow; - }, - setRealtimeSubscription: (subscriptionTimewindow) => { - this.updateRealtimeSubscription(deepClone(subscriptionTimewindow)); - } - }; - - /*if (this.comparisonEnabled && datasource.isAdditional) { - listener.subscriptionTimewindow = this.timewindowForComparison; - listener.updateRealtimeSubscription = () => { - this.subscriptionTimewindow = this.updateSubscriptionForComparison(); - return this.subscriptionTimewindow; - }; - listener.setRealtimeSubscription = () => { - this.updateSubscriptionForComparison(); - }; - }*/ - -/* let entityFieldKey = false; - - for (let a = 0; a < datasource.dataKeys.length; a++) { - if (datasource.dataKeys[a].type !== DataKeyType.entityField) { - this.data[index + a].data = []; - } else { - entityFieldKey = true; - } - } - index += datasource.dataKeys.length;*/ - - this.entityDataListeners.push(listener); - // this.datasourceListeners.push(listener); - - // if (datasource.dataKeys.length) { - // this.ctx.datasourceService.subscribeToDatasource(listener); - // } - - this.ctx.entityDataService.subscribeToEntityData(listener); - - /* if (datasource.unresolvedStateEntity || entityFieldKey || - !datasource.dataKeys.length || - (datasource.type === DatasourceType.entity && !datasource.entityId) - ) { - forceUpdate = true; - }*/ + this.entityDataListeners.forEach((listener) => { + listener.subscriptionTimewindow = this.subscriptionTimewindow; + this.ctx.entityDataService.startSubscription(listener); }); if (forceUpdate) { this.notifyDataLoaded(); @@ -1000,7 +1019,9 @@ export class WidgetSubscription implements IWidgetSubscription { this.alarmsUnsubscribe(); } else { this.entityDataListeners.forEach((listener) => { - this.ctx.entityDataService.unsubscribeFromDatasource(listener); + if (listener != null) { + this.ctx.entityDataService.stopSubscription(listener); + } }); this.entityDataListeners.length = 0; this.resetData(); @@ -1129,7 +1150,9 @@ export class WidgetSubscription implements IWidgetSubscription { return this.timewindowForComparison; } - private dataLoaded(pageData: PageData, data: Array>, datasourceIndex: number) { + private dataLoaded(pageData: PageData, + data: Array>, + datasourceIndex: number, isUpdate: boolean) { const datasource = this.configuredDatasources[datasourceIndex]; datasource.dataReceived = true; const datasources = pageData.data.map((entityData, index) => @@ -1152,14 +1175,8 @@ export class WidgetSubscription implements IWidgetSubscription { totalPages: pageData.totalPages }; this.dataPages[datasourceIndex] = datasourceDataPage; - this.configureLoadedData(); - const readyCount = this.configuredDatasources.filter(d => d.dataReceived).length; - if (this.configuredDatasources.length === readyCount) { - this.hasResolvedData = true; - this.initDataSubscriptionSubject.next(); - this.initDataSubscriptionSubject.complete(); + if (isUpdate) { this.configureLoadedData(); - this.notifyDataLoaded(); this.onDataUpdated(true); } } @@ -1238,6 +1255,9 @@ export class WidgetSubscription implements IWidgetSubscription { dataKey, data: [] }; + if (data && data[keyIndex] && data[keyIndex].data) { + datasourceData.data = data[keyIndex].data; + } return datasourceData; }); } @@ -1275,6 +1295,7 @@ export class WidgetSubscription implements IWidgetSubscription { const startIndex = configuredDatasource.dataKeyStartIndex; const dataKeysCount = configuredDatasource.dataKeys.length; const index = startIndex + dataIndex*dataKeysCount + dataKeyIndex; + this.notifyDataLoaded(); let update = true; let currentData: DataSetHolder; if (this.displayLegend && this.legendData.keys[index].dataKey.hidden) { diff --git a/ui-ngx/src/app/core/http/entity.service.ts b/ui-ngx/src/app/core/http/entity.service.ts index 076f132cb8..ff1e4e193d 100644 --- a/ui-ngx/src/app/core/http/entity.service.ts +++ b/ui-ngx/src/app/core/http/entity.service.ts @@ -54,9 +54,15 @@ import { import { EntityRelationService } from '@core/http/entity-relation.service'; import { deepClone, isDefined, isDefinedAndNotNull } from '@core/utils'; import { Asset, AssetSearchQuery } from '@shared/models/asset.models'; -import { Device, DeviceCredentialsType, DeviceSearchQuery } from '@shared/models/device.models'; +import { ClaimResult, Device, DeviceCredentialsType, DeviceSearchQuery } from '@shared/models/device.models'; import { EntityViewSearchQuery } from '@shared/models/entity-view.models'; import { AttributeService } from '@core/http/attribute.service'; +import { + createDefaultEntityDataPageLink, + EntityData, + EntityDataQuery, + EntityFilter, EntityKeyType +} from '@shared/models/query/query.models'; @Injectable({ providedIn: 'root' @@ -360,6 +366,54 @@ export class EntityService { } } + public findEntityDataByQuery(query: EntityDataQuery, config?: RequestConfig): Observable> { + return this.http.post>('/api/entitiesQuery/find', query, defaultHttpOptionsFromConfig(config)); + } + + private entityDataToEntityInfo(entityData: EntityData): EntityInfo { + const entityInfo: EntityInfo = { + id: entityData.entityId.id, + entityType: entityData.entityId.entityType as EntityType + }; + if (entityData.latest && entityData.latest[EntityKeyType.ENTITY_FIELD]) { + const fields = entityData.latest[EntityKeyType.ENTITY_FIELD]; + if (fields.name) { + entityInfo.name = fields.name.value; + } + if (fields.label) { + entityInfo.label = fields.label.value; + } + } + return entityInfo; + } + + public findSingleEntityInfoByEntityFilter(filter: EntityFilter, config?: RequestConfig): Observable { + const query: EntityDataQuery = { + entityFilter: filter, + pageLink: createDefaultEntityDataPageLink(1), + entityFields: [ + { + type: EntityKeyType.ENTITY_FIELD, + key: 'name' + }, + { + type: EntityKeyType.ENTITY_FIELD, + key: 'label' + } + ] + }; + return this.findEntityDataByQuery(query, config).pipe( + map((data) => { + if (data.data.length) { + const entityData = data.data[0]; + return this.entityDataToEntityInfo(entityData); + } else { + return null; + } + }) + ); + } + public getAliasFilterTypesByEntityTypes(entityTypes: Array): Array { const allAliasFilterTypes: Array = Object.keys(AliasFilterType).map((key) => AliasFilterType[key]); if (!entityTypes || !entityTypes.length) { @@ -605,7 +659,7 @@ export class EntityService { public resolveAlias(entityAlias: EntityAlias, stateParams: StateParams): Observable { const filter = entityAlias.filter; return this.resolveAliasFilter(filter, stateParams).pipe( - map((result) => { + mergeMap((result) => { const aliasInfo: AliasInfo = { alias: entityAlias.alias, entityFilter: result.entityFilter, @@ -615,30 +669,19 @@ export class EntityService { }; aliasInfo.resolvedEntities = result.entities; aliasInfo.currentEntity = null; - if (aliasInfo.resolvedEntities.length) { - aliasInfo.currentEntity = aliasInfo.resolvedEntities[0]; + if (!aliasInfo.resolveMultiple && aliasInfo.entityFilter) { + return this.findSingleEntityInfoByEntityFilter(aliasInfo.entityFilter, + {ignoreLoading: true, ignoreErrors: true}).pipe( + map((entity) => { + aliasInfo.currentEntity = entity; + return aliasInfo; + }) + ); } - return aliasInfo; + return of(aliasInfo); }) ); } -/* - public resolveEntityFilter(filter: EntityAliasFilter, stateParams: StateParams): EntityFilter { - const stateEntityInfo = this.getStateEntityInfo(filter, stateParams); - let result: EntityFilter = filter; - const stateEntityId = stateEntityInfo.entityId; - if (filter.type === AliasFilterType.stateEntity) { - result = { - singleEntity: stateEntityId, - type: AliasFilterType.singleEntity - }; - } else if (filter.rootStateEntity) { - let rootEntityType; - let rootEntityId; - - } - return result; - }*/ public resolveAliasFilter(filter: EntityAliasFilter, stateParams: StateParams): Observable { const result: EntityAliasFilterResult = { diff --git a/ui-ngx/src/app/core/ws/telemetry-websocket.service.ts b/ui-ngx/src/app/core/ws/telemetry-websocket.service.ts index 5d3daa9467..5610551d20 100644 --- a/ui-ngx/src/app/core/ws/telemetry-websocket.service.ts +++ b/ui-ngx/src/app/core/ws/telemetry-websocket.service.ts @@ -114,6 +114,17 @@ export class TelemetryWebsocketService implements TelemetryService { this.publishCommands(); } + public update(subscriber: TelemetrySubscriber) { + subscriber.subscriptionCommands.forEach( + (subscriptionCommand) => { + if (subscriptionCommand.cmdId && subscriptionCommand instanceof EntityDataCmd) { + this.cmdsWrapper.entityDataCmds.push(subscriptionCommand); + } + } + ); + this.publishCommands(); + } + public unsubscribe(subscriber: TelemetrySubscriber) { if (this.isActive) { subscriber.subscriptionCommands.forEach( diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/entities-table-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/entities-table-widget.component.html index 6a87650526..a7f9d8e678 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/entities-table-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/entities-table-widget.component.html @@ -39,7 +39,7 @@
+ matSort [matSortActive]="sortOrderProperty" [matSortDirection]="pageLinkSortDirection()" matSortDisableClear> {{ column.title }} = []; @@ -150,8 +152,13 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni private domSanitizer: DomSanitizer) { super(store); - const sortOrder: SortOrder = sortOrderFromString(this.defaultSortOrder); - this.pageLink = new PageLink(this.defaultPageSize, 0, null, sortOrder); + // const sortOrder: EntityDataSortOrder = sortOrderFromString(this.defaultSortOrder); + this.pageLink = { + page: 0, + pageSize: this.defaultPageSize, + textSearch: null + }; + // new PageLink(this.defaultPageSize, 0, null, sortOrder); } ngOnInit(): void { @@ -191,11 +198,15 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni public onDataUpdated() { this.ngZone.run(() => { - this.entityDatasource.updateEntitiesData(this.subscription.data); + this.entityDatasource.dataUpdated(); // .updateEntitiesData(this.subscription.data); this.ctx.detectChanges(); }); } + public pageLinkSortDirection(): SortDirection { + return entityDataPageLinkSortDirection(this.pageLink); + } + private initializeConfig() { this.ctx.widgetActions = [this.searchAction, this.columnDisplayAction]; @@ -256,7 +267,11 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni name: 'entityName', label: 'entityName', def: 'entityName', - title: entityNameColumnTitle + title: entityNameColumnTitle, + entityKey: { + key: 'name', + type: EntityKeyType.ENTITY_FIELD + } } as EntityColumn ); this.contentsInfo.entityName = { @@ -273,7 +288,11 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni name: 'entityLabel', label: 'entityLabel', def: 'entityLabel', - title: entityLabelColumnTitle + title: entityLabelColumnTitle, + entityKey: { + key: 'label', + type: EntityKeyType.ENTITY_FIELD + } } as EntityColumn ); this.contentsInfo.entityLabel = { @@ -291,6 +310,10 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni label: 'entityType', def: 'entityType', title: this.translate.instant('entity.entity-type'), + entityKey: { + key: 'entityType', + type: EntityKeyType.ENTITY_FIELD + } } as EntityColumn ); this.contentsInfo.entityType = { @@ -309,8 +332,19 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni if (datasource) { datasource.dataKeys.forEach((entityDataKey) => { const dataKey: EntityColumn = deepClone(entityDataKey) as EntityColumn; + dataKey.entityKey = { + key: dataKey.name, + type: null + }; if (dataKey.type === DataKeyType.function) { dataKey.name = dataKey.label; + dataKey.entityKey.type = EntityKeyType.ENTITY_FIELD; + } else if (dataKey.type === DataKeyType.entityField) { + dataKey.entityKey.type = EntityKeyType.ENTITY_FIELD; + } else if (dataKey.type === DataKeyType.attribute) { + dataKey.entityKey.type = EntityKeyType.ATTRIBUTE; + } else if (dataKey.type === DataKeyType.timeseries) { + dataKey.entityKey.type = EntityKeyType.TIME_SERIES; } dataKeys.push(dataKey); @@ -331,14 +365,19 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni if (this.settings.defaultSortOrder && this.settings.defaultSortOrder.length) { this.defaultSortOrder = this.settings.defaultSortOrder; } - this.pageLink.sortOrder = sortOrderFromString(this.defaultSortOrder); - this.sortOrderProperty = toEntityColumnDef(this.pageLink.sortOrder.property, this.columns); + + this.pageLink.sortOrder = entityDataSortOrderFromString(this.defaultSortOrder, this.columns); + let sortColumn: EntityColumn; + if (this.pageLink.sortOrder) { + sortColumn = findColumnByEntityKey(this.pageLink.sortOrder.key, this.columns); + } + this.sortOrderProperty = sortColumn ? sortColumn.def : null; if (this.actionCellDescriptors.length) { this.displayedColumns.push('actions'); } this.entityDatasource = new EntityDatasource( - this.translate, dataKeys, this.subscription.datasources); + this.translate, dataKeys, this.subscription); } private editColumnsToDisplay($event: Event) { @@ -416,9 +455,12 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni } else { this.pageLink.page = 0; } - this.pageLink.sortOrder.property = fromEntityColumnDef(this.sort.active, this.columns); - this.pageLink.sortOrder.direction = Direction[this.sort.direction.toUpperCase()]; - this.entityDatasource.loadEntities(this.pageLink); + this.pageLink.sortOrder = { + key: findEntityKeyByColumnDef(this.sort.active, this.columns), + direction: Direction[this.sort.direction.toUpperCase()] + }; + const keyFilters: KeyFilter[] = null; // TODO: + this.entityDatasource.loadEntities(this.pageLink, keyFilters); this.ctx.detectChanges(); } @@ -523,18 +565,19 @@ class EntityDatasource implements DataSource { private entitiesSubject = new BehaviorSubject([]); private pageDataSubject = new BehaviorSubject>(emptyPageData()); - private allEntities: Array = []; - private allEntitiesSubject = new BehaviorSubject([]); - private allEntities$: Observable> = this.allEntitiesSubject.asObservable(); +// private allEntities: Array = []; +// private allEntitiesSubject = new BehaviorSubject([]); +// private allEntities$: Observable> = this.allEntitiesSubject.asObservable(); private currentEntity: EntityData = null; constructor( private translate: TranslateService, private dataKeys: Array, - datasources: Array + private subscription: IWidgetSubscription + // datasources: Array ) { - +/* for (const datasource of datasources) { if (datasource.type === DatasourceType.entity && !datasource.entityId) { continue; @@ -558,7 +601,7 @@ class EntityDatasource implements DataSource { }); this.allEntities.push(entity); } - this.allEntitiesSubject.next(this.allEntities); + this.allEntitiesSubject.next(this.allEntities);*/ } connect(collectionViewer: CollectionViewer): Observable> { @@ -570,18 +613,63 @@ class EntityDatasource implements DataSource { this.pageDataSubject.complete(); } - loadEntities(pageLink: PageLink) { - this.fetchEntities(pageLink).pipe( + loadEntities(pageLink: EntityDataPageLink, keyFilters: KeyFilter[]) { + this.subscription.subscribeForLatestData(0, pageLink, keyFilters); +/* this.fetchEntities(pageLink).pipe( catchError(() => of(emptyPageData())), ).subscribe( (pageData) => { this.entitiesSubject.next(pageData.data); this.pageDataSubject.next(pageData); } - ); + );*/ } - updateEntitiesData(data: DatasourceData[]) { + dataUpdated() { + const datasourcesPageData = this.subscription.datasourcePages[0]; + const dataPageData = this.subscription.dataPages[0]; + const entities = new Array(); + datasourcesPageData.data.forEach((datasource, index) => { + entities.push(this.datasourceToEntityData(datasource, dataPageData.data[index])); + }); + const entitiesPageData: PageData = { + data: entities, + totalPages: datasourcesPageData.totalPages, + totalElements: datasourcesPageData.totalElements, + hasNext: datasourcesPageData.hasNext + }; + this.entitiesSubject.next(entities); + this.pageDataSubject.next(entitiesPageData); + } + + private datasourceToEntityData(datasource: Datasource, data: DatasourceData[]): EntityData { + const entity: EntityData = { + id: {} as EntityId, + entityName: datasource.entityName, + entityLabel: datasource.entityLabel ? datasource.entityLabel : datasource.entityName + }; + if (datasource.entityId) { + entity.id.id = datasource.entityId; + } + if (datasource.entityType) { + entity.id.entityType = datasource.entityType; + entity.entityType = this.translate.instant(entityTypeTranslations.get(datasource.entityType).type); + } else { + entity.entityType = ''; + } + this.dataKeys.forEach((dataKey, index) => { + const keyData = data[index].data; + if (keyData && keyData.length && keyData[0].length > 1) { + const value = keyData[0][1]; + entity[dataKey.label] = value; + } else { + entity[dataKey.label] = ''; + } + }); + return entity; + } + +/* updateEntitiesData(data: DatasourceData[]) { for (let i = 0; i < this.allEntities.length; i++) { const entity = this.allEntities[i]; for (let a = 0; a < this.dataKeys.length; a++) { @@ -597,7 +685,7 @@ class EntityDatasource implements DataSource { } } this.allEntitiesSubject.next(this.allEntities); - } + }*/ isEmpty(): Observable { return this.entitiesSubject.pipe( @@ -625,9 +713,9 @@ class EntityDatasource implements DataSource { (this.currentEntity.id.id === entity.id.id); } - private fetchEntities(pageLink: PageLink): Observable> { + /* private fetchEntities(pageLink: PageLink): Observable> { return this.allEntities$.pipe( map((data) => pageLink.filterData(data)) ); - } + }*/ } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/table-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/table-widget.models.ts index 29f9e4265a..77acf524df 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/table-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/table-widget.models.ts @@ -19,6 +19,7 @@ import { DataKey, WidgetConfig } from '@shared/models/widget.models'; import { getDescendantProp, isDefined } from '@core/utils'; import { alarmFields, AlarmInfo } from '@shared/models/alarm.models'; import * as tinycolor_ from 'tinycolor2'; +import { Direction, EntityDataSortOrder, EntityKey } from '@shared/models/query/query.models'; const tinycolor = tinycolor_; @@ -49,6 +50,7 @@ export interface EntityData { export interface EntityColumn extends DataKey { def: string; title: string; + entityKey?: EntityKey; } export interface DisplayColumn { @@ -73,6 +75,58 @@ export interface CellStyleInfo { cellStyleFunction?: CellStyleFunction; } + +export function entityDataSortOrderFromString(strSortOrder: string, columns: EntityColumn[]): EntityDataSortOrder { + if (!strSortOrder && !strSortOrder.length) { + return null; + } + let property: string; + let direction = Direction.ASC; + if (strSortOrder.startsWith('-')) { + direction = Direction.DESC; + property = strSortOrder.substring(1); + } else { + if (strSortOrder.startsWith('+')) { + property = strSortOrder.substring(1); + } else { + property = strSortOrder; + } + } + if (!property && !property.length) { + return null; + } + const column = findColumnByLabel(property, columns); + if (column && column.entityKey) { + return {key: column.entityKey, direction}; + } + return null; +} + +export function findColumnByEntityKey(key: EntityKey, columns: EntityColumn[]): EntityColumn { + if (key) { + return columns.find(theColumn => theColumn.entityKey && + theColumn.entityKey.type === key.type && theColumn.entityKey.key === key.key); + } else { + return null; + } +} + +export function findEntityKeyByColumnDef(def: string, columns: EntityColumn[]): EntityKey { + return findColumnByDef(def, columns).entityKey; +} + +export function findColumn(searchProperty: string, searchValue: string, columns: EntityColumn[]): EntityColumn { + return columns.find(theColumn => theColumn[searchProperty] === searchValue); +} + +export function findColumnByLabel(label: string, columns: EntityColumn[]): EntityColumn { + return findColumn('label', label, columns); +} + +export function findColumnByDef(def: string, columns: EntityColumn[]): EntityColumn { + return findColumn('def', def, columns); +} + export function findColumnProperty(searchProperty: string, searchValue: string, columnProperty: string, columns: EntityColumn[]): string { let res = searchValue; const column = columns.find(theColumn => theColumn[searchProperty] === searchValue); @@ -82,6 +136,10 @@ export function findColumnProperty(searchProperty: string, searchValue: string, return res; } +export function toEntityKey(def: string, columns: EntityColumn[]): string { + return findColumnProperty('def', def, 'label', columns); +} + export function toEntityColumnDef(label: string, columns: EntityColumn[]): string { return findColumnProperty('label', label, 'def', columns); } diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts b/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts index 3587201415..a9d7e332f4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts @@ -346,12 +346,19 @@ export class WidgetComponentService { } else { result.typeParameters.useCustomDatasources = false; } + if (isUndefined(result.typeParameters.hasDataPageLink)) { + result.typeParameters.hasDataPageLink = false; + } if (isUndefined(result.typeParameters.maxDatasources)) { result.typeParameters.maxDatasources = -1; } if (isUndefined(result.typeParameters.maxDataKeys)) { result.typeParameters.maxDataKeys = -1; } + if (isUndefined(result.typeParameters.singleEntity)) { + result.typeParameters.singleEntity = result.typeParameters.maxDatasources === 1 && + result.typeParameters.maxDataKeys === 1; + } if (isUndefined(result.typeParameters.dataKeysOptional)) { result.typeParameters.dataKeysOptional = false; } diff --git a/ui-ngx/src/app/modules/home/components/widget/widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/widget.component.ts index 1091b4c550..800ccab847 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget.component.ts @@ -620,14 +620,9 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI this.rxSubscriptions.push(this.widgetContext.dashboard.dashboardTimewindowChanged.subscribe( (dashboardTimewindow) => { - // TODO: - let subscriptionChanged = false; for (const id of Object.keys(this.widgetContext.subscriptions)) { const subscription = this.widgetContext.subscriptions[id]; - subscriptionChanged = subscriptionChanged || subscription.onDashboardTimewindowChanged(dashboardTimewindow); - } - if (subscriptionChanged && !this.typeParameters.useCustomDatasources) { - this.reInit(); + subscription.onDashboardTimewindowChanged(dashboardTimewindow); } } )); @@ -845,6 +840,8 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI options = { type: this.widget.type, stateData: this.typeParameters.stateData, + hasDataPageLink: this.typeParameters.hasDataPageLink, + singleEntity: this.typeParameters.singleEntity, comparisonEnabled: comparisonSettings.comparisonEnabled, timeForComparison: comparisonSettings.timeForComparison }; diff --git a/ui-ngx/src/app/shared/models/query/query.models.ts b/ui-ngx/src/app/shared/models/query/query.models.ts index 304968841e..b2eaa52d53 100644 --- a/ui-ngx/src/app/shared/models/query/query.models.ts +++ b/ui-ngx/src/app/shared/models/query/query.models.ts @@ -16,6 +16,7 @@ import { AliasFilterType, EntityFilters } from '@shared/models/alias.models'; import { EntityId } from '@shared/models/id/entity-id'; +import { SortDirection } from '@angular/material/sort'; export enum EntityKeyType { ATTRIBUTE = 'ATTRIBUTE', @@ -122,18 +123,30 @@ export interface EntityDataPageLink { sortOrder?: EntityDataSortOrder; } -export const defaultEntityDataPageLink: EntityDataPageLink = { - pageSize: 1024, - page: 0, - sortOrder: { - key: { - type: EntityKeyType.ENTITY_FIELD, - key: 'createdTime' - }, - direction: Direction.DESC +export function entityDataPageLinkSortDirection(pageLink: EntityDataPageLink): SortDirection { + if (pageLink.sortOrder) { + return (pageLink.sortOrder.direction + '').toLowerCase() as SortDirection; + } else { + return '' as SortDirection; } } +export function createDefaultEntityDataPageLink(pageSize: number): EntityDataPageLink { + return { + pageSize, + page: 0, + sortOrder: { + key: { + type: EntityKeyType.ENTITY_FIELD, + key: 'createdTime' + }, + direction: Direction.DESC + } + } +} + +export const defaultEntityDataPageLink: EntityDataPageLink = createDefaultEntityDataPageLink(1024); + export interface EntityCountQuery { entityFilter: EntityFilter; } diff --git a/ui-ngx/src/app/shared/models/telemetry/telemetry.models.ts b/ui-ngx/src/app/shared/models/telemetry/telemetry.models.ts index e3108004c8..c0ad2c80a0 100644 --- a/ui-ngx/src/app/shared/models/telemetry/telemetry.models.ts +++ b/ui-ngx/src/app/shared/models/telemetry/telemetry.models.ts @@ -21,7 +21,7 @@ import { Observable, ReplaySubject, Subject } from 'rxjs'; import { EntityId } from '@shared/models/id/entity-id'; import { map } from 'rxjs/operators'; import { NgZone } from '@angular/core'; -import { EntityData, EntityDataQuery } from '@shared/models/query/query.models'; +import { EntityData, EntityDataQuery, EntityKey } from '@shared/models/query/query.models'; import { PageData } from '@shared/models/page/page-data'; export enum DataKeyType { @@ -139,7 +139,7 @@ export interface EntityHistoryCmd { } export interface LatestValueCmd { - keys: Array; + keys: Array; } export interface TimeSeriesCmd { @@ -153,7 +153,7 @@ export interface TimeSeriesCmd { export class EntityDataCmd implements WebsocketCmd { cmdId: number; - query: EntityDataQuery; + query?: EntityDataQuery; historyCmd?: EntityHistoryCmd; latestCmd?: LatestValueCmd; tsCmd?: TimeSeriesCmd; @@ -314,6 +314,7 @@ export class EntityDataUpdate implements EntityDataUpdateMsg { export interface TelemetryService { subscribe(subscriber: TelemetrySubscriber); + update(subscriber: TelemetrySubscriber); unsubscribe(subscriber: TelemetrySubscriber); } @@ -360,6 +361,10 @@ export class TelemetrySubscriber { this.telemetryService.subscribe(this); } + public update() { + this.telemetryService.update(this); + } + public unsubscribe() { this.telemetryService.unsubscribe(this); this.complete(); diff --git a/ui-ngx/src/app/shared/models/widget.models.ts b/ui-ngx/src/app/shared/models/widget.models.ts index 3b3c29f44d..3a6937974b 100644 --- a/ui-ngx/src/app/shared/models/widget.models.ts +++ b/ui-ngx/src/app/shared/models/widget.models.ts @@ -150,6 +150,8 @@ export interface WidgetTypeParameters { maxDataKeys?: number; dataKeysOptional?: boolean; stateData?: boolean; + hasDataPageLink?: boolean; + singleEntity?: boolean; } export interface WidgetControllerDescriptor {