Bladeren bron

SONAR-6262 Persist links in compute stack

tags/5.2-RC1
Julien Lancelot 9 jaren geleden
bovenliggende
commit
c613bf937e
29 gewijzigde bestanden met toevoegingen van 4857 en 2004 verwijderingen
  1. 49
    0
      server/sonar-server/src/main/java/org/sonar/server/component/db/ComponentLinkDao.java
  2. 1
    0
      server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java
  3. 147
    0
      server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistComponentLinksStep.java
  4. 7
    0
      server/sonar-server/src/main/java/org/sonar/server/db/DbClient.java
  5. 117
    0
      server/sonar-server/src/test/java/org/sonar/server/component/db/ComponentLinkDaoTest.java
  6. 4
    3
      server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputationStepsTest.java
  7. 224
    0
      server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistComponentLinksStepTest.java
  8. 5
    0
      server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentLinkDaoTest/delete.xml
  9. 3
    0
      server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentLinkDaoTest/empty.xml
  10. 5
    0
      server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentLinkDaoTest/insert.xml
  11. 7
    0
      server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentLinkDaoTest/shared.xml
  12. 5
    0
      server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentLinkDaoTest/update-result.xml
  13. 5
    0
      server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentLinkDaoTest/update.xml
  14. 11
    0
      server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistComponentLinksStepTest/add_links_on_project_and_module-result.xml
  15. 5
    0
      server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistComponentLinksStepTest/delete_link.xml
  16. 3
    0
      server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistComponentLinksStepTest/empty.xml
  17. 5
    0
      server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistComponentLinksStepTest/nothing_to_do_when_link_already_exists.xml
  18. 5
    0
      server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistComponentLinksStepTest/update_link-result.xml
  19. 5
    0
      server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistComponentLinksStepTest/update_link.xml
  20. 195
    58
      sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/Constants.java
  21. 544
    365
      sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/input/BatchInput.java
  22. 2721
    1182
      sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/output/BatchReport.java
  23. 613
    391
      sonar-batch-protocol/src/main/gen-java/org/sonar/server/source/db/FileSourceDb.java
  24. 6
    0
      sonar-batch-protocol/src/main/protobuf/batch_report.proto
  25. 8
    0
      sonar-batch-protocol/src/main/protobuf/constants.proto
  26. 79
    0
      sonar-core/src/main/java/org/sonar/core/component/ComponentLinkDto.java
  27. 37
    0
      sonar-core/src/main/java/org/sonar/core/component/db/ComponentLinkMapper.java
  28. 4
    5
      sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java
  29. 37
    0
      sonar-core/src/main/resources/org/sonar/core/component/db/ComponentLinkMapper.xml

+ 49
- 0
server/sonar-server/src/main/java/org/sonar/server/component/db/ComponentLinkDao.java Bestand weergeven

@@ -0,0 +1,49 @@
/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package org.sonar.server.component.db;

import org.sonar.api.ServerComponent;
import org.sonar.core.component.ComponentLinkDto;
import org.sonar.core.component.db.ComponentLinkMapper;
import org.sonar.core.persistence.DaoComponent;
import org.sonar.core.persistence.DbSession;

import java.util.List;

public class ComponentLinkDao implements ServerComponent, DaoComponent {

public List<ComponentLinkDto> selectByComponentUuid(DbSession session, String componentUuid) {
return session.getMapper(ComponentLinkMapper.class).selectByComponentUuid(componentUuid);
}

public void insert(DbSession session, ComponentLinkDto item) {
session.getMapper(ComponentLinkMapper.class).insert(item);
}

public void update(DbSession session, ComponentLinkDto item) {
session.getMapper(ComponentLinkMapper.class).update(item);
}

public void delete(DbSession session, long id) {
session.getMapper(ComponentLinkMapper.class).delete(id);
}

}

+ 1
- 0
server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java Bestand weergeven

