Return-Path: X-Original-To: apmail-incubator-cloudstack-commits-archive@minotaur.apache.org Delivered-To: apmail-incubator-cloudstack-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 40B65C0A9 for ; Fri, 6 Jul 2012 23:58:44 +0000 (UTC) Received: (qmail 17531 invoked by uid 500); 6 Jul 2012 23:58:43 -0000 Delivered-To: apmail-incubator-cloudstack-commits-archive@incubator.apache.org Received: (qmail 17511 invoked by uid 500); 6 Jul 2012 23:58:43 -0000 Mailing-List: contact cloudstack-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: cloudstack-dev@incubator.apache.org Delivered-To: mailing list cloudstack-commits@incubator.apache.org Received: (qmail 17502 invoked by uid 99); 6 Jul 2012 23:58:43 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 06 Jul 2012 23:58:43 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id A8E3CC5C3; Fri, 6 Jul 2012 23:58:43 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: alena1108@apache.org To: cloudstack-commits@incubator.apache.org X-Mailer: ASF-Git Admin Mailer Subject: git commit: ResourceTags: respect tag parameter in listTemplates/listIsos commands Message-Id: <20120706235843.A8E3CC5C3@tyr.zones.apache.org> Date: Fri, 6 Jul 2012 23:58:43 +0000 (UTC) Updated Branches: refs/heads/master 8d38f4e05 -> 63d6941bd ResourceTags: respect tag parameter in listTemplates/listIsos commands Conflicts: server/src/com/cloud/storage/dao/VMTemplateDao.java server/src/com/cloud/storage/dao/VMTemplateDaoImpl.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/63d6941b Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/63d6941b Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/63d6941b Branch: refs/heads/master Commit: 63d6941bdc65859f17e0641288fe6d3190193e8b Parents: 8d38f4e Author: Alena Prokharchyk Authored: Fri Jul 6 16:37:16 2012 -0700 Committer: Alena Prokharchyk Committed: Fri Jul 6 16:59:14 2012 -0700 ---------------------------------------------------------------------- .../com/cloud/api/commands/ListTemplatesCmd.java | 1 - server/src/com/cloud/api/ApiResponseHelper.java | 19 ++++ .../src/com/cloud/server/ManagementServerImpl.java | 16 ++- .../src/com/cloud/storage/StorageManagerImpl.java | 2 +- .../src/com/cloud/storage/dao/VMTemplateDao.java | 25 +++-- .../com/cloud/storage/dao/VMTemplateDaoImpl.java | 79 +++++++++++++-- setup/db/create-schema.sql | 5 +- 7 files changed, 115 insertions(+), 32 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/63d6941b/api/src/com/cloud/api/commands/ListTemplatesCmd.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/api/commands/ListTemplatesCmd.java b/api/src/com/cloud/api/commands/ListTemplatesCmd.java index c1002b8..6e1e0b4 100755 --- a/api/src/com/cloud/api/commands/ListTemplatesCmd.java +++ b/api/src/com/cloud/api/commands/ListTemplatesCmd.java @@ -23,7 +23,6 @@ import java.util.Set; import org.apache.log4j.Logger; import com.cloud.api.ApiConstants; -import com.cloud.api.BaseCmd.CommandType; import com.cloud.api.BaseListTaggedResourcesCmd; import com.cloud.api.IdentityMapper; import com.cloud.api.Implementation; http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/63d6941b/server/src/com/cloud/api/ApiResponseHelper.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 305fdeb..4c88e2b 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -2120,6 +2120,15 @@ public class ApiResponseHelper implements ResponseGenerator { Account owner = ApiDBUtils.findAccountById(iso.getAccountId()); populateAccount(isoResponse, owner.getId()); populateDomain(isoResponse, owner.getDomainId()); + + //set tag information + List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.ISO, iso.getId()); + List tagResponses = new ArrayList(); + for (ResourceTag tag : tags) { + ResourceTagResponse tagResponse = createResourceTagResponse(tag, true); + tagResponses.add(tagResponse); + } + isoResponse.setTags(tagResponses); isoResponse.setObjectName("iso"); isoResponses.add(isoResponse); @@ -2268,6 +2277,16 @@ public class ApiResponseHelper implements ResponseGenerator { if (isoSize > 0) { isoResponse.setSize(isoSize); } + + //set tag information + List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.ISO, iso.getId()); + + List tagResponses = new ArrayList(); + for (ResourceTag tag : tags) { + ResourceTagResponse tagResponse = createResourceTagResponse(tag, true); + tagResponses.add(tagResponse); + } + isoResponse.setTags(tagResponses); isoResponse.setObjectName("iso"); isoResponses.add(isoResponse); http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/63d6941b/server/src/com/cloud/server/ManagementServerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index ddcf751..93c2f4c 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -1296,12 +1296,15 @@ public class ManagementServerImpl implements ManagementServer { boolean showDomr = ((templateFilter != TemplateFilter.selfexecutable) && (templateFilter != TemplateFilter.featured)); HypervisorType hypervisorType = HypervisorType.getType(cmd.getHypervisor()); - return listTemplates(id, cmd.getTemplateName(), cmd.getKeyword(), templateFilter, false, null, cmd.getPageSizeVal(), cmd.getStartIndex(), cmd.getZoneId(), hypervisorType, showDomr, + return listTemplates(id, cmd.getTemplateName(), cmd.getKeyword(), templateFilter, false, null, + cmd.getPageSizeVal(), cmd.getStartIndex(), cmd.getZoneId(), hypervisorType, showDomr, cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags); } - private Set> listTemplates(Long templateId, String name, String keyword, TemplateFilter templateFilter, boolean isIso, Boolean bootable, Long pageSize, Long startIndex, - Long zoneId, HypervisorType hyperType, boolean showDomr, boolean onlyReady, List permittedAccounts, Account caller, ListProjectResourcesCriteria listProjectResourcesCriteria, Map tags) { + private Set> listTemplates(Long templateId, String name, String keyword, TemplateFilter templateFilter, + boolean isIso, Boolean bootable, Long pageSize, Long startIndex, Long zoneId, HypervisorType hyperType, + boolean showDomr, boolean onlyReady, List permittedAccounts, Account caller, + ListProjectResourcesCriteria listProjectResourcesCriteria, Map tags) { VMTemplateVO template = null; if (templateId != null) { @@ -1339,11 +1342,12 @@ public class ManagementServerImpl implements ManagementServer { if (template == null) { templateZonePairSet = _templateDao.searchSwiftTemplates(name, keyword, templateFilter, isIso, hypers, bootable, domain, pageSize, startIndex, zoneId, hyperType, onlyReady, showDomr, - permittedAccounts, caller); + permittedAccounts, caller, tags); Set> templateZonePairSet2 = new HashSet>(); templateZonePairSet2 = _templateDao.searchTemplates(name, keyword, templateFilter, isIso, hypers, bootable, domain, pageSize, startIndex, zoneId, hyperType, onlyReady, showDomr, - permittedAccounts, caller, listProjectResourcesCriteria); + permittedAccounts, caller, listProjectResourcesCriteria, tags); + for (Pair tmpltPair : templateZonePairSet2) { if (!templateZonePairSet.contains(new Pair(tmpltPair.first(), -1L))) { templateZonePairSet.add(tmpltPair); @@ -1362,7 +1366,7 @@ public class ManagementServerImpl implements ManagementServer { if (template == null) { templateZonePairSet = _templateDao.searchTemplates(name, keyword, templateFilter, isIso, hypers, bootable, domain, pageSize, startIndex, zoneId, hyperType, onlyReady, showDomr, - permittedAccounts, caller, listProjectResourcesCriteria); + permittedAccounts, caller, listProjectResourcesCriteria, tags); } else { // if template is not public, perform permission check here if (!template.isPublicTemplate() && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/63d6941b/server/src/com/cloud/storage/StorageManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index 8f18b04..baea54c 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -3772,7 +3772,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag sb.join("vmSearch", vmSearch, sb.entity().getInstanceId(), vmSearch.entity().getId(), JoinBuilder.JoinType.LEFTOUTER); if (tags != null && !tags.isEmpty()) { - SearchBuilder tagSearch = _resourceTagDao.createSearchBuilder(); + SearchBuilder tagSearch = _resourceTagDao.createSearchBuilder(); for (int count=0; count < tags.size(); count++) { tagSearch.or().op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ); tagSearch.and("value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ); http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/63d6941b/server/src/com/cloud/storage/dao/VMTemplateDao.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/storage/dao/VMTemplateDao.java b/server/src/com/cloud/storage/dao/VMTemplateDao.java index 42f8147..ed80aae 100755 --- a/server/src/com/cloud/storage/dao/VMTemplateDao.java +++ b/server/src/com/cloud/storage/dao/VMTemplateDao.java @@ -17,6 +17,7 @@ package com.cloud.storage.dao; import java.util.List; +import java.util.Map; import java.util.Set; import com.cloud.domain.DomainVO; @@ -40,24 +41,28 @@ public interface VMTemplateDao extends GenericDao { //public void update(VMTemplateVO template); + public List listAllSystemVMTemplates(); - public List listDefaultBuiltinTemplates(); - public String getRoutingTemplateUniqueName(); - public List findIsosByIdAndPath(Long domainId, Long accountId, String path); - public List listReadyTemplates(); - public List listByAccountId(long accountId); - public Set> searchTemplates(String name, String keyword, TemplateFilter templateFilter, boolean isIso, List hypers, Boolean bootable, - DomainVO domain, Long pageSize, Long startIndex, Long zoneId, HypervisorType hyperType, boolean onlyReady, boolean showDomr, List permittedAccounts, Account caller, ListProjectResourcesCriteria listProjectResourcesCriteria); + public List listDefaultBuiltinTemplates(); + public String getRoutingTemplateUniqueName(); + public List findIsosByIdAndPath(Long domainId, Long accountId, String path); + public List listReadyTemplates(); + public List listByAccountId(long accountId); + public Set> searchTemplates(String name, String keyword, TemplateFilter templateFilter, boolean isIso, + List hypers, Boolean bootable, DomainVO domain, Long pageSize, Long startIndex, Long zoneId, + HypervisorType hyperType, boolean onlyReady, boolean showDomr, List permittedAccounts, Account caller, + ListProjectResourcesCriteria listProjectResourcesCriteria, Map tags); - public Set> searchSwiftTemplates(String name, String keyword, TemplateFilter templateFilter, boolean isIso, List hypers, Boolean bootable, DomainVO domain, - Long pageSize, Long startIndex, Long zoneId, HypervisorType hyperType, boolean onlyReady, boolean showDomr, List permittedAccounts, Account caller); + public Set> searchSwiftTemplates(String name, String keyword, TemplateFilter templateFilter, + boolean isIso, List hypers, Boolean bootable, DomainVO domain, Long pageSize, Long startIndex, + Long zoneId, HypervisorType hyperType, boolean onlyReady, boolean showDomr, List permittedAccounts, Account caller, Map tags); public long addTemplateToZone(VMTemplateVO tmplt, long zoneId); public List listAllInZone(long dataCenterId); public List listByHypervisorType(List hyperTypes); - public List publicIsoSearch(Boolean bootable, boolean listRemoved); + public List publicIsoSearch(Boolean bootable, boolean listRemoved, Map tags); VMTemplateVO findSystemVMTemplate(long zoneId); VMTemplateVO findSystemVMTemplate(long zoneId, HypervisorType hType); http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/63d6941b/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 6f513a3..1db12aa 100755 --- a/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java +++ b/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java @@ -33,7 +33,6 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; import com.cloud.api.BaseCmd; -import com.cloud.configuration.Resource; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.dao.DataCenterDao; import com.cloud.domain.DomainVO; @@ -50,6 +49,7 @@ import com.cloud.storage.Storage.TemplateType; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VMTemplateZoneVO; +import com.cloud.tags.ResourceTagVO; import com.cloud.tags.dao.ResourceTagsDaoImpl; import com.cloud.template.VirtualMachineTemplate.TemplateFilter; import com.cloud.user.Account; @@ -139,8 +139,32 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem } @Override - public List publicIsoSearch(Boolean bootable, boolean listRemoved){ - SearchCriteria sc = PublicIsoSearch.create(); + public List publicIsoSearch(Boolean bootable, boolean listRemoved, Map tags){ + + SearchBuilder sb = null; + if (tags == null || tags.isEmpty()) { + sb = PublicIsoSearch; + } else { + sb = createSearchBuilder(); + sb.and("public", sb.entity().isPublicTemplate(), SearchCriteria.Op.EQ); + sb.and("format", sb.entity().getFormat(), SearchCriteria.Op.EQ); + sb.and("type", sb.entity().getTemplateType(), SearchCriteria.Op.EQ); + sb.and("bootable", sb.entity().isBootable(), SearchCriteria.Op.EQ); + sb.and("removed", sb.entity().getRemoved(), SearchCriteria.Op.EQ); + + SearchBuilder tagSearch = _tagsDao.createSearchBuilder(); + for (int count=0; count < tags.size(); count++) { + tagSearch.or().op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ); + tagSearch.and("value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ); + tagSearch.cp(); + } + tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ); + sb.groupBy(sb.entity().getId()); + sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER); + } + + SearchCriteria sc = sb.create(); + sc.setParameters("public", 1); sc.setParameters("format", "ISO"); sc.setParameters("type", TemplateType.PERHOST.toString()); @@ -152,6 +176,16 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem sc.setParameters("removed", (Object)null); } + if (tags != null && !tags.isEmpty()) { + int count = 0; + sc.setJoinParameters("tagSearch", "resourceType", TaggedResourceType.ISO.toString()); + for (String key : tags.keySet()) { + sc.setJoinParameters("tagSearch", "key" + String.valueOf(count), key); + sc.setJoinParameters("tagSearch", "value" + String.valueOf(count), tags.get(key)); + count++; + } + } + return listBy(sc); } @@ -264,7 +298,6 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem PublicIsoSearch.and("type", PublicIsoSearch.entity().getTemplateType(), SearchCriteria.Op.EQ); PublicIsoSearch.and("bootable", PublicIsoSearch.entity().isBootable(), SearchCriteria.Op.EQ); PublicIsoSearch.and("removed", PublicIsoSearch.entity().getRemoved(), SearchCriteria.Op.EQ); - tmpltTypeHyperSearch = createSearchBuilder(); tmpltTypeHyperSearch.and("templateType", tmpltTypeHyperSearch.entity().getTemplateType(), SearchCriteria.Op.EQ); @@ -320,7 +353,7 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem @Override public Set> searchSwiftTemplates(String name, String keyword, TemplateFilter templateFilter, boolean isIso, List hypers, Boolean bootable, DomainVO domain, - Long pageSize, Long startIndex, Long zoneId, HypervisorType hyperType, boolean onlyReady, boolean showDomr, List permittedAccounts, Account caller) { + Long pageSize, Long startIndex, Long zoneId, HypervisorType hyperType, boolean onlyReady, boolean showDomr, List permittedAccounts, Account caller, Map tags) { StringBuilder builder = new StringBuilder(); if (!permittedAccounts.isEmpty()) { @@ -436,8 +469,12 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem return templateZonePairList; } - @Override - public Set> searchTemplates(String name, String keyword, TemplateFilter templateFilter, boolean isIso, List hypers, Boolean bootable, DomainVO domain, Long pageSize, Long startIndex, Long zoneId, HypervisorType hyperType, boolean onlyReady, boolean showDomr,List permittedAccounts, Account caller, ListProjectResourcesCriteria listProjectResourcesCriteria) { + + @Override + public Set> searchTemplates(String name, String keyword, TemplateFilter templateFilter, + boolean isIso, List hypers, Boolean bootable, DomainVO domain, Long pageSize, Long startIndex, + Long zoneId, HypervisorType hyperType, boolean onlyReady, boolean showDomr,List permittedAccounts, + Account caller, ListProjectResourcesCriteria listProjectResourcesCriteria, Map tags) { StringBuilder builder = new StringBuilder(); if (!permittedAccounts.isEmpty()) { for (Account permittedAccount : permittedAccounts) { @@ -468,6 +505,7 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem String guestOSJoin = ""; StringBuilder templateHostRefJoin = new StringBuilder(); String dataCenterJoin = "", lpjoin = ""; + String tagsJoin = ""; if (isIso && !hyperType.equals(HypervisorType.None)) { guestOSJoin = " INNER JOIN guest_os guestOS on (guestOS.id = t.guest_os_id) INNER JOIN guest_os_hypervisor goh on ( goh.guest_os_id = guestOS.id) "; @@ -480,11 +518,16 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem if ((templateFilter == TemplateFilter.featured) || (templateFilter == TemplateFilter.community)) { dataCenterJoin = " INNER JOIN data_center dc on (h.data_center_id = dc.id)"; } + if (templateFilter == TemplateFilter.sharedexecutable){ lpjoin = " INNER JOIN launch_permission lp ON t.id = lp.template_id "; } + + if (tags != null && !tags.isEmpty()) { + tagsJoin = " INNER JOIN resource_tags r ON t.id = r.resource_id "; + } - sql += guestOSJoin + templateHostRefJoin + dataCenterJoin + lpjoin; + sql += guestOSJoin + templateHostRefJoin + dataCenterJoin + lpjoin + tagsJoin; String whereClause = ""; //All joins have to be made before we start setting the condition settings @@ -497,7 +540,7 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem if (listProjectResourcesCriteria == ListProjectResourcesCriteria.SkipProjectResources) { whereClause += " AND a.type != " + Account.ACCOUNT_TYPE_PROJECT; } - }else + } else if (listProjectResourcesCriteria == ListProjectResourcesCriteria.SkipProjectResources) { whereClause += " WHERE a.type != " + Account.ACCOUNT_TYPE_PROJECT; } @@ -580,6 +623,19 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem } else if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN && !isIso) { return templateZonePairList; } + + if (tags != null && !tags.isEmpty()) { + whereClause += " AND ("; + boolean first = true; + for (String key : tags.keySet()) { + if (!first) { + whereClause += " OR "; + } + whereClause += "(r.key=\"" + key + "\" and r.value=\"" + tags.get(key) + "\")"; + first = false; + } + whereClause += ")"; + } if (whereClause.equals("")) { whereClause += " WHERE "; @@ -587,7 +643,8 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem whereClause += " AND "; } - sql += whereClause + getExtrasWhere(templateFilter, name, keyword, isIso, bootable, hyperType, zoneId, onlyReady, showDomr) + groupByClause + getOrderByLimit(pageSize, startIndex); + sql += whereClause + getExtrasWhere(templateFilter, name, keyword, isIso, bootable, hyperType, zoneId, + onlyReady, showDomr) + groupByClause + getOrderByLimit(pageSize, startIndex); pstmt = txn.prepareStatement(sql); rs = pstmt.executeQuery(); @@ -600,7 +657,7 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem if(isIso && templateZonePairList.size() < (pageSize != null ? pageSize : 500) && templateFilter != TemplateFilter.community && !(templateFilter == TemplateFilter.self && !BaseCmd.isRootAdmin(caller.getType())) ){ //evaluates to true If root admin and filter=self - List publicIsos = publicIsoSearch(bootable, false); + List publicIsos = publicIsoSearch(bootable, false, tags); for( int i=0; i < publicIsos.size(); i++){ if (keyword != null && publicIsos.get(i).getName().contains(keyword)) { templateZonePairList.add(new Pair(publicIsos.get(i).getId(), null)); http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/63d6941b/setup/db/create-schema.sql ---------------------------------------------------------------------- diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index bc8c906..c2efb27 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -2148,9 +2148,8 @@ CREATE TABLE `cloud`.`resource_tags` ( 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`), - CONSTRAINT `uc_resource_tags__uuid` UNIQUE (`uuid`), - CONSTRAINT `uc_resource_tags__resource_uuid` UNIQUE (`resource_uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; + CONSTRAINT `uc_resource_tags__uuid` UNIQUE (`uuid`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8; SET foreign_key_checks = 1;