You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by al...@apache.org on 2012/07/06 21:03:38 UTC

[6/30] git commit: Resource tags: CS-15473 - fixed delete/list by resourceId when UUID is specified as a value

Resource tags: CS-15473 - fixed delete/list by resourceId when UUID is specified as a value

Conflicts:

	server/src/com/cloud/network/dao/FirewallRulesDaoImpl.java
	server/src/com/cloud/network/vpc/Dao/StaticRouteDaoImpl.java
	server/src/com/cloud/network/vpc/Dao/VpcDaoImpl.java
	server/src/com/cloud/projects/dao/ProjectDaoImpl.java


Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/85677b71
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/85677b71
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/85677b71

Branch: refs/heads/vpc
Commit: 85677b71febe514fac85a9d1d2d179dd052617f5
Parents: 710fa36
Author: Alena Prokharchyk <al...@citrix.com>
Authored: Fri Jul 6 10:31:20 2012 -0700
Committer: Alena Prokharchyk <al...@citrix.com>
Committed: Fri Jul 6 11:43:31 2012 -0700

----------------------------------------------------------------------
 api/src/com/cloud/server/ResourceTag.java          |    5 +++
 .../cloud/network/dao/FirewallRulesDaoImpl.java    |    6 ++--
 .../com/cloud/network/dao/IPAddressDaoImpl.java    |    2 +-
 .../src/com/cloud/network/dao/NetworkDaoImpl.java  |    2 +-
 .../network/security/dao/SecurityGroupDaoImpl.java |    2 +-
 .../src/com/cloud/projects/dao/ProjectDaoImpl.java |    2 -
 .../src/com/cloud/storage/dao/SnapshotDaoImpl.java |    2 +-
 .../com/cloud/storage/dao/VMTemplateDaoImpl.java   |    4 +-
 .../src/com/cloud/storage/dao/VolumeDaoImpl.java   |    2 +-
 server/src/com/cloud/tags/ResourceTagVO.java       |   12 +++++++-
 .../com/cloud/tags/TaggedResourceManagerImpl.java  |   22 +++++++++++---
 server/src/com/cloud/tags/dao/ResourceTagDao.java  |    9 +++++-
 .../com/cloud/tags/dao/ResourceTagsDaoImpl.java    |   11 +++++++-
 server/src/com/cloud/vm/dao/UserVmDaoImpl.java     |    2 +-
 server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java |    2 +-
 setup/db/create-schema.sql                         |    5 +++-
 16 files changed, 67 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/85677b71/api/src/com/cloud/server/ResourceTag.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/server/ResourceTag.java b/api/src/com/cloud/server/ResourceTag.java