@@ -42,6 +42,7 @@ public class ComputationSteps {
SwitchSnapshotStep.class,
IndexComponentsStep.class,
PurgeDatastoresStep.class,
PersistComponentLinksStep.class,

// ES indexing is done after all db changes
ApplyPermissionsStep.class,

+ 147
- 0
server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistComponentLinksStep.java Bestand weergeven

@@ -0,0 +1,147 @@
/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package org.sonar.server.computation.step;

import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import org.sonar.api.i18n.I18n;
import org.sonar.api.resources.Qualifiers;
import org.sonar.batch.protocol.Constants;
import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.batch.protocol.output.BatchReportReader;
import org.sonar.core.component.ComponentLinkDto;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
import org.sonar.server.computation.ComputationContext;
import org.sonar.server.db.DbClient;

import javax.annotation.Nullable;

import java.util.List;
import java.util.Locale;
import java.util.Set;

import static com.google.common.collect.Sets.newHashSet;

public class PersistComponentLinksStep implements ComputationStep {

private final DbClient dbClient;
private final I18n i18n;

public PersistComponentLinksStep(DbClient dbClient, I18n i18n) {
this.dbClient = dbClient;
this.i18n = i18n;
}

@Override
public String[] supportedProjectQualifiers() {
return new String[] {Qualifiers.PROJECT};
}

@Override
public void execute(ComputationContext context) {
DbSession session = dbClient.openSession(false);
try {
int rootComponentRef = context.getReportMetadata().getRootComponentRef();
recursivelyProcessComponent(session, context, rootComponentRef);
session.commit();
} finally {
MyBatis.closeQuietly(session);
}
}

private void recursivelyProcessComponent(DbSession session, ComputationContext context, int componentRef) {
BatchReportReader reportReader = context.getReportReader();
BatchReport.Component component = reportReader.readComponent(componentRef);
processLinks(session, component);

for (Integer childRef : component.getChildRefsList()) {
recursivelyProcessComponent(session, context, childRef);
}
}

private void processLinks(DbSession session, BatchReport.Component component) {
if (component.getType().equals(Constants.ComponentType.PROJECT) || component.getType().equals(Constants.ComponentType.MODULE)) {
List<BatchReport.ComponentLink> links = component.getLinksList();
List<ComponentLinkDto> previousLinks = dbClient.componentLinkDao().selectByComponentUuid(session, component.getUuid());
mergeLinks(session, component.getUuid(), links, previousLinks);
}
}

private void mergeLinks(DbSession session, String componentUuid, List<BatchReport.ComponentLink> links, List<ComponentLinkDto> previousLinks) {
Set<String> linkType = newHashSet();
for (final BatchReport.ComponentLink link : links) {
String type = convertType(link.getType());
if (!linkType.contains(type)) {
linkType.add(type);
} else {
throw new IllegalArgumentException(String.format("Link of type '%s' has already been declared on component '%s'", type, componentUuid));
}

ComponentLinkDto previousLink = Iterables.find(previousLinks, new Predicate<ComponentLinkDto>() {
@Override
public boolean apply(@Nullable ComponentLinkDto input) {
return input != null && input.getType().equals(convertType(link.getType()));
}
}, null);
if (previousLink == null) {
dbClient.componentLinkDao().insert(session,
new ComponentLinkDto()
.setComponentUuid(componentUuid)
.setType(type)
.setName(i18n.message(Locale.ENGLISH, "project_links." + type, null))
.setHref(link.getHref())
);
} else {
previousLink.setHref(link.getHref());
dbClient.componentLinkDao().update(session, previousLink);
}
}

for (ComponentLinkDto dto : previousLinks) {
if (!linkType.contains(dto.getType())) {
dbClient.componentLinkDao().delete(session, dto.getId());
}
}
}

private static String convertType(Constants.ComponentLinkType type) {
switch (type) {
case HOME:
return "homepage";
case SCM:
return "scm";
case SCM_DEV:
return "scm_dev";
case CI:
return "ci";
case ISSUE:
return "issue";
default:
throw new IllegalArgumentException(String.format("Unsupported type %s", type.name()));
}
}

@Override
public String getDescription() {
return "Persist component links";
}
}

+ 7
- 0
server/sonar-server/src/main/java/org/sonar/server/db/DbClient.java Bestand weergeven

@@ -37,6 +37,7 @@ import org.sonar.core.user.AuthorizationDao;
import org.sonar.server.activity.db.ActivityDao;
import org.sonar.server.component.db.ComponentDao;
import org.sonar.server.component.db.ComponentIndexDao;
import org.sonar.server.component.db.ComponentLinkDao;
import org.sonar.server.component.db.SnapshotDao;
import org.sonar.server.computation.db.AnalysisReportDao;
import org.sonar.server.dashboard.db.DashboardDao;
@@ -89,6 +90,7 @@ public class DbClient implements ServerComponent {
private final FileSourceDao fileSourceDao;
private final AuthorDao authorDao;
private final ComponentIndexDao componentIndexDao;
private final ComponentLinkDao componentLinkDao;

public DbClient(Database db, MyBatis myBatis, DaoComponent... daoComponents) {
this.db = db;
@@ -123,6 +125,7 @@ public class DbClient implements ServerComponent {
fileSourceDao = getDao(map, FileSourceDao.class);
authorDao = getDao(map, AuthorDao.class);
componentIndexDao = getDao(map, ComponentIndexDao.class);
componentLinkDao = getDao(map, ComponentLinkDao.class);
}

public Database database() {
@@ -233,6 +236,10 @@ public class DbClient implements ServerComponent {
return componentIndexDao;
}

public ComponentLinkDao componentLinkDao() {
return componentLinkDao;
}

private <K> K getDao(Map<Class, DaoComponent> map, Class<K> clazz) {
return (K) map.get(clazz);
}

+ 117
- 0
server/sonar-server/src/test/java/org/sonar/server/component/db/ComponentLinkDaoTest.java Bestand weergeven

@@ -0,0 +1,117 @@
/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package org.sonar.server.component.db;

import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.sonar.core.component.ComponentLinkDto;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.DbTester;
import org.sonar.test.DbTests;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

@Category(DbTests.class)
public class ComponentLinkDaoTest {

@ClassRule
public static DbTester dbTester = new DbTester();

DbSession session;

ComponentLinkDao dao;

@Before
public void createDao() throws Exception {
session = dbTester.myBatis().openSession(false);
dao = new ComponentLinkDao();
}

@After
public void tearDown() throws Exception {
session.close();
}

@Test
public void select_by_component_uuid() throws Exception {
dbTester.prepareDbUnit(getClass(), "shared.xml");

List<ComponentLinkDto> links = dao.selectByComponentUuid(session, "ABCD");
assertThat(links).hasSize(2);

links = dao.selectByComponentUuid(session, "BCDE");
assertThat(links).hasSize(1);

ComponentLinkDto link = links.get(0);
assertThat(link.getId()).isEqualTo(3L);
assertThat(link.getComponentUuid()).isEqualTo("BCDE");
assertThat(link.getType()).isEqualTo("homepage");
assertThat(link.getName()).isEqualTo("Home");
assertThat(link.getHref()).isEqualTo("http://www.struts.org");
}

@Test
public void insert() throws Exception {
dbTester.prepareDbUnit(getClass(), "empty.xml");

dao.insert(session, new ComponentLinkDto()
.setComponentUuid("ABCD")
.setType("homepage")
.setName("Home")
.setHref("http://www.sonarqube.org")
);
session.commit();

dbTester.assertDbUnit(getClass(), "insert.xml", "project_links");
}

@Test
public void update() throws Exception {
dbTester.prepareDbUnit(getClass(), "update.xml");

dao.update(session, new ComponentLinkDto()
.setId(1L)
.setComponentUuid("ABCD")
.setType("homepage")
.setName("Home")
.setHref("http://www.sonarqube.org")
);
session.commit();

dbTester.assertDbUnit(getClass(), "update-result.xml", "project_links");
}

@Test
public void delete() throws Exception {
dbTester.prepareDbUnit(getClass(), "delete.xml");

dao.delete(session, 1L);
session.commit();

assertThat(dbTester.countRowsOfTable("project_links")).isEqualTo(0);
}

}

+ 4
- 3
server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputationStepsTest.java Bestand weergeven

@@ -42,11 +42,12 @@ public class ComputationStepsTest {
mock(SwitchSnapshotStep.class),
mock(PurgeDatastoresStep.class),
mock(SendIssueNotificationsStep.class),
mock(IndexComponentsStep.class));
mock(IndexComponentsStep.class),
mock(PersistComponentLinksStep.class));

assertThat(registry.orderedSteps()).hasSize(11);
assertThat(registry.orderedSteps()).hasSize(12);
assertThat(registry.orderedSteps().get(0)).isInstanceOf(ParseReportStep.class);
assertThat(registry.orderedSteps().get(10)).isInstanceOf(SendIssueNotificationsStep.class);
assertThat(registry.orderedSteps().get(11)).isInstanceOf(SendIssueNotificationsStep.class);
}

@Test

+ 224
- 0
server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistComponentLinksStepTest.java Bestand weergeven

@@ -0,0 +1,224 @@
/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package org.sonar.server.computation.step;

import org.junit.*;
import org.junit.experimental.categories.Category;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.i18n.I18n;
import org.sonar.batch.protocol.Constants;
import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.batch.protocol.output.BatchReportReader;
import org.sonar.batch.protocol.output.BatchReportWriter;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.DbTester;
import org.sonar.server.component.db.ComponentLinkDao;
import org.sonar.server.computation.ComputationContext;
import org.sonar.server.db.DbClient;
import org.sonar.test.DbTests;

import java.io.File;
import java.util.Locale;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@Category(DbTests.class)
public class PersistComponentLinksStepTest {

@Rule
public TemporaryFolder temp = new TemporaryFolder();

@ClassRule
public static DbTester dbTester = new DbTester();

DbSession session;

ComponentLinkDao dao;

I18n i18n;

PersistComponentLinksStep step;

@Before
public void setup() throws Exception {
session = dbTester.myBatis().openSession(false);
dao = new ComponentLinkDao();
DbClient dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), dao);

i18n = mock(I18n.class);
when(i18n.message(Locale.ENGLISH, "project_links.homepage", null)).thenReturn("Home");
when(i18n.message(Locale.ENGLISH, "project_links.scm", null)).thenReturn("Sources");
when(i18n.message(Locale.ENGLISH, "project_links.scm_dev", null)).thenReturn("Developer connection");
when(i18n.message(Locale.ENGLISH, "project_links.ci", null)).thenReturn("Continuous integration");
when(i18n.message(Locale.ENGLISH, "project_links.issue", null)).thenReturn("Issues");

step = new PersistComponentLinksStep(dbClient, i18n);
}

@After
public void tearDown() throws Exception {
session.close();
}

@Test
public void execute_only_on_projects() throws Exception {
assertThat(step.supportedProjectQualifiers()).containsOnly("TRK");
}

@Test
public void add_links_on_project_and_module() throws Exception {
dbTester.prepareDbUnit(getClass(), "empty.xml");

File reportDir = temp.newFolder();
// project and 1 module
BatchReportWriter writer = new BatchReportWriter(reportDir);
writer.writeMetadata(BatchReport.Metadata.newBuilder()
.setRootComponentRef(1)
.setProjectKey("PROJECT_KEY")
.setAnalysisDate(150000000L)
.build());

writer.writeComponent(BatchReport.Component.newBuilder()
.setRef(1)
.setType(Constants.ComponentType.PROJECT)
.setUuid("ABCD")
.addChildRefs(2)
.addLinks(BatchReport.ComponentLink.newBuilder().setType(Constants.ComponentLinkType.HOME).setHref("http://www.sonarqube.org").build())
.addLinks(BatchReport.ComponentLink.newBuilder().setType(Constants.ComponentLinkType.SCM).setHref("https://github.com/SonarSource/sonar").build())
.addLinks(BatchReport.ComponentLink.newBuilder().setType(Constants.ComponentLinkType.SCM_DEV).setHref("scm:git:git@github.com:SonarSource/sonar.git/sonar").build())
.addLinks(BatchReport.ComponentLink.newBuilder().setType(Constants.ComponentLinkType.ISSUE).setHref("http://jira.sonarsource.com/").build())
.addLinks(BatchReport.ComponentLink.newBuilder().setType(Constants.ComponentLinkType.CI).setHref("http://bamboo.ci.codehaus.org/browse/SONAR").build())
.build());
writer.writeComponent(BatchReport.Component.newBuilder()
.setRef(2)
.setType(Constants.ComponentType.MODULE)
.setUuid("BCDE")
.addLinks(BatchReport.ComponentLink.newBuilder().setType(Constants.ComponentLinkType.SCM).setHref("https://github.com/SonarSource/sonar/server").build())
.build());

step.execute(new ComputationContext(new BatchReportReader(reportDir), mock(ComponentDto.class)));

dbTester.assertDbUnit(getClass(), "add_links_on_project_and_module-result.xml", "project_links");
}

@Test
public void nothing_to_do_when_link_already_exists() throws Exception {
dbTester.prepareDbUnit(getClass(), "nothing_to_do_when_link_already_exists.xml");

File reportDir = temp.newFolder();
BatchReportWriter writer = new BatchReportWriter(reportDir);
writer.writeMetadata(BatchReport.Metadata.newBuilder()
.setRootComponentRef(1)
.setProjectKey("PROJECT_KEY")
.setAnalysisDate(150000000L)
.build());

writer.writeComponent(BatchReport.Component.newBuilder()
.setRef(1)
.setType(Constants.ComponentType.PROJECT)
.setUuid("ABCD")
.addLinks(BatchReport.ComponentLink.newBuilder().setType(Constants.ComponentLinkType.HOME).setHref("http://www.sonarqube.org").build())
.build());

step.execute(new ComputationContext(new BatchReportReader(reportDir), mock(ComponentDto.class)));

dbTester.assertDbUnit(getClass(), "nothing_to_do_when_link_already_exists.xml", "project_links");
}

@Test
public void update_link() throws Exception {
dbTester.prepareDbUnit(getClass(), "update_link.xml");

File reportDir = temp.newFolder();
BatchReportWriter writer = new BatchReportWriter(reportDir);
writer.writeMetadata(BatchReport.Metadata.newBuilder()
.setRootComponentRef(1)
.setProjectKey("PROJECT_KEY")
.setAnalysisDate(150000000L)
.build());

writer.writeComponent(BatchReport.Component.newBuilder()
.setRef(1)
.setType(Constants.ComponentType.PROJECT)
.setUuid("ABCD")
.addLinks(BatchReport.ComponentLink.newBuilder().setType(Constants.ComponentLinkType.HOME).setHref("http://www.sonarqube.org").build())
.build());

step.execute(new ComputationContext(new BatchReportReader(reportDir), mock(ComponentDto.class)));

dbTester.assertDbUnit(getClass(), "update_link-result.xml", "project_links");
}

@Test
public void delete_link() throws Exception {
dbTester.prepareDbUnit(getClass(), "delete_link.xml");

File reportDir = temp.newFolder();
BatchReportWriter writer = new BatchReportWriter(reportDir);
writer.writeMetadata(BatchReport.Metadata.newBuilder()
.setRootComponentRef(1)
.setProjectKey("PROJECT_KEY")
.setAnalysisDate(150000000L)
.build());

writer.writeComponent(BatchReport.Component.newBuilder()
.setRef(1)
.setType(Constants.ComponentType.PROJECT)
.setUuid("ABCD")
.build());

step.execute(new ComputationContext(new BatchReportReader(reportDir), mock(ComponentDto.class)));

assertThat(dbTester.countRowsOfTable("project_links")).isEqualTo(0);
}

@Test
public void fail_when_trying_to_add_same_link_type_multiple_times() throws Exception {
dbTester.prepareDbUnit(getClass(), "empty.xml");

File reportDir = temp.newFolder();
BatchReportWriter writer = new BatchReportWriter(reportDir);
writer.writeMetadata(BatchReport.Metadata.newBuilder()
.setRootComponentRef(1)
.setProjectKey("PROJECT_KEY")
.setAnalysisDate(150000000L)
.build());

writer.writeComponent(BatchReport.Component.newBuilder()
.setRef(1)
.setType(Constants.ComponentType.PROJECT)
.setUuid("ABCD")
.addLinks(BatchReport.ComponentLink.newBuilder().setType(Constants.ComponentLinkType.HOME).setHref("http://www.sonarqube.org").build())
.addLinks(BatchReport.ComponentLink.newBuilder().setType(Constants.ComponentLinkType.HOME).setHref("http://www.sonarqube.org").build())
.build());

try {
step.execute(new ComputationContext(new BatchReportReader(reportDir), mock(ComponentDto.class)));
failBecauseExceptionWasNotThrown(IllegalArgumentException.class);
} catch (IllegalArgumentException e) {
assertThat(e).hasMessage("Link of type 'homepage' has already been declared on component 'ABCD'");
}
}
}

