private ComponentQuery buildQuery(Request wsRequest, List<String> qualifiers) {
return new ComponentQuery(
- dbClient.getDatabase(),
wsRequest.param(Param.TEXT_QUERY),
qualifiers.toArray(new String[qualifiers.size()]));
}
query.setComponentUuid(componentUuid);
}
if (componentQuery != null) {
- ComponentQuery componentDtoQuery = new ComponentQuery(dbClient.getDatabase(), componentQuery, Qualifiers.PROJECT, Qualifiers.VIEW);
+ ComponentQuery componentDtoQuery = new ComponentQuery(componentQuery, Qualifiers.PROJECT, Qualifiers.VIEW);
List<ComponentDto> componentDtos = dbClient.componentDao().selectByQuery(dbSession, componentDtoQuery, 0, CeActivityQuery.MAX_COMPONENT_UUIDS);
query.setComponentUuids(Lists.transform(componentDtos, ComponentDtoFunctions.toUuid()));
}
}
}
+ /**
+ * Returns an escaped value in parameter, with the desired wildcards. Suitable to be used in a like sql query<br />
+ * Escapes the "/", "%" and "_" characters.<br/>
+ *
+ * You <strong>must</strong> add "ESCAPE '/'" after your like query. It defines '/' as the escape character.
+ */
+ /**
+ *
+ */
+ public static String buildLikeValue(String value, WildcardPosition wildcardPosition) {
+ String escapedValue = escapePercentAndUnderscore(value);
+ String wildcard = "%";
+ switch (wildcardPosition) {
+ case BEFORE:
+ escapedValue = wildcard + escapedValue;
+ break;
+ case AFTER:
+ escapedValue += wildcard;
+ break;
+ case BEFORE_AND_AFTER:
+ escapedValue = wildcard + escapedValue + wildcard;
+ break;
+ default:
+ throw new UnsupportedOperationException("Unhandled WildcardPosition: " + wildcardPosition);
+ }
+
+ return escapedValue;
+ }
+
+ /**
+ * Replace escape percent and underscore by adding a slash just before
+ */
+ private static String escapePercentAndUnderscore(String value) {
+ return value
+ .replaceAll("/", "//")
+ .replaceAll("%", "/%")
+ .replaceAll("_", "/_");
+ }
+
/**
* Partition by 1000 elements a list of input and execute a function on each part.
*
--- /dev/null
+/*
+ * 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.db;
+
+public enum WildcardPosition {
+ BEFORE, AFTER, BEFORE_AND_AFTER
+}
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-import org.sonar.db.Database;
import static com.google.common.base.Preconditions.checkArgument;
-import static org.sonar.db.dialect.WildcardPosition.AFTER;
+import static org.sonar.db.DatabaseUtils.buildLikeValue;
+import static org.sonar.db.WildcardPosition.AFTER;
public class ComponentQuery {
- private final Database database;
private final String nameOrKeyQuery;
private final String[] qualifiers;
- public ComponentQuery(Database database, @Nullable String nameOrKeyQuery, String... qualifiers) {
+ public ComponentQuery(@Nullable String nameOrKeyQuery, String... qualifiers) {
checkArgument(qualifiers.length > 0, "At least one qualifier must be provided");
- this.database = database;
this.nameOrKeyQuery = nameOrKeyQuery;
this.qualifiers = qualifiers;
}
@CheckForNull
public String getNameOrKeyQueryToSqlForResourceIndex() {
- return database.getDialect().buildLikeValue(nameOrKeyQuery, AFTER).toLowerCase();
+ return buildLikeValue(nameOrKeyQuery, AFTER).toLowerCase();
}
@CheckForNull
public String getNameOrKeyQueryToSqlForProjectKey() {
- return database.getDialect().buildLikeValue(nameOrKeyQuery, AFTER);
+ return buildLikeValue(nameOrKeyQuery, AFTER);
}
}
public int getScrollSingleRowFetchSize() {
return 1;
}
-
- @Override
- public String buildLikeValue(String value, WildcardPosition wildcardPosition) {
- String escapedValue = escapePercentAndUnderscore(value);
- String wildcard = "%";
- switch (wildcardPosition) {
- case BEFORE:
- escapedValue = wildcard + escapedValue;
- break;
- case AFTER:
- escapedValue += wildcard;
- break;
- case BEFORE_AND_AFTER:
- escapedValue = wildcard + escapedValue + wildcard;
- break;
- default:
- throw new UnsupportedOperationException("Unhandled WildcardPosition: " + wildcardPosition);
- }
-
- return appendEscapeBackslachForSomeDb(escapedValue);
- }
-
- /**
- * Replace escape percent and underscore by adding a slash just before
- */
- private static String escapePercentAndUnderscore(String value) {
- return value
- .replaceAll("%", "\\\\%")
- .replaceAll("_", "\\\\_");
- }
-
- private String appendEscapeBackslachForSomeDb(String value) {
- return isOracleOrMsSql()
- ? (value + " ESCAPE '\\'")
- : value;
- }
-
- private boolean isOracleOrMsSql() {
- return getId().equals(Oracle.ID) || getId().equals(MsSql.ID);
- }
}
* @return a boolean
*/
boolean supportsMigration();
-
- /**
- * Returns an escaped value in parameter, with the desired wildcards.
- * Suitable to be used in a like sql query
- */
- String buildLikeValue(String value, WildcardPosition wildcardPosition);
}
+++ /dev/null
-/*
- * 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.db.dialect;
-
-public enum WildcardPosition {
- BEFORE, AFTER, BEFORE_AND_AFTER
-}
<foreach collection="qualifiers" item="qualifier" open="(" close=")" separator=",">
#{qualifier}
</foreach>
- AND ri.kee like #{nameOrKeyQueryToSqlForResourceIndex})
- OR p.kee like #{nameOrKeyQueryToSqlForProjectKey})
+ AND ri.kee like #{nameOrKeyQueryToSqlForResourceIndex} ESCAPE '/')
+ OR p.kee like #{nameOrKeyQueryToSqlForProjectKey} ESCAPE '/')
</if>
</where>
</sql>
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+import static org.sonar.db.DatabaseUtils.buildLikeValue;
+import static org.sonar.db.WildcardPosition.AFTER;
+import static org.sonar.db.WildcardPosition.BEFORE;
+import static org.sonar.db.WildcardPosition.BEFORE_AND_AFTER;
@Category(DbTests.class)
public class DatabaseUtilsTest {
assertThat(logTester.logs(LoggerLevel.ERROR)).contains("SQL error: 456. Message: this is next");
}
+
+ @Test
+ public void buildLikeValue_with_special_characters() {
+ String escapedValue = "like-\\/_/%//-value";
+ String wildcard = "%";
+
+ assertThat(buildLikeValue("like-\\_%/-value", BEFORE)).isEqualTo(wildcard + escapedValue);
+ assertThat(buildLikeValue("like-\\_%/-value", AFTER)).isEqualTo(escapedValue + wildcard);
+ assertThat(buildLikeValue("like-\\_%/-value", BEFORE_AND_AFTER)).isEqualTo(wildcard + escapedValue + wildcard);
+ }
}
db.commit();
componentDb.indexProjects();
- ComponentQuery query = new ComponentQuery(db.database(), "oJect", Qualifiers.PROJECT);
+ ComponentQuery query = new ComponentQuery("oJect", Qualifiers.PROJECT);
List<ComponentDto> result = underTest.selectByQuery(dbSession, query, 1, 3);
assertThat(result).hasSize(3);
@Test
public void select_by_query_name_with_special_characters() {
- componentDb.insertProjectAndSnapshot(dbSession, newProjectDto().setName("project-_%-name"));
+ componentDb.insertProjectAndSnapshot(dbSession, newProjectDto().setName("project-\\_%/-name"));
db.commit();
componentDb.indexProjects();
- ComponentQuery query = new ComponentQuery(db.database(), "-_%-", Qualifiers.PROJECT);
+ ComponentQuery query = new ComponentQuery("-\\_%/-", Qualifiers.PROJECT);
List<ComponentDto> result = underTest.selectByQuery(dbSession, query, 0, 10);
assertThat(result).hasSize(1);
- assertThat(result.get(0).name()).isEqualTo("project-_%-name");
+ assertThat(result.get(0).name()).isEqualTo("project-\\_%/-name");
}
@Test
db.commit();
componentDb.indexProjects();
- ComponentQuery query = new ComponentQuery(db.database(), "project-_%-", Qualifiers.PROJECT);
+ ComponentQuery query = new ComponentQuery("project-_%-", Qualifiers.PROJECT);
List<ComponentDto> result = underTest.selectByQuery(dbSession, query, 0, 10);
assertThat(result).hasSize(1);
+++ /dev/null
-/*
- * 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.db.dialect;
-
-import org.junit.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.db.dialect.WildcardPosition.AFTER;
-import static org.sonar.db.dialect.WildcardPosition.BEFORE;
-import static org.sonar.db.dialect.WildcardPosition.BEFORE_AND_AFTER;
-
-public class DialectTest {
-
- Dialect underTest = new H2();
-
- @Test
- public void buildLikeValue_with_H2() {
- String escapedValue = "like-\\_\\%-value";
- String wildcard = "%";
-
- assertThat(underTest.buildLikeValue("like-_%-value", BEFORE)).isEqualTo(wildcard + escapedValue);
- assertThat(underTest.buildLikeValue("like-_%-value", AFTER)).isEqualTo(escapedValue + wildcard);
- assertThat(underTest.buildLikeValue("like-_%-value", BEFORE_AND_AFTER)).isEqualTo(wildcard + escapedValue + wildcard);
- }
-
- @Test
- public void buildLikeValue_with_Oracle() {
- underTest = new Oracle();
- String escapedValue = "like-\\_\\%-value";
- String wildcard = "%";
-
- assertThat(underTest.buildLikeValue("like-_%-value", BEFORE_AND_AFTER)).isEqualTo(wildcard + escapedValue + wildcard + " ESCAPE '\\'");
-
- }
-}