index e11320e..640512b 100644
--- a/api/src/com/cloud/server/ResourceTag.java
+++ b/api/src/com/cloud/server/ResourceTag.java
@@ -64,4 +64,9 @@ public interface ResourceTag extends ControlledEntity{
      */
     String getCustomer();
 
+    /**
+     * @return
+     */
+    String getResourceUuid();
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/85677b71/server/src/com/cloud/network/dao/FirewallRulesDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/dao/FirewallRulesDaoImpl.java b/server/src/com/cloud/network/dao/FirewallRulesDaoImpl.java
index b9825b5..8cf9bbf 100644
--- a/server/src/com/cloud/network/dao/FirewallRulesDaoImpl.java
+++ b/server/src/com/cloud/network/dao/FirewallRulesDaoImpl.java
@@ -280,11 +280,11 @@ public class FirewallRulesDaoImpl extends GenericDaoBase<FirewallRuleVO, Long> i
         FirewallRuleVO entry = findById(id);
         if (entry != null) {
             if (entry.getPurpose() == Purpose.LoadBalancing) {
-                _tagsDao.removeBy(id, TaggedResourceType.LoadBalancer);
+                _tagsDao.removeByIdAndType(id, TaggedResourceType.LoadBalancer);
             } else if (entry.getPurpose() == Purpose.PortForwarding) {
-                _tagsDao.removeBy(id, TaggedResourceType.PortForwardingRule);
+                _tagsDao.removeByIdAndType(id, TaggedResourceType.PortForwardingRule);
             } else if (entry.getPurpose() == Purpose.Firewall) {
-                _tagsDao.removeBy(id, TaggedResourceType.FirewallRule);
+                _tagsDao.removeByIdAndType(id, TaggedResourceType.FirewallRule);
             }
         }
         boolean result = super.remove(id);

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/85677b71/server/src/com/cloud/network/dao/IPAddressDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/dao/IPAddressDaoImpl.java b/server/src/com/cloud/network/dao/IPAddressDaoImpl.java
index bf6d152..9755184 100755
--- a/server/src/com/cloud/network/dao/IPAddressDaoImpl.java
+++ b/server/src/com/cloud/network/dao/IPAddressDaoImpl.java
@@ -323,7 +323,7 @@ public class IPAddressDaoImpl extends GenericDaoBase<IPAddressVO, Long> implemen
         txn.start();
         IPAddressVO entry = findById(id);
         if (entry != null) {
-            _tagsDao.removeBy(id, TaggedResourceType.SecurityGroup);
+            _tagsDao.removeByIdAndType(id, TaggedResourceType.SecurityGroup);
         }
         boolean result = super.remove(id);
         txn.commit();

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/85677b71/server/src/com/cloud/network/dao/NetworkDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/dao/NetworkDaoImpl.java b/server/src/com/cloud/network/dao/NetworkDaoImpl.java
index a5b036b..04a79b8 100644
--- a/server/src/com/cloud/network/dao/NetworkDaoImpl.java
+++ b/server/src/com/cloud/network/dao/NetworkDaoImpl.java
@@ -495,7 +495,7 @@ public class NetworkDaoImpl extends GenericDaoBase<NetworkVO, Long> implements N
         txn.start();
         NetworkVO entry = findById(id);
         if (entry != null) {
-            _tagsDao.removeBy(id, TaggedResourceType.Network);
+            _tagsDao.removeByIdAndType(id, TaggedResourceType.Network);
         }
         boolean result = super.remove(id);
         txn.commit();

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/85677b71/server/src/com/cloud/network/security/dao/SecurityGroupDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/security/dao/SecurityGroupDaoImpl.java b/server/src/com/cloud/network/security/dao/SecurityGroupDaoImpl.java
index 7f921a2..0c9bdc5 100644
--- a/server/src/com/cloud/network/security/dao/SecurityGroupDaoImpl.java
+++ b/server/src/com/cloud/network/security/dao/SecurityGroupDaoImpl.java
@@ -108,7 +108,7 @@ public class SecurityGroupDaoImpl extends GenericDaoBase<SecurityGroupVO, Long>
         txn.start();
         SecurityGroupVO entry = findById(id);
         if (entry != null) {
-            _tagsDao.removeBy(id, TaggedResourceType.SecurityGroup);
+            _tagsDao.removeByIdAndType(id, TaggedResourceType.SecurityGroup);
         }
         boolean result = super.remove(id);
         txn.commit();

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/85677b71/server/src/com/cloud/projects/dao/ProjectDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/projects/dao/ProjectDaoImpl.java b/server/src/com/cloud/projects/dao/ProjectDaoImpl.java
index a7eeb26..87c8d21 100644
--- a/server/src/com/cloud/projects/dao/ProjectDaoImpl.java
+++ b/server/src/com/cloud/projects/dao/ProjectDaoImpl.java
@@ -73,8 +73,6 @@ public class ProjectDaoImpl extends GenericDaoBase<ProjectVO, Long> implements P
         if (!update(projectId, projectToRemove)) {
             s_logger.warn("Failed to reset name for the project id=" + projectId + " as a part of project remove");
             return false;
-        } else {
-
         }
         result = super.remove(projectId);
         txn.commit();

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/85677b71/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java b/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
index ae657bf..ac4bb6f 100644
--- a/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
+++ b/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
@@ -301,7 +301,7 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements
         txn.start();
         SnapshotVO entry = findById(id);
         if (entry != null) {
-            _tagsDao.removeBy(id, TaggedResourceType.Snapshot);
+            _tagsDao.removeByIdAndType(id, TaggedResourceType.Snapshot);
         }
         boolean result = super.remove(id);
         txn.commit();

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/85677b71/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java b/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java
index e8b6b26..6f513a3 100755
--- a/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java
+++ b/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java
@@ -805,9 +805,9 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
         template.setRemoved(new Date());
         if (template != null) {
             if (template.getFormat() == ImageFormat.ISO) {
-                _tagsDao.removeBy(id, TaggedResourceType.ISO);
+                _tagsDao.removeByIdAndType(id, TaggedResourceType.ISO);
             } else {
-                _tagsDao.removeBy(id, TaggedResourceType.Template);
+                _tagsDao.removeByIdAndType(id, TaggedResourceType.Template);
             }
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/85677b71/server/src/com/cloud/storage/dao/VolumeDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/dao/VolumeDaoImpl.java b/server/src/com/cloud/storage/dao/VolumeDaoImpl.java
index 49e248b..638d209 100755
--- a/server/src/com/cloud/storage/dao/VolumeDaoImpl.java
+++ b/server/src/com/cloud/storage/dao/VolumeDaoImpl.java
@@ -407,7 +407,7 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
         txn.start();
         VolumeVO entry = findById(id);
         if (entry != null) {
-            _tagsDao.removeBy(id, TaggedResourceType.Volume);
+            _tagsDao.removeByIdAndType(id, TaggedResourceType.Volume);
         }
         boolean result = super.remove(id);
         txn.commit();

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/85677b71/server/src/com/cloud/tags/ResourceTagVO.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/tags/ResourceTagVO.java b/server/src/com/cloud/tags/ResourceTagVO.java
index f175006..d5b28eb 100644
--- a/server/src/com/cloud/tags/ResourceTagVO.java
+++ b/server/src/com/cloud/tags/ResourceTagVO.java
@@ -61,6 +61,9 @@ public class ResourceTagVO implements Identity, ResourceTag{
     @Column(name="resource_id")
     long resourceId;
     
+    @Column(name="resource_uuid")
+    private String resourceUuid;
+    
     @Column(name="resource_type")
     @Enumerated(value=EnumType.STRING)
     private TaggedResourceType resourceType;
@@ -81,9 +84,10 @@ public class ResourceTagVO implements Identity, ResourceTag{
      * @param resourceId
      * @param resourceType
      * @param customer TODO
+     * @param resourceUuid TODO
      */
     public ResourceTagVO(String key, String value, long accountId, long domainId, long resourceId, 
-            TaggedResourceType resourceType, String customer) {
+            TaggedResourceType resourceType, String customer, String resourceUuid) {
         super();
         this.key = key;
         this.value = value;
@@ -93,6 +97,7 @@ public class ResourceTagVO implements Identity, ResourceTag{
         this.resourceType = resourceType;
         this.uuid = UUID.randomUUID().toString();
         this.customer = customer;
+        this.resourceUuid = resourceUuid;
     }
     
     
@@ -149,4 +154,9 @@ public class ResourceTagVO implements Identity, ResourceTag{
     public String getCustomer() {
         return customer;
     }
+
+    @Override
+    public String getResourceUuid() {
+        return resourceUuid;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/85677b71/server/src/com/cloud/tags/TaggedResourceManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/tags/TaggedResourceManagerImpl.java b/server/src/com/cloud/tags/TaggedResourceManagerImpl.java
index bfadb78..0386425 100644
--- a/server/src/com/cloud/tags/TaggedResourceManagerImpl.java
+++ b/server/src/com/cloud/tags/TaggedResourceManagerImpl.java
@@ -236,10 +236,12 @@ public class TaggedResourceManagerImpl implements TaggedResourceService, Manager
         for (String tag : tags.keySet()) {
             for (String resourceId : resourceIds) {
                 Long id = getResourceId(resourceId, resourceType);
+                String resourceUuid = getUuid(resourceId, resourceType);
                 
                 //check if object exists
                 if (_daoMap.get(resourceType).findById(id) == null) {
-                    throw new InvalidParameterValueException("Unable to find resource by id " + resourceId + " and type " + resourceType);
+                    throw new InvalidParameterValueException("Unable to find resource by id " + resourceId + 
+                            " and type " + resourceType);
                 }
                 
                 Pair<Long, Long> accountDomainPair = getAccountDomain(id, resourceType);
@@ -257,10 +259,9 @@ public class TaggedResourceManagerImpl implements TaggedResourceService, Manager
                
                 ResourceTagVO resourceTag = new ResourceTagVO(tag, tags.get(tag), accountDomainPair.first(),
                         accountDomainPair.second(), 
-                        id, resourceType, customer);
+                        id, resourceType, customer, resourceUuid);
                 resourceTag = _resourceTagDao.persist(resourceTag);
                 resourceTags.add(resourceTag);
-
             }
         }
         
@@ -324,7 +325,9 @@ public class TaggedResourceManagerImpl implements TaggedResourceService, Manager
 
        sb.and("key", sb.entity().getKey(), SearchCriteria.Op.EQ);
        sb.and("value", sb.entity().getValue(), SearchCriteria.Op.EQ);
-       sb.and("resourceId", sb.entity().getResourceId(), SearchCriteria.Op.EQ);
+       sb.and().op("resourceId", sb.entity().getResourceId(), SearchCriteria.Op.EQ);
+       sb.or("resourceUuid", sb.entity().getResourceUuid(), SearchCriteria.Op.EQ);
+       sb.cp();
        sb.and("resourceType", sb.entity().getResourceType(), SearchCriteria.Op.EQ);
        sb.and("customer", sb.entity().getCustomer(), SearchCriteria.Op.EQ);
        
@@ -342,6 +345,7 @@ public class TaggedResourceManagerImpl implements TaggedResourceService, Manager
        
        if (resourceId != null) {
            sc.setParameters("resourceId", resourceId);
+           sc.setParameters("resourceUuid", resourceId);
        }
        
        if (resourceType != null) {
@@ -362,10 +366,14 @@ public class TaggedResourceManagerImpl implements TaggedResourceService, Manager
         Account caller = UserContext.current().getCaller();
         
         SearchBuilder<ResourceTagVO> sb = _resourceTagDao.createSearchBuilder();
-        sb.and("resourceId", sb.entity().getResourceId(), SearchCriteria.Op.IN);
+        sb.and().op("resourceId", sb.entity().getResourceId(), SearchCriteria.Op.IN);
+        sb.or("resourceUuid", sb.entity().getResourceUuid(), SearchCriteria.Op.IN);
+        sb.cp();
         sb.and("resourceType", sb.entity().getResourceType(), SearchCriteria.Op.EQ);
+        
         SearchCriteria<ResourceTagVO> sc = sb.create();
         sc.setParameters("resourceId", resourceIds.toArray());
+        sc.setParameters("resourceUuid", resourceIds.toArray());
         sc.setParameters("resourceType", resourceType);
         
         List<? extends ResourceTag> resourceTags = _resourceTagDao.search(sc, null);;
@@ -400,6 +408,10 @@ public class TaggedResourceManagerImpl implements TaggedResourceService, Manager
             }
         }
         
+        if (tagsToRemove.isEmpty()) {
+            throw new InvalidParameterValueException("Unable to find tags by parameters specified");
+        }
+        
         //Remove the tags
         Transaction txn = Transaction.currentTxn();
         txn.start();

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/85677b71/server/src/com/cloud/tags/dao/ResourceTagDao.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/tags/dao/ResourceTagDao.java b/server/src/com/cloud/tags/dao/ResourceTagDao.java
index 58b2aeb..2a5c339 100644
--- a/server/src/com/cloud/tags/dao/ResourceTagDao.java
+++ b/server/src/com/cloud/tags/dao/ResourceTagDao.java
@@ -33,8 +33,15 @@ public interface ResourceTagDao extends GenericDao<ResourceTagVO, Long>{
      * @param resourceType
      * @return
      */
-    boolean removeBy(long resourceId, TaggedResourceType resourceType);
+    boolean removeByIdAndType(long resourceId, TaggedResourceType resourceType);
     
     List<? extends ResourceTag> listBy(long resourceId, TaggedResourceType resourceType);
 
+//    /**
+//     * @param resourceUuId
+//     * @param resourceType
+//     * @return
+//     */
+//    ResourceTag findByUuid(String resourceUuId, TaggedResourceType resourceType);
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/85677b71/server/src/com/cloud/tags/dao/ResourceTagsDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/tags/dao/ResourceTagsDaoImpl.java b/server/src/com/cloud/tags/dao/ResourceTagsDaoImpl.java
index ae7895b..255f940 100644
--- a/server/src/com/cloud/tags/dao/ResourceTagsDaoImpl.java
+++ b/server/src/com/cloud/tags/dao/ResourceTagsDaoImpl.java
@@ -39,18 +39,27 @@ public class ResourceTagsDaoImpl extends GenericDaoBase<ResourceTagVO, Long> imp
     protected ResourceTagsDaoImpl() {
         AllFieldsSearch = createSearchBuilder();
         AllFieldsSearch.and("resourceId", AllFieldsSearch.entity().getResourceId(), Op.EQ);
+        AllFieldsSearch.and("uuid", AllFieldsSearch.entity().getResourceUuid(), Op.EQ);
         AllFieldsSearch.and("resourceType", AllFieldsSearch.entity().getResourceType(), Op.EQ);
         AllFieldsSearch.done();
     }
     
     @Override
-    public boolean removeBy(long resourceId, ResourceTag.TaggedResourceType resourceType) {
+    public boolean removeByIdAndType(long resourceId, ResourceTag.TaggedResourceType resourceType) {
         SearchCriteria<ResourceTagVO> sc = AllFieldsSearch.create();
         sc.setParameters("resourceId", resourceId);
         sc.setParameters("resourceType", resourceType);
         remove(sc);
         return true;
     }
+    
+//    @Override
+//    public ResourceTag findByUuid(String resourceUuId, ResourceTag.TaggedResourceType resourceType) {
+//        SearchCriteria<ResourceTagVO> sc = AllFieldsSearch.create();
+//        sc.setParameters("uuid", resourceUuId);
+//        sc.setParameters("resourceType", resourceType);
+//        return findOneBy(sc);
+//    }
 
     @Override
     public List<? extends ResourceTag> listBy(long resourceId, TaggedResourceType resourceType) {

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/85677b71/server/src/com/cloud/vm/dao/UserVmDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/dao/UserVmDaoImpl.java b/server/src/com/cloud/vm/dao/UserVmDaoImpl.java
index 20c5c0f..db1d877 100755
--- a/server/src/com/cloud/vm/dao/UserVmDaoImpl.java
+++ b/server/src/com/cloud/vm/dao/UserVmDaoImpl.java
@@ -556,7 +556,7 @@ public class UserVmDaoImpl extends GenericDaoBase<UserVmVO, Long> implements Use
     public boolean remove(Long id) {
         Transaction txn = Transaction.currentTxn();
         txn.start();
-        _tagsDao.removeBy(id, TaggedResourceType.UserVm);
+        _tagsDao.removeByIdAndType(id, TaggedResourceType.UserVm);
         boolean result = super.remove(id);
         txn.commit();
         return result;

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/85677b71/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java b/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java
index 042b153..e743a35 100644
--- a/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java
+++ b/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java
@@ -562,7 +562,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
         txn.start();
         VMInstanceVO vm = findById(id);
         if (vm != null && vm.getType() == Type.User) {
-            _tagsDao.removeBy(id, TaggedResourceType.UserVm);
+            _tagsDao.removeByIdAndType(id, TaggedResourceType.UserVm);
         }
         boolean result = super.remove(id);
         txn.commit();

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/85677b71/setup/db/create-schema.sql
----------------------------------------------------------------------
diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql
index afcee3f..bc8c906 100755
--- a/setup/db/create-schema.sql
+++ b/setup/db/create-schema.sql
@@ -2139,6 +2139,7 @@ CREATE TABLE `cloud`.`resource_tags` (
   `key` varchar(255),
   `value` varchar(255),
   `resource_id` bigint unsigned NOT NULL,
+  `resource_uuid` varchar(40),
   `resource_type` varchar(255),
   `customer` varchar(255),
   `domain_id` bigint unsigned NOT NULL COMMENT 'foreign key to domain id',
@@ -2146,7 +2147,9 @@ CREATE TABLE `cloud`.`resource_tags` (
   PRIMARY KEY (`id`),
   CONSTRAINT `fk_tags__account_id` FOREIGN KEY(`account_id`) REFERENCES `account`(`id`),
   CONSTRAINT `fk_tags__domain_id` FOREIGN KEY(`domain_id`) REFERENCES `domain`(`id`),
-  UNIQUE `i_tags__resource_id__resource_type__key`(`resource_id`, `resource_type`, `key`)
+  UNIQUE `i_tags__resource_id__resource_type__key`(`resource_id`, `resource_type`, `key`),
+  CONSTRAINT `uc_resource_tags__uuid` UNIQUE (`uuid`),
+  CONSTRAINT `uc_resource_tags__resource_uuid` UNIQUE (`resource_uuid`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;