+ 5
- 0
server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentLinkDaoTest/delete.xml Bestand weergeven

@@ -0,0 +1,5 @@
<dataset>

<project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>

</dataset>

+ 3
- 0
server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentLinkDaoTest/empty.xml Bestand weergeven

@@ -0,0 +1,3 @@
<dataset>

</dataset>

+ 5
- 0
server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentLinkDaoTest/insert.xml Bestand weergeven

@@ -0,0 +1,5 @@
<dataset>

<project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>

</dataset>

+ 7
- 0
server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentLinkDaoTest/shared.xml Bestand weergeven

@@ -0,0 +1,7 @@
<dataset>

<project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>
<project_links id="2" component_uuid="ABCD" link_type="scm" name="Sources" href="https://github.com/SonarSource/sonar"/>
<project_links id="3" component_uuid="BCDE" link_type="homepage" name="Home" href="http://www.struts.org"/>

</dataset>

+ 5
- 0
server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentLinkDaoTest/update-result.xml Bestand weergeven

@@ -0,0 +1,5 @@
<dataset>

<project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>

</dataset>

+ 5
- 0
server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentLinkDaoTest/update.xml Bestand weergeven

@@ -0,0 +1,5 @@
<dataset>

<project_links id="1" component_uuid="BCDE" link_type="ci" name="CI" href="github"/>

