/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.ohdsi.webapi.cohortdefinition;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.ArrayList;
import org.apache.commons.lang3.StringUtils;
import org.ohdsi.webapi.helper.ResourceHelper;
import org.ohdsi.webapi.vocabulary.Concept;
import org.ohdsi.webapi.vocabulary.ConceptSetExpressionQueryBuilder;
/**
*
* @author cknoll1
*/
public class CohortExpressionQueryBuilder implements IGetCriteriaSqlDispatcher, IGetEndStrategySqlDispatcher {
private final static ConceptSetExpressionQueryBuilder conceptSetQueryBuilder = new ConceptSetExpressionQueryBuilder();
private final static String CODESET_QUERY_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/codesetQuery.sql");
private final static String COHORT_QUERY_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/generateCohort.sql");
private final static String PRIMARY_EVENTS_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/primaryEventsQuery.sql");
private final static String ADDITIONAL_CRITERIA_TEMMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/additionalCriteria.sql");
private final static String GROUP_QUERY_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/groupQuery.sql");
private final static String CONDITION_ERA_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/conditionEra.sql");
private final static String CONDITION_OCCURRENCE_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/conditionOccurrence.sql");
private final static String DEATH_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/death.sql");
private final static String DEVICE_EXPOSURE_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/deviceExposure.sql");
private final static String DOSE_ERA_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/doseEra.sql");
private final static String DRUG_ERA_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/drugEra.sql");
private final static String DRUG_EXPOSURE_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/drugExposure.sql");
private final static String MEASUREMENT_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/measurement.sql");;
private final static String OBSERVATION_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/observation.sql");;
private final static String OBSERVATION_PERIOD_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/observationPeriod.sql");;
private final static String PROCEDURE_OCCURRENCE_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/procedureOccurrence.sql");
private final static String SPECIMEN_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/specimen.sql");
private final static String VISIT_OCCURRENCE_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/visitOccurrence.sql");
private final static String PRIMARY_CRITERIA_EVENTS_TABLE = "primary_events";
private final static String INCLUSION_RULE_QUERY_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/inclusionrule.sql");
private final static String CENSORING_QUERY_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/censoringInsert.sql");
private final static String EVENT_TABLE_EXPRESSION_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/eventTableExpression.sql");
private final static String DEMOGRAPHIC_CRITERIA_QUERY_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/demographicCriteria.sql");
// Strategy templates
private final static String DATE_OFFSET_STRATEGY_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/dateOffsetStrategy.sql");
private final static String CUSTOM_ERA_STRATEGY_TEMPLATE = ResourceHelper.GetResourceAsString("/resources/cohortdefinition/sql/customEraStrategy.sql");
public static class BuildExpressionQueryOptions {
@JsonProperty("cohortId")
public Integer cohortId;
@JsonProperty("cdmSchema")
public String cdmSchema;
@JsonProperty("targetTable")
public String targetTable;
@JsonProperty("resultSchema")
public String resultSchema;
@JsonProperty("generateStats")
public boolean generateStats;
}
private ArrayList<Long> getConceptIdsFromConcepts(Concept[] concepts) {
ArrayList<Long> conceptIdList = new ArrayList<>();
for (Concept concept : concepts) {
conceptIdList.add(concept.conceptId);
}
return conceptIdList;
}
private String getOperator(String op)
{
switch(op)
{
case "lt": return "<";
case "lte" : return "<=";
case "eq": return "=";
case "!eq": return "<>";
case "gt": return ">";
case "gte": return ">=";
}
throw new RuntimeException("Unknown operator type: " + op);
}
private String getOccurrenceOperator(int type)
{
// Occurance check { id: 0, name: 'Exactly', id: 1, name: 'At Most' }, { id: 2, name: 'At Least' }
switch (type)
{
case 0: return "=";
case 1: return "<=";
case 2: return ">=";
}
// recieved an unknown operator value
return "??";
}
private String getOperator(DateRange range)
{
return getOperator(range.op);
}
private String getOperator(NumericRange range)
{
return getOperator(range.op);
}
private String dateStringToSql(String date)
{
String[] dateParts = StringUtils.split(date,'-');
return String.format("DATEFROMPARTS(%s, %s, %s)", dateParts[0], dateParts[1], dateParts[2]);
}
private String buildDateRangeClause(String sqlExpression, DateRange range)
{
String clause;
if (range.op.endsWith("bt")) // range with a 'between' op
{
clause = String.format("%s(%s >= %s and %s <= %s)",
range.op.startsWith("!") ? "not " : "",
sqlExpression,
dateStringToSql(range.value),
sqlExpression,
dateStringToSql(range.extent));
}
else // single value range (less than/eq/greater than, etc)
{
clause = String.format("%s %s %s", sqlExpression, getOperator(range), dateStringToSql(range.value));
}
return clause;
}
// Assumes integer numeric range
private String buildNumericRangeClause(String sqlExpression, NumericRange range)
{
String clause;
if (range.op.endsWith("bt"))
{
clause = String.format("%s(%s >= %d and %s <= %d)",
range.op.startsWith("!") ? "not " : "",
sqlExpression,
range.value.intValue(),
sqlExpression,
range.extent.intValue());
}
else
{
clause = String.format("%s %s %d", sqlExpression, getOperator(range), range.value.intValue());
}
return clause;
}
// assumes decimal range
private String buildNumericRangeClause(String sqlExpression, NumericRange range, String format)
{
String clause;
if (range.op.endsWith("bt"))
{
clause = String.format("%s(%s >= %" + format + " and %s <= %" + format + ")",
range.op.startsWith("!") ? "not " : "",
sqlExpression,
range.value.doubleValue(),
sqlExpression,
range.extent.doubleValue());
}
else
{
clause = String.format("%s %s %" + format, sqlExpression, getOperator(range), range.value.doubleValue());
}
return clause;
}
private String buildTextFilterClause(String sqlExpression, TextFilter filter)
{
String negation = filter.op.startsWith("!") ? "not" : "";
String prefix = filter.op.endsWith("endsWith") || filter.op.endsWith("contains") ? "%" : "";
String value = filter.text;
String postfix = filter.op.endsWith("startsWith") || filter.op.endsWith("contains") ? "%" : "";
return String.format("%s %s like '%s%s%s'", sqlExpression, negation, prefix, value, postfix);
}
private String wrapCriteriaQuery(String query, CriteriaGroup group)
{
String eventQuery = StringUtils.replace(EVENT_TABLE_EXPRESSION_TEMPLATE, "@eventQuery", query);
String groupQuery = this.getCriteriaGroupQuery(group, String.format("(%s)", eventQuery));
groupQuery = StringUtils.replace(groupQuery,"@indexId", "" + 0);
String wrappedQuery = String.format(
"select PE.person_id, PE.event_id, PE.start_date, PE.end_date, PE.target_concept_id FROM (\n%s\n) PE\nJOIN (\n%s) AC on AC.person_id = pe.person_id and AC.event_id = pe.event_id\n",
query, groupQuery);
return wrappedQuery;
}
public String getCodesetQuery(ConceptSet[] conceptSets) {
String codesetQuery = CODESET_QUERY_TEMPLATE;
ArrayList<String> codesetInserts = new ArrayList<>();
if (conceptSets.length > 0) {
for (ConceptSet cs : conceptSets) {
// construct main target codeset query
String conceptExpressionQuery = conceptSetQueryBuilder.buildExpressionQuery(cs.expression);
// attach the conceptSetId to the result query from the expession query builder
String conceptSetInsert = String.format("INSERT INTO #Codesets (codeset_id, concept_id)\nSELECT %d as codeset_id, c.concept_id FROM (%s) C;", cs.id, conceptExpressionQuery);
codesetInserts.add(conceptSetInsert);
}
}
codesetQuery = StringUtils.replace(codesetQuery, "@codesetInserts", StringUtils.join(codesetInserts, "\n"));
return codesetQuery;
}
private String getCensoringEventsQuery(Criteria[] censoringCriteria)
{
if (censoringCriteria == null || censoringCriteria.length == 0)
return "";
ArrayList<String> criteriaQueries = new ArrayList<>();
for (Criteria c : censoringCriteria)
{
String criteriaQuery = c.accept(this);
criteriaQueries.add(StringUtils.replace(CENSORING_QUERY_TEMPLATE, "@criteriaQuery", criteriaQuery));
}
return StringUtils.join(criteriaQueries,"\n");
}
public String getPrimaryEventsQuery(PrimaryCriteria primaryCriteria) {
String query = PRIMARY_EVENTS_TEMPLATE;
ArrayList<String> criteriaQueries = new ArrayList<>();
for (Criteria c : primaryCriteria.criteriaList)
{
criteriaQueries.add(c.accept(this));
}
query = StringUtils.replace(query,"@criteriaQueries", StringUtils.join(criteriaQueries, "\nUNION ALL\n"));
ArrayList<String> primaryEventsFilters = new ArrayList<>();
primaryEventsFilters.add(String.format(
"DATEADD(day,%d,OP.OBSERVATION_PERIOD_START_DATE) <= P.START_DATE AND DATEADD(day,%d,P.START_DATE) <= OP.OBSERVATION_PERIOD_END_DATE",
primaryCriteria.observationWindow.priorDays,
primaryCriteria.observationWindow.postDays
)
);
query = StringUtils.replace(query, "@EventSort", (primaryCriteria.primaryLimit.type != null && primaryCriteria.primaryLimit.type.equalsIgnoreCase("LAST")) ? "DESC" : "ASC");
if (!primaryCriteria.primaryLimit.type.equalsIgnoreCase("ALL"))
{
primaryEventsFilters.add("P.ordinal = 1");
}
query = StringUtils.replace(query,"@primaryEventsFilter", StringUtils.join(primaryEventsFilters," AND "));
return query;
}
public String buildExpressionQuery(CohortExpression expression, BuildExpressionQueryOptions options) {
String resultSql = COHORT_QUERY_TEMPLATE;
String codesetQuery = getCodesetQuery(expression.conceptSets);
resultSql = StringUtils.replace(resultSql, "@codesetQuery", codesetQuery);
String primaryEventsQuery = getPrimaryEventsQuery(expression.primaryCriteria);
resultSql = StringUtils.replace(resultSql, "@primaryEventsQuery", primaryEventsQuery);
String additionalCriteriaQuery = "";
if (expression.additionalCriteria != null)
{
CriteriaGroup acGroup = expression.additionalCriteria;
String acGroupQuery = this.getCriteriaGroupQuery(acGroup, this.PRIMARY_CRITERIA_EVENTS_TABLE);//acGroup.accept(this);
acGroupQuery = StringUtils.replace(acGroupQuery,"@indexId", "" + 0);
additionalCriteriaQuery = "\nJOIN (\n" + acGroupQuery + ") AC on AC.person_id = pe.person_id and AC.event_id = pe.event_id\n";
}
resultSql = StringUtils.replace(resultSql, "@additionalCriteriaQuery", additionalCriteriaQuery);
resultSql = StringUtils.replace(resultSql, "@QualifiedEventSort", (expression.qualifiedLimit.type != null && expression.qualifiedLimit.type.equalsIgnoreCase("LAST")) ? "DESC" : "ASC");
// Only apply qualified limit filter if additional criteria is specified.
if (expression.additionalCriteria != null && expression.qualifiedLimit.type != null && !expression.qualifiedLimit.type.equalsIgnoreCase("ALL"))
{
resultSql = StringUtils.replace(resultSql, "@QualifiedLimitFilter","WHERE QE.ordinal = 1");
}
else
resultSql = StringUtils.replace(resultSql, "@QualifiedLimitFilter","");
ArrayList<String> inclusionRuleInserts = new ArrayList<>();
for (int i = 0; i < expression.inclusionRules.size(); i++)
{
CriteriaGroup cg = expression.inclusionRules.get(i).expression;
String inclusionRuleInsert = getInclusionRuleQuery(cg);
inclusionRuleInsert = StringUtils.replace(inclusionRuleInsert, "@inclusion_rule_id", "" + i);
inclusionRuleInserts.add(inclusionRuleInsert);
}
resultSql = StringUtils.replace(resultSql,"@inclusionCohortInserts", StringUtils.join(inclusionRuleInserts,"\n"));
resultSql = StringUtils.replace(resultSql, "@IncludedEventSort", (expression.expressionLimit.type != null && expression.expressionLimit.type.equalsIgnoreCase("LAST")) ? "DESC" : "ASC");
if (expression.expressionLimit.type != null && !expression.expressionLimit.type.equalsIgnoreCase("ALL"))
{
resultSql = StringUtils.replace(resultSql, "@ResultLimitFilter","WHERE Results.ordinal = 1");
}
else
resultSql = StringUtils.replace(resultSql, "@ResultLimitFilter","");
resultSql = StringUtils.replace(resultSql, "@ruleTotal", String.valueOf(expression.inclusionRules.size()));
if (expression.endStrategy != null)
resultSql = StringUtils.replace(resultSql, "@strategyInserts", expression.endStrategy.accept(this, "#included_events"));
else
resultSql = StringUtils.replace(resultSql, "@strategyInserts", "");
resultSql = StringUtils.replace(resultSql, "@censoringInserts", getCensoringEventsQuery(expression.censoringCriteria));
if (options != null)
{
// replease query parameters with tokens
if (options.cdmSchema != null)
resultSql = StringUtils.replace(resultSql, "@cdm_database_schema", options.cdmSchema);
if (options.targetTable != null)
resultSql = StringUtils.replace(resultSql, "@target_database_schema.@target_cohort_table", options.targetTable);
if (options.resultSchema != null)
resultSql = StringUtils.replace(resultSql, "@results_database_schema", options.resultSchema);
if (options.cohortId != null)
resultSql = StringUtils.replace(resultSql, "@target_cohort_id", options.cohortId.toString());
resultSql = StringUtils.replace(resultSql, "@generateStats", options.generateStats ? "1": "0");
}
return resultSql;
}
public String getCriteriaGroupQuery(CriteriaGroup group, String eventTable) {
String query = GROUP_QUERY_TEMPLATE;
ArrayList<String> additionalCriteriaQueries = new ArrayList<>();
int indexId = 0;
for(CorelatedCriteria cc : group.criteriaList)
{
String acQuery = this.getCorelatedlCriteriaQuery(cc, eventTable); //ac.accept(this);
acQuery = StringUtils.replace(acQuery, "@indexId", "" + indexId);
additionalCriteriaQueries.add(acQuery);
indexId++;
}
for(DemographicCriteria dc : group.demographicCriteriaList)
{
String dcQuery = this.getDemographicCriteriaQuery(dc, eventTable); //ac.accept(this);
dcQuery = StringUtils.replace(dcQuery, "@indexId", "" + indexId);
additionalCriteriaQueries.add(dcQuery);
indexId++;
}
for(CriteriaGroup g : group.groups)
{
String gQuery = this.getCriteriaGroupQuery(g, eventTable); //g.accept(this);
gQuery = StringUtils.replace(gQuery, "@indexId", "" + indexId);
additionalCriteriaQueries.add(gQuery);
indexId++;
}
if (indexId > 0) // this group is not empty
{
query = StringUtils.replace(query, "@criteriaQueries", StringUtils.join(additionalCriteriaQueries, "\nUNION ALL\n"));
String occurrenceCountClause = "HAVING COUNT(index_id) ";
if (group.type.equalsIgnoreCase("ALL")) // count must match number of criteria + sub-groups in group.
occurrenceCountClause += "= " + indexId;
if (group.type.equalsIgnoreCase("ANY")) // count must be > 0 for an 'ANY' criteria
occurrenceCountClause += "> 0";
if (group.type.toUpperCase().startsWith("AT_"))
{
if (group.type.toUpperCase().endsWith("LEAST"))
occurrenceCountClause += ">= " + group.count;
else
occurrenceCountClause += "<= " + group.count;
}
query = StringUtils.replace(query, "@occurrenceCountClause", occurrenceCountClause);
}
else // query group is empty so replace queries and occurence count clause with a friendly default
{
query = StringUtils.replace(query, "@criteriaQueries", "select ET.person_id, ET.event_id from @eventTable ET");
query = StringUtils.replace(query, "@occurrenceCountClause", "");
}
query = StringUtils.replace(query, "@eventTable", eventTable);
return query;
}
private String getInclusionRuleQuery(CriteriaGroup inclusionRule)
{
String resultSql = INCLUSION_RULE_QUERY_TEMPLATE;
String additionalCriteriaQuery = "\nJOIN (\n" + getCriteriaGroupQuery(inclusionRule, "#qualified_events") + ") AC on AC.person_id = pe.person_id AND AC.event_id = pe.event_id";
additionalCriteriaQuery = StringUtils.replace(additionalCriteriaQuery,"@indexId", "" + 0);
resultSql = StringUtils.replace(resultSql, "@additionalCriteriaQuery", additionalCriteriaQuery);
return resultSql;
}
public String getDemographicCriteriaQuery(DemographicCriteria criteria, String eventTable)
{
String query = DEMOGRAPHIC_CRITERIA_QUERY_TEMPLATE;
query = StringUtils.replace(query,"@eventTable",eventTable);
ArrayList<String> whereClauses = new ArrayList<>();
// Age
if (criteria.age != null)
{
whereClauses.add(buildNumericRangeClause("YEAR(E.start_date) - P.year_of_birth", criteria.age));
}
// Gender
if (criteria.gender != null && criteria.gender.length > 0)
{
whereClauses.add(String.format("P.gender_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.gender),",")));
}
// Race
if (criteria.race != null && criteria.race.length > 0)
{
whereClauses.add(String.format("P.race_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.race),",")));
}
// Race
if (criteria.race != null && criteria.race.length > 0)
{
whereClauses.add(String.format("P.race_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.race),",")));
}
// Ethnicity
if (criteria.ethnicity != null && criteria.ethnicity.length > 0)
{
whereClauses.add(String.format("P.ethnicity_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.ethnicity),",")));
}
// occurrenceStartDate
if (criteria.occurrenceStartDate != null)
{
whereClauses.add(buildDateRangeClause("E.start_date",criteria.occurrenceStartDate));
}
// occurrenceEndDate
if (criteria.occurrenceEndDate != null)
{
whereClauses.add(buildDateRangeClause("E.end_date",criteria.occurrenceEndDate));
}
if (whereClauses.size() > 0) {
query = StringUtils.replace(query, "@whereClause", "WHERE " + StringUtils.join(whereClauses, " AND "));
} else {
query = StringUtils.replace(query, "@whereClause", "");
}
return query;
}
public String getCorelatedlCriteriaQuery(CorelatedCriteria corelatedCriteria, String eventTable)
{
String query = ADDITIONAL_CRITERIA_TEMMPLATE;
String criteriaQuery = corelatedCriteria.criteria.accept(this);
query = StringUtils.replace(query,"@criteriaQuery",criteriaQuery);
query = StringUtils.replace(query,"@eventTable",eventTable);
// build index date window expression
String startExpression;
String endExpression;
ArrayList<String> clauses = new ArrayList<>();
clauses.add("A.START_DATE >= P.OP_START_DATE AND A.START_DATE <= P.OP_END_DATE");
// StartWindow
Window startWindow = corelatedCriteria.startWindow;
if (startWindow.start.days != null)
startExpression = String.format("DATEADD(day,%d,P.START_DATE)", startWindow.start.coeff * startWindow.start.days);
else
startExpression = startWindow.start.coeff == -1 ? "P.OP_START_DATE" : "P.OP_END_DATE";
if (startWindow.end.days != null)
endExpression = String.format("DATEADD(day,%d,P.START_DATE)", startWindow.end.coeff * startWindow.end.days);
else
endExpression = startWindow.end.coeff == -1 ? "P.OP_START_DATE" : "P.OP_END_DATE";
clauses.add(String.format("A.START_DATE >= %s and A.START_DATE <= %s", startExpression, endExpression));
// EndWindow
Window endWindow = corelatedCriteria.endWindow;
if (endWindow != null)
{
if (endWindow.start.days != null)
startExpression = String.format("DATEADD(day,%d,P.START_DATE)", endWindow.start.coeff * endWindow.start.days);
else
startExpression = endWindow.start.coeff == -1 ? "P.OP_START_DATE" : "P.OP_END_DATE";
if (endWindow.end.days != null)
endExpression = String.format("DATEADD(day,%d,P.START_DATE)", endWindow.end.coeff * endWindow.end.days);
else
endExpression = endWindow.end.coeff == -1 ? "P.OP_START_DATE" : "P.OP_END_DATE";
clauses.add(String.format("A.END_DATE >= %s AND A.END_DATE <= %s", startExpression, endExpression));
}
query = StringUtils.replace(query,"@windowCriteria",StringUtils.join(clauses, " AND "));
// Occurrence criteria
String occurrenceCriteria = String.format(
"HAVING COUNT(%sA.TARGET_CONCEPT_ID) %s %d",
corelatedCriteria.occurrence.isDistinct ? "DISTINCT " : "",
getOccurrenceOperator(corelatedCriteria.occurrence.type),
corelatedCriteria.occurrence.count
);
query = StringUtils.replace(query, "@occurrenceCriteria", occurrenceCriteria);
return query;
}
// <editor-fold defaultstate="collapsed" desc="ICriteriaSqlDispatcher implementation">
@Override
public String getCriteriaSql(ConditionEra criteria)
{
String query = CONDITION_ERA_TEMPLATE;
String codesetClause = "";
if (criteria.codesetId != null)
{
codesetClause = String.format("where ce.condition_concept_id in (SELECT concept_id from #Codesets where codeset_id = %d)", criteria.codesetId);
}
query = StringUtils.replace(query, "@codesetClause",codesetClause);
ArrayList<String> joinClauses = new ArrayList<>();
if (criteria.ageAtStart != null || criteria.ageAtEnd != null || (criteria.gender != null && criteria.gender.length > 0)) // join to PERSON
joinClauses.add("JOIN @cdm_database_schema.PERSON P on C.person_id = P.person_id");
query = StringUtils.replace(query,"@joinClause", StringUtils.join(joinClauses,"\n"));
ArrayList<String> whereClauses = new ArrayList<>();
// first
if (criteria.first != null && criteria.first == true)
whereClauses.add("C.ordinal = 1");
// eraStartDate
if (criteria.eraStartDate != null)
{
whereClauses.add(buildDateRangeClause("C.condition_era_start_date",criteria.eraStartDate));
}
// eraEndDate
if (criteria.eraEndDate != null)
{
whereClauses.add(buildDateRangeClause("C.condition_era_end_date",criteria.eraEndDate));
}
// occurrenceCount
if (criteria.occurrenceCount != null)
{
whereClauses.add(buildNumericRangeClause("C.condition_occurrence_count", criteria.occurrenceCount));
}
// eraLength
if (criteria.eraLength != null)
{
whereClauses.add(buildNumericRangeClause("DATEDIFF(d,C.condition_era_start_date, C.condition_era_end_date)", criteria.eraLength));
}
// ageAtStart
if (criteria.ageAtStart != null)
{
whereClauses.add(buildNumericRangeClause("YEAR(C.condition_era_start_date) - P.year_of_birth", criteria.ageAtStart));
}
// ageAtEnd
if (criteria.ageAtEnd != null)
{
whereClauses.add(buildNumericRangeClause("YEAR(C.condition_era_end_date) - P.year_of_birth", criteria.ageAtEnd));
}
// gender
if (criteria.gender != null && criteria.gender.length > 0)
{
whereClauses.add(String.format("P.gender_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.gender),",")));
}
String whereClause = "";
if (whereClauses.size() > 0)
whereClause = "WHERE " + StringUtils.join(whereClauses, "\nAND ");
query = StringUtils.replace(query, "@whereClause",whereClause);
if (criteria.CorrelatedCriteria != null)
{
query = wrapCriteriaQuery(query, criteria.CorrelatedCriteria);
}
return query;
}
@Override
public String getCriteriaSql(ConditionOccurrence criteria)
{
String query = CONDITION_OCCURRENCE_TEMPLATE;
String codesetClause = "";
if (criteria.codesetId != null)
{
codesetClause = String.format("where co.condition_concept_id in (SELECT concept_id from #Codesets where codeset_id = %d)", criteria.codesetId);
}
query = StringUtils.replace(query, "@codesetClause",codesetClause);
ArrayList<String> joinClauses = new ArrayList<>();
if (criteria.age != null || (criteria.gender != null && criteria.gender.length > 0)) // join to PERSON
joinClauses.add("JOIN @cdm_database_schema.PERSON P on C.person_id = P.person_id");
if (criteria.visitType != null && criteria.visitType.length > 0)
joinClauses.add("JOIN @cdm_database_schema.VISIT_OCCURRENCE V on C.visit_occurrence_id = V.visit_occurrence_id and C.person_id = V.person_id");
if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0)
joinClauses.add("LEFT JOIN @cdm_database_schema.PROVIDER PR on C.provider_id = PR.provider_id");
query = StringUtils.replace(query,"@joinClause", StringUtils.join(joinClauses,"\n"));
ArrayList<String> whereClauses = new ArrayList<>();
// first
if (criteria.first != null && criteria.first == true)
whereClauses.add("C.ordinal = 1");
// occurrenceStartDate
if (criteria.occurrenceStartDate != null)
{
whereClauses.add(buildDateRangeClause("C.condition_start_date",criteria.occurrenceStartDate));
}
// occurrenceEndDate
if (criteria.occurrenceEndDate != null)
{
whereClauses.add(buildDateRangeClause("C.condition_end_date",criteria.occurrenceEndDate));
}
// conditionType
if (criteria.conditionType != null && criteria.conditionType.length > 0)
{
ArrayList<Long> conceptIds = getConceptIdsFromConcepts(criteria.conditionType);
whereClauses.add(String.format("C.condition_type_concept_id in (%s)", StringUtils.join(conceptIds, ",")));
}
// Stop Reason
if (criteria.stopReason != null)
{
whereClauses.add(buildTextFilterClause("C.stop_reason",criteria.stopReason));
}
// conditionSourceConcept
if (criteria.conditionSourceConcept != null)
{
whereClauses.add(String.format("C.condition_source_concept_id in (SELECT concept_id from #Codesets where codeset_id = %d)", criteria.conditionSourceConcept));
}
// age
if (criteria.age != null)
{
whereClauses.add(buildNumericRangeClause("YEAR(C.condition_start_date) - P.year_of_birth", criteria.age));
}
// gender
if (criteria.gender != null && criteria.gender.length > 0)
{
whereClauses.add(String.format("P.gender_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.gender),",")));
}
// providerSpecialty
if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0)
{
whereClauses.add(String.format("PR.specialty_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.providerSpecialty),",")));
}
// visitType
if (criteria.visitType != null && criteria.visitType.length > 0)
{
whereClauses.add(String.format("V.visit_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.visitType),",")));
}
String whereClause = "";
if (whereClauses.size() > 0)
whereClause = "WHERE " + StringUtils.join(whereClauses, "\nAND ");
query = StringUtils.replace(query, "@whereClause",whereClause);
if (criteria.CorrelatedCriteria != null)
{
query = wrapCriteriaQuery(query, criteria.CorrelatedCriteria);
}
return query;
}
@Override
public String getCriteriaSql(Death criteria)
{
String query = DEATH_TEMPLATE;
String codesetClause = "";
if (criteria.codesetId != null)
{
codesetClause = String.format("where d.cause_concept_id in (SELECT concept_id from #Codesets where codeset_id = %d)", criteria.codesetId);
}
query = StringUtils.replace(query, "@codesetClause",codesetClause);
ArrayList<String> joinClauses = new ArrayList<>();
if (criteria.age != null || (criteria.gender != null && criteria.gender.length > 0)) // join to PERSON
joinClauses.add("JOIN @cdm_database_schema.PERSON P on C.person_id = P.person_id");
query = StringUtils.replace(query,"@joinClause", StringUtils.join(joinClauses,"\n"));
ArrayList<String> whereClauses = new ArrayList<>();
// occurrenceStartDate
if (criteria.occurrenceStartDate != null)
{
whereClauses.add(buildDateRangeClause("C.death_date",criteria.occurrenceStartDate));
}
// deathType
if (criteria.deathType != null && criteria.deathType.length > 0)
{
ArrayList<Long> conceptIds = getConceptIdsFromConcepts(criteria.deathType);
whereClauses.add(String.format("C.death_type_concept_id in (%s)", StringUtils.join(conceptIds, ",")));
}
// deathSourceConcept
if (criteria.deathSourceConcept != null)
{
whereClauses.add(String.format("C.cause_source_concept_id in (SELECT concept_id from #Codesets where codeset_id = %d)", criteria.deathSourceConcept));
}
// age
if (criteria.age != null)
{
whereClauses.add(buildNumericRangeClause("YEAR(C.death_date) - P.year_of_birth", criteria.age));
}
// gender
if (criteria.gender != null && criteria.gender.length > 0)
{
whereClauses.add(String.format("P.gender_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.gender),",")));
}
String whereClause = "";
if (whereClauses.size() > 0)
whereClause = "WHERE " + StringUtils.join(whereClauses, "\nAND ");
query = StringUtils.replace(query, "@whereClause",whereClause);
if (criteria.CorrelatedCriteria != null)
{
query = wrapCriteriaQuery(query, criteria.CorrelatedCriteria);
}
return query;
}
@Override
public String getCriteriaSql(DeviceExposure criteria)
{
String query = DEVICE_EXPOSURE_TEMPLATE;
String codesetClause = "";
if (criteria.codesetId != null)
{
codesetClause = String.format("where de.device_concept_id in (SELECT concept_id from #Codesets where codeset_id = %d)", criteria.codesetId);
}
query = StringUtils.replace(query, "@codesetClause",codesetClause);
ArrayList<String> joinClauses = new ArrayList<>();
if (criteria.age != null || (criteria.gender != null && criteria.gender.length > 0)) // join to PERSON
joinClauses.add("JOIN @cdm_database_schema.PERSON P on C.person_id = P.person_id");
if (criteria.visitType != null && criteria.visitType.length > 0)
joinClauses.add("JOIN @cdm_database_schema.VISIT_OCCURRENCE V on C.visit_occurrence_id = V.visit_occurrence_id and C.person_id = V.person_id");
if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0)
joinClauses.add("LEFT JOIN @cdm_database_schema.PROVIDER PR on C.provider_id = PR.provider_id");
query = StringUtils.replace(query,"@joinClause", StringUtils.join(joinClauses,"\n"));
ArrayList<String> whereClauses = new ArrayList<>();
// first
if (criteria.first != null && criteria.first == true)
whereClauses.add("C.ordinal = 1");
// occurrenceStartDate
if (criteria.occurrenceStartDate != null)
{
whereClauses.add(buildDateRangeClause("C.device_exposure_start_date",criteria.occurrenceStartDate));
}
// occurrenceEndDate
if (criteria.occurrenceEndDate != null)
{
whereClauses.add(buildDateRangeClause("C.device_exposure_end_date",criteria.occurrenceEndDate));
}
// deviceType
if (criteria.deviceType != null && criteria.deviceType.length > 0)
{
ArrayList<Long> conceptIds = getConceptIdsFromConcepts(criteria.deviceType);
whereClauses.add(String.format("C.device_type_concept_id in (%s)", StringUtils.join(conceptIds, ",")));
}
// uniqueDeviceId
if (criteria.uniqueDeviceId != null)
{
whereClauses.add(buildTextFilterClause("C.unique_device_id",criteria.uniqueDeviceId));
}
// quantity
if (criteria.quantity != null)
{
whereClauses.add(buildNumericRangeClause("C.quantity",criteria.quantity));
}
// deviceSourceConcept
if (criteria.deviceSourceConcept != null)
{
whereClauses.add(String.format("C.device_source_concept_id in (SELECT concept_id from #Codesets where codeset_id = %d)", criteria.deviceSourceConcept));
}
// age
if (criteria.age != null)
{
whereClauses.add(buildNumericRangeClause("YEAR(C.device_exposure_start_date) - P.year_of_birth", criteria.age));
}
// gender
if (criteria.gender != null && criteria.gender.length > 0)
{
whereClauses.add(String.format("P.gender_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.gender),",")));
}
// providerSpecialty
if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0)
{
whereClauses.add(String.format("PR.specialty_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.providerSpecialty),",")));
}
// visitType
if (criteria.visitType != null && criteria.visitType.length > 0)
{
whereClauses.add(String.format("V.visit_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.visitType),",")));
}
String whereClause = "";
if (whereClauses.size() > 0)
whereClause = "WHERE " + StringUtils.join(whereClauses, "\nAND ");
query = StringUtils.replace(query, "@whereClause",whereClause);
if (criteria.CorrelatedCriteria != null)
{
query = wrapCriteriaQuery(query, criteria.CorrelatedCriteria);
}
return query;
}
@Override
public String getCriteriaSql(DoseEra criteria)
{
String query = DOSE_ERA_TEMPLATE;
String codesetClause = "";
if (criteria.codesetId != null)
{
codesetClause = String.format("where de.drug_concept_id in (SELECT concept_id from #Codesets where codeset_id = %d)", criteria.codesetId);
}
query = StringUtils.replace(query, "@codesetClause",codesetClause);
ArrayList<String> joinClauses = new ArrayList<>();
if (criteria.ageAtStart != null || criteria.ageAtEnd != null) // join to PERSON
joinClauses.add("JOIN @cdm_database_schema.PERSON P on C.person_id = P.person_id");
query = StringUtils.replace(query,"@joinClause", StringUtils.join(joinClauses,"\n"));
ArrayList<String> whereClauses = new ArrayList<>();
// first
if (criteria.first != null && criteria.first == true)
whereClauses.add("C.ordinal = 1");
// eraStartDate
if (criteria.eraStartDate != null)
{
whereClauses.add(buildDateRangeClause("C.dose_era_start_date",criteria.eraStartDate));
}
// eraEndDate
if (criteria.eraEndDate != null)
{
whereClauses.add(buildDateRangeClause("C.dose_era_end_date",criteria.eraEndDate));
}
// unit
if (criteria.unit != null && criteria.unit.length > 0)
{
whereClauses.add(String.format("c.unit_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.unit),",")));
}
// doseValue
if (criteria.doseValue != null)
{
whereClauses.add(buildNumericRangeClause("c.dose_value", criteria.doseValue, ".4f"));
}
// eraLength
if (criteria.eraLength != null)
{
whereClauses.add(buildNumericRangeClause("DATEDIFF(d,C.dose_era_start_date, C.dose_era_end_date)", criteria.eraLength));
}
// ageAtStart
if (criteria.ageAtStart != null)
{
whereClauses.add(buildNumericRangeClause("YEAR(C.dose_era_start_date) - P.year_of_birth", criteria.ageAtStart));
}
// ageAtEnd
if (criteria.ageAtEnd != null)
{
whereClauses.add(buildNumericRangeClause("YEAR(C.dose_era_end_date) - P.year_of_birth", criteria.ageAtEnd));
}
// gender
if (criteria.gender != null && criteria.gender.length > 0)
{
whereClauses.add(String.format("P.gender_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.gender),",")));
}
String whereClause = "";
if (whereClauses.size() > 0)
whereClause = "WHERE " + StringUtils.join(whereClauses, "\nAND ");
query = StringUtils.replace(query, "@whereClause",whereClause);
if (criteria.CorrelatedCriteria != null)
{
query = wrapCriteriaQuery(query, criteria.CorrelatedCriteria);
}
return query;
}
@Override
public String getCriteriaSql(DrugEra criteria)
{
String query = DRUG_ERA_TEMPLATE;
String codesetClause = "";
if (criteria.codesetId != null)
{
codesetClause = String.format("where de.drug_concept_id in (SELECT concept_id from #Codesets where codeset_id = %d)", criteria.codesetId);
}
query = StringUtils.replace(query, "@codesetClause",codesetClause);
ArrayList<String> joinClauses = new ArrayList<>();
if (criteria.ageAtStart != null || criteria.ageAtEnd != null) // join to PERSON
joinClauses.add("JOIN @cdm_database_schema.PERSON P on C.person_id = P.person_id");
query = StringUtils.replace(query,"@joinClause", StringUtils.join(joinClauses,"\n"));
ArrayList<String> whereClauses = new ArrayList<>();
// first
if (criteria.first != null && criteria.first == true)
whereClauses.add("C.ordinal = 1");
// eraStartDate
if (criteria.eraStartDate != null)
{
whereClauses.add(buildDateRangeClause("C.drug_era_start_date",criteria.eraStartDate));
}
// eraEndDate
if (criteria.eraEndDate != null)
{
whereClauses.add(buildDateRangeClause("C.drug_era_end_date",criteria.eraEndDate));
}
// occurrenceCount
if (criteria.occurrenceCount != null)
{
whereClauses.add(buildNumericRangeClause("C.drug_exposure_count", criteria.occurrenceCount));
}
// eraLength
if (criteria.eraLength != null)
{
whereClauses.add(buildNumericRangeClause("DATEDIFF(d,C.drug_era_start_date, C.drug_era_end_date)", criteria.eraLength));
}
// gapDays
if (criteria.gapDays != null)
{
whereClauses.add(buildNumericRangeClause("C.gap_days", criteria.eraLength));
}
// ageAtStart
if (criteria.ageAtStart != null)
{
whereClauses.add(buildNumericRangeClause("YEAR(C.drug_era_start_date) - P.year_of_birth", criteria.ageAtStart));
}
// ageAtEnd
if (criteria.ageAtEnd != null)
{
whereClauses.add(buildNumericRangeClause("YEAR(C.drug_era_end_date) - P.year_of_birth", criteria.ageAtEnd));
}
// gender
if (criteria.gender != null && criteria.gender.length > 0)
{
whereClauses.add(String.format("P.gender_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.gender),",")));
}
String whereClause = "";
if (whereClauses.size() > 0)
whereClause = "WHERE " + StringUtils.join(whereClauses, "\nAND ");
query = StringUtils.replace(query, "@whereClause",whereClause);
if (criteria.CorrelatedCriteria != null)
{
query = wrapCriteriaQuery(query, criteria.CorrelatedCriteria);
}
return query;
}
@Override
public String getCriteriaSql(DrugExposure criteria)
{
String query = DRUG_EXPOSURE_TEMPLATE;
String codesetClause = "";
if (criteria.codesetId != null)
{
codesetClause = String.format("where de.drug_concept_id in (SELECT concept_id from #Codesets where codeset_id = %d)", criteria.codesetId);
}
query = StringUtils.replace(query, "@codesetClause",codesetClause);
ArrayList<String> joinClauses = new ArrayList<>();
if (criteria.age != null || (criteria.gender != null && criteria.gender.length > 0)) // join to PERSON
joinClauses.add("JOIN @cdm_database_schema.PERSON P on C.person_id = P.person_id");
if (criteria.visitType != null && criteria.visitType.length > 0)
joinClauses.add("JOIN @cdm_database_schema.VISIT_OCCURRENCE V on C.visit_occurrence_id = V.visit_occurrence_id and C.person_id = V.person_id");
if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0)
joinClauses.add("LEFT JOIN @cdm_database_schema.PROVIDER PR on C.provider_id = PR.provider_id");
query = StringUtils.replace(query,"@joinClause", StringUtils.join(joinClauses,"\n"));
ArrayList<String> whereClauses = new ArrayList<>();
// first
if (criteria.first != null && criteria.first == true)
whereClauses.add("C.ordinal = 1");
// occurrenceStartDate
if (criteria.occurrenceStartDate != null)
{
whereClauses.add(buildDateRangeClause("C.drug_exposure_start_date",criteria.occurrenceStartDate));
}
// occurrenceEndDate
if (criteria.occurrenceEndDate != null)
{
whereClauses.add(buildDateRangeClause("C.drug_exposure_end_date",criteria.occurrenceEndDate));
}
// drugType
if (criteria.drugType != null && criteria.drugType.length > 0)
{
ArrayList<Long> conceptIds = getConceptIdsFromConcepts(criteria.drugType);
whereClauses.add(String.format("C.drug_type_concept_id in (%s)", StringUtils.join(conceptIds, ",")));
}
// Stop Reason
if (criteria.stopReason != null)
{
whereClauses.add(buildTextFilterClause("C.stop_reason",criteria.stopReason));
}
// refills
if (criteria.refills != null)
{
whereClauses.add(buildNumericRangeClause("C.refills",criteria.refills));
}
// quantity
if (criteria.quantity != null)
{
whereClauses.add(buildNumericRangeClause("C.quantity",criteria.quantity,".4f"));
}
// days supply
if (criteria.daysSupply != null)
{
whereClauses.add(buildNumericRangeClause("C.days_supply",criteria.daysSupply));
}
// routeConcept
if (criteria.routeConcept != null && criteria.routeConcept.length > 0)
{
whereClauses.add(String.format("C.route_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.routeConcept),",")));
}
// effectiveDrugDose
if (criteria.effectiveDrugDose != null)
{
whereClauses.add(buildNumericRangeClause("C.effective_drug_dose",criteria.effectiveDrugDose,".4f"));
}
// doseUnit
if (criteria.doseUnit != null && criteria.doseUnit.length > 0)
{
whereClauses.add(String.format("C.dose_unit_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.doseUnit),",")));
}
// LotNumber
if (criteria.lotNumber != null)
{
whereClauses.add(buildTextFilterClause("C.lot_number", criteria.lotNumber));
}
// drugSourceConcept
if (criteria.drugSourceConcept != null)
{
whereClauses.add(String.format("C.drug_source_concept_id in (SELECT concept_id from #Codesets where codeset_id = %d)", criteria.drugSourceConcept));
}
// age
if (criteria.age != null)
{
whereClauses.add(buildNumericRangeClause("YEAR(C.drug_exposure_start_date) - P.year_of_birth", criteria.age));
}
// gender
if (criteria.gender != null && criteria.gender.length > 0)
{
whereClauses.add(String.format("P.gender_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.gender),",")));
}
// providerSpecialty
if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0)
{
whereClauses.add(String.format("PR.specialty_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.providerSpecialty),",")));
}
// visitType
if (criteria.visitType != null && criteria.visitType.length > 0)
{
whereClauses.add(String.format("V.visit_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.visitType),",")));
}
String whereClause = "";
if (whereClauses.size() > 0)
whereClause = "WHERE " + StringUtils.join(whereClauses, "\nAND ");
query = StringUtils.replace(query, "@whereClause",whereClause);
if (criteria.CorrelatedCriteria != null)
{
query = wrapCriteriaQuery(query, criteria.CorrelatedCriteria);
}
return query;
}
@Override
public String getCriteriaSql(Measurement criteria)
{
String query = MEASUREMENT_TEMPLATE;
String codesetClause = "";
if (criteria.codesetId != null)
{
codesetClause = String.format("where m.measurement_concept_id in (SELECT concept_id from #Codesets where codeset_id = %d)", criteria.codesetId);
}
query = StringUtils.replace(query, "@codesetClause",codesetClause);
ArrayList<String> joinClauses = new ArrayList<>();
if (criteria.age != null || (criteria.gender != null && criteria.gender.length > 0)) // join to PERSON
joinClauses.add("JOIN @cdm_database_schema.PERSON P on C.person_id = P.person_id");
if (criteria.visitType != null && criteria.visitType.length > 0)
joinClauses.add("JOIN @cdm_database_schema.VISIT_OCCURRENCE V on C.visit_occurrence_id = V.visit_occurrence_id and C.person_id = V.person_id");
if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0)
joinClauses.add("LEFT JOIN @cdm_database_schema.PROVIDER PR on C.provider_id = PR.provider_id");
query = StringUtils.replace(query,"@joinClause", StringUtils.join(joinClauses,"\n"));
ArrayList<String> whereClauses = new ArrayList<>();
// first
if (criteria.first != null && criteria.first == true)
whereClauses.add("C.ordinal = 1");
// occurrenceStartDate
if (criteria.occurrenceStartDate != null)
{
whereClauses.add(buildDateRangeClause("C.measurement_date",criteria.occurrenceStartDate));
}
// measurementType
if (criteria.measurementType != null && criteria.measurementType.length > 0)
{
ArrayList<Long> conceptIds = getConceptIdsFromConcepts(criteria.measurementType);
whereClauses.add(String.format("C.measurement_type_concept_id in (%s)", StringUtils.join(conceptIds, ",")));
}
// operator
if (criteria.operator != null && criteria.operator.length > 0)
{
ArrayList<Long> conceptIds = getConceptIdsFromConcepts(criteria.operator);
whereClauses.add(String.format("C.operator_concept_id in (%s)", StringUtils.join(conceptIds, ",")));
}
// valueAsNumber
if (criteria.valueAsNumber != null)
{
whereClauses.add(buildNumericRangeClause("C.value_as_number",criteria.valueAsNumber,".4f"));
}
// valueAsConcept
if (criteria.valueAsConcept != null && criteria.valueAsConcept.length > 0)
{
ArrayList<Long> conceptIds = getConceptIdsFromConcepts(criteria.valueAsConcept);
whereClauses.add(String.format("C.value_as_concept_id in (%s)", StringUtils.join(conceptIds, ",")));
}
// unit
if (criteria.unit != null && criteria.unit.length > 0)
{
ArrayList<Long> conceptIds = getConceptIdsFromConcepts(criteria.unit);
whereClauses.add(String.format("C.unit_concept_id in (%s)", StringUtils.join(conceptIds, ",")));
}
// rangeLow
if (criteria.rangeLow != null)
{
whereClauses.add(buildNumericRangeClause("C.range_low",criteria.rangeLow,".4f"));
}
// rangeHigh
if (criteria.rangeHigh != null)
{
whereClauses.add(buildNumericRangeClause("C.range_high",criteria.rangeHigh,".4f"));
}
// rangeLowRatio
if (criteria.rangeLowRatio != null)
{
whereClauses.add(buildNumericRangeClause("(C.value_as_number / C.range_low)",criteria.rangeLowRatio,".4f"));
}
// rangeHighRatio
if (criteria.rangeHighRatio != null)
{
whereClauses.add(buildNumericRangeClause("(C.value_as_number / C.range_high)",criteria.rangeHighRatio,".4f"));
}
// abnormal
if (criteria.abnormal != null && criteria.abnormal.booleanValue())
{
whereClauses.add("(C.value_as_number < C.range_low or C.value_as_number > C.range_high or C.value_as_concept_id in (4155142, 4155143))");
}
// measurementSourceConcept
if (criteria.measurementSourceConcept != null)
{
whereClauses.add(String.format("C.measurement_source_concept_id in (SELECT concept_id from #Codesets where codeset_id = %d)", criteria.measurementSourceConcept));
}
// age
if (criteria.age != null)
{
whereClauses.add(buildNumericRangeClause("YEAR(C.measurement_date) - P.year_of_birth", criteria.age));
}
// gender
if (criteria.gender != null && criteria.gender.length > 0)
{
whereClauses.add(String.format("P.gender_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.gender),",")));
}
// providerSpecialty
if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0)
{
whereClauses.add(String.format("PR.specialty_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.providerSpecialty),",")));
}
// visitType
if (criteria.visitType != null && criteria.visitType.length > 0)
{
whereClauses.add(String.format("V.visit_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.visitType),",")));
}
String whereClause = "";
if (whereClauses.size() > 0)
whereClause = "WHERE " + StringUtils.join(whereClauses, "\nAND ");
query = StringUtils.replace(query, "@whereClause",whereClause);
if (criteria.CorrelatedCriteria != null)
{
query = wrapCriteriaQuery(query, criteria.CorrelatedCriteria);
}
return query;
}
@Override
public String getCriteriaSql(Observation criteria)
{
String query = OBSERVATION_TEMPLATE;
String codesetClause = "";
if (criteria.codesetId != null)
{
codesetClause = String.format("where o.observation_concept_id in (SELECT concept_id from #Codesets where codeset_id = %d)", criteria.codesetId);
}
query = StringUtils.replace(query, "@codesetClause",codesetClause);
ArrayList<String> joinClauses = new ArrayList<>();
if (criteria.age != null || (criteria.gender != null && criteria.gender.length > 0)) // join to PERSON
joinClauses.add("JOIN @cdm_database_schema.PERSON P on C.person_id = P.person_id");
if (criteria.visitType != null && criteria.visitType.length > 0)
joinClauses.add("JOIN @cdm_database_schema.VISIT_OCCURRENCE V on C.visit_occurrence_id = V.visit_occurrence_id and C.person_id = V.person_id");
if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0)
joinClauses.add("LEFT JOIN @cdm_database_schema.PROVIDER PR on C.provider_id = PR.provider_id");
query = StringUtils.replace(query,"@joinClause", StringUtils.join(joinClauses,"\n"));
ArrayList<String> whereClauses = new ArrayList<>();
// first
if (criteria.first != null && criteria.first == true)
whereClauses.add("C.ordinal = 1");
// occurrenceStartDate
if (criteria.occurrenceStartDate != null)
{
whereClauses.add(buildDateRangeClause("C.observation_date",criteria.occurrenceStartDate));
}
// measurementType
if (criteria.observationType != null && criteria.observationType.length > 0)
{
ArrayList<Long> conceptIds = getConceptIdsFromConcepts(criteria.observationType);
whereClauses.add(String.format("C.observation_type_concept_id in (%s)", StringUtils.join(conceptIds, ",")));
}
// valueAsNumber
if (criteria.valueAsNumber != null)
{
whereClauses.add(buildNumericRangeClause("C.value_as_number",criteria.valueAsNumber,".4f"));
}
// valueAsString
if (criteria.valueAsString != null)
{
whereClauses.add(buildTextFilterClause("C.value_as_string",criteria.valueAsString));
}
// valueAsConcept
if (criteria.valueAsConcept != null && criteria.valueAsConcept.length > 0)
{
ArrayList<Long> conceptIds = getConceptIdsFromConcepts(criteria.valueAsConcept);
whereClauses.add(String.format("C.value_as_concept_id in (%s)", StringUtils.join(conceptIds, ",")));
}
// qualifier
if (criteria.qualifier != null && criteria.qualifier.length > 0)
{
ArrayList<Long> conceptIds = getConceptIdsFromConcepts(criteria.qualifier);
whereClauses.add(String.format("C.qualifier_concept_id in (%s)", StringUtils.join(conceptIds, ",")));
}
// unit
if (criteria.unit != null && criteria.unit.length > 0)
{
ArrayList<Long> conceptIds = getConceptIdsFromConcepts(criteria.unit);
whereClauses.add(String.format("C.unit_concept_id in (%s)", StringUtils.join(conceptIds, ",")));
}
// observationSourceConcept
if (criteria.observationSourceConcept != null)
{
whereClauses.add(String.format("C.observation_source_concept_id in (SELECT concept_id from #Codesets where codeset_id = %d)", criteria.observationSourceConcept));
}
// age
if (criteria.age != null)
{
whereClauses.add(buildNumericRangeClause("YEAR(C.observation_date) - P.year_of_birth", criteria.age));
}
// gender
if (criteria.gender != null && criteria.gender.length > 0)
{
whereClauses.add(String.format("P.gender_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.gender),",")));
}
// providerSpecialty
if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0)
{
whereClauses.add(String.format("PR.specialty_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.providerSpecialty),",")));
}
// visitType
if (criteria.visitType != null && criteria.visitType.length > 0)
{
whereClauses.add(String.format("V.visit_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.visitType),",")));
}
String whereClause = "";
if (whereClauses.size() > 0)
whereClause = "WHERE " + StringUtils.join(whereClauses, "\nAND ");
query = StringUtils.replace(query, "@whereClause",whereClause);
if (criteria.CorrelatedCriteria != null)
{
query = wrapCriteriaQuery(query, criteria.CorrelatedCriteria);
}
return query;
}
@Override
public String getCriteriaSql(ObservationPeriod criteria)
{
String query = OBSERVATION_PERIOD_TEMPLATE;
String startDateExpression = "C.observation_period_start_date";
String endDateExpression = "C.observation_period_end_date";
ArrayList<String> joinClauses = new ArrayList<>();
if (criteria.ageAtStart != null || criteria.ageAtEnd != null) // join to PERSON
joinClauses.add("JOIN @cdm_database_schema.PERSON P on C.person_id = P.person_id");
query = StringUtils.replace(query,"@joinClause", StringUtils.join(joinClauses,"\n"));
ArrayList<String> whereClauses = new ArrayList<>();
if (criteria.first != null && criteria.first == true)
whereClauses.add("C.ordinal = 1");
// check for user defined start/end dates
if (criteria.userDefinedPeriod != null)
{
Period userDefinedPeriod = criteria.userDefinedPeriod;
if (userDefinedPeriod.startDate != null)
{
startDateExpression = String.format("CAST('%s' as Date)", userDefinedPeriod.startDate);
whereClauses.add(String.format("C.OBSERVATION_PERIOD_START_DATE <= %s and C.OBSERVATION_PERIOD_END_DATE >= %s", startDateExpression, startDateExpression));
}
if (userDefinedPeriod.endDate != null)
{
endDateExpression = String.format("CAST('%s' as Date)", userDefinedPeriod.endDate);
whereClauses.add(String.format("C.OBSERVATION_PERIOD_START_DATE <= %s and C.OBSERVATION_PERIOD_END_DATE >= %s", endDateExpression, endDateExpression));
}
}
query = StringUtils.replace(query, "@startDateExpression",startDateExpression);
query = StringUtils.replace(query, "@endDateExpression",endDateExpression);
// periodStartDate
if (criteria.periodStartDate != null)
{
whereClauses.add(buildDateRangeClause("C.observation_period_start_date",criteria.periodStartDate));
}
// periodEndDate
if (criteria.periodEndDate != null)
{
whereClauses.add(buildDateRangeClause("C.observation_period_end_date",criteria.periodEndDate));
}
// periodType
if (criteria.periodType != null && criteria.periodType.length > 0)
{
ArrayList<Long> conceptIds = getConceptIdsFromConcepts(criteria.periodType);
whereClauses.add(String.format("C.period_type_concept_id in (%s)", StringUtils.join(conceptIds, ",")));
}
// periodLength
if (criteria.periodLength != null)
{
whereClauses.add(buildNumericRangeClause("DATEDIFF(d,C.observation_period_start_date, C.observation_period_end_date)", criteria.periodLength));
}
// ageAtStart
if (criteria.ageAtStart != null)
{
whereClauses.add(buildNumericRangeClause("YEAR(C.observation_period_start_date) - P.year_of_birth", criteria.ageAtStart));
}
// ageAtEnd
if (criteria.ageAtEnd != null)
{
whereClauses.add(buildNumericRangeClause("YEAR(C.observation_period_end_date) - P.year_of_birth", criteria.ageAtEnd));
}
String whereClause = "";
if (whereClauses.size() > 0)
whereClause = "WHERE " + StringUtils.join(whereClauses, "\nAND ");
query = StringUtils.replace(query, "@whereClause",whereClause);
if (criteria.CorrelatedCriteria != null)
{
query = wrapCriteriaQuery(query, criteria.CorrelatedCriteria);
}
return query;
}
@Override
public String getCriteriaSql(ProcedureOccurrence criteria)
{
String query = PROCEDURE_OCCURRENCE_TEMPLATE;
String codesetClause = "";
if (criteria.codesetId != null)
{
codesetClause = String.format("where po.procedure_concept_id in (SELECT concept_id from #Codesets where codeset_id = %d)", criteria.codesetId);
}
query = StringUtils.replace(query, "@codesetClause",codesetClause);
ArrayList<String> joinClauses = new ArrayList<>();
if (criteria.age != null || (criteria.gender != null && criteria.gender.length > 0)) // join to PERSON
joinClauses.add("JOIN @cdm_database_schema.PERSON P on C.person_id = P.person_id");
if (criteria.visitType != null && criteria.visitType.length > 0)
joinClauses.add("JOIN @cdm_database_schema.VISIT_OCCURRENCE V on C.visit_occurrence_id = V.visit_occurrence_id and C.person_id = V.person_id");
if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0)
joinClauses.add("LEFT JOIN @cdm_database_schema.PROVIDER PR on C.provider_id = PR.provider_id");
query = StringUtils.replace(query,"@joinClause", StringUtils.join(joinClauses,"\n"));
ArrayList<String> whereClauses = new ArrayList<>();
// first
if (criteria.first != null && criteria.first == true)
whereClauses.add("C.ordinal = 1");
// occurrenceStartDate
if (criteria.occurrenceStartDate != null)
{
whereClauses.add(buildDateRangeClause("C.procedure_date",criteria.occurrenceStartDate));
}
// procedureType
if (criteria.procedureType != null && criteria.procedureType.length > 0)
{
ArrayList<Long> conceptIds = getConceptIdsFromConcepts(criteria.procedureType);
whereClauses.add(String.format("C.procedure_type_concept_id in (%s)", StringUtils.join(conceptIds, ",")));
}
// modifier
if (criteria.modifier != null && criteria.modifier.length > 0)
{
ArrayList<Long> conceptIds = getConceptIdsFromConcepts(criteria.modifier);
whereClauses.add(String.format("C.modifier_concept_id in (%s)", StringUtils.join(conceptIds, ",")));
}
// quantity
if (criteria.quantity != null)
{
whereClauses.add(buildNumericRangeClause("C.quantity",criteria.quantity));
}
// procedureSourceConcept
if (criteria.procedureSourceConcept != null)
{
whereClauses.add(String.format("C.procedure_source_concept_id in (SELECT concept_id from #Codesets where codeset_id = %d)", criteria.procedureSourceConcept));
}
// age
if (criteria.age != null)
{
whereClauses.add(buildNumericRangeClause("YEAR(C.procedure_date) - P.year_of_birth", criteria.age));
}
// gender
if (criteria.gender != null && criteria.gender.length > 0)
{
whereClauses.add(String.format("P.gender_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.gender),",")));
}
// providerSpecialty
if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0)
{
whereClauses.add(String.format("PR.specialty_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.providerSpecialty),",")));
}
// visitType
if (criteria.visitType != null && criteria.visitType.length > 0)
{
whereClauses.add(String.format("V.visit_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.visitType),",")));
}
String whereClause = "";
if (whereClauses.size() > 0)
whereClause = "WHERE " + StringUtils.join(whereClauses, "\nAND ");
query = StringUtils.replace(query, "@whereClause",whereClause);
if (criteria.CorrelatedCriteria != null)
{
query = wrapCriteriaQuery(query, criteria.CorrelatedCriteria);
}
return query;
}
@Override
public String getCriteriaSql(Specimen criteria)
{
String query = SPECIMEN_TEMPLATE;
String codesetClause = "";
if (criteria.codesetId != null)
{
codesetClause = String.format("where s.specimen_concept_id in (SELECT concept_id from #Codesets where codeset_id = %d)", criteria.codesetId);
}
query = StringUtils.replace(query, "@codesetClause",codesetClause);
ArrayList<String> joinClauses = new ArrayList<>();
if (criteria.age != null || (criteria.gender != null && criteria.gender.length > 0)) // join to PERSON
joinClauses.add("JOIN @cdm_database_schema.PERSON P on C.person_id = P.person_id");
query = StringUtils.replace(query,"@joinClause", StringUtils.join(joinClauses,"\n"));
ArrayList<String> whereClauses = new ArrayList<>();
// first
if (criteria.first != null && criteria.first == true)
whereClauses.add("C.ordinal = 1");
// occurrenceStartDate
if (criteria.occurrenceStartDate != null)
{
whereClauses.add(buildDateRangeClause("C.specimen_date",criteria.occurrenceStartDate));
}
// specimenType
if (criteria.specimenType != null && criteria.specimenType.length > 0)
{
ArrayList<Long> conceptIds = getConceptIdsFromConcepts(criteria.specimenType);
whereClauses.add(String.format("C.specimen_type_concept_id in (%s)", StringUtils.join(conceptIds, ",")));
}
// quantity
if (criteria.quantity != null)
{
whereClauses.add(buildNumericRangeClause("C.quantity", criteria.quantity, ".4f"));
}
// unit
if (criteria.unit != null && criteria.unit.length > 0)
{
ArrayList<Long> conceptIds = getConceptIdsFromConcepts(criteria.unit);
whereClauses.add(String.format("C.unit_concept_id in (%s)", StringUtils.join(conceptIds, ",")));
}
// anatomicSite
if (criteria.anatomicSite != null && criteria.anatomicSite.length > 0)
{
ArrayList<Long> conceptIds = getConceptIdsFromConcepts(criteria.anatomicSite);
whereClauses.add(String.format("C.anatomic_site_concept_id in (%s)", StringUtils.join(conceptIds, ",")));
}
// diseaseStatus
if (criteria.diseaseStatus != null && criteria.diseaseStatus.length > 0)
{
ArrayList<Long> conceptIds = getConceptIdsFromConcepts(criteria.diseaseStatus);
whereClauses.add(String.format("C.disease_status_concept_id in (%s)", StringUtils.join(conceptIds, ",")));
}
// sourceId
if (criteria.sourceId != null)
{
whereClauses.add(buildTextFilterClause("C.specimen_source_id",criteria.sourceId));
}
// age
if (criteria.age != null)
{
whereClauses.add(buildNumericRangeClause("YEAR(C.specimen_date) - P.year_of_birth", criteria.age));
}
// gender
if (criteria.gender != null && criteria.gender.length > 0)
{
whereClauses.add(String.format("P.gender_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.gender),",")));
}
String whereClause = "";
if (whereClauses.size() > 0)
whereClause = "WHERE " + StringUtils.join(whereClauses, "\nAND ");
query = StringUtils.replace(query, "@whereClause",whereClause);
if (criteria.CorrelatedCriteria != null)
{
query = wrapCriteriaQuery(query, criteria.CorrelatedCriteria);
}
return query;
}
@Override
public String getCriteriaSql(VisitOccurrence criteria)
{
String query = VISIT_OCCURRENCE_TEMPLATE;
String codesetClause = "";
if (criteria.codesetId != null)
{
codesetClause = String.format("where vo.visit_concept_id in (SELECT concept_id from #Codesets where codeset_id = %d)", criteria.codesetId);
}
query = StringUtils.replace(query, "@codesetClause",codesetClause);
ArrayList<String> joinClauses = new ArrayList<>();
if (criteria.age != null || (criteria.gender != null && criteria.gender.length > 0)) // join to PERSON
joinClauses.add("JOIN @cdm_database_schema.PERSON P on C.person_id = P.person_id");
if (criteria.placeOfService != null && criteria.placeOfService.length > 0)
joinClauses.add("JOIN @cdm_database_schema.CARE_SITE CS on C.care_site_id = CS.care_site_id");
if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0)
joinClauses.add("LEFT JOIN @cdm_database_schema.PROVIDER PR on C.provider_id = PR.provider_id");
query = StringUtils.replace(query,"@joinClause", StringUtils.join(joinClauses,"\n"));
ArrayList<String> whereClauses = new ArrayList<>();
// first
if (criteria.first != null && criteria.first == true)
whereClauses.add("C.ordinal = 1");
// occurrenceStartDate
if (criteria.occurrenceStartDate != null)
{
whereClauses.add(buildDateRangeClause("C.visit_start_date",criteria.occurrenceStartDate));
}
// occurrenceEndDate
if (criteria.occurrenceEndDate != null)
{
whereClauses.add(buildDateRangeClause("C.visit_end_date",criteria.occurrenceEndDate));
}
// visitType
if (criteria.visitType != null && criteria.visitType.length > 0)
{
ArrayList<Long> conceptIds = getConceptIdsFromConcepts(criteria.visitType);
whereClauses.add(String.format("C.visit_type_concept_id in (%s)", StringUtils.join(conceptIds, ",")));
}
// visitSourceConcept
if (criteria.visitSourceConcept != null)
{
whereClauses.add(String.format("C.visit_source_concept_id in (SELECT concept_id from #Codesets where codeset_id = %d)", criteria.visitSourceConcept));
}
// visitLength
if (criteria.visitLength != null)
{
whereClauses.add(buildNumericRangeClause("DATEDIFF(d,C.visit_start_date, C.visit_end_date)", criteria.visitLength));
}
// age
if (criteria.age != null)
{
whereClauses.add(buildNumericRangeClause("YEAR(C.visit_start_date) - P.year_of_birth", criteria.age));
}
// gender
if (criteria.gender != null && criteria.gender.length > 0)
{
whereClauses.add(String.format("P.gender_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.gender),",")));
}
// providerSpecialty
if (criteria.providerSpecialty != null && criteria.providerSpecialty.length > 0)
{
whereClauses.add(String.format("PR.specialty_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.providerSpecialty),",")));
}
// placeOfService
if (criteria.placeOfService != null && criteria.placeOfService.length > 0)
{
whereClauses.add(String.format("CS.place_of_service_concept_id in (%s)", StringUtils.join(getConceptIdsFromConcepts(criteria.placeOfService),",")));
}
String whereClause = "";
if (whereClauses.size() > 0)
whereClause = "WHERE " + StringUtils.join(whereClauses, "\nAND ");
query = StringUtils.replace(query, "@whereClause",whereClause);
if (criteria.CorrelatedCriteria != null)
{
query = wrapCriteriaQuery(query, criteria.CorrelatedCriteria);
}
return query;
}
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="IEndStrategyDispatcher implementation">
private String getDateFieldForOffsetStrategy (DateOffsetStrategy.DateField dateField) {
switch (dateField) {
case StartDate:
return "start_date";
case EndDate:
return "end_date";
}
return "start_date";
}
@Override
public String getStrategySql(DateOffsetStrategy strat, String eventTable)
{
String insertSql = "-- Date Offset Strategy\nINSERT INTO #cohort_ends (event_id, person_id, end_date)\n@dateOffsetStrategySql;";
String strategySql = StringUtils.replace(DATE_OFFSET_STRATEGY_TEMPLATE, "@eventTable",eventTable);
strategySql = StringUtils.replace(strategySql, "@offset",Integer.toString(strat.offset));
strategySql = StringUtils.replace(strategySql, "@dateField",getDateFieldForOffsetStrategy(strat.dateField));
insertSql = StringUtils.replace(insertSql, "@dateOffsetStrategySql",strategySql);
return insertSql;
}
@Override
public String getStrategySql(CustomEraStrategy strat, String eventTable)
{
if (strat.drugCodesetId == null)
throw new RuntimeException("Drug Codeset ID can not be NULL.");
String insertSql = "-- Custom Era Strategy\nINSERT INTO #cohort_ends (event_id, person_id, end_date)\n@customEraStrategySql;";
String strategySql = StringUtils.replace(CUSTOM_ERA_STRATEGY_TEMPLATE, "@eventTable",eventTable);
strategySql = StringUtils.replace(strategySql, "@drugCodesetId",strat.drugCodesetId.toString());
strategySql = StringUtils.replace(strategySql, "@gapDays",Integer.toString(strat.gapDays));
strategySql = StringUtils.replace(strategySql, "@offset",Integer.toString(strat.offset));
insertSql = StringUtils.replace(insertSql, "@customEraStrategySql",strategySql);
return insertSql;
}
// </editor-fold>
}