import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.apache.commons.lang.StringUtils;
+import org.sonar.db.DatabaseUtils;
+import org.sonar.db.WildcardPosition;
public class ProjectQgateAssociationQuery {
private final String projectSearch;
// for internal use in MyBatis
- private final String projectSearchSql;
+ private final String projectSearchUpperLikeSql;
// max results per page
private final int pageSize;
this.gateId = builder.gateId;
this.membership = builder.membership;
this.projectSearch = builder.projectSearch;
- this.projectSearchSql = projectSearchToSql(projectSearch);
+ if (this.projectSearch == null) {
+ this.projectSearchUpperLikeSql = null;
+ } else {
+ this.projectSearchUpperLikeSql = DatabaseUtils.buildLikeValue(projectSearch.toUpperCase(Locale.ENGLISH), WildcardPosition.BEFORE_AND_AFTER);
+ }
this.pageSize = builder.pageSize;
this.pageIndex = builder.pageIndex;
}
- private String projectSearchToSql(@Nullable String value) {
- if (value == null) {
- return null;
- }
-
- return value
- .replaceAll("%", "\\\\%")
- .replaceAll("_", "\\\\_")
- .toLowerCase(Locale.ENGLISH) + "%";
- }
-
public String gateId() {
return gateId;
}
return projectSearch;
}
- public String projectSearchSql() {
- return projectSearchSql;
- }
-
public int pageSize() {
return pageSize;
}
<select id="selectProjects" parameterType="map" resultType="ProjectQgateAssociation">
SELECT proj.id as id, proj.name as name, prop.text_value as gateId
FROM projects proj
+ LEFT JOIN properties prop ON prop.resource_id=proj.id AND prop.prop_key='sonar.qualitygate' AND prop.text_value = #{query.gateId}
+ where
+ proj.qualifier = 'TRK'
+ and proj.enabled = ${_true}
+ and proj.copy_component_uuid is null
+ <choose>
+ <when test="query.membership() == 'selected'">
+ and prop.text_value IS NOT NULL
+ </when>
+ <when test="query.membership() == 'deselected'">
+ and prop.text_value IS NULL
+ </when>
+ </choose>
<if test="query.projectSearch() != null">
- JOIN resource_index ind ON ind.root_component_uuid=proj.uuid
+ and (proj.kee = #{query.projectSearch} or upper(proj.name) like #{query.projectSearchUpperLikeSql} escape '/')
</if>
- LEFT JOIN properties prop ON prop.resource_id=proj.id AND prop.prop_key='sonar.qualitygate' AND prop.text_value LIKE
- #{query.gateId}
- <where>
- <choose>
- <when test="query.membership() == 'selected'">
- AND prop.text_value IS NOT NULL
- </when>
- <when test="query.membership() == 'deselected'">
- AND prop.text_value IS NULL
- </when>
- </choose>
- <if test="query.projectSearch() != null">
- AND ind.kee LIKE #{query.projectSearchSql}
- </if>
- AND proj.qualifier='TRK'
- AND proj.scope='PRJ'
- <if test="query.projectSearch() != null">
- AND ind.qualifier='TRK'
- </if>
- </where>
- ORDER BY proj.name
+ order by proj.name
</select>
<select id="selectQGateIdByComponentId" parameterType="long" resultType="string">
@Rule
public DbTester db = DbTester.create(System2.INSTANCE);
- ComponentDbTester componentDb = new ComponentDbTester(db);
- DbClient dbClient = db.getDbClient();
- DbSession dbSession = db.getSession();
- ProjectQgateAssociationDao underTest = db.getDbClient().projectQgateAssociationDao();
+ private ComponentDbTester componentDb = new ComponentDbTester(db);
+ private DbClient dbClient = db.getDbClient();
+ private DbSession dbSession = db.getSession();
+ private ProjectQgateAssociationDao underTest = db.getDbClient().projectQgateAssociationDao();
@Test
public void select_all_projects_by_query() {
result = underTest.selectProjects(dbSession, ProjectQgateAssociationQuery.builder().gateId("42").projectSearch("one").build());
assertThat(result).hasSize(1);
result = underTest.selectProjects(dbSession, ProjectQgateAssociationQuery.builder().gateId("42").projectSearch("project").build());
- assertThat(result).hasSize(2);
+ assertThat(result).hasSize(5);
}
@Test
import org.junit.Test;
import org.junit.rules.ExpectedException;
-import static org.assertj.core.api.Assertions.assertThat;
-
public class ProjectQgateAssociationQueryTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
- @Test
- public void handle_underscore_and_percent() {
- ProjectQgateAssociationQuery underTest = ProjectQgateAssociationQuery.builder()
- .projectSearch("project-_%-search")
- .gateId("1").build();
-
- assertThat(underTest.projectSearchSql()).isEqualTo("project-\\_\\%-search%");
- }
-
@Test
public void fail_on_null_login() {
expectedException.expect(NullPointerException.class);
name="Project One"
qualifier="TRK"
scope="PRJ"
+ enabled="[true]"
+ copy_component_uuid="[null]"
id="1"/>
<projects organization_uuid="org1"
uuid="B"
name="Project Two"
qualifier="TRK"
scope="PRJ"
+ enabled="[true]"
+ copy_component_uuid="[null]"
id="2"/>
<projects organization_uuid="org1"
uuid="C"
name="Project Three"
qualifier="TRK"
scope="PRJ"
+ enabled="[true]"
+ copy_component_uuid="[null]"
id="3"/>
<projects organization_uuid="org1"
uuid="D"
name="Project Four"
qualifier="TRK"
scope="PRJ"
+ enabled="[true]"
+ copy_component_uuid="[null]"
id="4"/>
<projects organization_uuid="org1"
uuid="E"
name="Project Five"
qualifier="TRK"
scope="PRJ"
+ enabled="[true]"
+ copy_component_uuid="[null]"
id="5"/>
<projects organization_uuid="org1"
uuid="F"
name="View Six"
qualifier="VW"
scope="PRJ"
+ enabled="[true]"
+ copy_component_uuid="[null]"
id="6"/>
<projects organization_uuid="org1"
uuid="G"
name="File One"
qualifier="TRK"
scope="FIL"
+ enabled="[true]"
+ copy_component_uuid="C"
id="7"/>
- <resource_index id="1"
- kee="project one"
- component_uuid="A"
- root_component_uuid="A"
- position="0"
- name_size="11"
- qualifier="TRK"/>
- <resource_index id="2"
- kee="roject one"
- component_uuid="A"
- root_component_uuid="A"
- position="1"
- name_size="11"
- qualifier="TRK"/>
- <resource_index id="3"
- kee="oject one"
- component_uuid="A"
- root_component_uuid="A"
- position="2"
- name_size="11"
- qualifier="TRK"/>
- <resource_index id="4"
- kee="ject one"
- component_uuid="A"
- root_component_uuid="A"
- position="3"
- name_size="11"
- qualifier="TRK"/>
- <resource_index id="5"
- kee="ect one"
- component_uuid="A"
- root_component_uuid="A"
- position="4"
- name_size="11"
- qualifier="TRK"/>
- <resource_index id="6"
- kee="ct one"
- component_uuid="A"
- root_component_uuid="A"
- position="5"
- name_size="11"
- qualifier="TRK"/>
- <resource_index id="7"
- kee="t one"
- component_uuid="A"
- root_component_uuid="A"
- position="6"
- name_size="11"
- qualifier="TRK"/>
- <resource_index id="8"
- kee=" one"
- component_uuid="A"
- root_component_uuid="A"
- position="7"
- name_size="11"
- qualifier="TRK"/>
- <resource_index id="9"
- kee="one"
- component_uuid="A"
- root_component_uuid="A"
- position="8"
- name_size="11"
- qualifier="TRK"/>
- <resource_index id="10"
- kee="project two"
- component_uuid="B"
- root_component_uuid="B"
- position="0"
- name_size="11"
- qualifier="TRK"/>
- <resource_index id="11"
- kee="roject two"
- component_uuid="B"
- root_component_uuid="B"
- position="1"
- name_size="11"
- qualifier="TRK"/>
- <resource_index id="12"
- kee="oject two"
- component_uuid="B"
- root_component_uuid="B"
- position="2"
- name_size="11"
- qualifier="TRK"/>
- <resource_index id="13"
- kee="ject two"
- component_uuid="B"
- root_component_uuid="B"
- position="3"
- name_size="11"
- qualifier="TRK"/>
- <resource_index id="14"
- kee="ect two"
- component_uuid="B"
- root_component_uuid="B"
- position="4"
- name_size="11"
- qualifier="TRK"/>
- <resource_index id="15"
- kee="ct two"
- component_uuid="B"
- root_component_uuid="B"
- position="5"
- name_size="11"
- qualifier="TRK"/>
- <resource_index id="16"
- kee="t two"
- component_uuid="B"
- root_component_uuid="B"
- position="6"
- name_size="11"
- qualifier="TRK"/>
- <resource_index id="17"
- kee=" two"
- component_uuid="B"
- root_component_uuid="B"
- position="7"
- name_size="11"
- qualifier="TRK"/>
-
<properties id="1"
prop_key="sonar.qualitygate"
resource_id="[null]"