</dataset>

+ 11
- 0
server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistComponentLinksStepTest/add_links_on_project_and_module-result.xml Bestand weergeven

@@ -0,0 +1,11 @@
<dataset>

<project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>
<project_links id="2" component_uuid="ABCD" link_type="scm" name="Sources" href="https://github.com/SonarSource/sonar"/>
<project_links id="3" component_uuid="ABCD" link_type="scm_dev" name="Developer connection" href="scm:git:git@github.com:SonarSource/sonar.git/sonar"/>
<project_links id="4" component_uuid="ABCD" link_type="issue" name="Issues" href="http://jira.sonarsource.com/"/>
<project_links id="5" component_uuid="ABCD" link_type="ci" name="Continuous integration" href="http://bamboo.ci.codehaus.org/browse/SONAR"/>

<project_links id="6" component_uuid="BCDE" link_type="scm" name="Sources" href="https://github.com/SonarSource/sonar/server"/>

</dataset>

+ 5
- 0
server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistComponentLinksStepTest/delete_link.xml Bestand weergeven

@@ -0,0 +1,5 @@
<dataset>

<project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>

</dataset>

+ 3
- 0
server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistComponentLinksStepTest/empty.xml Bestand weergeven

@@ -0,0 +1,3 @@
<dataset>

</dataset>

