/**
* The contents of this file are subject to the OpenMRS Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://license.openmrs.org
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* Copyright (C) OpenMRS, LLC. All Rights Reserved.
*/
package org.openmrs.module.reporting.evaluation.querybuilder;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.openmrs.Cohort;
import org.openmrs.EncounterType;
import org.openmrs.api.context.Context;
import org.openmrs.module.reporting.common.DateUtil;
import org.openmrs.module.reporting.common.TestUtil;
import org.openmrs.module.reporting.dataset.DataSetColumn;
import org.openmrs.module.reporting.evaluation.EvaluationContext;
import org.openmrs.module.reporting.evaluation.service.EvaluationService;
import org.openmrs.test.BaseModuleContextSensitiveTest;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
/**
* Tests for the EvaluationContext expression parsing
*/
public class SqlQueryBuilderTest extends BaseModuleContextSensitiveTest {
protected static final String XML_DATASET_PATH = "org/openmrs/module/reporting/include/";
protected static final String XML_REPORT_TEST_DATASET = "ReportTestDataset";
@Autowired
EvaluationService evaluationService;
@Before
public void setup() throws Exception {
executeDataSet(XML_DATASET_PATH + new TestUtil().getTestDatasetFilename(XML_REPORT_TEST_DATASET));
}
@Test
public void getColumns_shouldReturnTheConfiguredColumns() throws Exception {
SqlQueryBuilder q = new SqlQueryBuilder();
q.append("select p.person_id id, p.gender, p.birthdate as bd from person p where voided = 0");
List<DataSetColumn> columns = evaluationService.getColumns(q);
Assert.assertEquals("id", columns.get(0).getName().toLowerCase());
Assert.assertEquals("gender", columns.get(1).getName().toLowerCase());
Assert.assertEquals("bd", columns.get(2).getName().toLowerCase());
}
@Test
public void buildQuery_shouldHandleNoParameters() throws Exception {
SqlQueryBuilder q = new SqlQueryBuilder();
q.append("select p.person_id, p.gender, p.birthdate as bd from person p where person_id = 2");
List<Object[]> result = evaluationService.evaluateToList(q, new EvaluationContext());
Assert.assertEquals(1, result.size());
Object[] row = result.get(0);
Assert.assertEquals(2, row[0]);
Assert.assertEquals("M", row[1]);
Assert.assertEquals(DateUtil.getDateTime(1975,4,8), row[2]);
}
@Test
public void buildQuery_shouldHandleSimpleParameters() throws Exception {
SqlQueryBuilder q = new SqlQueryBuilder();
q.append("select p.person_id from person p where gender = :g and p.person_id <= 9");
q.addParameter("g", "M");
List<Object[]> result = evaluationService.evaluateToList(q, new EvaluationContext());
Assert.assertEquals(3, result.size());
q.addParameter("g", "F");
result = evaluationService.evaluateToList(q, new EvaluationContext());
Assert.assertEquals(2, result.size());
}
@Test
public void buildQuery_shouldHandleOpenmrsObjectParameters() throws Exception {
SqlQueryBuilder q = new SqlQueryBuilder();
q.append("select e.encounter_id from encounter e where e.encounter_type = :type");
q.addParameter("type", Context.getEncounterService().getEncounterType("Scheduled"));
List<Object[]> result = evaluationService.evaluateToList(q, new EvaluationContext());
Assert.assertEquals(2, result.size());
}
@Test
public void buildQuery_shouldHandleListParameters() throws Exception {
SqlQueryBuilder q = new SqlQueryBuilder();
q.append("select e.encounter_datetime, e.encounter_type from encounter e where e.encounter_id in (:ids)");
q.addParameter("ids", Arrays.asList(3,4,5,6));
List<Object[]> result = evaluationService.evaluateToList(q, new EvaluationContext());
Assert.assertEquals(4, result.size());
}
@Test
public void buildQuery_shouldHandleListsOfOpenmrsObjectParameters() throws Exception {
SqlQueryBuilder q = new SqlQueryBuilder();
q.append("select e.encounter_datetime from encounter e where e.encounter_type in (:types)");
List<EncounterType> typeList = new ArrayList<EncounterType>();
typeList.add(Context.getEncounterService().getEncounterType("Scheduled"));
typeList.add(Context.getEncounterService().getEncounterType("Emergency"));
q.addParameter("types", typeList);
List<Object[]> result = evaluationService.evaluateToList(q, new EvaluationContext());
Assert.assertEquals(3, result.size());
}
@Test
public void buildQuery_shouldHandleCohortParameters() throws Exception {
SqlQueryBuilder q = new SqlQueryBuilder();
q.append("select p.gender from person p where p.person_id in (:cohort)");
Cohort baseCohort = new Cohort("2,6,7");
q.addParameter("cohort", baseCohort);
List<Object[]> result = evaluationService.evaluateToList(q, new EvaluationContext());
Assert.assertEquals(3, result.size());
}
@Test
public void buildQuery_shouldHandleComments() throws Exception {
SqlQueryBuilder q = new SqlQueryBuilder();
q.append("-- This query selects genders for the given cohort\n");
q.append("select p.gender from person p where p.person_id in (:cohort)");
Cohort baseCohort = new Cohort("2,6,7");
q.addParameter("cohort", baseCohort);
List<Object[]> result = evaluationService.evaluateToList(q, new EvaluationContext());
Assert.assertEquals(3, result.size());
}
@Test
public void buildQuery_shouldSupportParametersThatStartWithSameSequence() throws Exception {
SqlQueryBuilder q = new SqlQueryBuilder();
q.append("select patient_id from patient where patient_id = :patient24 and patient_id <> :patient2");
q.addParameter("patient2", 2);
q.addParameter("patient24", 24);
List<Object[]> result = evaluationService.evaluateToList(q, new EvaluationContext());
Assert.assertEquals(1, result.size());
}
@Test
public void buildQuery_shouldSupportMultipleParametersWithSameName() throws Exception {
SqlQueryBuilder q = new SqlQueryBuilder();
String repeatingClause = "(value_coded = :concept and value_datetime > :fromDate and value_datetime < :toDate)";
q.append("select obs_id from obs where ").append(repeatingClause);
for (int i=0; i<100; i++) {
q.append(" and ").append(repeatingClause);
}
q.addParameter("concept", 5097);
q.addParameter("fromDate", DateUtil.getDateTime(2011, 1, 1));
q.addParameter("toDate", DateUtil.getDateTime(2011, 12, 31));
List<Object[]> result = evaluationService.evaluateToList(q, new EvaluationContext());
}
@Override
public Properties getRuntimeProperties() {
Properties p = super.getRuntimeProperties();
//p.setProperty("hibernate.show_sql", "true");
return p;
}
}