From 5f3c06969457338967ec7d1b757aa68bb32f169f Mon Sep 17 00:00:00 2001 From: Ace Date: Fri, 30 Aug 2019 12:42:09 +0530 Subject: [PATCH] introducing a group properties table & ability to add/remove group properties --- .../mgt/common/group/mgt/DeviceGroup.java | 11 ++ .../carbon/device/mgt/core/dao/GroupDAO.java | 44 ++++++++ .../core/dao/impl/AbstractGroupDAOImpl.java | 101 ++++++++++++++++++ .../GroupManagementProviderServiceImpl.java | 23 +++- .../src/test/resources/sql/h2.sql | 8 ++ .../src/main/resources/dbscripts/cdm/h2.sql | 8 ++ .../main/resources/dbscripts/cdm/mssql.sql | 9 ++ .../main/resources/dbscripts/cdm/mysql.sql | 8 ++ .../main/resources/dbscripts/cdm/oracle.sql | 8 ++ .../resources/dbscripts/cdm/postgresql.sql | 8 ++ 10 files changed, 227 insertions(+), 1 deletion(-) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/group/mgt/DeviceGroup.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/group/mgt/DeviceGroup.java index b107d79e87..9dff875672 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/group/mgt/DeviceGroup.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/group/mgt/DeviceGroup.java @@ -21,6 +21,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import java.io.Serializable; +import java.util.Map; /** * Holds Device Group details and expose to external access @@ -43,6 +44,8 @@ public class DeviceGroup implements Serializable { private String owner; + private Map groupProperties; + public DeviceGroup() {} public DeviceGroup(String name) { @@ -81,4 +84,12 @@ public class DeviceGroup implements Serializable { this.owner = owner; } + public Map getGroupProperties() { + return groupProperties; + } + + public void setGroupProperties(Map groupProperties) { + this.groupProperties = groupProperties; + } + } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/GroupDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/GroupDAO.java index 2536aa40e2..4bfbe51cb4 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/GroupDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/GroupDAO.java @@ -23,6 +23,7 @@ import org.wso2.carbon.device.mgt.common.GroupPaginationRequest; import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; import java.util.List; +import java.util.Map; /** * This interface represents the key operations associated with persisting group related information. @@ -38,6 +39,49 @@ public interface GroupDAO { */ int addGroup(DeviceGroup deviceGroup, int tenantId) throws GroupManagementDAOException; + /** + * Add properties for device group. + * Note that groupId parameter is considered seperately due to the groupId parameter passed with + * device group Payload is ignored in the add/update logic instead the internal groupId reference is used. + * + * @param deviceGroup to be added. + * @param tenantId of the group. + * @return sql execution result. + * @throws GroupManagementDAOException + */ + boolean addGroupProperties(DeviceGroup deviceGroup, int groupId, int tenantId) throws GroupManagementDAOException; + + /** + * Update properties for device group. + * Note that groupId parameter is considered seperately due to the groupId parameter passed with + * device group Payload is ignored in the add/update logic instead the internal groupId reference is used. + * + * @param deviceGroup to be updated. + * @param tenantId of the group. + * @return sql execution result. + * @throws GroupManagementDAOException + */ + boolean updateGroupProperties(DeviceGroup deviceGroup, int groupId, int tenantId) throws GroupManagementDAOException; + + /** + * Remove properties for device group. + * + * @param groupId to be deleted. + * @param tenantId of the group. + * @throws GroupManagementDAOException + */ + void deleteAllGroupProperties(int groupId, int tenantId) throws GroupManagementDAOException; + + /** + * Retrives all properties stored against a group. + * + * @param groupId to be deleted. + * @param tenantId of the group. + * @return sql execution result. + * @throws GroupManagementDAOException + */ + Map getAllGroupProperties(int groupId, int tenantId) throws GroupManagementDAOException; + /** * Update an existing Device Group. * diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractGroupDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractGroupDAOImpl.java index 44b1384c09..228d564c0c 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractGroupDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractGroupDAOImpl.java @@ -30,7 +30,9 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * This class represents implementation of GroupDAO @@ -64,6 +66,62 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { } } + public boolean addGroupProperties(DeviceGroup deviceGroup, int groupId, int tenantId) + throws GroupManagementDAOException { + boolean status; + PreparedStatement stmt = null; + try { + Connection conn = GroupManagementDAOFactory.getConnection(); + stmt = conn.prepareStatement( + "INSERT INTO GROUP_PROPERTIES(GROUP_ID, PROPERTY_NAME, " + + "PROPERTY_VALUE, TENANT_ID) VALUES (?, ?, ?, ?)"); + for (Map.Entry entry : deviceGroup.getGroupProperties().entrySet()) { + stmt.setInt(1, groupId); + stmt.setString(2, entry.getKey()); + stmt.setString(3, entry.getValue()); + stmt.setInt(4, tenantId); + stmt.addBatch(); + } + stmt.executeBatch(); + status = true; + } catch (SQLException e) { + String msg = "Error occurred while adding properties for group '" + + deviceGroup.getName() + "' values : " + deviceGroup.getGroupProperties(); + throw new GroupManagementDAOException(msg, e); + } finally { + GroupManagementDAOUtil.cleanupResources(stmt, null); + } + return status; + } + + public boolean updateGroupProperties(DeviceGroup deviceGroup, int groupId, int tenantId) + throws GroupManagementDAOException { + boolean status; + PreparedStatement stmt = null; + try { + Connection conn = GroupManagementDAOFactory.getConnection(); + stmt = conn.prepareStatement( + "UPDATE GROUP_PROPERTIES SET PROPERTY_VALUE = ? WHERE GROUP_ID = ? AND " + + "TENANT_ID = ? AND PROPERTY_NAME = ?"); + for (Map.Entry entry : deviceGroup.getGroupProperties().entrySet()) { + stmt.setString(1, entry.getValue()); + stmt.setInt(2, groupId); + stmt.setInt(3, tenantId); + stmt.setString(4, entry.getKey()); + stmt.addBatch(); + } + stmt.executeBatch(); + status = true; + } catch (SQLException e) { + String msg = "Error occurred while adding properties for group '" + + deviceGroup.getName() + "' values : " + deviceGroup.getGroupProperties(); + throw new GroupManagementDAOException(msg, e); + } finally { + GroupManagementDAOUtil.cleanupResources(stmt, null); + } + return status; + } + @Override public void updateGroup(DeviceGroup deviceGroup, int groupId, int tenantId) throws GroupManagementDAOException { @@ -128,6 +186,49 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { } } + public void deleteAllGroupProperties(int groupId, int tenantId) + throws GroupManagementDAOException { + PreparedStatement stmt = null; + try { + Connection conn = GroupManagementDAOFactory.getConnection(); + stmt = conn.prepareStatement( + "DELETE GROUP_PROPERTIES WHERE GROUP_ID = ? AND TENANT_ID = ?"); + stmt.setInt(1, groupId); + stmt.setInt(2, tenantId); + stmt.executeUpdate(); + } catch (SQLException e) { + String msg = "Error occurred while deleting group ID : " + groupId; + throw new GroupManagementDAOException(msg, e); + } finally { + GroupManagementDAOUtil.cleanupResources(stmt, null); + } + } + + public Map getAllGroupProperties(int groupId, int tenantId) + throws GroupManagementDAOException { + PreparedStatement stmt = null; + ResultSet resultSet = null; + Map properties = new HashMap(); + try { + Connection conn = GroupManagementDAOFactory.getConnection(); + stmt = conn.prepareStatement( + "SELECT PROPERTY_NAME, PROPERTY_VALUE FROM GROUP_PROPERTIES WHERE GROUP_ID = ? AND TENANT_ID = ?"); + stmt.setInt(1, groupId); + stmt.setInt(2, tenantId); + resultSet = stmt.executeQuery(); + while (resultSet.next()) { + properties.put(resultSet.getString("PROPERTY_NAME"), + resultSet.getString("PROPERTY_VALUE")); + } + } catch (SQLException e) { + String msg = "Error occurred while deleting group ID : " + groupId; + throw new GroupManagementDAOException(msg, e); + } finally { + GroupManagementDAOUtil.cleanupResources(stmt, null); + } + return properties; + } + @Override public DeviceGroup getGroup(int groupId, int tenantId) throws GroupManagementDAOException { PreparedStatement stmt = null; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java index d2e4efdcb0..fea3a3ed81 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java @@ -83,7 +83,10 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid GroupManagementDAOFactory.beginTransaction(); DeviceGroup existingGroup = this.groupDAO.getGroup(deviceGroup.getName(), tenantId); if (existingGroup == null) { - this.groupDAO.addGroup(deviceGroup, tenantId); + int updatedGroupID = this.groupDAO.addGroup(deviceGroup, tenantId); + if (deviceGroup.getGroupProperties() != null && deviceGroup.getGroupProperties().size() > 0) { + this.groupDAO.addGroupProperties(deviceGroup, updatedGroupID, tenantId); + } GroupManagementDAOFactory.commitTransaction(); } else { throw new GroupAlreadyExistException("Group exist with name " + deviceGroup.getName()); @@ -132,6 +135,9 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid DeviceGroup existingGroup = this.groupDAO.getGroup(groupId, tenantId); if (existingGroup != null) { this.groupDAO.updateGroup(deviceGroup, groupId, tenantId); + if (deviceGroup.getGroupProperties() != null && deviceGroup.getGroupProperties().size() > 0) { + this.groupDAO.updateGroupProperties(deviceGroup, groupId, tenantId); + } GroupManagementDAOFactory.commitTransaction(); } else { throw new GroupNotExistException("Group with ID - '" + groupId + "' doesn't exists!"); @@ -171,6 +177,7 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid try { GroupManagementDAOFactory.beginTransaction(); this.groupDAO.deleteGroup(groupId, CarbonContext.getThreadLocalCarbonContext().getTenantId()); + this.groupDAO.deleteAllGroupProperties(groupId, CarbonContext.getThreadLocalCarbonContext().getTenantId()); GroupManagementDAOFactory.commitTransaction(); if (log.isDebugEnabled()) { log.debug("DeviceGroup " + deviceGroup.getName() + " removed."); @@ -206,6 +213,8 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid try { GroupManagementDAOFactory.openConnection(); deviceGroup = this.groupDAO.getGroup(groupId, CarbonContext.getThreadLocalCarbonContext().getTenantId()); + deviceGroup.setGroupProperties(this.groupDAO.getAllGroupProperties(deviceGroup.getGroupId(), + CarbonContext.getThreadLocalCarbonContext().getTenantId())); } catch (GroupManagementDAOException e) { String msg = "Error occurred while obtaining group '" + groupId + "'"; log.error(msg, e); @@ -241,6 +250,8 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid try { GroupManagementDAOFactory.openConnection(); deviceGroup = this.groupDAO.getGroup(groupName, CarbonContext.getThreadLocalCarbonContext().getTenantId()); + deviceGroup.setGroupProperties(this.groupDAO.getAllGroupProperties(deviceGroup.getGroupId(), + CarbonContext.getThreadLocalCarbonContext().getTenantId())); } catch (GroupManagementDAOException e) { String msg = "Error occurred while obtaining group with name: '" + groupName + "'"; log.error(msg, e); @@ -269,6 +280,9 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); GroupManagementDAOFactory.openConnection(); deviceGroups = this.groupDAO.getGroups(tenantId); + for(DeviceGroup group : deviceGroups){ + group.setGroupProperties(this.groupDAO.getAllGroupProperties(group.getGroupId(), tenantId)); + } } catch (GroupManagementDAOException e) { String msg = "Error occurred while retrieving all groups in tenant"; log.error(msg, e); @@ -303,6 +317,9 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); GroupManagementDAOFactory.openConnection(); deviceGroups = this.groupDAO.getGroups(request, tenantId); + for(DeviceGroup group : deviceGroups){ + group.setGroupProperties(this.groupDAO.getAllGroupProperties(group.getGroupId(), tenantId)); + } } catch (GroupManagementDAOException e) { String msg = "Error occurred while retrieving all groups in tenant"; log.error(msg, e); @@ -348,6 +365,7 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid } deviceGroups = this.groupDAO.getGroups(roleList, tenantId); for (DeviceGroup deviceGroup : deviceGroups) { + deviceGroup.setGroupProperties(this.groupDAO.getAllGroupProperties(deviceGroup.getGroupId(), tenantId)); groups.put(deviceGroup.getGroupId(), deviceGroup); } } catch (UserStoreException | SQLException | GroupManagementDAOException e) { @@ -410,6 +428,9 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); GroupManagementDAOFactory.openConnection(); allMatchingGroups = this.groupDAO.getGroups(request, allDeviceGroupIdsOfUser, tenantId); + for(DeviceGroup group : allMatchingGroups){ + group.setGroupProperties(this.groupDAO.getAllGroupProperties(group.getGroupId(), tenantId)); + } } catch (GroupManagementDAOException | SQLException e) { String msg = "Error occurred while retrieving all groups in tenant"; log.error(msg, e); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/sql/h2.sql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/sql/h2.sql index 6a7ff48814..89eaa6d335 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/sql/h2.sql +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/sql/h2.sql @@ -50,6 +50,14 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_PROPERTIES ( PRIMARY KEY (DEVICE_TYPE_NAME, DEVICE_IDENTIFICATION, PROPERTY_NAME, TENANT_ID) ); +CREATE TABLE IF NOT EXISTS GROUP_PROPERTIES ( + GROUP_ID INTEGER NOT NULL, + PROPERTY_NAME VARCHAR(100) DEFAULT 0, + PROPERTY_VALUE VARCHAR(100) DEFAULT NULL, + TENANT_ID VARCHAR(100), + PRIMARY KEY (GROUP_ID, PROPERTY_NAME, TENANT_ID) +); + CREATE TABLE IF NOT EXISTS DM_DEVICE_GROUP_MAP ( ID INTEGER AUTO_INCREMENT NOT NULL, DEVICE_ID INTEGER DEFAULT NULL, diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql index 736e6a1adb..b4edb11609 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql @@ -50,6 +50,14 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_PROPERTIES ( PRIMARY KEY (DEVICE_TYPE_NAME, DEVICE_IDENTIFICATION, PROPERTY_NAME, TENANT_ID) ); +CREATE TABLE IF NOT EXISTS GROUP_PROPERTIES ( + GROUP_ID INTEGER NOT NULL, + PROPERTY_NAME VARCHAR(100) DEFAULT 0, + PROPERTY_VALUE VARCHAR(100) DEFAULT NULL, + TENANT_ID VARCHAR(100), + PRIMARY KEY (GROUP_ID, PROPERTY_NAME, TENANT_ID) +); + CREATE TABLE IF NOT EXISTS DM_DEVICE_GROUP_MAP ( ID INTEGER AUTO_INCREMENT NOT NULL, DEVICE_ID INTEGER DEFAULT NULL, diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql index 30e680a4c8..bcb8073218 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql @@ -64,6 +64,15 @@ CREATE TABLE DM_DEVICE_PROPERTIES ( PRIMARY KEY (DEVICE_TYPE_NAME, DEVICE_IDENTIFICATION, PROPERTY_NAME, TENANT_ID) ); +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[GROUP_PROPERTIES]') AND TYPE IN (N'U')) +CREATE TABLE GROUP_PROPERTIES ( + GROUP_ID INTEGER NOT NULL, + PROPERTY_NAME VARCHAR(100) DEFAULT 0, + PROPERTY_VALUE VARCHAR(100) DEFAULT NULL, + TENANT_ID VARCHAR(100), + PRIMARY KEY (GROUP_ID, PROPERTY_NAME, TENANT_ID) +); + IF NOT EXISTS(SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[DM_DEVICE_GROUP_MAP]') AND TYPE IN (N'U')) diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql index b8ef339105..df2a6fbb4c 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql @@ -60,6 +60,14 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_PROPERTIES ( PRIMARY KEY (DEVICE_TYPE_NAME, DEVICE_IDENTIFICATION, PROPERTY_NAME, TENANT_ID) )ENGINE = InnoDB; +CREATE TABLE IF NOT EXISTS GROUP_PROPERTIES ( + GROUP_ID INTEGER NOT NULL, + PROPERTY_NAME VARCHAR(100) DEFAULT 0, + PROPERTY_VALUE VARCHAR(100) DEFAULT NULL, + TENANT_ID VARCHAR(100), + PRIMARY KEY (GROUP_ID, PROPERTY_NAME, TENANT_ID) +)ENGINE = InnoDB; + CREATE TABLE IF NOT EXISTS DM_DEVICE_GROUP_MAP ( ID INTEGER AUTO_INCREMENT NOT NULL, DEVICE_ID INTEGER DEFAULT NULL, diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql index 77b51da66a..847c86d87f 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql @@ -111,6 +111,14 @@ CREATE TABLE DM_DEVICE_PROPERTIES ( ) / +CREATE TABLE GROUP_PROPERTIES ( + GROUP_ID NUMBER(10) NOT NULL, + PROPERTY_NAME VARCHAR2(100) DEFAULT 0, + PROPERTY_VALUE VARCHAR2(100) DEFAULT NULL, + TENANT_ID VARCHAR2(100), + CONSTRAINT PK_DM_GROUP_PROPERTIES PRIMARY KEY (GROUP_ID, PROPERTY_NAME, TENANT_ID) +) +/ CREATE TABLE DM_DEVICE_GROUP_MAP ( ID NUMBER(10) NOT NULL, diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql index f1a05feabd..e9b4e75eff 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql @@ -48,6 +48,14 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_PROPERTIES ( PRIMARY KEY (DEVICE_TYPE_NAME, DEVICE_IDENTIFICATION, PROPERTY_NAME, TENANT_ID) ); +CREATE TABLE IF NOT EXISTS GROUP_PROPERTIES ( + GROUP_ID INTEGER NOT NULL, + PROPERTY_NAME VARCHAR(100) DEFAULT 0, + PROPERTY_VALUE VARCHAR(100) DEFAULT NULL, + TENANT_ID INTEGER DEFAULT 0, + PRIMARY KEY (GROUP_ID, PROPERTY_NAME, TENANT_ID) +); + CREATE INDEX IDX_DM_DEVICE ON DM_DEVICE(TENANT_ID, DEVICE_TYPE_ID); CREATE TABLE IF NOT EXISTS DM_DEVICE_GROUP_MAP (