+ 5
- 0
server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistComponentLinksStepTest/nothing_to_do_when_link_already_exists.xml Bestand weergeven

@@ -0,0 +1,5 @@
<dataset>

<project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>

</dataset>

+ 5
- 0
server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistComponentLinksStepTest/update_link-result.xml Bestand weergeven

@@ -0,0 +1,5 @@
<dataset>

<project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>

</dataset>

+ 5
- 0
server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistComponentLinksStepTest/update_link.xml Bestand weergeven

@@ -0,0 +1,5 @@
<dataset>

<project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonar.org"/>

</dataset>

+ 195
- 58
sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/Constants.java Bestand weergeven

@@ -4,15 +4,18 @@
package org.sonar.batch.protocol;

public final class Constants {
private Constants() {}
private Constants() {
}

public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistry registry) {
com.google.protobuf.ExtensionRegistry registry) {
}

/**
* Protobuf enum {@code Severity}
*/
public enum Severity
implements com.google.protobuf.ProtocolMessageEnum {
implements com.google.protobuf.ProtocolMessageEnum {
/**
* <code>INFO = 0;</code>
*/
@@ -32,8 +35,7 @@ public final class Constants {
/**
* <code>BLOCKER = 4;</code>
*/
BLOCKER(4, 4),
;
BLOCKER(4, 4), ;

/**
* <code>INFO = 0;</code>
@@ -56,49 +58,58 @@ public final class Constants {
*/
public static final int BLOCKER_VALUE = 4;


public final int getNumber() { return value; }
public final int getNumber() {
return value;
}

public static Severity valueOf(int value) {
switch (value) {
case 0: return INFO;
case 1: return MINOR;
case 2: return MAJOR;
case 3: return CRITICAL;
case 4: return BLOCKER;
default: return null;
case 0:
return INFO;
case 1:
return MINOR;
case 2:
return MAJOR;
case 3:
return CRITICAL;
case 4:
return BLOCKER;
default:
return null;
}
}

public static com.google.protobuf.Internal.EnumLiteMap<Severity>
internalGetValueMap() {
internalGetValueMap() {
return internalValueMap;
}
private static com.google.protobuf.Internal.EnumLiteMap<Severity>
internalValueMap =
new com.google.protobuf.Internal.EnumLiteMap<Severity>() {
public Severity findValueByNumber(int number) {
return Severity.valueOf(number);
}
};
private static com.google.protobuf.Internal.EnumLiteMap<Severity> internalValueMap =
new com.google.protobuf.Internal.EnumLiteMap<Severity>() {
public Severity findValueByNumber(int number) {
return Severity.valueOf(number);
}
};

public final com.google.protobuf.Descriptors.EnumValueDescriptor
getValueDescriptor() {
getValueDescriptor() {
return getDescriptor().getValues().get(index);
}

public final com.google.protobuf.Descriptors.EnumDescriptor
getDescriptorForType() {
getDescriptorForType() {
return getDescriptor();
}

public static final com.google.protobuf.Descriptors.EnumDescriptor
getDescriptor() {
getDescriptor() {
return org.sonar.batch.protocol.Constants.getDescriptor().getEnumTypes().get(0);
}

private static final Severity[] VALUES = values();

public static Severity valueOf(
com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
if (desc.getType() != getDescriptor()) {
throw new java.lang.IllegalArgumentException(
"EnumValueDescriptor is not for this type.");
@@ -121,7 +132,7 @@ public final class Constants {
* Protobuf enum {@code ComponentType}
*/
public enum ComponentType
implements com.google.protobuf.ProtocolMessageEnum {
implements com.google.protobuf.ProtocolMessageEnum {
/**
* <code>PROJECT = 0;</code>
*/
@@ -145,8 +156,7 @@ public final class Constants {
/**
* <code>SUBVIEW = 5;</code>
*/
SUBVIEW(5, 5),
;
SUBVIEW(5, 5), ;

/**
* <code>PROJECT = 0;</code>
@@ -173,50 +183,60 @@ public final class Constants {
*/
public static final int SUBVIEW_VALUE = 5;


public final int getNumber() { return value; }
public final int getNumber() {
return value;
}

public static ComponentType valueOf(int value) {
switch (value) {
case 0: return PROJECT;
case 1: return MODULE;
case 2: return DIRECTORY;
case 3: return FILE;
case 4: return VIEW;
case 5: return SUBVIEW;
default: return null;
case 0:
return PROJECT;
case 1:
return MODULE;
case 2:
return DIRECTORY;
case 3:
return FILE;
case 4:
return VIEW;
case 5:
return SUBVIEW;
default:
return null;
}
}

public static com.google.protobuf.Internal.EnumLiteMap<ComponentType>
internalGetValueMap() {
internalGetValueMap() {
return internalValueMap;
}
private static com.google.protobuf.Internal.EnumLiteMap<ComponentType>
internalValueMap =
new com.google.protobuf.Internal.EnumLiteMap<ComponentType>() {
public ComponentType findValueByNumber(int number) {
return ComponentType.valueOf(number);
}
};
private static com.google.protobuf.Internal.EnumLiteMap<ComponentType> internalValueMap =
new com.google.protobuf.Internal.EnumLiteMap<ComponentType>() {
public ComponentType findValueByNumber(int number) {
return ComponentType.valueOf(number);
}
};

public final com.google.protobuf.Descriptors.EnumValueDescriptor
getValueDescriptor() {
getValueDescriptor() {
return getDescriptor().getValues().get(index);
}

public final com.google.protobuf.Descriptors.EnumDescriptor
getDescriptorForType() {
getDescriptorForType() {
return getDescriptor();
}

public static final com.google.protobuf.Descriptors.EnumDescriptor
getDescriptor() {
getDescriptor() {
return org.sonar.batch.protocol.Constants.getDescriptor().getEnumTypes().get(1);
}

private static final ComponentType[] VALUES = values();

public static ComponentType valueOf(
com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
if (desc.getType() != getDescriptor()) {
throw new java.lang.IllegalArgumentException(
"EnumValueDescriptor is not for this type.");
@@ -235,26 +255,143 @@ public final class Constants {
// @@protoc_insertion_point(enum_scope:ComponentType)
}

/**
* Protobuf enum {@code ComponentLinkType}
*/
public enum ComponentLinkType
implements com.google.protobuf.ProtocolMessageEnum {
/**
* <code>HOME = 0;</code>
*/
HOME(0, 0),
/**
* <code>SCM = 1;</code>
*/
SCM(1, 1),
/**
* <code>SCM_DEV = 2;</code>
*/
SCM_DEV(2, 2),
/**
* <code>ISSUE = 3;</code>
*/
ISSUE(3, 3),
/**
* <code>CI = 4;</code>
*/
CI(4, 4), ;

public static com.google.protobuf.Descriptors.FileDescriptor
/**
* <code>HOME = 0;</code>
*/
public static final int HOME_VALUE = 0;
/**
* <code>SCM = 1;</code>
*/
public static final int SCM_VALUE = 1;
/**
* <code>SCM_DEV = 2;</code>
*/
public static final int SCM_DEV_VALUE = 2;
/**
* <code>ISSUE = 3;</code>
*/
public static final int ISSUE_VALUE = 3;
/**
* <code>CI = 4;</code>
*/
public static final int CI_VALUE = 4;

public final int getNumber() {
return value;
}

public static ComponentLinkType valueOf(int value) {
switch (value) {
case 0:
return HOME;
case 1:
return SCM;
case 2:
return SCM_DEV;
case 3:
return ISSUE;
case 4:
return CI;
default:
return null;
}
}

public static com.google.protobuf.Internal.EnumLiteMap<ComponentLinkType>
internalGetValueMap() {
return internalValueMap;
}

private static com.google.protobuf.Internal.EnumLiteMap<ComponentLinkType> internalValueMap =
new com.google.protobuf.Internal.EnumLiteMap<ComponentLinkType>() {
public ComponentLinkType findValueByNumber(int number) {
return ComponentLinkType.valueOf(number);
}
};

public final com.google.protobuf.Descriptors.EnumValueDescriptor
getValueDescriptor() {
return getDescriptor().getValues().get(index);
}

public final com.google.protobuf.Descriptors.EnumDescriptor
getDescriptorForType() {
return getDescriptor();
}

public static final com.google.protobuf.Descriptors.EnumDescriptor
getDescriptor() {
return org.sonar.batch.protocol.Constants.getDescriptor().getEnumTypes().get(2);
}

private static final ComponentLinkType[] VALUES = values();

public static ComponentLinkType valueOf(
com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
if (desc.getType() != getDescriptor()) {
throw new java.lang.IllegalArgumentException(
"EnumValueDescriptor is not for this type.");
}
return VALUES[desc.getIndex()];
}

private final int index;
private final int value;

private ComponentLinkType(int index, int value) {
this.index = index;
this.value = value;
}

// @@protoc_insertion_point(enum_scope:ComponentLinkType)
}

public static com.google.protobuf.Descriptors.FileDescriptor
getDescriptor() {
return descriptor;
}
private static com.google.protobuf.Descriptors.FileDescriptor
descriptor;
private static com.google.protobuf.Descriptors.FileDescriptor descriptor;
static {
java.lang.String[] descriptorData = {
"\n\017constants.proto*E\n\010Severity\022\010\n\004INFO\020\000\022" +
"\t\n\005MINOR\020\001\022\t\n\005MAJOR\020\002\022\014\n\010CRITICAL\020\003\022\013\n\007B" +
"LOCKER\020\004*X\n\rComponentType\022\013\n\007PROJECT\020\000\022\n" +
"\n\006MODULE\020\001\022\r\n\tDIRECTORY\020\002\022\010\n\004FILE\020\003\022\010\n\004V" +
"IEW\020\004\022\013\n\007SUBVIEW\020\005B\034\n\030org.sonar.batch.pr" +
"otocolH\001"
"\t\n\005MINOR\020\001\022\t\n\005MAJOR\020\002\022\014\n\010CRITICAL\020\003\022\013\n\007B" +
"LOCKER\020\004*X\n\rComponentType\022\013\n\007PROJECT\020\000\022\n" +
"\n\006MODULE\020\001\022\r\n\tDIRECTORY\020\002\022\010\n\004FILE\020\003\022\010\n\004V" +
"IEW\020\004\022\013\n\007SUBVIEW\020\005*F\n\021ComponentLinkType\022" +
"\010\n\004HOME\020\000\022\007\n\003SCM\020\001\022\013\n\007SCM_DEV\020\002\022\t\n\005ISSUE" +
"\020\003\022\006\n\002CI\020\004B\034\n\030org.sonar.batch.protocolH\001"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
public com.google.protobuf.ExtensionRegistry assignDescriptors(
com.google.protobuf.Descriptors.FileDescriptor root) {
com.google.protobuf.Descriptors.FileDescriptor root) {
descriptor = root;
return null;
}

+ 544
- 365
sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/input/BatchInput.java
Diff onderdrukt omdat het te groot bestand
Bestand weergeven


+ 2721
- 1182
sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/output/BatchReport.java
Diff onderdrukt omdat het te groot bestand
Bestand weergeven


+ 613
- 391
sonar-batch-protocol/src/main/gen-java/org/sonar/server/source/db/FileSourceDb.java
Diff onderdrukt omdat het te groot bestand
Bestand weergeven


+ 6
- 0
sonar-batch-protocol/src/main/protobuf/batch_report.proto Bestand weergeven

@@ -48,6 +48,11 @@ message Metadata {
optional int32 deleted_components_count = 5;
}

message ComponentLink {
optional ComponentLinkType type = 1;
optional string href = 2;
}

message Component {
optional int32 ref = 1;
optional string path = 2;
@@ -56,6 +61,7 @@ message Component {
optional bool is_test = 5;
optional string language = 6;
repeated int32 child_refs = 7 [packed=true];
repeated ComponentLink links = 10;

// temporary fields during development of computation stack
optional int32 snapshot_id = 8;

+ 8
- 0
sonar-batch-protocol/src/main/protobuf/constants.proto Bestand weergeven

@@ -37,3 +37,11 @@ enum ComponentType {
VIEW = 4;
SUBVIEW = 5;
}

enum ComponentLinkType {
HOME = 0;
SCM = 1;
SCM_DEV = 2;
ISSUE = 3;
CI = 4;
}

+ 79
- 0
sonar-core/src/main/java/org/sonar/core/component/ComponentLinkDto.java Bestand weergeven

@@ -0,0 +1,79 @@
/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package org.sonar.core.component;

/**
* Component links should be merge in a 'links' column (using protobuf for instance) of the projects table.
* But to do this we'll have to wait for the measure filters page (where links are displayed) to be rewritten in JS/WS (because it's in Rails for the moment).
*/
public class ComponentLinkDto {

private Long id;
private String componentUuid;
private String type;
private String name;
private String href;

public String getName() {
return name;
}

public ComponentLinkDto setName(String name) {
this.name = name;
return this;
}

public String getComponentUuid() {
return componentUuid;
}

public ComponentLinkDto setComponentUuid(String componentUuid) {
this.componentUuid = componentUuid;
return this;
}

public String getHref() {
return href;
}

public ComponentLinkDto setHref(String href) {
this.href = href;
return this;
}

public Long getId() {
return id;
}

public ComponentLinkDto setId(Long id) {
this.id = id;
return this;
}

public String getType() {
return type;
}

public ComponentLinkDto setType(String type) {
this.type = type;
return this;
}
}

+ 37
- 0
sonar-core/src/main/java/org/sonar/core/component/db/ComponentLinkMapper.java Bestand weergeven

@@ -0,0 +1,37 @@
/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package org.sonar.core.component.db;

import org.sonar.core.component.ComponentLinkDto;

import java.util.List;

public interface ComponentLinkMapper {

List<ComponentLinkDto> selectByComponentUuid(String componentUuid);

void insert(ComponentLinkDto dto);

void update(ComponentLinkDto dto);

void delete(long id);

}

+ 4
- 5
sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java Bestand weergeven

@@ -35,11 +35,9 @@ import org.sonar.api.database.model.MeasureModel;
import org.sonar.core.activity.db.ActivityDto;
import org.sonar.core.activity.db.ActivityMapper;
import org.sonar.core.cluster.WorkQueue;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.component.FilePathWithHashDto;
import org.sonar.core.component.SnapshotDto;
import org.sonar.core.component.UuidWithProjectUuidDto;
import org.sonar.core.component.*;
import org.sonar.core.component.db.ComponentIndexMapper;
import org.sonar.core.component.db.ComponentLinkMapper;
import org.sonar.core.component.db.ComponentMapper;
import org.sonar.core.component.db.SnapshotMapper;
import org.sonar.core.computation.db.AnalysisReportDto;
@@ -133,6 +131,7 @@ public class MyBatis implements BatchComponent, ServerComponent {
loadAlias(conf, "ActiveDashboard", ActiveDashboardDto.class);
loadAlias(conf, "Author", AuthorDto.class);
loadAlias(conf, "Component", ComponentDto.class);
loadAlias(conf, "ComponentLink", ComponentLinkDto.class);
loadAlias(conf, "Dashboard", DashboardDto.class);
loadAlias(conf, "Dependency", DependencyDto.class);
loadAlias(conf, "DuplicationUnit", DuplicationUnitDto.class);
@@ -204,7 +203,7 @@ public class MyBatis implements BatchComponent, ServerComponent {
GroupMembershipMapper.class, QualityProfileMapper.class, ActiveRuleMapper.class,
MeasureMapper.class, MetricMapper.class, QualityGateMapper.class, QualityGateConditionMapper.class, ComponentMapper.class, SnapshotMapper.class,
ProjectQgateAssociationMapper.class,
AnalysisReportMapper.class, ComponentIndexMapper.class,
AnalysisReportMapper.class, ComponentIndexMapper.class, ComponentLinkMapper.class,
Migration45Mapper.class, Migration50Mapper.class
};
loadMappers(conf, mappers);

+ 37
- 0
sonar-core/src/main/resources/org/sonar/core/component/db/ComponentLinkMapper.xml Bestand weergeven

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.sonar.core.component.db.ComponentLinkMapper">

<sql id="componentLinkColumns">
p.id,
p.component_uuid as "componentUuid",
p.link_type as "type",
p.name as name,
p.href as href
</sql>

<select id="selectByComponentUuid" parameterType="String" resultType="ComponentLink">
SELECT
<include refid="componentLinkColumns"/>
FROM project_links p
<where>
AND p.component_uuid=#{uuid}
</where>
</select>

<insert id="insert" parameterType="ComponentLink" keyColumn="id" useGeneratedKeys="true" keyProperty="id">
INSERT INTO project_links (component_uuid, link_type, name, href)
VALUES (#{componentUuid,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{href,jdbcType=VARCHAR})
</insert>

<insert id="update" parameterType="ComponentLink" keyColumn="id" useGeneratedKeys="true" keyProperty="id">
UPDATE project_links SET component_uuid=#{componentUuid,jdbcType=VARCHAR}, link_type=#{type,jdbcType=VARCHAR}, name=#{name,jdbcType=VARCHAR}, href=#{href,jdbcType=VARCHAR}
WHERE id=#{id}
</insert>

<delete id="delete">
DELETE FROM project_links WHERE id=#{id}
</delete>

</mapper>


Laden…
Annuleren
Opslaan