package org.openmrs.module.reporting.dataset.definition.evaluator;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.openmrs.Location;
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.DataSetRow;
import org.openmrs.module.reporting.dataset.SimpleDataSet;
import org.openmrs.module.reporting.dataset.definition.DataSetDefinition;
import org.openmrs.module.reporting.dataset.definition.SqlDataSetDefinition;
import org.openmrs.module.reporting.dataset.definition.service.DataSetDefinitionService;
import org.openmrs.module.reporting.evaluation.EvaluationContext;
import org.openmrs.module.reporting.evaluation.EvaluationException;
import org.openmrs.test.BaseModuleContextSensitiveTest;
import org.openmrs.test.Verifies;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
public class SqlDataSetEvaluatorTest extends BaseModuleContextSensitiveTest {
protected static final String XML_DATASET_PATH = "org/openmrs/module/reporting/include/";
protected static final String XML_REPORT_TEST_DATASET = "ReportTestDataset";
@Before
public void setup() throws Exception {
executeDataSet(XML_DATASET_PATH + new TestUtil().getTestDatasetFilename(XML_REPORT_TEST_DATASET));
}
/**
* @see {@link SqlDataSetEvaluator#evaluate(DataSetDefinition,EvaluationContext)}
*/
@Test
@Verifies(value = "should evaluate a SQLDataSetDefinition", method = "evaluate(DataSetDefinition,EvaluationContext)")
public void evaluate_shouldEvaluateASQLDataSetDefinition() throws Exception {
SqlDataSetDefinition d = new SqlDataSetDefinition();
d.setSqlQuery("select t.patient_id, p.gender, p.birthdate from patient t, person p where t.patient_id = p.person_id and t.patient_id = 2");
SimpleDataSet result = (SimpleDataSet) Context.getService(DataSetDefinitionService.class).evaluate(d, null);
Assert.assertEquals(1, result.getRows().size());
Assert.assertEquals(3, result.getMetaData().getColumnCount());
DataSetRow firstRow = result.getRows().get(0);
Assert.assertEquals(2, firstRow.getColumnValue("patient_id"));
Assert.assertEquals("M", firstRow.getColumnValue("gender"));
Assert.assertEquals(DateUtil.getDateTime(1975, 4, 8), firstRow.getColumnValue("birthdate"));
}
/**
* @see {@link SqlDataSetEvaluator#evaluate(DataSetDefinition,EvaluationContext)}
*/
@Test
@Verifies(value = "should evaluate a SQLDataSetDefinition with parameters", method = "evaluate(DataSetDefinition,EvaluationContext)")
public void evaluate_shouldEvaluateASQLDataSetDefinitionWithParameters() throws Exception {
SqlDataSetDefinition d = new SqlDataSetDefinition();
EvaluationContext c = new EvaluationContext(new Date());
c.addParameterValue("patientId", 21);
d.setSqlQuery("select t.patient_id, p.gender, p.birthdate from patient t inner join person p on t.patient_id = p.person_id where t.patient_id = :patientId order by patient_id asc");
SimpleDataSet result = (SimpleDataSet) Context.getService(DataSetDefinitionService.class).evaluate(d, c);
Assert.assertEquals(1, result.getRows().size());
Assert.assertEquals(3, result.getMetaData().getColumnCount());
DataSetRow firstRow = result.getRows().get(0);
Assert.assertEquals(21, firstRow.getColumnValue("patient_id"));
Assert.assertEquals("M", firstRow.getColumnValue("gender"));
Assert.assertEquals(DateUtil.getDateTime(1959, 6, 8), firstRow.getColumnValue("birthdate"));
}
/**
* @see {@link SqlDataSetEvaluator#evaluate(DataSetDefinition,EvaluationContext)}
*/
@Test
@Verifies(value = "should evaluate a SQLDataSetDefinition with in statement", method = "evaluate(DataSetDefinition,EvaluationContext)")
public void evaluate_shouldEvaluateASQLDataSetDefinitionWithInStatement() throws Exception {
SqlDataSetDefinition d = new SqlDataSetDefinition();
EvaluationContext c = new EvaluationContext(new Date());
c.addParameterValue("patientId", Arrays.asList(21, 22));
d.setSqlQuery("select t.patient_id, p.gender, p.birthdate from patient t inner join person p on t.patient_id = p.person_id where t.patient_id in :patientId order by patient_id desc");
SimpleDataSet result = (SimpleDataSet) Context.getService(DataSetDefinitionService.class).evaluate(d, c);
Assert.assertEquals(2, result.getRows().size());
Assert.assertEquals(3, result.getMetaData().getColumnCount());
DataSetRow firstRow = result.getRows().get(0);
Assert.assertEquals(22, firstRow.getColumnValue("patient_id"));
Assert.assertEquals("F", firstRow.getColumnValue("gender"));
Assert.assertEquals(DateUtil.getDateTime(1997, 7, 8), firstRow.getColumnValue("birthdate"));
}
/**
* @see {@link SqlDataSetEvaluator#evaluate(DataSetDefinition,EvaluationContext)}
*/
@Test(expected=EvaluationException.class)
@Verifies(value = "should protect SQL Query Against database modifications", method = "evaluate(DataSetDefinition,EvaluationContext)")
public void evaluate_shouldProtectSQLQueryAgainstDatabaseModifications() throws EvaluationException {
SqlDataSetDefinition dataSetDefinition = new SqlDataSetDefinition();
EvaluationContext context = new EvaluationContext(new Date());
String query = "update person set gender='F'";
dataSetDefinition.setSqlQuery(query);
Context.getService(DataSetDefinitionService.class).evaluate(dataSetDefinition, context);
}
@Test(expected = EvaluationException.class)
public void buildQuery_shouldThrowAnExceptionIfDuplicateColumnsExist() throws EvaluationException {
SqlDataSetDefinition dataSetDefinition = new SqlDataSetDefinition();
dataSetDefinition.setSqlQuery("select patient_id, patient_id from patient");
Context.getService(DataSetDefinitionService.class).evaluate(dataSetDefinition, new EvaluationContext());
}
/**
* @see {@link SqlDataSetEvaluator#evaluate(DataSetDefinition,EvaluationContext)}
*/
@Test
@Verifies(value = "should handle boolean parameters", method = "evaluate(DataSetDefinition,EvaluationContext)")
public void evaluate_shouldHandleBooleanParameters() throws EvaluationException {
SqlDataSetDefinition dataSetDefinition = new SqlDataSetDefinition();
String query = "select name from location where retired = :Retired order by name";
dataSetDefinition.setSqlQuery(query);
EvaluationContext context = new EvaluationContext(new Date());
context.addParameterValue("Retired", Boolean.TRUE);
SimpleDataSet ds = (SimpleDataSet)Context.getService(DataSetDefinitionService.class).evaluate(dataSetDefinition, context);
Assert.assertEquals(1, ds.getRows().size());
context.addParameterValue("Retired", Boolean.FALSE);
ds = (SimpleDataSet)Context.getService(DataSetDefinitionService.class).evaluate(dataSetDefinition, context);
Assert.assertEquals(2, ds.getRows().size());
}
@Test
public void evaluate_shouldHandleMetadataListParameters() throws Exception {
SqlDataSetDefinition dataSetDefinition = new SqlDataSetDefinition();
String query = "select encounter_id, encounter_datetime, location_id from encounter where location_id in (:locations)";
dataSetDefinition.setSqlQuery(query);
List<Location> locationList = new ArrayList<Location>();
locationList.add(Context.getLocationService().getLocation(1));
locationList.add(Context.getLocationService().getLocation(3));
EvaluationContext context = new EvaluationContext();
context.addParameterValue("locations", locationList);
SimpleDataSet ds = (SimpleDataSet)Context.getService(DataSetDefinitionService.class).evaluate(dataSetDefinition, context);
Assert.assertEquals(2, ds.getRows().size());
}
}